[PATCH] score: Avoid Giant lock for CORE spinlock

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Mar 18 13:07:34 UTC 2016


Use an ISR lock to protect the spinlock state.  Remove empty attributes.

Update #2555.
---
 cpukit/posix/include/rtems/posix/spinlockimpl.h    | 27 ++++------
 cpukit/posix/src/pspindestroy.c                    | 63 +++++++---------------
 cpukit/posix/src/pspininit.c                       |  5 +-
 cpukit/posix/src/pspinlock.c                       | 50 ++++++-----------
 cpukit/posix/src/pspintrylock.c                    | 52 +++++-------------
 cpukit/posix/src/pspinunlock.c                     | 47 ++++------------
 cpukit/score/Makefile.am                           |  2 +-
 cpukit/score/include/rtems/score/corespinlock.h    | 30 +++++------
 .../score/include/rtems/score/corespinlockimpl.h   | 55 +++++++++++--------
 cpukit/score/src/corespinlock.c                    | 37 -------------
 cpukit/score/src/corespinlockrelease.c             | 19 +++----
 cpukit/score/src/corespinlockwait.c                | 63 +++++++++-------------
 12 files changed, 149 insertions(+), 301 deletions(-)
 delete mode 100644 cpukit/score/src/corespinlock.c

diff --git a/cpukit/posix/include/rtems/posix/spinlockimpl.h b/cpukit/posix/include/rtems/posix/spinlockimpl.h
index 01fe372..0904050 100644
--- a/cpukit/posix/include/rtems/posix/spinlockimpl.h
+++ b/cpukit/posix/include/rtems/posix/spinlockimpl.h
@@ -75,26 +75,19 @@ RTEMS_INLINE_ROUTINE void _POSIX_Spinlock_Free (
   _Objects_Free( &_POSIX_Spinlock_Information, &the_spinlock->Object );
 }
 
-/**
- * @brief Get a spinlock control block.
- *
- * This function maps spinlock IDs to spinlock control blocks.
- * If ID corresponds to a local spinlock, then it returns
- * the_spinlock control pointer which maps to ID and location
- * is set to OBJECTS_LOCAL.  if the spinlock ID is global and
- * resides on a remote node, then location is set to OBJECTS_REMOTE,
- * and the_spinlock is undefined.  Otherwise, location is set
- * to OBJECTS_ERROR and the_spinlock is undefined.
- */
-RTEMS_INLINE_ROUTINE POSIX_Spinlock_Control *_POSIX_Spinlock_Get (
+RTEMS_INLINE_ROUTINE POSIX_Spinlock_Control *_POSIX_Spinlock_Get(
   pthread_spinlock_t *spinlock,
-  Objects_Locations *location
+  ISR_lock_Context   *lock_context
 )
 {
-  return (POSIX_Spinlock_Control *) _Objects_Get(
-      &_POSIX_Spinlock_Information,
-      (Objects_Id) *spinlock,
-      location
+  if ( spinlock == NULL ) {
+    return NULL;
+  }
+
+  return (POSIX_Spinlock_Control *) _Objects_Get_local(
+    &_POSIX_Spinlock_Information,
+    *spinlock,
+    lock_context
   );
 }
 
diff --git a/cpukit/posix/src/pspindestroy.c b/cpukit/posix/src/pspindestroy.c
index ab45ad1..42a6e76 100644
--- a/cpukit/posix/src/pspindestroy.c
+++ b/cpukit/posix/src/pspindestroy.c
@@ -18,58 +18,35 @@
 #include "config.h"
 #endif
 
-#include <pthread.h>
-#include <errno.h>
-
-#include <rtems/system.h>
 #include <rtems/posix/spinlockimpl.h>
 
-/**
- *  This directive allows a thread to delete a spinlock specified by
- *  the spinlock id.  The spinlock is freed back to the inactive
- *  spinlock chain.
- *
- *  @param[in] spinlock is the spinlock id
- *
- *  @return This method returns 0 if there was not an
- *  error. Otherwise, a status code is returned indicating the
- *  source of the error.
- */
-int pthread_spin_destroy(
-  pthread_spinlock_t *spinlock
-)
-{
-  POSIX_Spinlock_Control *the_spinlock = NULL;
-  Objects_Locations      location;
+#include <errno.h>
 
-  if ( !spinlock )
-    return EINVAL;
+int pthread_spin_destroy( pthread_spinlock_t *spinlock )
+{
+  POSIX_Spinlock_Control *the_spinlock;
+  ISR_lock_Context        lock_context;
 
   _Objects_Allocator_lock();
-  the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
-  switch ( location ) {
 
-    case OBJECTS_LOCAL:
-      if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) {
-        _Objects_Put( &the_spinlock->Object );
-        return EBUSY;
-      }
-
-      _Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object );
-      _Objects_Put( &the_spinlock->Object );
-      _POSIX_Spinlock_Free( the_spinlock );
-      _Objects_Allocator_unlock();
+  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
+  if ( the_spinlock == NULL ) {
+    _Objects_Allocator_unlock();
+    return EINVAL;
+  }
 
-      return 0;
+  _CORE_spinlock_Acquire_critical( &the_spinlock->Spinlock, &lock_context );
 
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
+  if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) {
+    _CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context );
+    _Objects_Allocator_unlock();
+    return EBUSY;
   }
 
-  _Objects_Allocator_unlock();
+  _CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context );
 
