[PATCH 8/8] score: Implement fine-grained locking for events

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Mar 4 15:07:08 UTC 2015


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.
---
 cpukit/rtems/Makefile.am                     |   1 -
 cpukit/rtems/include/rtems/rtems/eventimpl.h |  49 +++-------
 cpukit/rtems/src/event.c                     |   3 -
 cpukit/rtems/src/eventdata.c                 |  23 -----
 cpukit/rtems/src/eventreceive.c              |  13 +--
 cpukit/rtems/src/eventseize.c                |  77 +++++++--------
 cpukit/rtems/src/eventsend.c                 |   8 +-
 cpukit/rtems/src/eventsurrender.c            | 139 ++++++++++++++++-----------
 cpukit/rtems/src/eventtimeout.c              |  90 +++++++++--------
 cpukit/rtems/src/systemeventreceive.c        |  13 +--
 cpukit/rtems/src/systemeventsend.c           |   8 +-
 cpukit/rtems/src/tasks.c                     |   2 -
 testsuites/sptests/spintrcritical10/init.c   |  64 ++++++------
 testsuites/sptests/spintrcritical21/init.c   |  14 ++-
 testsuites/sptests/spsize/size.c             |   2 -
 15 files changed, 254 insertions(+), 252 deletions(-)
 delete mode 100644 cpukit/rtems/src/eventdata.c

diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am
index a1fafb1..5e6f2ea 100644
--- a/cpukit/rtems/Makefile.am
+++ b/cpukit/rtems/Makefile.am
@@ -211,7 +211,6 @@ librtems_a_SOURCES += src/eventseize.c
 librtems_a_SOURCES += src/eventsend.c
 librtems_a_SOURCES += src/eventsurrender.c
 librtems_a_SOURCES += src/eventtimeout.c
-librtems_a_SOURCES += src/eventdata.c
 librtems_a_SOURCES += src/systemeventsend.c
 librtems_a_SOURCES += src/systemeventreceive.c
 
