Module: xenomai-3
Branch: next
Commit: 139d2e4c0dc78e3868f9fb0509ace488dc4f902c
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=139d2e4c0dc78e3868f9fb0509ace488dc4f902c

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Jun  1 17:33:56 2015 +0200

alchemy/task: fix for remote messages (pshared)

---

 include/alchemy/task.h |    5 ++++-
 lib/alchemy/task.c     |   54 +++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/include/alchemy/task.h b/include/alchemy/task.h
index cc3e3c0..685d478 100644
--- a/include/alchemy/task.h
+++ b/include/alchemy/task.h
@@ -52,7 +52,10 @@ typedef struct RT_TASK RT_TASK;
 struct RT_TASK_MCB {
        int flowid;
        int opcode;
-       void *data;
+       union {
+               dref_type(void *) __dref;
+               void *data;
+       };
        ssize_t size;
 };
 
diff --git a/lib/alchemy/task.c b/lib/alchemy/task.c
index 327e916..857496b 100644
--- a/lib/alchemy/task.c
+++ b/lib/alchemy/task.c
@@ -1698,6 +1698,7 @@ ssize_t rt_task_send_timed(RT_TASK *task,
                           RT_TASK_MCB *mcb_s, RT_TASK_MCB *mcb_r,
                           const struct timespec *abs_timeout)
 {
+       void *rbufin = NULL, *rbufout = NULL;
        struct alchemy_task_wait *wait;
        struct threadobj *current;
        struct alchemy_task *tcb;
@@ -1741,10 +1742,31 @@ ssize_t rt_task_send_timed(RT_TASK *task,
                tcb->flowgen = 1;
 
        wait->request = *mcb_s;
+       /*
+        * Payloads exchanged with remote tasks have to go through the
+        * main heap.
+        */
+       if (mcb_s->size > 0 && !threadobj_local_p(&tcb->thobj)) {
+               rbufin = xnmalloc(mcb_s->size);
+               if (rbufin == NULL) {
+                       ret = -ENOMEM;
+                       goto cleanup;
+               }
+               memcpy(rbufin, mcb_s->data, mcb_s->size);
+               wait->request.__dref = __moff(rbufin);
+       }
        wait->request.flowid = tcb->flowgen;
        if (mcb_r) {
-               wait->reply.data = mcb_r->data;
                wait->reply.size = mcb_r->size;
+               wait->reply.data = mcb_r->data;
+               if (mcb_r->size > 0 && !threadobj_local_p(&tcb->thobj)) {
+                       rbufout = xnmalloc(mcb_r->size);
+                       if (rbufout == NULL) {
+                               ret = -ENOMEM;
+                               goto cleanup;
+                       }
+                       wait->reply.__dref = __moff(rbufout);
+               }
        } else {
                wait->reply.data = NULL;
                wait->reply.size = 0;
@@ -1760,12 +1782,20 @@ ssize_t rt_task_send_timed(RT_TASK *task,
                        goto out;
                goto done;
        }
-       ret = wait->reply.size;
 
+       ret = wait->reply.size;
+       if (!threadobj_local_p(&tcb->thobj) && ret > 0 && mcb_r)
+               memcpy(mcb_r->data, rbufout, ret);
+cleanup:
        threadobj_finish_wait();
 done:
        syncobj_unlock(&tcb->sobj_msg, &syns);
 out:
+       if (rbufin)
+               xnfree(rbufin);
+       if (rbufout)
+               xnfree(rbufout);
+       
        CANCEL_RESTORE(svc);
 
        return ret;
@@ -1903,8 +1933,12 @@ int rt_task_receive_timed(RT_TASK_MCB *mcb_r,
                goto fixup;
        }
 
-       if (mcb_s->size > 0)
-               memcpy(mcb_r->data, mcb_s->data, mcb_s->size);
+       if (mcb_s->size > 0) {
+               if (!threadobj_local_p(thobj))
+                       memcpy(mcb_r->data, __mptr(mcb_s->__dref), mcb_s->size);
+               else
+                       memcpy(mcb_r->data, mcb_s->data, mcb_s->size);
+       }
 
        /* The flow identifier is always strictly positive. */
        ret = mcb_s->flowid;
@@ -2020,8 +2054,8 @@ int rt_task_reply(int flowid, RT_TASK_MCB *mcb_s)
        /*
         * NOTE: sending back a NULL or zero-length reply is perfectly
         * valid; it just means to unblock the client without passing
-        * it back any reply data. What is invalid is sending a
-        * response larger than what the client expects.
+        * it back any reply data. Sending a response larger than what
+        * the client expects is invalid.
         */
        if (mcb_r->size < size) {
                ret = -ENOBUFS; /* Client will get this too. */
@@ -2029,8 +2063,12 @@ int rt_task_reply(int flowid, RT_TASK_MCB *mcb_s)
        } else {
                ret = 0;
                mcb_r->size = size;
-               if (size > 0)
-                       memcpy(mcb_r->data, mcb_s->data, size);
+               if (size > 0) {
+                       if (!threadobj_local_p(thobj))
+                               memcpy(__mptr(mcb_r->__dref), mcb_s->data, 
size);
+                       else
+                               memcpy(mcb_r->data, mcb_s->data, size);
+               }
        }
 
        mcb_r->flowid = flowid;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to