-  return EINVAL;
+  _Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object );
+  _POSIX_Spinlock_Free( the_spinlock );
+  _Objects_Allocator_unlock();
+  return 0;
 }
diff --git a/cpukit/posix/src/pspininit.c b/cpukit/posix/src/pspininit.c
index 02b07c8..bc131e2 100644
--- a/cpukit/posix/src/pspininit.c
+++ b/cpukit/posix/src/pspininit.c
@@ -47,7 +47,6 @@ int pthread_spin_init(
 )
 {
   POSIX_Spinlock_Control   *the_spinlock;
-  CORE_spinlock_Attributes  attributes;
 
   if ( !spinlock )
     return EINVAL;
@@ -67,9 +66,7 @@ int pthread_spin_init(
     return EAGAIN;
   }
 
-  _CORE_spinlock_Initialize_attributes( &attributes );
-
-  _CORE_spinlock_Initialize( &the_spinlock->Spinlock, &attributes );
+  _CORE_spinlock_Initialize( &the_spinlock->Spinlock );
 
   _Objects_Open_u32( &_POSIX_Spinlock_Information, &the_spinlock->Object, 0 );
 
diff --git a/cpukit/posix/src/pspinlock.c b/cpukit/posix/src/pspinlock.c
index d13ffe6..502177c 100644
--- a/cpukit/posix/src/pspinlock.c
+++ b/cpukit/posix/src/pspinlock.c
@@ -18,46 +18,26 @@
 #include "config.h"
 #endif
 
-#include <pthread.h>
-#include <errno.h>
-
-#include <rtems/system.h>
 #include <rtems/posix/spinlockimpl.h>
 
-/**
- *  This directive allows a thread to wait at a spinlock.
- *
- *  @param[in] spinlock is spinlock id
- * 
- *  @return This method returns 0 if there was not an
- *  error. Otherwise, a status code is returned indicating the
- *  source of the error.
- */
-int pthread_spin_lock(
-  pthread_spinlock_t *spinlock
-)
+#include <errno.h>
+
+int pthread_spin_lock( pthread_spinlock_t *spinlock )
 {
-  POSIX_Spinlock_Control  *the_spinlock = NULL;
-  Objects_Locations        location;
-  CORE_spinlock_Status     status;
+  POSIX_Spinlock_Control *the_spinlock;
+  ISR_lock_Context        lock_context;
+  CORE_spinlock_Status    status;
 
-  if ( !spinlock )
+  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
+  if ( the_spinlock == NULL ) {
     return EINVAL;
-
-  the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, true, 0 );
-      _Objects_Put( &the_spinlock->Object );
-      return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
-
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
   }
 
-  return EINVAL;
+  status = _CORE_spinlock_Seize(
+    &the_spinlock->Spinlock,
+    true,
+    0,
+    &lock_context
+  );
+  return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
 }