diff --git a/cpukit/rtems/include/rtems/rtems/eventimpl.h b/cpukit/rtems/include/rtems/rtems/eventimpl.h
index 60b6b51..460b7ce 100644
--- a/cpukit/rtems/include/rtems/rtems/eventimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/eventimpl.h
@@ -33,16 +33,6 @@ extern "C" {
  */
 
 /**
- *  This constant is defined to extern most of the time when using
- *  this header file.  However by defining it to nothing, the data
- *  declared in this header file can be instantiated.  This is done
- *  in a single per manager file.
- */
-#ifndef RTEMS_EVENT_EXTERN
-#define RTEMS_EVENT_EXTERN extern
-#endif
-
-/**
  *  This constant is passed as the event_in to the
  *  rtems_event_receive directive to determine which events are pending.
  */
@@ -54,10 +44,6 @@ extern "C" {
  */
 #define EVENT_SETS_NONE_PENDING 0
 
-RTEMS_EVENT_EXTERN Thread_blocking_operation_States _Event_Sync_state;
-
-RTEMS_EVENT_EXTERN Thread_blocking_operation_States _System_event_Sync_state;
-
 /**
  *  @brief Event Manager Initialization
  *
@@ -71,30 +57,23 @@ RTEMS_EVENT_EXTERN Thread_blocking_operation_States _System_event_Sync_state;
 void _Event_Manager_initialization( void );
 
 void _Event_Seize(
-  rtems_event_set                   event_in,
-  rtems_option                      option_set,
-  rtems_interval                    ticks,
-  rtems_event_set                  *event_out,
-  Thread_Control                   *executing,
-  Event_Control                    *event,
-  Thread_blocking_operation_States *sync_state,
-  States_Control                    wait_state
+  rtems_event_set    event_in,
+  rtems_option       option_set,
+  rtems_interval     ticks,
+  rtems_event_set   *event_out,
+  Thread_Control    *executing,
+  Event_Control     *event,
+  Thread_Wait_flags  wait_class,
+  States_Control     block_state,
+  ISR_lock_Context  *lock_context
 );
 
-/**
- *  @brief Surrender Event
- *
- *  - INTERRUPT LATENCY:
- *    + before flash
- *    + after flash
- *    + check sync
- */
 void _Event_Surrender(
-  Thread_Control                   *the_thread,
-  rtems_event_set                   event_in,
-  Event_Control                    *event,
-  Thread_blocking_operation_States *sync_state,
-  States_Control                    wait_state
+  Thread_Control    *the_thread,
+  rtems_event_set    event_in,
+  Event_Control     *event,
+  Thread_Wait_flags  wait_class,
+  ISR_lock_Context  *lock_context
 );
 
 /**
diff --git a/cpukit/rtems/src/event.c b/cpukit/rtems/src/event.c
index 3a1359e..7ec44d7 100644
--- a/cpukit/rtems/src/event.c
+++ b/cpukit/rtems/src/event.c
@@ -22,9 +22,6 @@
 
 void _Event_Manager_initialization( void )
 {
-  _Event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
-  _System_event_Sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
-
   /*
    *  Register the MP Process Packet routine.
    */
diff --git a/cpukit/rtems/src/eventdata.c b/cpukit/rtems/src/eventdata.c
deleted file mode 100644
index 93fa473..0000000
--- a/cpukit/rtems/src/eventdata.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- *  @file
- *
- *  @brief Instantiate RTEMS Event Data
- *  @ingroup ClassicEvent
- */
-
-/*
- *  COPYRIGHT (c) 1989-2007.
- *  On-Line Applications Research Corporation (OAR).
- *
- *  The license and distribution terms for this file may be
- *  found in the file LICENSE in this distribution or at
- *  http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define RTEMS_EVENT_EXTERN
-
-#include <rtems/rtems/eventimpl.h>
diff --git a/cpukit/rtems/src/eventreceive.c b/cpukit/rtems/src/eventreceive.c
index 49fdb2a..07e1c57 100644
--- a/cpukit/rtems/src/eventreceive.c
+++ b/cpukit/rtems/src/eventreceive.c
@@ -21,7 +21,7 @@
 #include <rtems/rtems/eventimpl.h>
 #include <rtems/rtems/tasks.h>
 #include <rtems/score/statesimpl.h>
-#include <rtems/score/threaddispatch.h>
+#include <rtems/score/threadimpl.h>
 
 rtems_status_code rtems_event_receive(
   rtems_event_set  event_in,
@@ -33,12 +33,12 @@ rtems_status_code rtems_event_receive(
   rtems_status_code sc;
 
   if ( event_out != NULL ) {
-    Thread_Control    *executing = _Thread_Get_executing();
+    ISR_lock_Context   lock_context;
+    Thread_Control    *executing = _Thread_Acquire_executing( &lock_context );
     RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
     Event_Control     *event = &api->Event;
 
     if ( !_Event_sets_Is_empty( event_in ) ) {
-      _Thread_Disable_dispatch();
       _Event_Seize(
         event_in,
         option_set,
@@ -46,14 +46,15 @@ rtems_status_code rtems_event_receive(
         event_out,
         executing,
         event,
-        &_Event_Sync_state,
-        STATES_WAITING_FOR_EVENT
+        THREAD_WAIT_CLASS_EVENT,
+        STATES_WAITING_FOR_EVENT,
+        &lock_context
       );
-      _Thread_Enable_dispatch();
 
       sc = executing->Wait.return_code;
     } else {
       *event_out = event->pending_events;
+      _Objects_Release_and_ISR_enable( &executing->Object, &lock_context );
       sc = RTEMS_SUCCESSFUL;
     }
   } else {
diff --git a/cpukit/rtems/src/eventseize.c b/cpukit/rtems/src/eventseize.c
index ca7c111..59a2b62 100644
--- a/cpukit/rtems/src/eventseize.c
+++ b/cpukit/rtems/src/eventseize.c
@@ -31,24 +31,25 @@
  */
 
 void _Event_Seize(
-  rtems_event_set                   event_in,
-  rtems_option                      option_set,
-  rtems_interval                    ticks,
-  rtems_event_set                  *event_out,
-  Thread_Control                   *executing,
-  Event_Control                    *event,
-  Thread_blocking_operation_States *sync_state,
-  States_Control                    wait_state
+  rtems_event_set    event_in,
+  rtems_option       option_set,
+  rtems_interval     ticks,
+  rtems_event_set   *event_out,
+  Thread_Control    *executing,
+  Event_Control     *event,
+  Thread_Wait_flags  wait_class,
+  States_Control     block_state,
+  ISR_lock_Context  *lock_context
 )
 {
-  rtems_event_set                  seized_events;
-  rtems_event_set                  pending_events;
-  ISR_Level                        level;
-  Thread_blocking_operation_States current_sync_state;
+  rtems_event_set    seized_events;
+  rtems_event_set    pending_events;
+  bool               success;
+  Thread_Wait_flags  intend_to_block;
+  Per_CPU_Control   *cpu_self;
 
   executing->Wait.return_code = RTEMS_SUCCESSFUL;
 
-  _ISR_Disable( level );
   pending_events = event->pending_events;
   seized_events  = _Event_sets_Get( pending_events, event_in );
 
@@ -56,18 +57,20 @@ void _Event_Seize(
        (seized_events == event_in || _Options_Is_any( option_set )) ) {
     event->pending_events =
       _Event_sets_Clear( pending_events, seized_events );
-    _ISR_Enable( level );
+    _Objects_Release_and_ISR_enable( &executing->Object, lock_context );
     *event_out = seized_events;
     return;
   }
 
   if ( _Options_Is_no_wait( option_set ) ) {
-    _ISR_Enable( level );
+    _Objects_Release_and_ISR_enable( &executing->Object, lock_context );
     executing->Wait.return_code = RTEMS_UNSATISFIED;
     *event_out = seized_events;
     return;
   }
 
+  intend_to_block = wait_class | THREAD_WAIT_STATE_INTEND_TO_BLOCK;
+
   /*
    *  Note what we are waiting for BEFORE we enter the critical section.
    *  The interrupt critical section management code needs this to be
@@ -76,41 +79,39 @@ void _Event_Seize(
    *  NOTE: Since interrupts are disabled, this isn't that much of an
    *        issue but better safe than sorry.
    */
-  executing->Wait.option            = option_set;
-  executing->Wait.count             = event_in;
-  executing->Wait.return_argument   = event_out;
-
-  *sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+  executing->Wait.option          = option_set;
+  executing->Wait.count           = event_in;
+  executing->Wait.return_argument = event_out;
+  _Thread_Wait_flags_set( executing, intend_to_block );
 
-  _ISR_Enable( level );
+  cpu_self = _Objects_Release_and_thread_dispatch_disable(
+    &executing->Object,
+    lock_context
+  );
+  _Giant_Acquire( cpu_self );
 
   if ( ticks ) {
     _Watchdog_Initialize(
       &executing->Timer,
       _Event_Timeout,
       executing->Object.id,
-      sync_state
+      NULL
     );
     _Watchdog_Insert_ticks( &executing->Timer, ticks );
   }
 
-  _Thread_Set_state( executing, wait_state );
+  _Thread_Set_state( executing, block_state );
 
-  _ISR_Disable( level );
-
-  current_sync_state = *sync_state;
-  *sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
-  if ( current_sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
-    _ISR_Enable( level );
-    return;
+  success = _Thread_Wait_flags_try_change(
+    executing,
+    intend_to_block,
+    wait_class | THREAD_WAIT_STATE_BLOCKED
+  );
+  if ( !success ) {
+    _Watchdog_Remove( &executing->Timer );
+    _Thread_Unblock( executing );
   }
 
-  /*
-   *  An interrupt completed the thread's blocking request.
-   *  The blocking thread was satisfied by an ISR or timed out.
-   *
-   *  WARNING! Entering with interrupts disabled and returning with interrupts
-   *  enabled!
-   */
-  _Thread_blocking_operation_Cancel( current_sync_state, executing, level );
+  _Giant_Release( cpu_self );
+  _Thread_Dispatch_enable( cpu_self );
 }
diff --git a/cpukit/rtems/src/eventsend.c b/cpukit/rtems/src/eventsend.c
index 89bc3e1..bb9ca33 100644
--- a/cpukit/rtems/src/eventsend.c
+++ b/cpukit/rtems/src/eventsend.c
@@ -31,8 +31,9 @@ rtems_status_code rtems_event_send(
   Thread_Control    *thread;
   Objects_Locations  location;
   RTEMS_API_Control *api;
+  ISR_lock_Context   lock_context;
 
-  thread = _Thread_Get( id, &location );
+  thread = _Thread_Acquire( id, &location, &lock_context );
   switch ( location ) {
     case OBJECTS_LOCAL:
       api = thread->API_Extensions[ THREAD_API_RTEMS ];
@@ -40,10 +41,9 @@ rtems_status_code rtems_event_send(
         thread,
         event_in,
         &api->Event,
-        &_Event_Sync_state,
-        STATES_WAITING_FOR_EVENT
+        THREAD_WAIT_CLASS_EVENT,
+        &lock_context
       );
-      _Objects_Put( &thread->Object );
       sc = RTEMS_SUCCESSFUL;
       break;
 #ifdef RTEMS_MULTIPROCESSING
diff --git a/cpukit/rtems/src/eventsurrender.c b/cpukit/rtems/src/eventsurrender.c
index cc33501..824912b 100644
--- a/cpukit/rtems/src/eventsurrender.c
+++ b/cpukit/rtems/src/eventsurrender.c
@@ -23,75 +23,100 @@
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/watchdogimpl.h>
 
-void _Event_Surrender(
-  Thread_Control                   *the_thread,
-  rtems_event_set                   event_in,
-  Event_Control                    *event,
-  Thread_blocking_operation_States *sync_state,
-  States_Control                    wait_state
+static void _Event_Satisfy(
+  Thread_Control  *the_thread,
+  Event_Control   *event,
+  rtems_event_set  pending_events,
+  rtems_event_set  seized_events
+)
+{
+  event->pending_events = _Event_sets_Clear( pending_events, seized_events );
+  *(rtems_event_set *) the_thread->Wait.return_argument = seized_events;
+}
+
+static bool _Event_Is_satisfied(
+  const Thread_Control *the_thread,
+  rtems_event_set       pending_events,
+  rtems_event_set      *seized_events
 )
 {
-  ISR_Level       level;
-  rtems_event_set pending_events;
-  rtems_event_set event_condition;
-  rtems_event_set seized_events;
   rtems_option    option_set;
+  rtems_event_set event_condition;
 
   option_set = the_thread->Wait.option;
+  event_condition = the_thread->Wait.count;
+  *seized_events = _Event_sets_Get( pending_events, event_condition );
 
-  _ISR_Disable( level );
-  _Event_sets_Post( event_in, &event->pending_events );
-  pending_events  = event->pending_events;
+  return !_Event_sets_Is_empty( *seized_events )
+    && ( *seized_events == event_condition || _Options_Is_any( option_set ) );
+}
 
-  /*
-   * At this point the event condition is a speculative quantity.  Later state
-   * checks will show if the thread actually waits for an event.
-   */
-  event_condition = the_thread->Wait.count;
+void _Event_Surrender(
+  Thread_Control    *the_thread,
+  rtems_event_set    event_in,
+  Event_Control     *event,
+  Thread_Wait_flags  wait_class,
+  ISR_lock_Context  *lock_context
+)
+{
+  rtems_event_set   pending_events;
+  rtems_event_set   seized_events;
+  Thread_Wait_flags wait_flags;
+  bool              unblock;
+
+  _Event_sets_Post( event_in, &event->pending_events );
+  pending_events = event->pending_events;
 
-  seized_events = _Event_sets_Get( pending_events, event_condition );
+  wait_flags = _Thread_Wait_flags_get( the_thread );
 
   if (
-    !_Event_sets_Is_empty( seized_events )
-      && ( seized_events == event_condition || _Options_Is_any( option_set ) )
+    ( wait_flags & THREAD_WAIT_CLASS_MASK ) == wait_class
+      && _Event_Is_satisfied( the_thread, pending_events, &seized_events )
   ) {
-    /*
-     *  If we are sending to the executing thread, then we have a critical
-     *  section issue to deal with.  The entity sending to the executing thread
-     *  can be either the executing thread or an ISR.  In case it is the
-     *  executing thread, then the blocking operation state is not equal to
-     *  THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED.
-     */
-    if ( _Thread_Is_executing( the_thread ) &&
-         *sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
-      event->pending_events = _Event_sets_Clear(
-        pending_events,
-        seized_events
-      );
-      the_thread->Wait.count = 0;
-      *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
-      *sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
-    } else if ( _States_Are_set( the_thread->current_state, wait_state ) ) {
-      event->pending_events = _Event_sets_Clear(
-        pending_events,
-        seized_events
+    Thread_Wait_flags intend_to_block;
+    Thread_Wait_flags blocked;
+    bool success;
+
+    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_SATISFIED
+    );
+    if ( success ) {
+      _Event_Satisfy( the_thread, event, pending_events, seized_events );
+      unblock = false;
+    } else if ( _Thread_Wait_flags_get( the_thread ) == blocked ) {
+      _Event_Satisfy( the_thread, event, pending_events, seized_events );
+      _Thread_Wait_flags_set(
+        the_thread,
+        wait_class | THREAD_WAIT_STATE_SATISFIED
       );
-      the_thread->Wait.count = 0;
-      *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
-
-      _ISR_Flash( level );
-
-      if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
-        _ISR_Enable( level );
-        _Thread_Unblock( the_thread );
-      } else {
-        _Watchdog_Deactivate( &the_thread->Timer );
-        _ISR_Enable( level );
-        (void) _Watchdog_Remove( &the_thread->Timer );
-        _Thread_Unblock( the_thread );
-      }
-      return;
+      unblock = true;
+    } else {
+      unblock = false;
     }
+  } else {
+    unblock = false;
+  }
+
+  if ( unblock ) {
+    Per_CPU_Control *cpu_self;
+
+    cpu_self = _Objects_Release_and_thread_dispatch_disable(
+      &the_thread->Object,
+      lock_context
+    );
+    _Giant_Acquire( cpu_self );
+
+    _Watchdog_Remove( &the_thread->Timer );
+    _Thread_Unblock( the_thread );
+
+    _Giant_Release( cpu_self );
+    _Thread_Dispatch_enable( cpu_self );
+  } else {
+    _Objects_Release_and_ISR_enable( &the_thread->Object, lock_context );
   }
-  _ISR_Enable( level );
 }
diff --git a/cpukit/rtems/src/eventtimeout.c b/cpukit/rtems/src/eventtimeout.c
index 11d2f11..295f0c5 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
diff --git a/cpukit/rtems/src/systemeventreceive.c b/cpukit/rtems/src/systemeventreceive.c
index c24e19a..394b26e 100644
--- a/cpukit/rtems/src/systemeventreceive.c
+++ b/cpukit/rtems/src/systemeventreceive.c
@@ -27,7 +27,7 @@
 #include <rtems/rtems/eventimpl.h>
 #include <rtems/rtems/tasks.h>
 #include <rtems/score/statesimpl.h>
-#include <rtems/score/threaddispatch.h>
+#include <rtems/score/threadimpl.h>
 
 rtems_status_code rtems_event_system_receive(
   rtems_event_set  event_in,
@@ -39,12 +39,12 @@ rtems_status_code rtems_event_system_receive(
   rtems_status_code sc;
 
   if ( event_out != NULL ) {
-    Thread_Control    *executing = _Thread_Get_executing();
+    ISR_lock_Context   lock_context;
+    Thread_Control    *executing = _Thread_Acquire_executing( &lock_context );
     RTEMS_API_Control *api = executing->API_Extensions[ THREAD_API_RTEMS ];
     Event_Control     *event = &api->System_event;
 
     if ( !_Event_sets_Is_empty( event_in ) ) {
-      _Thread_Disable_dispatch();
       _Event_Seize(
         event_in,
         option_set,
@@ -52,14 +52,15 @@ rtems_status_code rtems_event_system_receive(
         event_out,
         executing,
         event,
-        &_System_event_Sync_state,
-        STATES_WAITING_FOR_SYSTEM_EVENT
+        THREAD_WAIT_CLASS_SYSTEM_EVENT,
+        STATES_WAITING_FOR_SYSTEM_EVENT,
+        &lock_context
       );
-      _Thread_Enable_dispatch();
 
       sc = executing->Wait.return_code;
     } else {
       *event_out = event->pending_events;
+      _Objects_Release_and_ISR_enable( &executing->Object, &lock_context );
       sc = RTEMS_SUCCESSFUL;
     }
   } else {
diff --git a/cpukit/rtems/src/systemeventsend.c b/cpukit/rtems/src/systemeventsend.c
index b2d5552..d35127d 100644
--- a/cpukit/rtems/src/systemeventsend.c
+++ b/cpukit/rtems/src/systemeventsend.c
@@ -37,8 +37,9 @@ rtems_status_code rtems_event_system_send(
   Thread_Control    *thread;
   Objects_Locations  location;
   RTEMS_API_Control *api;
+  ISR_lock_Context   lock_context;
 
-  thread = _Thread_Get( id, &location );
+  thread = _Thread_Acquire( id, &location, &lock_context );
   switch ( location ) {
     case OBJECTS_LOCAL:
       api = thread->API_Extensions[ THREAD_API_RTEMS ];
@@ -46,10 +47,9 @@ rtems_status_code rtems_event_system_send(
         thread,
         event_in,
         &api->System_event,
-        &_System_event_Sync_state,
-        STATES_WAITING_FOR_SYSTEM_EVENT
+        THREAD_WAIT_CLASS_SYSTEM_EVENT,
+        &lock_context
       );
-      _Objects_Put( &thread->Object );
       sc = RTEMS_SUCCESSFUL;
       break;
 #ifdef RTEMS_MULTIPROCESSING
diff --git a/cpukit/rtems/src/tasks.c b/cpukit/rtems/src/tasks.c
index c8c0acc..237a313 100644
--- a/cpukit/rtems/src/tasks.c
+++ b/cpukit/rtems/src/tasks.c
@@ -54,8 +54,6 @@ static bool _RTEMS_tasks_Create_extension(
 
   api = created->API_Extensions[ THREAD_API_RTEMS ];
 
-  _Event_Initialize( &api->Event );
-  _Event_Initialize( &api->System_event );
   _ASR_Create( &api->Signal );
   _Thread_Action_initialize( &api->Signal_action, _Signal_Action_handler );
 #if !defined(RTEMS_SMP)
diff --git a/testsuites/sptests/spintrcritical10/init.c b/testsuites/sptests/spintrcritical10/init.c
index 1d6720c..4d25ce6 100644
--- a/testsuites/sptests/spintrcritical10/init.c
+++ b/testsuites/sptests/spintrcritical10/init.c
@@ -16,6 +16,7 @@
 #include <tmacros.h>
 #include <intrcritical.h>
 
+#include <rtems/score/threadimpl.h>
 #include <rtems/rtems/eventimpl.h>
 
 const char rtems_test_name[] = "SPINTRCRITICAL 10";
@@ -34,16 +35,28 @@ typedef struct {
   bool hit;
 } test_context;
 
+static bool blocks_for_event(Thread_Wait_flags flags)
+{
+  return flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK)
+    || flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_BLOCKED);
+}
+
+static bool interrupts_blocking_op(Thread_Wait_flags flags)
+{
+  return
+    flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK);
+}
+
 static void any_satisfy_before_timeout(rtems_id timer, void *arg)
 {
   rtems_status_code sc;
   test_context *ctx = arg;
   const Thread_Control *thread = ctx->thread;
+  Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
 
-  if (thread->Wait.count != 0) {
-    ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+  if (blocks_for_event(flags)) {
+    ctx->hit = interrupts_blocking_op(flags);
 
-    rtems_test_assert(thread->Wait.count == EVENTS);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     );
@@ -52,7 +65,6 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg)
     sc = rtems_event_send(thread->Object.id, GREEN);
     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-    rtems_test_assert(thread->Wait.count == 0);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == GREEN
     );
@@ -61,15 +73,13 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg)
     sc = rtems_event_send(thread->Object.id, RED);
     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-    rtems_test_assert(thread->Wait.count == 0);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == GREEN
     );
     rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
 
-    _Event_Timeout(thread->Object.id, &_Event_Sync_state);
+    _Event_Timeout(thread->Object.id, NULL);
 
-    rtems_test_assert(thread->Wait.count == 0);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == GREEN
     );
@@ -77,9 +87,12 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg)
 
     if (ctx->hit) {
       rtems_test_assert(
-        _Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
+        _Thread_Wait_flags_get(thread)
+          == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTERRUPT_SATISFIED)
       );
     }
+
+    rtems_test_assert(thread->Wait.count == EVENTS);
   }
 
   sc = rtems_timer_reset(timer);
@@ -115,7 +128,6 @@ static void test_any_satisfy_before_timeout(test_context *ctx)
   );
 
   ctx->hit = false;
-  ctx->thread->Wait.count = 0;
 
   sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx);
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
@@ -137,11 +149,11 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
   rtems_status_code sc;
   test_context *ctx = arg;
   const Thread_Control *thread = ctx->thread;
+  Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
 
-  if (thread->Wait.count != 0) {
-    ctx->hit = _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+  if (blocks_for_event(flags)) {
+    ctx->hit = interrupts_blocking_op(flags);
 
-    rtems_test_assert(thread->Wait.count == EVENTS);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     );
@@ -150,7 +162,6 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
     sc = rtems_event_send(thread->Object.id, GREEN);
     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-    rtems_test_assert(thread->Wait.count == EVENTS);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     );
@@ -159,15 +170,13 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
     sc = rtems_event_send(thread->Object.id, RED);
     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-    rtems_test_assert(thread->Wait.count == 0);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == EVENTS
     );
     rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
 
-    _Event_Timeout(thread->Object.id, &_Event_Sync_state);
+    _Event_Timeout(thread->Object.id, NULL);
 
-    rtems_test_assert(thread->Wait.count == 0);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == EVENTS
     );
