This patch improves the performance of xnsynch_sleep_on when it is
called with (XN_RELATIVE, XN_NONBLOCK) timeout parameters. For this
purpose, it introduces a new thread info XNNONBLCK that is set in case
xnsynch_sleep_on fails while in XN_NONBLOCK mode. Maybe this should be
solved via a dedicated trylock (but that would duplicate quite some
code), hopefully we can avoid it completely by doing lock stealing on
trylock via (generic) fast locks, even in user space.

---
 include/nucleus/thread.h  |    1 +
 ksrc/nucleus/pod.c        |    8 +++++---
 ksrc/nucleus/synch.c      |   20 +++++++++++++++++---
 ksrc/skins/native/mutex.c |   13 +++++++------
 ksrc/skins/posix/mutex.c  |    5 +----
 ksrc/skins/posix/mutex.h  |    8 +++++++-
 6 files changed, 38 insertions(+), 17 deletions(-)

Index: b/include/nucleus/thread.h
===================================================================
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -116,6 +116,7 @@
 #define XNROBBED  0x00000020 /**< Robbed from resource ownership */
 #define XNATOMIC  0x00000040 /**< In atomic switch from secondary to primary 
mode */
 #define XNAFFSET  0x00000080 /**< CPU affinity changed from primary mode */
+#define XNNONBLCK 0x00000100 /**< Non-blocking mode prevented suspension */
 
 /* These information flags are available to the real-time interfaces */
 #define XNTHREAD_INFO_SPARE0  0x10000000
Index: b/ksrc/nucleus/pod.c
===================================================================
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -1401,14 +1401,16 @@ void xnpod_suspend_thread(xnthread_t *th
                                                thread->name, mask);
                                );
                        xnthread_clear_info(thread,
-                                           XNRMID | XNTIMEO | XNROBBED);
+                                           XNRMID | XNTIMEO | XNROBBED |
+                                           XNNONBLCK);
                        xnthread_set_info(thread, XNBREAK);
                        goto unlock_and_exit;
                }
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
-               xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK |
-                                           XNWAKEN | XNROBBED);
+               xnthread_clear_info(thread,
+                                   XNRMID | XNTIMEO | XNBREAK | XNWAKEN |
+                                   XNROBBED | XNNONBLCK);
        }
 
        /* Don't start the timer for a thread indefinitely delayed by
Index: b/ksrc/nucleus/synch.c
===================================================================
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -194,7 +194,8 @@ redo:
 
        if (!owner) {
                synch->owner = thread;
-               xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
+               xnthread_clear_info(thread,
+                                   XNRMID | XNTIMEO | XNBREAK | XNNONBLCK);
                goto unlock_and_exit;
        }
 
@@ -202,11 +203,18 @@ redo:
                if (xnthread_test_info(owner, XNWAKEN) && owner->wwake == 
synch) {
                        /* Ownership is still pending, steal the resource. */
                        synch->owner = thread;
-                       xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
+                       xnthread_clear_info(thread,
+                                           XNRMID | XNTIMEO | XNBREAK |
+                                           XNNONBLCK);
                        xnthread_set_info(owner, XNROBBED);
                        goto unlock_and_exit;
                }
 
+               if (timeout == XN_NONBLOCK && timeout_mode == XN_RELATIVE) {
+                       xnthread_set_info(thread, XNNONBLCK);
+                       goto unlock_and_exit;
+               }
+
                if (!xnthread_test_state(owner, XNBOOST)) {
                        owner->bprio = owner->cprio;
                        xnthread_set_state(owner, XNBOOST);
@@ -220,8 +228,14 @@ redo:
                insertpqf(&owner->claimq, &synch->link, thread->cprio);
                insertpqf(&synch->pendq, &thread->plink, thread->cprio);
                xnsynch_renice_thread(owner, thread->cprio);
-       } else
+       } else {
+               if (timeout == XN_NONBLOCK && timeout_mode == XN_RELATIVE) {
+                       xnthread_set_info(thread, XNNONBLCK);
+                       goto unlock_and_exit;
+               }
+
                insertpqf(&synch->pendq, &thread->plink, thread->cprio);
+       }
 
        xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
 
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -388,17 +388,18 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
 
        if (unlikely
            (xnthread_test_info(thread,
-                               XNBREAK | XNRMID | XNROBBED | XNTIMEO))) {
+                               XNBREAK | XNNONBLCK | XNRMID | XNROBBED |
+                               XNTIMEO))) {
+               if (xnthread_test_info(thread, XNNONBLCK)) {
+                       err = -EWOULDBLOCK;     /* Try-to-lock failed. */
+                       goto cleanup_and_exit;
+               }
                if (xnthread_test_info(thread, XNROBBED)) {
                        xnlock_put_irqrestore(&nklock, s);
                        goto retry;
                }
                if (xnthread_test_info(thread, XNTIMEO)) {
-                       if (timeout_mode == XN_RELATIVE &&
-                           timeout == XN_NONBLOCK)
-                               err = -EWOULDBLOCK;
-                       else
-                               err = -ETIMEDOUT;
+                       err = -ETIMEDOUT;
                        goto cleanup_and_exit;
                }
                if (xnthread_test_info(thread, XNBREAK)) {
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -406,13 +406,10 @@ int pthread_mutex_trylock(pthread_mutex_
                                err = 0;
                        }
                }
-       } else {
+       } else
                err =
                    -pse51_mutex_timedlock_internal(cur, shadow, 1,
                                                    XN_RELATIVE, XN_NONBLOCK);
-               if (err == ETIMEDOUT)
-                       err = EBUSY;
-       }
 
        cb_read_unlock(&shadow->lock, s);
 
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -174,7 +174,13 @@ static inline int pse51_mutex_timedlock_
        xnsynch_sleep_on(&mutex->synchbase, timeout, timeout_mode);
 
        if (unlikely
-           (xnthread_test_info(cur, XNBREAK | XNRMID | XNROBBED | XNTIMEO))) {
+           (xnthread_test_info(cur,
+                               XNBREAK | XNNONBLCK | XNRMID | XNROBBED |
+                               XNTIMEO))) {
+               if (xnthread_test_info(cur, XNNONBLCK)) {
+                       err = -EBUSY;
+                       goto error;
+               }
                if (xnthread_test_info(cur, XNROBBED)) {
                        xnlock_put_irqrestore(&nklock, s);
                        goto retry_lock;


_______________________________________________
Xenomai-core mailing list
Xenomai-core@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to