summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-20 06:59:16 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-22 09:25:09 +0200
commit0b590858ac014ba7cbedeae2b1914c57363dd6a7 (patch)
treeb7eb067e54f185fe9979ff6d624abb70868179d5
parentscore: Add _Thread_queue_Is_empty() (diff)
downloadrtems-0b590858ac014ba7cbedeae2b1914c57363dd6a7.tar.bz2
score: Use _Thread_queue_Flush_critical for futex
-rw-r--r--cpukit/score/src/futex.c98
1 files changed, 28 insertions, 70 deletions
diff --git a/cpukit/score/src/futex.c b/cpukit/score/src/futex.c
index 73d48fd4df..59a625cb29 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 */