diff --git a/cpukit/posix/src/pspintrylock.c b/cpukit/posix/src/pspintrylock.c
index d304908..5f132a3 100644
--- a/cpukit/posix/src/pspintrylock.c
+++ b/cpukit/posix/src/pspintrylock.c
@@ -18,50 +18,26 @@
 #include "config.h"
 #endif
 
-#include <pthread.h>
-#include <errno.h>
-
-#include <rtems/system.h>
 #include <rtems/posix/spinlockimpl.h>
 
-/*
- *  pthread_spin_trylock
- *
- *  This directive allows a thread to poll an attempt at locking a spinlock.
- *
- *  Input parameters:
- *    spinlock    - spinlock id
- *
- *  Output parameters:
- *    0          - if successful
- *    error code - if unsuccessful
- */
+#include <errno.h>
 
-int pthread_spin_trylock(
-  pthread_spinlock_t *spinlock
-)
+int pthread_spin_trylock( pthread_spinlock_t *spinlock )
 {
-  POSIX_Spinlock_Control  *the_spinlock = NULL;
-  Objects_Locations        location;
-  CORE_spinlock_Status     status;
+  POSIX_Spinlock_Control *the_spinlock;
+  ISR_lock_Context        lock_context;
+  CORE_spinlock_Status    status;
 
-  if ( !spinlock )
+  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
+  if ( the_spinlock == NULL ) {
     return EINVAL;
-
-  the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, false, 0 );
-      _Objects_Put( &the_spinlock->Object );
-      return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
-
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
   }
 
-  return EINVAL;
+  status = _CORE_spinlock_Seize(
+    &the_spinlock->Spinlock,
+    false,
+    0,
+    &lock_context
+  );
+  return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
 }
diff --git a/cpukit/posix/src/pspinunlock.c b/cpukit/posix/src/pspinunlock.c
index 3a483ad..35dbcb9 100644
--- a/cpukit/posix/src/pspinunlock.c
+++ b/cpukit/posix/src/pspinunlock.c
@@ -20,50 +20,21 @@
 #include "config.h"
 #endif
 
-#include <pthread.h>
-#include <errno.h>
-
-#include <rtems/system.h>
 #include <rtems/posix/spinlockimpl.h>
 
-/*
- *  pthread_spin_unlock
- *
- *  This directive allows a thread to wait at a spinlock.
- *
- *  Input parameters:
- *    spinlock    - spinlock id
- *
- *  Output parameters:
- *    0          - if successful
- *    error code - if unsuccessful
- */
+#include <errno.h>
 
-int pthread_spin_unlock(
-  pthread_spinlock_t *spinlock
-)
+int pthread_spin_unlock( pthread_spinlock_t *spinlock )
 {
-  POSIX_Spinlock_Control  *the_spinlock = NULL;
-  Objects_Locations        location;
-  CORE_spinlock_Status     status;
+  POSIX_Spinlock_Control *the_spinlock;
+  ISR_lock_Context        lock_context;
+  CORE_spinlock_Status    status;
 
-  if ( !spinlock )
+  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
+  if ( the_spinlock == NULL ) {
     return EINVAL;
-
-  the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      status = _CORE_spinlock_Release( &the_spinlock->Spinlock );
-      _Objects_Put( &the_spinlock->Object );
-      return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
-
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
   }
 
-  return EINVAL;
+  status = _CORE_spinlock_Surrender( &the_spinlock->Spinlock, &lock_context );
+  return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
 }
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index b6824ad..6ff4e02 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -194,7 +194,7 @@ libscore_a_SOURCES += src/coresem.c
 
 ## CORE_SPINLOCK_C_FILES
 if HAS_PTHREADS
-libscore_a_SOURCES += src/corespinlock.c src/corespinlockrelease.c \
+libscore_a_SOURCES += src/corespinlockrelease.c \
     src/corespinlockwait.c
 endif
 