@@ -175,9 +184,12 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
 
     if (ctx->hit) {
       rtems_test_assert(
-        _Event_Sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
+        _Thread_Wait_flags_get(thread)
+          == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTERRUPT_SATISFIED)
       );
     }
+
+    rtems_test_assert(thread->Wait.count == EVENTS);
   }
 
   sc = rtems_timer_reset(timer);
@@ -208,7 +220,6 @@ static void test_all_satisfy_before_timeout(test_context *ctx)
   );
 
   ctx->hit = false;
-  ctx->thread->Wait.count = 0;
 
   sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx);
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
@@ -230,20 +241,18 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
   rtems_status_code sc;
   test_context *ctx = arg;
   const Thread_Control *thread = ctx->thread;
+  Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
 
-  if (thread->Wait.count != 0) {
-    ctx->hit =
-      _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+  if (blocks_for_event(flags)) {
+    ctx->hit = interrupts_blocking_op(flags);
 
-    rtems_test_assert(thread->Wait.count == EVENTS);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     );
     rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
 
-    _Event_Timeout(thread->Object.id, &_Event_Sync_state);
+    _Event_Timeout(thread->Object.id, NULL);
 
-    rtems_test_assert(thread->Wait.count == 0);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     );
@@ -252,7 +261,6 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
     sc = rtems_event_send(thread->Object.id, EVENTS);
     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-    rtems_test_assert(thread->Wait.count == 0);
     rtems_test_assert(
       *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
     );
