[PATCH 05/10] score: Use _Thread_queue_Flush_critical for futex

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Apr 21 07:20:09 UTC 2016


---
 cpukit/score/src/futex.c | 98 ++++++++++++++----------------------------------
 1 file changed, 28 insertions(+), 70 deletions(-)

diff --git a/cpukit/score/src/futex.c b/cpukit/score/src/futex.c
index 73d48fd..59a625c 100644
--- a/cpukit/score/src/futex.c
+++ b/cpukit/score/src/futex.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2015, 2016 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -103,99 +103,57 @@ int _Futex_Wait( struct _Futex_Control *_futex, int *uaddr, int val )
   return eno;
 }
 
-/*
- * Use a noinline function to force the compiler to set up and tear down the
- * large stack frame only in the slow case.
- */
-static __attribute__((noinline)) int _Futex_Wake_slow(
-  Futex_Control      *futex,
-  int                 count,
-  Thread_queue_Heads *heads,
+typedef struct {
+  ISR_lock_Context Base;
+  int              count;
+} Futex_Lock_context;
+
+static Thread_Control *_Futex_Flush_filter(
+  Thread_Control     *the_thread,
+  Thread_queue_Queue *queue,
   ISR_lock_Context   *lock_context
 )
 {
-  Chain_Control  unblock;
-  Chain_Node    *node;
-  Chain_Node    *tail;
-  int            woken;
-
-  woken = 0;
-  _Chain_Initialize_empty( &unblock );
-
-  while ( count > 0 && heads != NULL ) {
-    const Thread_queue_Operations *operations;
-    Thread_Control                *first;
-    bool                           do_unblock;
+  Futex_Lock_context *futex_lock_context;
 
-    operations = FUTEX_TQ_OPERATIONS;
-    first = ( *operations->first )( heads );
+  futex_lock_context = (Futex_Lock_context *) lock_context;
 
-    do_unblock = _Thread_queue_Extract_locked(
-      &futex->Queue.Queue,
-      operations,
-      first,
-      NULL,
-      0
-    );
-    if (do_unblock) {
-      _Chain_Append_unprotected( &unblock, &first->Wait.Node.Chain );
-    }
-
-    ++woken;
-    --count;
-    heads = futex->Queue.Queue.heads;
+  if ( futex_lock_context->count <= 0 ) {
+    return NULL;
   }
 
-  node = _Chain_First( &unblock );
-  tail = _Chain_Tail( &unblock );
-
-  if ( node != tail ) {
-    Per_CPU_Control *cpu_self;
-
-    cpu_self = _Thread_Dispatch_disable_critical( lock_context );
-    _Futex_Queue_release( futex, lock_context );
+  --futex_lock_context->count;
 
-    do {
-      Thread_Control *thread;
-      Chain_Node     *next;
-
-      next = _Chain_Next( node );
-      thread = THREAD_CHAIN_NODE_TO_THREAD( node );
-      _Thread_Unblock( thread );
-
-      node = next;
-    } while ( node != tail );
-
-    _Thread_Dispatch_enable( cpu_self );
-  } else {
-    _Futex_Queue_release( futex, lock_context );
-  }
-
-  return woken;
+  return the_thread;
 }
 
 int _Futex_Wake( struct _Futex_Control *_futex, int count )
 {
   Futex_Control      *futex;
-  ISR_lock_Context    lock_context;
-  Thread_queue_Heads *heads;
+  Futex_Lock_context  lock_context;
 
   futex = _Futex_Get( _futex );
-  _Futex_Queue_acquire( futex, &lock_context );
+  _Futex_Queue_acquire( futex, &lock_context.Base );
 
   /*
    * For some synchronization objects like barriers the _Futex_Wake() must be
    * called in the fast path.  Normally there are no threads on the queue, so
    * check this condition early.
    */
-  heads = futex->Queue.Queue.heads;
-  if ( __predict_true( heads == NULL ) ) {
-    _Futex_Queue_release( futex, &lock_context );
-
+  if ( __predict_true( _Thread_queue_Is_empty( &futex->Queue.Queue ) ) ) {
+    _Futex_Queue_release( futex, &lock_context.Base );
     return 0;
   }
 
-  return _Futex_Wake_slow( futex, count, heads, &lock_context );
+  lock_context.count = count;
+  return (int) _Thread_queue_Flush_critical(
+    &futex->Queue.Queue,
+    FUTEX_TQ_OPERATIONS,
+    _Futex_Flush_filter,
+    NULL,
+    0,
+    &lock_context.Base
+  );
 }
 
 #endif /* HAVE_STRUCT__THREAD_QUEUE_QUEUE */
-- 
1.8.4.5




More information about the devel mailing list