diff --git a/cpukit/score/include/rtems/score/corespinlock.h b/cpukit/score/include/rtems/score/corespinlock.h
index ca50eed..1666538 100644
--- a/cpukit/score/include/rtems/score/corespinlock.h
+++ b/cpukit/score/include/rtems/score/corespinlock.h
@@ -19,7 +19,8 @@
 #ifndef _RTEMS_SCORE_CORESPINLOCK_H
 #define _RTEMS_SCORE_CORESPINLOCK_H
 
-#include <rtems/score/object.h>
+#include <rtems/score/isrlock.h>
+#include <rtems/score/thread.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -36,37 +37,34 @@ extern "C" {
 /**@{*/
 
 /**
- *  The following defines the control block used to manage the
- *  attributes of each spinlock.
- */
-typedef struct {
-  /** This element indicates XXX
-   */
-  uint32_t                  XXX;
-}   CORE_spinlock_Attributes;
-
-/**
  *  The following defines the control block used to manage each
  *  spinlock.
  */
 typedef struct {
-  /** XXX may not be needed */
-  CORE_spinlock_Attributes  Attributes;
+  /**
+   * @brief Lock to protect the other fields.
+   *
+   * This implementation is a bit stupid.  However, test cases in the Linux
+   * Test Project do things like sleep() and printf() while owning a
+   * pthread_spinlock_t, e.g.
+   * testcases/open_posix_testsuite/conformance/interfaces/pthread_spin_lock/1-2.c
+   */
+  ISR_LOCK_MEMBER( Lock )
 
   /** This field is the lock.
    */
-  volatile uint32_t     lock;
+  uint32_t lock;
 
   /** This field is a count of the current number of threads using
    *  this spinlock.  It includes the thread holding the lock as well
    *  as those waiting.
    */
-  volatile uint32_t     users;
+  uint32_t users;
 
   /** This field is the Id of the thread holding the lock.  It may or may
    *  not be the thread which acquired it.
    */
-  volatile Objects_Id   holder;
+  Thread_Control *holder;
 }   CORE_spinlock_Control;
 
 /**@}*/
diff --git a/cpukit/score/include/rtems/score/corespinlockimpl.h b/cpukit/score/include/rtems/score/corespinlockimpl.h
index fe6f9b6..189bddb 100644
--- a/cpukit/score/include/rtems/score/corespinlockimpl.h
+++ b/cpukit/score/include/rtems/score/corespinlockimpl.h
@@ -22,6 +22,8 @@
 #include <rtems/score/corespinlock.h>
 #include <rtems/score/watchdog.h>
 
+#include <string.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -78,12 +80,29 @@ typedef enum {
  *  This routine initializes the spinlock based on the parameters passed.
  *
  *  @param[in] the_spinlock is the spinlock control block to initialize
- *  @param[in] the_spinlock_attributes define the behavior of this instance
  */