@@ -260,9 +268,12 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
 
     if (ctx->hit) {
       rtems_test_assert(
-        _Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT
+        _Thread_Wait_flags_get(thread)
+          == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTERRUPT_TIMEOUT)
       );
     }
+
+    rtems_test_assert(thread->Wait.count == EVENTS);
   }
 
   sc = rtems_timer_reset(timer);
@@ -298,7 +309,6 @@ static void test_timeout_before_all_satisfy(test_context *ctx)
   );
 
   ctx->hit = false;
-  ctx->thread->Wait.count = 0;
 
   sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx);
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
diff --git a/testsuites/sptests/spintrcritical21/init.c b/testsuites/sptests/spintrcritical21/init.c
index 8b1ddcf..faa48f7 100644
--- a/testsuites/sptests/spintrcritical21/init.c
+++ b/testsuites/sptests/spintrcritical21/init.c
@@ -18,6 +18,7 @@
 
 #include <intrcritical.h>
 
+#include <rtems/score/threadimpl.h>
 #include <rtems/rtems/eventimpl.h>
 
 const char rtems_test_name[] = "SPINTRCRITICAL 21";
@@ -34,8 +35,16 @@ static volatile bool case_hit;
 
 static rtems_id main_task;
 
+static Thread_Control *main_thread;
+
 static rtems_id other_task;
 
