summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems/src/eventtimeout.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-04 08:02:19 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-05 11:36:45 +0100
commit7d6e94b12ab94f13d3e769702d50f91be7d5884b (patch)
tree2e2db2c1bb80c1f287f2c4c25f819ffa8b958704 /cpukit/rtems/src/eventtimeout.c
parentscore: Add thread wait flags (diff)
downloadrtems-7d6e94b12ab94f13d3e769702d50f91be7d5884b.tar.bz2
score: Implement fine-grained locking for events
Use the ISR lock of the thread object to protect the event state and use the Giant lock only for the blocking operations. Update #2273.
Diffstat (limited to 'cpukit/rtems/src/eventtimeout.c')
-rw-r--r--cpukit/rtems/src/eventtimeout.c90
1 files changed, 48 insertions, 42 deletions
diff --git a/cpukit/rtems/src/eventtimeout.c b/cpukit/rtems/src/eventtimeout.c
index 11d2f118b3..295f0c5b5f 100644
--- a/cpukit/rtems/src/eventtimeout.c
+++ b/cpukit/rtems/src/eventtimeout.c
@@ -26,55 +26,61 @@ void _Event_Timeout(
void *arg
)
{
- Thread_Control *the_thread;
- Objects_Locations location;
- ISR_Level level;
- Thread_blocking_operation_States *sync_state;
+ Thread_Control *the_thread;
+ Objects_Locations location;
+ ISR_lock_Context lock_context;
+ Thread_Wait_flags wait_flags;
+ Thread_Wait_flags wait_class;
+ Thread_Wait_flags intend_to_block;
+ Thread_Wait_flags blocked;
+ bool success;
+ bool unblock;
- sync_state = arg;
-
- the_thread = _Thread_Get( id, &location );
+ the_thread = _Thread_Acquire( id, &location, &lock_context );
switch ( location ) {
-
case OBJECTS_LOCAL:
+ wait_flags = _Thread_Wait_flags_get( the_thread );
+ wait_class = wait_flags & THREAD_WAIT_CLASS_MASK;
+ intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
+ blocked = wait_class | THREAD_WAIT_STATE_BLOCKED;
+ success = _Thread_Wait_flags_try_change_critical(
+ the_thread,
+ intend_to_block,
+ wait_class | THREAD_WAIT_STATE_INTERRUPT_TIMEOUT
+ );
- /*
- * If the event manager is not synchronized, then it is either
- * "nothing happened", "timeout", or "satisfied". If the_thread
- * is the executing thread, then it is in the process of blocking
- * and it is the thread which is responsible for the synchronization
- * process.
- *
- * If it is not satisfied, then it is "nothing happened" and
- * this is the "timeout" transition. After a request is satisfied,
- * a timeout is not allowed to occur.
- */
- _ISR_Disable( level );
- /*
- * Verify that the thread is still waiting for the event condition.
- * This test is necessary to avoid state corruption if the timeout
- * happens after the event condition is satisfied in
- * _Event_Surrender(). A satisfied event condition is indicated with
- * count set to zero.
- */
- if ( !the_thread->Wait.count ) {
- _ISR_Enable( level );
- _Objects_Put_without_thread_dispatch( &the_thread->Object );
- return;
- }
+ if ( success ) {
+ the_thread->Wait.return_code = RTEMS_TIMEOUT;
+ unblock = false;
+ } else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
+ the_thread->Wait.return_code = RTEMS_TIMEOUT;
+ _Thread_Wait_flags_set(
+ the_thread,
+ wait_class | THREAD_WAIT_STATE_TIMEOUT
+ );
+ unblock = true;
+ } else {
+ unblock = false;
+ }
- the_thread->Wait.count = 0;
- if ( _Thread_Is_executing( the_thread ) ) {
- if ( *sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
- *sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
- }
+ if ( unblock ) {
+ Per_CPU_Control *cpu_self;
- the_thread->Wait.return_code = RTEMS_TIMEOUT;
- _ISR_Enable( level );
- _Thread_Unblock( the_thread );
- _Objects_Put_without_thread_dispatch( &the_thread->Object );
- break;
+ cpu_self = _Objects_Release_and_thread_dispatch_disable(
+ &the_thread->Object,
+ &lock_context
+ );
+ _Giant_Acquire( cpu_self );
+
+ _Thread_Unblock( the_thread );
+ _Giant_Release( cpu_self );
+ _Thread_Dispatch_enable( cpu_self );
+ } else {
+ _Objects_Release_and_ISR_enable( &the_thread->Object, &lock_context );
+ }
+
+ break;
#if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE: /* impossible */
#endif