-void _CORE_spinlock_Initialize(
-  CORE_spinlock_Control       *the_spinlock,
-  CORE_spinlock_Attributes    *the_spinlock_attributes
-);
+RTEMS_INLINE_ROUTINE void _CORE_spinlock_Initialize(
+  CORE_spinlock_Control *the_spinlock
+)
+{
+  memset( the_spinlock, 0, sizeof( *the_spinlock ) );
+}
+
+RTEMS_INLINE_ROUTINE void _CORE_spinlock_Acquire_critical(
+  CORE_spinlock_Control *the_spinlock,
+  ISR_lock_Context      *lock_context
+)
+{
+  _ISR_lock_Acquire( &the_spinlock->Lock, lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _CORE_spinlock_Release(
+  CORE_spinlock_Control *the_spinlock,
+  ISR_lock_Context      *lock_context
+)
+{
+  _ISR_lock_Release_and_ISR_enable( &the_spinlock->Lock, lock_context );
+}
 
 /**
  *  @brief Wait for spinlock.
@@ -100,10 +119,11 @@ void _CORE_spinlock_Initialize(
  * @retval A status is returned which indicates the success or failure of
  *         this operation.
  */
-CORE_spinlock_Status _CORE_spinlock_Wait(
-  CORE_spinlock_Control  *the_spinlock,
-  bool                    wait,
-  Watchdog_Interval       timeout
+CORE_spinlock_Status _CORE_spinlock_Seize(
+  CORE_spinlock_Control *the_spinlock,
+  bool                   wait,
+  Watchdog_Interval      timeout,
+  ISR_lock_Context      *lock_context
 );
 
 /**
@@ -114,23 +134,12 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
  *
  *  @param[in] the_spinlock is the spinlock to surrender
  */
-CORE_spinlock_Status _CORE_spinlock_Release(
-  CORE_spinlock_Control *the_spinlock
+CORE_spinlock_Status _CORE_spinlock_Surrender(
+  CORE_spinlock_Control *the_spinlock,
+  ISR_lock_Context      *lock_context
 );
 
 /**
- * This method is used to initialize core spinlock attributes.
- *
- * @param[in] the_attributes pointer to the attributes to initialize.
- */
-RTEMS_INLINE_ROUTINE void _CORE_spinlock_Initialize_attributes(
-  CORE_spinlock_Attributes *the_attributes
-)
-{
-  the_attributes->XXX = 0;
-}
-
-/**
  * This method is used to determine if the spinlock is available or not.
  *
  * @param[in] the_spinlock will be checked
diff --git a/cpukit/score/src/corespinlock.c b/cpukit/score/src/corespinlock.c
deleted file mode 100644
index b84eb2e..0000000
--- a/cpukit/score/src/corespinlock.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * @file
- *
- * @brief Initialize a Spinlock
- *
- * @ingroup ScoreSpinlock
- */
-
-/*
- *  COPYRIGHT (c) 1989-2006.
- *  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
-
-#include <rtems/system.h>
-#include <rtems/score/corespinlockimpl.h>
-#include <rtems/score/thread.h>
-
-void _CORE_spinlock_Initialize(
-  CORE_spinlock_Control       *the_spinlock,
-  CORE_spinlock_Attributes    *the_spinlock_attributes
-)
-{
-
-  the_spinlock->Attributes                = *the_spinlock_attributes;
-
-  the_spinlock->lock   = 0;
-  the_spinlock->users  = 0;
-  the_spinlock->holder = 0;
-}
diff --git a/cpukit/score/src/corespinlockrelease.c b/cpukit/score/src/corespinlockrelease.c
index c10337a..358d352 100644
--- a/cpukit/score/src/corespinlockrelease.c
+++ b/cpukit/score/src/corespinlockrelease.c
@@ -20,30 +20,27 @@
 
 #include <rtems/score/corespinlockimpl.h>
 #include <rtems/score/percpu.h>
-#include <rtems/score/thread.h>
-#include <rtems/score/watchdog.h>
 
-CORE_spinlock_Status _CORE_spinlock_Release(
-  CORE_spinlock_Control  *the_spinlock
+CORE_spinlock_Status _CORE_spinlock_Surrender(
+  CORE_spinlock_Control *the_spinlock,
+  ISR_lock_Context      *lock_context
 )
 {
-  ISR_Level level;
-
-  _ISR_Disable( level );
+  _CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
 
     /*
      *  It must locked before it can be unlocked.
      */
     if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
-      _ISR_Enable( level );
+      _CORE_spinlock_Release( the_spinlock, lock_context );
       return CORE_SPINLOCK_NOT_LOCKED;
     }
 
     /*
      *  It must locked by the current thread before it can be unlocked.
      */
-    if ( the_spinlock->holder != _Thread_Executing->Object.id ) {
-      _ISR_Enable( level );
+    if ( the_spinlock->holder != _Thread_Executing ) {
+      _CORE_spinlock_Release( the_spinlock, lock_context );
       return CORE_SPINLOCK_NOT_HOLDER;
     }
 
@@ -54,6 +51,6 @@ CORE_spinlock_Status _CORE_spinlock_Release(
     the_spinlock->lock   = CORE_SPINLOCK_UNLOCKED;
     the_spinlock->holder = 0;
 
-  _ISR_Enable( level );
+  _CORE_spinlock_Release( the_spinlock, lock_context );
   return CORE_SPINLOCK_SUCCESSFUL;
 }
diff --git a/cpukit/score/src/corespinlockwait.c b/cpukit/score/src/corespinlockwait.c
index 1f10296..cc939c2 100644
--- a/cpukit/score/src/corespinlockwait.c
+++ b/cpukit/score/src/corespinlockwait.c
@@ -18,48 +18,36 @@
 #include "config.h"
 #endif
 
-#include <rtems/system.h>
 #include <rtems/score/corespinlockimpl.h>
-#include <rtems/score/thread.h>
-#include <rtems/score/threaddispatch.h>
+#include <rtems/score/percpu.h>
 
-/*
- *  _CORE_spinlock_Wait
- *
- *  This function waits for the spinlock to become available.  Optionally,
- *  a limit may be placed on the duration of the spin.
- *
- *  Input parameters:
- *    the_spinlock - the spinlock control block to initialize
- *    wait         - true if willing to wait
- *    timeout      - the maximum number of ticks to spin (0 is forever)
- *
- *  Output parameters:  NONE
- */
-
-CORE_spinlock_Status _CORE_spinlock_Wait(
-  CORE_spinlock_Control  *the_spinlock,
-  bool                    wait,
-  Watchdog_Interval       timeout
+CORE_spinlock_Status _CORE_spinlock_Seize(
+  CORE_spinlock_Control *the_spinlock,
+  bool                   wait,
+  Watchdog_Interval      timeout,
+  ISR_lock_Context      *lock_context
 )
 {
-  ISR_Level level;
+  Thread_Control *executing;
+
   #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
     Watchdog_Interval       limit = _Watchdog_Ticks_since_boot + timeout;
   #endif
 
-  _ISR_Disable( level );
-    if ( (the_spinlock->lock == CORE_SPINLOCK_LOCKED) &&
-         (the_spinlock->holder == _Thread_Executing->Object.id) ) {
-      _ISR_Enable( level );
+  executing = _Thread_Executing;
+
+  _CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
+    if ( the_spinlock->lock == CORE_SPINLOCK_LOCKED &&
+         the_spinlock->holder == executing ) {
+      _CORE_spinlock_Release( the_spinlock, lock_context );
       return CORE_SPINLOCK_HOLDER_RELOCKING;
     }
     the_spinlock->users += 1;
     for ( ;; ) {
       if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
         the_spinlock->lock = CORE_SPINLOCK_LOCKED;
-        the_spinlock->holder = _Thread_Executing->Object.id;
-        _ISR_Enable( level );
+        the_spinlock->holder = executing;
+        _CORE_spinlock_Release( the_spinlock, lock_context );
         return CORE_SPINLOCK_SUCCESSFUL;
       }
 
@@ -68,7 +56,7 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
        */
       if ( !wait ) {
         the_spinlock->users -= 1;
-        _ISR_Enable( level );
+        _CORE_spinlock_Release( the_spinlock, lock_context );
         return CORE_SPINLOCK_UNAVAILABLE;
       }
 
@@ -78,7 +66,7 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
          */
         if ( timeout && (limit <= _Watchdog_Ticks_since_boot) ) {
           the_spinlock->users -= 1;
-          _ISR_Enable( level );
+          _CORE_spinlock_Release( the_spinlock, lock_context );
           return CORE_SPINLOCK_TIMEOUT;
         }
       #endif
@@ -100,16 +88,15 @@ CORE_spinlock_Status _CORE_spinlock_Wait(
        *  safe from deletion.
        */
 
-       _ISR_Enable( level );
-       /* An ISR could occur here */
-
-       _Thread_Enable_dispatch();
-       /* Another thread could get dispatched here */
+       _CORE_spinlock_Release( the_spinlock, lock_context );
 
-       /* Reenter the critical sections so we can attempt the lock again. */
-       _Thread_Disable_dispatch();
+       /*
+        * An ISR could occur here.  Another thread could get dispatched here.
+        * Reenter the critical sections so we can attempt the lock again.
+        */
 
-       _ISR_Disable( level );
+       _ISR_lock_ISR_disable( lock_context );
+       _CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
     }
 
 }
-- 
1.8.4.5



More information about the devel mailing list