From: Philippe Gerum <[email protected]>

Unlike the I-pipe, Dovetail does not copy the work descriptor but
merely hands over the request to the common irq_work() mechanism. We
must guarantee that such descriptor lives in a portion of memory which
won't go stale until the handler has run, which by design can only
happen once the calling out-of-band context unwinds.

Therefore, we have to move the in-band work descriptor used in
triggering fd closure off the stack to a global variable, which is
fine since the action of flushing the lingering fds is globally
scoped.

Signed-off-by: Philippe Gerum <[email protected]>
Signed-off-by: Jan Kiszka <[email protected]>
---
 kernel/cobalt/rtdm/fd.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c
index 038247d54..151884a24 100644
--- a/kernel/cobalt/rtdm/fd.c
+++ b/kernel/cobalt/rtdm/fd.c
@@ -257,10 +257,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(rtdm_fd_get);
 
-struct lostage_trigger_close {
-       struct pipeline_inband_work inband_work; /* Must be first. */
-};
-
 static int fd_cleanup_thread(void *data)
 {
        struct rtdm_fd *fd;
@@ -293,9 +289,16 @@ static void lostage_trigger_close(struct 
pipeline_inband_work *inband_work)
        up(&rtdm_fd_cleanup_sem);
 }
 
+static struct lostage_trigger_close {
+       struct pipeline_inband_work inband_work; /* Must be first. */
+} fd_closework =  {
+       .inband_work = PIPELINE_INBAND_WORK_INITIALIZER(fd_closework,
+                                               lostage_trigger_close),
+};
+
 static void __put_fd(struct rtdm_fd *fd, spl_t s)
 {
-       bool destroy;
+       bool destroy, trigger;
 
        XENO_WARN_ON(COBALT, fd->refs <= 0);
        destroy = --fd->refs == 0;
@@ -310,16 +313,13 @@ static void __put_fd(struct rtdm_fd *fd, spl_t s)
        if (is_secondary_domain())
                fd->ops->close(fd);
        else {
-               struct lostage_trigger_close closework = {
-                       .inband_work = 
PIPELINE_INBAND_WORK_INITIALIZER(closework,
-                                       lostage_trigger_close),
-               };
-
                xnlock_get_irqsave(&fdtree_lock, s);
+               trigger = list_empty(&rtdm_fd_cleanup_queue);
                list_add_tail(&fd->cleanup, &rtdm_fd_cleanup_queue);
                xnlock_put_irqrestore(&fdtree_lock, s);
 
-               pipeline_post_inband_work(&closework);
+               if (trigger)
+                       pipeline_post_inband_work(&fd_closework);
        }
 }
 
-- 
2.26.2


Reply via email to