Changeset 5a5fb3b in rtems


Ignore:
Timestamp:
Mar 18, 2016, 1:03:01 PM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
19e855d7
Parents:
c904df5
git-author:
Sebastian Huber <sebastian.huber@…> (03/18/16 13:03:01)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/18/16 14:36:58)
Message:

score: Avoid Giant lock for CORE spinlock

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

Update #2555.

Location:
cpukit
Files:
1 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • cpukit/posix/include/rtems/posix/spinlockimpl.h

    rc904df5 r5a5fb3b  
    7676}
    7777
    78 /**
    79  * @brief Get a spinlock control block.
    80  *
    81  * This function maps spinlock IDs to spinlock control blocks.
    82  * If ID corresponds to a local spinlock, then it returns
    83  * the_spinlock control pointer which maps to ID and location
    84  * is set to OBJECTS_LOCAL.  if the spinlock ID is global and
    85  * resides on a remote node, then location is set to OBJECTS_REMOTE,
    86  * and the_spinlock is undefined.  Otherwise, location is set
    87  * to OBJECTS_ERROR and the_spinlock is undefined.
    88  */
    89 RTEMS_INLINE_ROUTINE POSIX_Spinlock_Control *_POSIX_Spinlock_Get (
     78RTEMS_INLINE_ROUTINE POSIX_Spinlock_Control *_POSIX_Spinlock_Get(
    9079  pthread_spinlock_t *spinlock,
    91   Objects_Locations *location
     80  ISR_lock_Context   *lock_context
    9281)
    9382{
    94   return (POSIX_Spinlock_Control *) _Objects_Get(
    95       &_POSIX_Spinlock_Information,
    96       (Objects_Id) *spinlock,
    97       location
     83  if ( spinlock == NULL ) {
     84    return NULL;
     85  }
     86
     87  return (POSIX_Spinlock_Control *) _Objects_Get_local(
     88    &_POSIX_Spinlock_Information,
     89    *spinlock,
     90    lock_context
    9891  );
    9992}
  • cpukit/posix/src/pspindestroy.c

    rc904df5 r5a5fb3b  
    1919#endif
    2020
    21 #include <pthread.h>
     21#include <rtems/posix/spinlockimpl.h>
     22
    2223#include <errno.h>
    2324
    24 #include <rtems/system.h>
    25 #include <rtems/posix/spinlockimpl.h>
    26 
    27 /**
    28  *  This directive allows a thread to delete a spinlock specified by
    29  *  the spinlock id.  The spinlock is freed back to the inactive
    30  *  spinlock chain.
    31  *
    32  *  @param[in] spinlock is the spinlock id
    33  *
    34  *  @return This method returns 0 if there was not an
    35  *  error. Otherwise, a status code is returned indicating the
    36  *  source of the error.
    37  */
    38 int pthread_spin_destroy(
    39   pthread_spinlock_t *spinlock
    40 )
     25int pthread_spin_destroy( pthread_spinlock_t *spinlock )
    4126{
    42   POSIX_Spinlock_Control *the_spinlock = NULL;
    43   Objects_Locations      location;
    44 
    45   if ( !spinlock )
    46     return EINVAL;
     27  POSIX_Spinlock_Control *the_spinlock;
     28  ISR_lock_Context        lock_context;
    4729
    4830  _Objects_Allocator_lock();
    49   the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
    50   switch ( location ) {
    5131
    52     case OBJECTS_LOCAL:
    53       if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) {
    54         _Objects_Put( &the_spinlock->Object );
    55         return EBUSY;
    56       }
    57 
    58       _Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object );
    59       _Objects_Put( &the_spinlock->Object );
    60       _POSIX_Spinlock_Free( the_spinlock );
    61       _Objects_Allocator_unlock();
    62 
    63       return 0;
    64 
    65 #if defined(RTEMS_MULTIPROCESSING)
    66     case OBJECTS_REMOTE:
    67 #endif
    68     case OBJECTS_ERROR:
    69       break;
     32  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
     33  if ( the_spinlock == NULL ) {
     34    _Objects_Allocator_unlock();
     35    return EINVAL;
    7036  }
    7137
     38  _CORE_spinlock_Acquire_critical( &the_spinlock->Spinlock, &lock_context );
     39
     40  if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) {
     41    _CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context );
     42    _Objects_Allocator_unlock();
     43    return EBUSY;
     44  }
     45
     46  _CORE_spinlock_Release( &the_spinlock->Spinlock, &lock_context );
     47
     48  _Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object );
     49  _POSIX_Spinlock_Free( the_spinlock );
    7250  _Objects_Allocator_unlock();
    73 
    74   return EINVAL;
     51  return 0;
    7552}
  • cpukit/posix/src/pspininit.c

    rc904df5 r5a5fb3b  
    4848{
    4949  POSIX_Spinlock_Control   *the_spinlock;
    50   CORE_spinlock_Attributes  attributes;
    5150
    5251  if ( !spinlock )
     
    6867  }
    6968
    70   _CORE_spinlock_Initialize_attributes( &attributes );
    71 
    72   _CORE_spinlock_Initialize( &the_spinlock->Spinlock, &attributes );
     69  _CORE_spinlock_Initialize( &the_spinlock->Spinlock );
    7370
    7471  _Objects_Open_u32( &_POSIX_Spinlock_Information, &the_spinlock->Object, 0 );
  • cpukit/posix/src/pspinlock.c

    rc904df5 r5a5fb3b  
    1919#endif
    2020
    21 #include <pthread.h>
     21#include <rtems/posix/spinlockimpl.h>
     22
    2223#include <errno.h>
    2324
    24 #include <rtems/system.h>
    25 #include <rtems/posix/spinlockimpl.h>
     25int pthread_spin_lock( pthread_spinlock_t *spinlock )
     26{
     27  POSIX_Spinlock_Control *the_spinlock;
     28  ISR_lock_Context        lock_context;
     29  CORE_spinlock_Status    status;
    2630
    27 /**
    28  *  This directive allows a thread to wait at a spinlock.
    29  *
    30  *  @param[in] spinlock is spinlock id
    31  *
    32  *  @return This method returns 0 if there was not an
    33  *  error. Otherwise, a status code is returned indicating the
    34  *  source of the error.
    35  */
    36 int pthread_spin_lock(
    37   pthread_spinlock_t *spinlock
    38 )
    39 {
    40   POSIX_Spinlock_Control  *the_spinlock = NULL;
    41   Objects_Locations        location;
    42   CORE_spinlock_Status     status;
    43 
    44   if ( !spinlock )
     31  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
     32  if ( the_spinlock == NULL ) {
    4533    return EINVAL;
    46 
    47   the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
    48   switch ( location ) {
    49 
    50     case OBJECTS_LOCAL:
    51       status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, true, 0 );
    52       _Objects_Put( &the_spinlock->Object );
    53       return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
    54 
    55 #if defined(RTEMS_MULTIPROCESSING)
    56     case OBJECTS_REMOTE:
    57 #endif
    58     case OBJECTS_ERROR:
    59       break;
    6034  }
    6135
    62   return EINVAL;
     36  status = _CORE_spinlock_Seize(
     37    &the_spinlock->Spinlock,
     38    true,
     39    0,
     40    &lock_context
     41  );
     42  return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
    6343}
  • cpukit/posix/src/pspintrylock.c

    rc904df5 r5a5fb3b  
    1919#endif
    2020
    21 #include <pthread.h>
     21#include <rtems/posix/spinlockimpl.h>
     22
    2223#include <errno.h>
    2324
    24 #include <rtems/system.h>
    25 #include <rtems/posix/spinlockimpl.h>
     25int pthread_spin_trylock( pthread_spinlock_t *spinlock )
     26{
     27  POSIX_Spinlock_Control *the_spinlock;
     28  ISR_lock_Context        lock_context;
     29  CORE_spinlock_Status    status;
    2630
    27 /*
    28  *  pthread_spin_trylock
    29  *
    30  *  This directive allows a thread to poll an attempt at locking a spinlock.
    31  *
    32  *  Input parameters:
    33  *    spinlock    - spinlock id
    34  *
    35  *  Output parameters:
    36  *    0          - if successful
    37  *    error code - if unsuccessful
    38  */
    39 
    40 int pthread_spin_trylock(
    41   pthread_spinlock_t *spinlock
    42 )
    43 {
    44   POSIX_Spinlock_Control  *the_spinlock = NULL;
    45   Objects_Locations        location;
    46   CORE_spinlock_Status     status;
    47 
    48   if ( !spinlock )
     31  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
     32  if ( the_spinlock == NULL ) {
    4933    return EINVAL;
    50 
    51   the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
    52   switch ( location ) {
    53 
    54     case OBJECTS_LOCAL:
    55       status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, false, 0 );
    56       _Objects_Put( &the_spinlock->Object );
    57       return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
    58 
    59 #if defined(RTEMS_MULTIPROCESSING)
    60     case OBJECTS_REMOTE:
    61 #endif
    62     case OBJECTS_ERROR:
    63       break;
    6434  }
    6535
    66   return EINVAL;
     36  status = _CORE_spinlock_Seize(
     37    &the_spinlock->Spinlock,
     38    false,
     39    0,
     40    &lock_context
     41  );
     42  return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
    6743}
  • cpukit/posix/src/pspinunlock.c

    rc904df5 r5a5fb3b  
    2121#endif
    2222
    23 #include <pthread.h>
     23#include <rtems/posix/spinlockimpl.h>
     24
    2425#include <errno.h>
    2526
    26 #include <rtems/system.h>
    27 #include <rtems/posix/spinlockimpl.h>
     27int pthread_spin_unlock( pthread_spinlock_t *spinlock )
     28{
     29  POSIX_Spinlock_Control *the_spinlock;
     30  ISR_lock_Context        lock_context;
     31  CORE_spinlock_Status    status;
    2832
    29 /*
    30  *  pthread_spin_unlock
    31  *
    32  *  This directive allows a thread to wait at a spinlock.
    33  *
    34  *  Input parameters:
    35  *    spinlock    - spinlock id
    36  *
    37  *  Output parameters:
    38  *    0          - if successful
    39  *    error code - if unsuccessful
    40  */
    41 
    42 int pthread_spin_unlock(
    43   pthread_spinlock_t *spinlock
    44 )
    45 {
    46   POSIX_Spinlock_Control  *the_spinlock = NULL;
    47   Objects_Locations        location;
    48   CORE_spinlock_Status     status;
    49 
    50   if ( !spinlock )
     33  the_spinlock = _POSIX_Spinlock_Get( spinlock, &lock_context );
     34  if ( the_spinlock == NULL ) {
    5135    return EINVAL;
    52 
    53   the_spinlock = _POSIX_Spinlock_Get( spinlock, &location );
    54   switch ( location ) {
    55 
    56     case OBJECTS_LOCAL:
    57       status = _CORE_spinlock_Release( &the_spinlock->Spinlock );
    58       _Objects_Put( &the_spinlock->Object );
    59       return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
    60 
    61 #if defined(RTEMS_MULTIPROCESSING)
    62     case OBJECTS_REMOTE:
    63 #endif
    64     case OBJECTS_ERROR:
    65       break;
    6636  }
    6737
    68   return EINVAL;
     38  status = _CORE_spinlock_Surrender( &the_spinlock->Spinlock, &lock_context );
     39  return _POSIX_Spinlock_Translate_core_spinlock_return_code( status );
    6940}
  • cpukit/score/Makefile.am

    rc904df5 r5a5fb3b  
    195195## CORE_SPINLOCK_C_FILES
    196196if HAS_PTHREADS
    197 libscore_a_SOURCES += src/corespinlock.c src/corespinlockrelease.c \
     197libscore_a_SOURCES += src/corespinlockrelease.c \
    198198    src/corespinlockwait.c
    199199endif
  • cpukit/score/include/rtems/score/corespinlock.h

    rc904df5 r5a5fb3b  
    2020#define _RTEMS_SCORE_CORESPINLOCK_H
    2121
    22 #include <rtems/score/object.h>
     22#include <rtems/score/isrlock.h>
     23#include <rtems/score/thread.h>
    2324
    2425#ifdef __cplusplus
     
    3738
    3839/**
    39  *  The following defines the control block used to manage the
    40  *  attributes of each spinlock.
    41  */
    42 typedef struct {
    43   /** This element indicates XXX
    44    */
    45   uint32_t                  XXX;
    46 }   CORE_spinlock_Attributes;
    47 
    48 /**
    4940 *  The following defines the control block used to manage each
    5041 *  spinlock.
    5142 */
    5243typedef struct {
    53   /** XXX may not be needed */
    54   CORE_spinlock_Attributes  Attributes;
     44  /**
     45   * @brief Lock to protect the other fields.
     46   *
     47   * This implementation is a bit stupid.  However, test cases in the Linux
     48   * Test Project do things like sleep() and printf() while owning a
     49   * pthread_spinlock_t, e.g.
     50   * testcases/open_posix_testsuite/conformance/interfaces/pthread_spin_lock/1-2.c
     51   */
     52  ISR_LOCK_MEMBER( Lock )
    5553
    5654  /** This field is the lock.
    5755   */
    58   volatile uint32_t    lock;
     56  uint32_t lock;
    5957
    6058  /** This field is a count of the current number of threads using
     
    6260   *  as those waiting.
    6361   */
    64   volatile uint32_t    users;
     62  uint32_t users;
    6563
    6664  /** This field is the Id of the thread holding the lock.  It may or may
    6765   *  not be the thread which acquired it.
    6866   */
    69   volatile Objects_Id   holder;
     67  Thread_Control *holder;
    7068}   CORE_spinlock_Control;
    7169
  • cpukit/score/include/rtems/score/corespinlockimpl.h

    rc904df5 r5a5fb3b  
    2222#include <rtems/score/corespinlock.h>
    2323#include <rtems/score/watchdog.h>
     24
     25#include <string.h>
    2426
    2527#ifdef __cplusplus
     
    7981 *
    8082 *  @param[in] the_spinlock is the spinlock control block to initialize
    81  *  @param[in] the_spinlock_attributes define the behavior of this instance
    8283 */
    83 void _CORE_spinlock_Initialize(
    84   CORE_spinlock_Control       *the_spinlock,
    85   CORE_spinlock_Attributes    *the_spinlock_attributes
    86 );
     84RTEMS_INLINE_ROUTINE void _CORE_spinlock_Initialize(
     85  CORE_spinlock_Control *the_spinlock
     86)
     87{
     88  memset( the_spinlock, 0, sizeof( *the_spinlock ) );
     89}
     90
     91RTEMS_INLINE_ROUTINE void _CORE_spinlock_Acquire_critical(
     92  CORE_spinlock_Control *the_spinlock,
     93  ISR_lock_Context      *lock_context
     94)
     95{
     96  _ISR_lock_Acquire( &the_spinlock->Lock, lock_context );
     97}
     98
     99RTEMS_INLINE_ROUTINE void _CORE_spinlock_Release(
     100  CORE_spinlock_Control *the_spinlock,
     101  ISR_lock_Context      *lock_context
     102)
     103{
     104  _ISR_lock_Release_and_ISR_enable( &the_spinlock->Lock, lock_context );
     105}
    87106
    88107/**
     
    101120 *         this operation.
    102121 */
    103 CORE_spinlock_Status _CORE_spinlock_Wait(
    104   CORE_spinlock_Control  *the_spinlock,
    105   bool                    wait,
    106   Watchdog_Interval       timeout
     122CORE_spinlock_Status _CORE_spinlock_Seize(
     123  CORE_spinlock_Control *the_spinlock,
     124  bool                   wait,
     125  Watchdog_Interval      timeout,
     126  ISR_lock_Context      *lock_context
    107127);
    108128
     
    115135 *  @param[in] the_spinlock is the spinlock to surrender
    116136 */
    117 CORE_spinlock_Status _CORE_spinlock_Release(
    118   CORE_spinlock_Control *the_spinlock
     137CORE_spinlock_Status _CORE_spinlock_Surrender(
     138  CORE_spinlock_Control *the_spinlock,
     139  ISR_lock_Context      *lock_context
    119140);
    120 
    121 /**
    122  * This method is used to initialize core spinlock attributes.
    123  *
    124  * @param[in] the_attributes pointer to the attributes to initialize.
    125  */
    126 RTEMS_INLINE_ROUTINE void _CORE_spinlock_Initialize_attributes(
    127   CORE_spinlock_Attributes *the_attributes
    128 )
    129 {
    130   the_attributes->XXX = 0;
    131 }
    132141
    133142/**
  • cpukit/score/src/corespinlockrelease.c

    rc904df5 r5a5fb3b  
    2121#include <rtems/score/corespinlockimpl.h>
    2222#include <rtems/score/percpu.h>
    23 #include <rtems/score/thread.h>
    24 #include <rtems/score/watchdog.h>
    2523
    26 CORE_spinlock_Status _CORE_spinlock_Release(
    27   CORE_spinlock_Control  *the_spinlock
     24CORE_spinlock_Status _CORE_spinlock_Surrender(
     25  CORE_spinlock_Control *the_spinlock,
     26  ISR_lock_Context      *lock_context
    2827)
    2928{
    30   ISR_Level level;
    31 
    32   _ISR_Disable( level );
     29  _CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
    3330
    3431    /*
     
    3633     */
    3734    if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
    38       _ISR_Enable( level );
     35      _CORE_spinlock_Release( the_spinlock, lock_context );
    3936      return CORE_SPINLOCK_NOT_LOCKED;
    4037    }
     
    4340     *  It must locked by the current thread before it can be unlocked.
    4441     */
    45     if ( the_spinlock->holder != _Thread_Executing->Object.id ) {
    46       _ISR_Enable( level );
     42    if ( the_spinlock->holder != _Thread_Executing ) {
     43      _CORE_spinlock_Release( the_spinlock, lock_context );
    4744      return CORE_SPINLOCK_NOT_HOLDER;
    4845    }
     
    5552    the_spinlock->holder = 0;
    5653
    57   _ISR_Enable( level );
     54  _CORE_spinlock_Release( the_spinlock, lock_context );
    5855  return CORE_SPINLOCK_SUCCESSFUL;
    5956}
  • cpukit/score/src/corespinlockwait.c

    rc904df5 r5a5fb3b  
    1919#endif
    2020
    21 #include <rtems/system.h>
    2221#include <rtems/score/corespinlockimpl.h>
    23 #include <rtems/score/thread.h>
    24 #include <rtems/score/threaddispatch.h>
     22#include <rtems/score/percpu.h>
    2523
    26 /*
    27  *  _CORE_spinlock_Wait
    28  *
    29  *  This function waits for the spinlock to become available.  Optionally,
    30  *  a limit may be placed on the duration of the spin.
    31  *
    32  *  Input parameters:
    33  *    the_spinlock - the spinlock control block to initialize
    34  *    wait         - true if willing to wait
    35  *    timeout      - the maximum number of ticks to spin (0 is forever)
    36  *
    37  *  Output parameters:  NONE
    38  */
    39 
    40 CORE_spinlock_Status _CORE_spinlock_Wait(
    41   CORE_spinlock_Control  *the_spinlock,
    42   bool                    wait,
    43   Watchdog_Interval       timeout
     24CORE_spinlock_Status _CORE_spinlock_Seize(
     25  CORE_spinlock_Control *the_spinlock,
     26  bool                   wait,
     27  Watchdog_Interval      timeout,
     28  ISR_lock_Context      *lock_context
    4429)
    4530{
    46   ISR_Level level;
     31  Thread_Control *executing;
     32
    4733  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
    4834    Watchdog_Interval       limit = _Watchdog_Ticks_since_boot + timeout;
    4935  #endif
    5036
    51   _ISR_Disable( level );
    52     if ( (the_spinlock->lock == CORE_SPINLOCK_LOCKED) &&
    53          (the_spinlock->holder == _Thread_Executing->Object.id) ) {
    54       _ISR_Enable( level );
     37  executing = _Thread_Executing;
     38
     39  _CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
     40    if ( the_spinlock->lock == CORE_SPINLOCK_LOCKED &&
     41         the_spinlock->holder == executing ) {
     42      _CORE_spinlock_Release( the_spinlock, lock_context );
    5543      return CORE_SPINLOCK_HOLDER_RELOCKING;
    5644    }
     
    5947      if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
    6048        the_spinlock->lock = CORE_SPINLOCK_LOCKED;
    61         the_spinlock->holder = _Thread_Executing->Object.id;
    62         _ISR_Enable( level );
     49        the_spinlock->holder = executing;
     50        _CORE_spinlock_Release( the_spinlock, lock_context );
    6351        return CORE_SPINLOCK_SUCCESSFUL;
    6452      }
     
    6957      if ( !wait ) {
    7058        the_spinlock->users -= 1;
    71         _ISR_Enable( level );
     59        _CORE_spinlock_Release( the_spinlock, lock_context );
    7260        return CORE_SPINLOCK_UNAVAILABLE;
    7361      }
     
    7967        if ( timeout && (limit <= _Watchdog_Ticks_since_boot) ) {
    8068          the_spinlock->users -= 1;
    81           _ISR_Enable( level );
     69          _CORE_spinlock_Release( the_spinlock, lock_context );
    8270          return CORE_SPINLOCK_TIMEOUT;
    8371        }
     
    10189       */
    10290
    103        _ISR_Enable( level );
    104        /* An ISR could occur here */
     91       _CORE_spinlock_Release( the_spinlock, lock_context );
    10592
    106        _Thread_Enable_dispatch();
    107        /* Another thread could get dispatched here */
     93       /*
     94        * An ISR could occur here.  Another thread could get dispatched here.
     95        * Reenter the critical sections so we can attempt the lock again.
     96        */
    10897
    109        /* Reenter the critical sections so we can attempt the lock again. */
    110        _Thread_Disable_dispatch();
    111 
    112        _ISR_Disable( level );
     98       _ISR_lock_ISR_disable( lock_context );
     99       _CORE_spinlock_Acquire_critical( the_spinlock, lock_context );
    113100    }
    114101
Note: See TracChangeset for help on using the changeset viewer.