Module: xenomai-forge
Branch: master
Commit: 25eb373eeb1a56d5961a2e9ae6c0bd7b1da91015
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=25eb373eeb1a56d5961a2e9ae6c0bd7b1da91015

Author: Philippe Gerum <r...@xenomai.org>
Date:   Wed Jun  5 19:41:30 2013 +0200

psos/tm: fix race in timer removal code

The initial code would race in delete_timer() against the task
finalizer by lack of synchronization on the task lock.

In addition, as observed in a SMP situation, such lack of locking
results in no memory barrier being issued after removing the timer
from the per-task timer_list queue, which eventually causes a remote
CPU altering this queue concurrently to work on stale pointers.

---

 lib/psos/task.c |   35 ++++++++++++++++++++---------------
 lib/psos/task.h |    2 ++
 lib/psos/tm.c   |   27 ++++++++++++++++++++-------
 3 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/lib/psos/task.c b/lib/psos/task.c
index 3218cba..51feff6 100644
--- a/lib/psos/task.c
+++ b/lib/psos/task.c
@@ -643,24 +643,14 @@ out:
        return ret;
 }
 
-u_long ev_send(u_long tid, u_long events)
+int __ev_send(struct psos_task *task, u_long events)
 {
-       struct psos_task *task;
        struct syncstate syns;
-       struct service svc;
-       int ret = SUCCESS;
-
-       task = find_psos_task(tid, &ret);
-       if (task == NULL)
-               return ret;
-
-       COPPERPLATE_PROTECT(svc);
+       int ret;
 
        ret = syncobj_lock(&task->sobj, &syns);
-       if (ret) {
-               ret = ERR_OBJDEL;
-               goto out;
-       }
+       if (ret)
+               return ERR_OBJDEL;
 
        task->events |= events;
        /*
@@ -672,7 +662,22 @@ u_long ev_send(u_long tid, u_long events)
        syncobj_grant_one(&task->sobj);
 
        syncobj_unlock(&task->sobj, &syns);
-out:
+
+       return 0;
+}
+
+u_long ev_send(u_long tid, u_long events)
+{
+       struct psos_task *task;
+       struct service svc;
+       int ret = SUCCESS;
+
+       task = find_psos_task(tid, &ret);
+       if (task == NULL)
+               return ret;
+
+       COPPERPLATE_PROTECT(svc);
+       ret = __ev_send(task, events);
        COPPERPLATE_UNPROTECT(svc);
 
        return ret;
diff --git a/lib/psos/task.h b/lib/psos/task.h
index 1476f36..a62028a 100644
--- a/lib/psos/task.h
+++ b/lib/psos/task.h
@@ -69,6 +69,8 @@ struct psos_task *get_psos_task_or_self(u_long tid, int 
*err_r);
 
 void put_psos_task(struct psos_task *task);
 
+int __ev_send(struct psos_task *task, unsigned long events);
+
 extern struct cluster psos_task_table;
 
 #endif /* _PSOS_TASK_H */
diff --git a/lib/psos/tm.c b/lib/psos/tm.c
index febcd10..7c58631 100644
--- a/lib/psos/tm.c
+++ b/lib/psos/tm.c
@@ -60,11 +60,24 @@ objid_error:
        return NULL;
 }
 
-static void delete_timer(struct psos_tm *tm)
+static void delete_timer(struct psos_tm *tm, int signal_p)
 {
+       struct psos_task *task;
+       int ret;
+
        tm->magic = ~tm_magic;  /* Prevent further reference. */
        timerobj_destroy(&tm->tmobj);
-       pvlist_remove(&tm->link);
+       task = get_psos_task(tm->tid, &ret);
+       if (task) {
+               pvlist_remove(&tm->link);
+               /*
+                * Send out the pending event set carried by the
+                * deleted timer to the owner thread if requested.
+                */
+               if (signal_p)
+                       __ev_send(task, tm->events);
+               put_psos_task(task);
+       }
        pvfree(tm);
 }
 
@@ -75,11 +88,11 @@ static void post_event_once(struct timerobj *tmobj)
        int ret;
 
        COPPERPLATE_PROTECT(svc);
+
        ret = timerobj_lock(&tm->tmobj);
-       if (ret == 0) {
-               ev_send(tm->tid, tm->events);
-               delete_timer(tm);
-       }
+       if (ret == 0)
+               delete_timer(tm, 1);
+
        COPPERPLATE_UNPROTECT(svc);
 }
 
@@ -253,7 +266,7 @@ u_long tm_cancel(u_long tmid)
 
        tm = get_tm(tmid, &ret);
        if (tm)
-               delete_timer(tm);
+               delete_timer(tm, 0);
 
        COPPERPLATE_UNPROTECT(svc);
 


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

Reply via email to