Module: xenomai-forge
Branch: next
Commit: 9c1174591e0f7dd343e26c721ae2fc13c65b36df
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=9c1174591e0f7dd343e26c721ae2fc13c65b36df

Author: Philippe Gerum <r...@xenomai.org>
Date:   Wed Aug 28 11:41:50 2013 +0200

copperplate: introduce fast scheduler lock management helpers

Locking the scheduler does not require to hold the current thread lock
over Cobalt, we just have to care about SMP cache synchronization if
applicable, for maintaining the nesting count which is private to the
current thread.

This change causes all high level locking helpers
(i.e. threadobj_[un]lock_sched[_once]) to assume unlocked call
context, and provides a set of inner routines assuming the converse
situation.

Existing call sites have been fixed accordingly, depending on the
preferred context.

---

 include/copperplate/threadobj.h |   12 +++++++
 lib/copperplate/threadobj.c     |   68 +++++++++++++++++++++++++++++----------
 lib/psos/task.c                 |    6 ++--
 lib/vxworks/taskLib.c           |    6 +--
 4 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/include/copperplate/threadobj.h b/include/copperplate/threadobj.h
index b7af004..62515d7 100644
--- a/include/copperplate/threadobj.h
+++ b/include/copperplate/threadobj.h
@@ -302,8 +302,12 @@ int threadobj_resume(struct threadobj *thobj);
 
 int threadobj_unblock(struct threadobj *thobj);
 
+int __threadobj_lock_sched(struct threadobj *current);
+
 int threadobj_lock_sched(void);
 
+int __threadobj_unlock_sched(struct threadobj *current);
+
 int threadobj_unlock_sched(void);
 
 int threadobj_set_priority(struct threadobj *thobj, int prio);
@@ -403,6 +407,14 @@ static inline int threadobj_current_p(void)
        return current && current != THREADOBJ_IRQCONTEXT;
 }
 
+static inline int __threadobj_lock_sched_once(struct threadobj *current)
+{
+       if (current->schedlock_depth == 0)
+               return __threadobj_lock_sched(current);
+
+       return -EBUSY;
+}
+
 static inline int threadobj_lock_sched_once(void)
 {
        struct threadobj *current = threadobj_current();
diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c
index 64eb138..08c8ea2 100644
--- a/lib/copperplate/threadobj.c
+++ b/lib/copperplate/threadobj.c
@@ -174,11 +174,9 @@ int threadobj_resume(struct threadobj *thobj) /* 
thobj->lock held */
        return __bt(-ret);
 }
 
-int threadobj_lock_sched(void) /* current->lock held */
+int __threadobj_lock_sched(struct threadobj *current)
 {
-       struct threadobj *current = threadobj_current();
-
-       __threadobj_check_locked(current);
+       smp_rmb();
 
        if (current->schedlock_depth++ > 0)
                return 0;
@@ -191,18 +189,24 @@ int threadobj_lock_sched(void) /* current->lock held */
        return __bt(-pthread_set_mode_np(0, PTHREAD_LOCK_SCHED, NULL));
 }
 
-int threadobj_unlock_sched(void) /* current->lock held */
+int threadobj_lock_sched(void)
 {
        struct threadobj *current = threadobj_current();
 
-       __threadobj_check_locked(current);
+       /* This call is lock-free over Cobalt. */
+       return __bt(__threadobj_lock_sched(current));
+}
 
+int __threadobj_unlock_sched(struct threadobj *current)
+{
        /*
-        * Higher layers may not know about the current locking level
-        * and fully rely on us to track it, so we gracefully handle
-        * unbalanced calls here, and let them decide of the outcome
-        * in case of error.
+        * Higher layers may not know about the current scheduler
+        * locking level and fully rely on us to track it, so we
+        * gracefully handle unbalanced calls here, and let them
+        * decide of the outcome in case of error.
         */
+       smp_rmb();
+
        if (current->schedlock_depth == 0)
                return __bt(-EINVAL);
 
@@ -212,6 +216,14 @@ int threadobj_unlock_sched(void) /* current->lock held */
        return __bt(-pthread_set_mode_np(PTHREAD_LOCK_SCHED, 0, NULL));
 }
 
+int threadobj_unlock_sched(void)
+{
+       struct threadobj *current = threadobj_current();
+
+       /* This call is lock-free over Cobalt. */
+       return __bt(__threadobj_unlock_sched(current));
+}
+
 int threadobj_set_priority(struct threadobj *thobj, int prio) /* thobj->lock 
held, dropped */
 {
        struct sched_param_ex xparam;
@@ -260,9 +272,9 @@ int threadobj_set_mode(int clrmask, int setmask, int 
*mode_r) /* current->lock h
                __clrmask |= PTHREAD_CONFORMING;
 
        if (setmask & __THREAD_M_LOCK)
-               threadobj_lock_sched_once();
+               __threadobj_lock_sched_once(current);
        else if (clrmask & __THREAD_M_LOCK)
-               threadobj_unlock_sched();
+               __threadobj_unlock_sched(current);
 
        if (mode_r || __setmask || __clrmask)
                return __bt(-pthread_set_mode_np(__clrmask, __setmask, mode_r));
@@ -486,9 +498,8 @@ int threadobj_resume(struct threadobj *thobj) /* 
thobj->lock held */
        return __bt(notifier_release(&thobj->core.notifier));
 }
 