+static bool is_case_hit( void )
+{
+  return _Thread_Wait_flags_get( main_thread)
+    == ( THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK );
+}
+
 static rtems_timer_service_routine test_event_from_isr(
   rtems_id  timer,
   void     *arg
@@ -43,7 +52,7 @@ static rtems_timer_service_routine test_event_from_isr(
 {
   rtems_status_code     status;
 
-  if ( _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
+  if ( is_case_hit() ) {
     /*
      *  This event send hits the critical section but sends to
      *  another task so doesn't impact this critical section.
@@ -84,7 +93,7 @@ static rtems_timer_service_routine test_event_with_timeout_from_isr(
 {
   rtems_status_code     status;
 
-  if ( _Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
+  if ( is_case_hit() ) {
     /*
      *  We want to catch the task while it is blocking.  Otherwise
      *  just send and make it happy.
@@ -117,6 +126,7 @@ rtems_task Init(
   TEST_BEGIN();
 
   main_task = rtems_task_self();
+  main_thread = _Thread_Get_executing();
 
   status = rtems_task_create(
     0xa5a5a5a5,
diff --git a/testsuites/sptests/spsize/size.c b/testsuites/sptests/spsize/size.c
index c68199d..f427bd2 100644
--- a/testsuites/sptests/spsize/size.c
+++ b/testsuites/sptests/spsize/size.c
@@ -268,8 +268,6 @@ uninitialized =
 
 /*dpmemimpl.h*/ (sizeof _Dual_ported_memory_Information)  +
 
-/*eventimpl.h*/ (sizeof _Event_Sync_state)                +
-
 #if defined(RTEMS_MULTIPROCESSING)
 /*eventmp.h*/   0                                         +
 #endif
-- 
1.8.4.5




More information about the devel mailing list