-int threadobj_lock_sched(void) /* current->lock held */
+int __threadobj_lock_sched(struct threadobj *current) /* current->lock held */
 {
-       struct threadobj *current = threadobj_current();
        pthread_t tid = current->tid;
        struct sched_param param;
 
@@ -506,9 +517,20 @@ int threadobj_lock_sched(void) /* current->lock held */
        return __bt(-pthread_setschedparam(tid, SCHED_RT, &param));
 }
 
-int threadobj_unlock_sched(void) /* current->lock held */
+int threadobj_lock_sched(void)
 {
        struct threadobj *current = threadobj_current();
+       int ret;
+
+       threadobj_lock(current);
+       ret = __threadobj_lock_sched(current);
+       threadobj_unlock(current);
+
+       return __bt(ret);
+}
+
+int __threadobj_unlock_sched(struct threadobj *current) /* current->lock held 
*/
+{
        pthread_t tid = current->tid;
        struct sched_param param;
        int policy, ret;
@@ -531,6 +553,18 @@ int threadobj_unlock_sched(void) /* current->lock held */
        return __bt(-ret);
 }
 
+int threadobj_unlock_sched(void)
+{
+       struct threadobj *current = threadobj_current();
+       int ret;
+
+       threadobj_lock(current);
+       ret = __threadobj_unlock_sched(current);
+       threadobj_unlock(current);
+
+       return __bt(ret);
+}
+
 int threadobj_set_priority(struct threadobj *thobj, int prio) /* thobj->lock 
held, dropped */
 {
        pthread_t tid = thobj->tid;
@@ -581,11 +615,11 @@ int threadobj_set_mode(int clrmask, int setmask, int 
*mode_r) /* current->lock h
                old |= __THREAD_M_LOCK;
 
        if (setmask & __THREAD_M_LOCK) {
-               ret = threadobj_lock_sched_once();
+               ret = __threadobj_lock_sched_once(current);
                if (ret == -EBUSY)
                        ret = 0;
        } else if (clrmask & __THREAD_M_LOCK)
-               threadobj_unlock_sched();
+               __threadobj_unlock_sched(current);
 
        if (mode_r)
                *mode_r = old;
diff --git a/lib/psos/task.c b/lib/psos/task.c
index 51feff6..d733152 100644
--- a/lib/psos/task.c
+++ b/lib/psos/task.c
@@ -190,7 +190,7 @@ static void *task_trampoline(void *arg)
                threadobj_set_rr(&task->thobj, &psos_rrperiod);
 
        if (task->mode & T_NOPREEMPT)
-               threadobj_lock_sched();
+               __threadobj_lock_sched(&task->thobj);
 
        threadobj_unlock(&task->thobj);
 
@@ -549,9 +549,9 @@ u_long t_mode(u_long mask, u_long newmask, u_long 
*oldmode_r)
        task->mode |= (newmask & mask);
 
        if (task->mode & T_NOPREEMPT)
-               threadobj_lock_sched_once();
+               __threadobj_lock_sched_once(&task->thobj);
        else if (*oldmode_r & T_NOPREEMPT)
-               threadobj_unlock_sched();
+               __threadobj_unlock_sched(&task->thobj);
 
        /*
         * Copperplate won't accept to turn round-robin on/off when
diff --git a/lib/vxworks/taskLib.c b/lib/vxworks/taskLib.c
index b3244b4..ae460d9 100644
--- a/lib/vxworks/taskLib.c
+++ b/lib/vxworks/taskLib.c
@@ -779,7 +779,7 @@ STATUS taskLock(void)
                return ERROR;
        }
 
-       task = get_wind_task_or_self(0);
+       task = find_wind_task_or_self(0);
        if (task == NULL) {
                errno = S_objLib_OBJ_ID_ERROR;
                return ERROR;
@@ -788,7 +788,6 @@ STATUS taskLock(void)
        COPPERPLATE_PROTECT(svc);
        threadobj_lock_sched();
        COPPERPLATE_UNPROTECT(svc);
-       put_wind_task(task);
 
        return OK;
 }
@@ -803,7 +802,7 @@ STATUS taskUnlock(void)
                return ERROR;
        }
 
-       task = get_wind_task_or_self(0);
+       task = find_wind_task_or_self(0);
        if (task == NULL) {
                errno = S_objLib_OBJ_ID_ERROR;
                return ERROR;
@@ -812,7 +811,6 @@ STATUS taskUnlock(void)
        COPPERPLATE_PROTECT(svc);
        threadobj_unlock_sched();
        COPPERPLATE_UNPROTECT(svc);
-       put_wind_task(task);
 
        return OK;
 }


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

Reply via email to