Changeset 4438ac25 in rtems


Ignore:
Timestamp:
May 2, 2015, 12:27:24 PM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
900d337f
Parents:
d12b313
git-author:
Sebastian Huber <sebastian.huber@…> (05/02/15 12:27:24)
git-committer:
Sebastian Huber <sebastian.huber@…> (05/19/15 10:00:47)
Message:

score: Fine grained locking for mutexes

Update #2273.

Location:
cpukit
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libnetworking/rtems/rtems_glue.c

    rd12b313 r4438ac25  
    379379        ISR_lock_Context lock_context;
    380380        Thread_Control *executing;
    381 #ifdef RTEMS_SMP
    382         _Thread_Disable_dispatch();
    383 #endif
    384381        _ISR_lock_ISR_disable(&lock_context);
    385382        if (!the_networkSemaphore)
     
    394391                &lock_context
    395392                );
    396 #ifdef RTEMS_SMP
    397         _Thread_Enable_dispatch();
    398 #endif
    399393        if (executing->Wait.return_code)
    400394                rtems_panic ("rtems-net: can't obtain network sema: %d\n",
     
    417411{
    418412#ifdef RTEMS_FAST_MUTEX
    419         int i;
    420 
    421         _Thread_Disable_dispatch();
     413        ISR_lock_Context lock_context;
     414        CORE_mutex_Status status;
     415
    422416        if (!the_networkSemaphore)
    423417                rtems_panic ("rtems-net: network sema obtain: network not initialised\n");
    424         i = _CORE_mutex_Surrender (
     418        _ISR_lock_ISR_disable(&lock_context);
     419        status = _CORE_mutex_Surrender (
    425420                &the_networkSemaphore->Core_control.mutex,
    426421                networkSemaphore,
    427                 NULL
     422                NULL,
     423                &lock_context
    428424                );
    429         _Thread_Enable_dispatch();
    430         if (i)
     425        if (status != CORE_MUTEX_STATUS_SUCCESSFUL)
    431426                rtems_panic ("rtems-net: can't release network sema: %i\n");
    432427#else
  • cpukit/posix/src/mutexlocksupp.c

    rd12b313 r4438ac25  
    5555
    5656    case OBJECTS_LOCAL:
    57 #if defined(RTEMS_SMP)
    58       _Thread_Disable_dispatch();
    59 #endif
    6057      executing = _Thread_Executing;
    6158      _CORE_mutex_Seize(
     
    6764        &lock_context
    6865      );
    69 #if defined(RTEMS_SMP)
    70       _Thread_Enable_dispatch();
    71 #endif
    72       _Objects_Put_for_get_isr_disable( &the_mutex->Object );
    7366      return _POSIX_Mutex_Translate_core_mutex_return_code(
    7467        (CORE_mutex_Status) executing->Wait.return_code
  • cpukit/posix/src/mutexsetprioceiling.c

    rd12b313 r4438ac25  
    4242  Objects_Locations             location;
    4343  Priority_Control              the_priority;
     44  ISR_lock_Context              lock_context;
    4445
    4546  if ( !old_ceiling )
     
    6566   *        bad Id case is handled by the switch.
    6667   */
    67   the_mutex = _POSIX_Mutex_Get( mutex, &location );
     68  the_mutex = _POSIX_Mutex_Get_interrupt_disable(
     69    mutex,
     70    &location,
     71    &lock_context
     72  );
    6873  switch ( location ) {
    6974
     
    7984        &the_mutex->Mutex,
    8085        the_mutex->Object.id,
    81         NULL
     86        NULL,
     87        &lock_context
    8288      );
    83       _Objects_Put( &the_mutex->Object );
    8489
    8590      return 0;
  • cpukit/posix/src/mutexunlock.c

    rd12b313 r4438ac25  
    4242  Objects_Locations             location;
    4343  CORE_mutex_Status             status;
     44  ISR_lock_Context              lock_context;
    4445
    45   the_mutex = _POSIX_Mutex_Get( mutex, &location );
     46  the_mutex = _POSIX_Mutex_Get_interrupt_disable(
     47    mutex,
     48    &location,
     49    &lock_context
     50  );
    4651  switch ( location ) {
    4752
     
    5055        &the_mutex->Mutex,
    5156        the_mutex->Object.id,
    52         NULL
     57        NULL,
     58        &lock_context
    5359      );
    54       _Objects_Put( &the_mutex->Object );
    5560      return _POSIX_Mutex_Translate_core_mutex_return_code( status );
    5661
  • cpukit/rtems/src/semobtain.c

    rd12b313 r4438ac25  
    7474#endif
    7575      if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) {
    76 #if defined(RTEMS_SMP)
    77         _Thread_Disable_dispatch();
    78 #endif
    7976        _CORE_mutex_Seize(
    8077          &the_semaphore->Core_control.mutex,
     
    8582          &lock_context
    8683        );
    87 #if defined(RTEMS_SMP)
    88         _Thread_Enable_dispatch();
    89 #endif
    90         _Objects_Put_for_get_isr_disable( &the_semaphore->Object );
    9184        return _Semaphore_Translate_core_mutex_return_code(
    9285                  executing->Wait.return_code );
  • cpukit/rtems/src/semrelease.c

    rd12b313 r4438ac25  
    8787#endif
    8888      if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) {
    89         _Thread_Disable_dispatch();
    90         _ISR_lock_ISR_enable( &lock_context );
    9189        mutex_status = _CORE_mutex_Surrender(
    9290          &the_semaphore->Core_control.mutex,
    9391          id,
    94           MUTEX_MP_SUPPORT
     92          MUTEX_MP_SUPPORT,
     93          &lock_context
    9594        );
    96         _Thread_Enable_dispatch();
    9795        return _Semaphore_Translate_core_mutex_return_code( mutex_status );
    9896      } else {
  • cpukit/score/include/rtems/score/coremuteximpl.h

    rd12b313 r4438ac25  
    211211 *  @retval this method returns true if dispatch is in an unsafe state.
    212212 */
    213 #ifdef RTEMS_SMP
    214   #define _CORE_mutex_Check_dispatch_for_seize(_wait) \
    215       (_Thread_Dispatch_get_disable_level() != 1 \
    216         && (_wait) \
    217         && (_System_state_Get() >= SYSTEM_STATE_UP))
    218 #else
    219   #define _CORE_mutex_Check_dispatch_for_seize(_wait) \
    220       (!_Thread_Dispatch_is_enabled() \
    221         && (_wait) \
    222         && (_System_state_Get() >= SYSTEM_STATE_UP))
    223 #endif
     213#define _CORE_mutex_Check_dispatch_for_seize(_wait) \
     214  (!_Thread_Dispatch_is_enabled() \
     215    && (_wait) \
     216    && (_System_state_Get() >= SYSTEM_STATE_UP))
    224217
    225218/**
     
    266259    );
    267260  }
     261  _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context );
    268262  if ( _CORE_mutex_Seize_interrupt_trylock( the_mutex, executing, lock_context ) ) {
    269263    if ( !wait ) {
    270       _ISR_lock_ISR_enable( lock_context );
     264      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    271265      executing->Wait.return_code =
    272266        CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT;
     
    321315 *  @param[in] api_mutex_mp_support is the routine that will be called when
    322316 *         unblocking a remote mutex
     317 *  @param[in] lock_context is the interrupt level
    323318 *
    324319 *  @retval an indication of whether the routine succeeded or failed
     
    327322  CORE_mutex_Control                *the_mutex,
    328323  Objects_Id                         id,
    329   CORE_mutex_API_mp_support_callout  api_mutex_mp_support
     324  CORE_mutex_API_mp_support_callout  api_mutex_mp_support,
     325  ISR_lock_Context                  *lock_context
    330326);
    331327
     
    473469
    474470    if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
    475       _ISR_lock_ISR_enable( lock_context );
     471      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    476472      return 0;
    477473    } /* else must be CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
     
    487483      current = executing->current_priority;
    488484      if ( current == ceiling ) {
    489         _ISR_lock_ISR_enable( lock_context );
     485        _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    490486        return 0;
    491487      }
    492488
    493489      if ( current > ceiling ) {
    494         _Thread_Disable_dispatch();
    495         _ISR_lock_ISR_enable( lock_context );
     490        Per_CPU_Control *cpu_self;
     491
     492        cpu_self = _Thread_Dispatch_disable_critical();
     493        _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    496494        _Thread_Change_priority(
    497495          executing,
     
    499497          false
    500498        );
    501         _Thread_Enable_dispatch();
     499        _Thread_Dispatch_enable( cpu_self );
    502500        return 0;
    503501      }
     
    507505        the_mutex->nest_count = 0;     /* undo locking above */
    508506        executing->resource_count--;   /* undo locking above */
    509         _ISR_lock_ISR_enable( lock_context );
     507        _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    510508        return 0;
    511509      }
     
    523521      case CORE_MUTEX_NESTING_ACQUIRES:
    524522        the_mutex->nest_count++;
    525         _ISR_lock_ISR_enable( lock_context );
     523        _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    526524        return 0;
    527525      #if defined(RTEMS_POSIX_API)
    528526        case CORE_MUTEX_NESTING_IS_ERROR:
    529527          executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
    530           _ISR_lock_ISR_enable( lock_context );
     528          _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    531529          return 0;
    532530      #endif
  • cpukit/score/src/apimutexlock.c

    rd12b313 r4438ac25  
    3131  previous_thread_life_protection = _Thread_Set_life_protection( true );
    3232
    33   #if defined(RTEMS_SMP)
    34     _Thread_Disable_dispatch();
    35   #endif
    36 
    3733  _ISR_lock_ISR_disable( &lock_context );
    3834
     
    5046      previous_thread_life_protection;
    5147  }
    52 
    53   #if defined(RTEMS_SMP)
    54     _Thread_Enable_dispatch();
    55   #endif
    5648}
  • cpukit/score/src/apimutexunlock.c

    rd12b313 r4438ac25  
    2525void _API_Mutex_Unlock( API_Mutex_Control *the_mutex )
    2626{
    27   bool previous_thread_life_protection;
    28   bool restore_thread_life_protection;
    29 
    30   _Thread_Disable_dispatch();
     27  ISR_lock_Context lock_context;
     28  bool             previous_thread_life_protection;
     29  bool             restore_thread_life_protection;
    3130
    3231  previous_thread_life_protection =
     
    3433  restore_thread_life_protection = the_mutex->Mutex.nest_count == 1;
    3534
    36   _CORE_mutex_Surrender( &the_mutex->Mutex, the_mutex->Object.id, NULL );
    37 
    38   _Thread_Enable_dispatch();
     35  _ISR_lock_ISR_disable( &lock_context );
     36  _CORE_mutex_Surrender(
     37    &the_mutex->Mutex,
     38    the_mutex->Object.id,
     39    NULL,
     40    &lock_context
     41  );
    3942
    4043  if ( restore_thread_life_protection ) {
  • cpukit/score/src/coremutex.c

    rd12b313 r4438ac25  
    4949         _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
    5050      Priority_Control ceiling = the_mutex->Attributes.priority_ceiling;
     51      Per_CPU_Control *cpu_self;
    5152
    5253      /*
     
    5556       * prevent interference with priority inheritance.
    5657       */
    57       _Thread_Disable_dispatch();
     58      cpu_self = _Thread_Dispatch_disable();
    5859
    5960      if ( is_priority_ceiling && executing->current_priority < ceiling ) {
     
    7475      }
    7576
    76       _Thread_Enable_dispatch();
     77      _Thread_Dispatch_enable( cpu_self );
    7778    }
    7879  } else {
  • cpukit/score/src/coremutexseize.c

    rd12b313 r4438ac25  
    5454)
    5555{
    56   _Thread_Disable_dispatch();
     56#if !defined(RTEMS_SMP)
     57  /*
     58   * We must disable thread dispatching here since we enable the interrupts for
     59   * priority inheritance mutexes.
     60   */
     61  _Thread_Dispatch_disable();
     62#endif
    5763
    5864  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
    5965    Thread_Control *holder = the_mutex->holder;
    6066
     67#if !defined(RTEMS_SMP)
    6168    /*
    62      * To enable interrupts here works only since we own the Giant lock and
    63      * only threads are allowed to seize and surrender mutexes with the
    64      * priority inheritance protocol.
     69     * To enable interrupts here works only since exactly one executing thread
     70     * exists and only threads are allowed to seize and surrender mutexes with
     71     * the priority inheritance protocol.  On SMP configurations more than one
     72     * executing thread may exist, so here we must not release the lock, since
     73     * otherwise the current holder may be no longer the holder of the mutex
     74     * once we released the lock.
    6575     */
    66     _ISR_lock_ISR_enable( lock_context );
     76    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
     77#endif
    6778
    6879    _Scheduler_Change_priority_if_higher(
     
    7384    );
    7485
    75     _ISR_lock_ISR_disable( lock_context );
     86#if !defined(RTEMS_SMP)
     87    _Thread_queue_Acquire( &the_mutex->Wait_queue, lock_context );
     88#endif
    7689  }
    7790
    78   _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context );
    7991  _Thread_queue_Enqueue_critical(
    8092    &the_mutex->Wait_queue,
     
    8698  );
    8799
    88   _Thread_Enable_dispatch();
     100#if !defined(RTEMS_SMP)
     101  _Thread_Dispatch_enable( _Per_CPU_Get() );
     102#endif
    89103}
    90104
  • cpukit/score/src/coremutexsurrender.c

    rd12b313 r4438ac25  
    9090#if defined(RTEMS_MULTIPROCESSING)
    9191  Objects_Id                         id,
    92   CORE_mutex_API_mp_support_callout  api_mutex_mp_support
     92  CORE_mutex_API_mp_support_callout  api_mutex_mp_support,
    9393#else
    9494  Objects_Id                         id __attribute__((unused)),
    95   CORE_mutex_API_mp_support_callout  api_mutex_mp_support __attribute__((unused))
    96 #endif
     95  CORE_mutex_API_mp_support_callout  api_mutex_mp_support __attribute__((unused)),
     96#endif
     97  ISR_lock_Context                  *lock_context
    9798)
    9899{
     
    111112
    112113  if ( the_mutex->Attributes.only_owner_release ) {
    113     if ( !_Thread_Is_executing( holder ) )
     114    if ( !_Thread_Is_executing( holder ) ) {
     115      _ISR_lock_ISR_enable( lock_context );
    114116      return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
    115   }
     117    }
     118  }
     119
     120  _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context );
    116121
    117122  /* XXX already unlocked -- not right status */
    118123
    119   if ( !the_mutex->nest_count )
     124  if ( !the_mutex->nest_count ) {
     125    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    120126    return CORE_MUTEX_STATUS_SUCCESSFUL;
     127  }
    121128
    122129  the_mutex->nest_count--;
     
    131138      switch ( the_mutex->Attributes.lock_nesting_behavior ) {
    132139        case CORE_MUTEX_NESTING_ACQUIRES:
     140          _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    133141          return CORE_MUTEX_STATUS_SUCCESSFUL;
    134142        #if defined(RTEMS_POSIX_API)
    135143          case CORE_MUTEX_NESTING_IS_ERROR:
    136144            /* should never occur */
     145            _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    137146            return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
    138147        #endif
     
    142151      }
    143152    #else
     153      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    144154      /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */
    145155      return CORE_MUTEX_STATUS_SUCCESSFUL;
     
    156166      _CORE_mutex_Pop_priority( the_mutex, holder );
    157167
    158     if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL )
     168    if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL ) {
     169      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
    159170      return pop_status;
     171    }
    160172
    161173    holder->resource_count--;
    162 
    163     /*
    164      *  Whether or not someone is waiting for the mutex, an
    165      *  inherited priority must be lowered if this is the last
    166      *  mutex (i.e. resource) this task has.
    167      */
    168     if ( !_Thread_Owns_resources( holder ) &&
    169          holder->real_priority != holder->current_priority ) {
    170       _Thread_Change_priority( holder, holder->real_priority, true );
    171     }
    172174  }
    173175  the_mutex->holder = NULL;
     
    177179   *  transfer the mutex to that thread.
    178180   */
    179   if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {
     181  if ( ( the_thread = _Thread_queue_First_locked( &the_mutex->Wait_queue ) ) ) {
     182    /*
     183     * We must extract the thread now since this will restore its default
     184     * thread lock.  This is necessary to avoid a deadlock in the
     185     * _Thread_Change_priority() below due to a recursive thread queue lock
     186     * acquire.
     187     */
     188    _Thread_queue_Extract_locked( &the_mutex->Wait_queue, the_thread );
    180189
    181190#if defined(RTEMS_MULTIPROCESSING)
    182     if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
    183 
    184       the_mutex->holder     = NULL;
    185       the_mutex->nest_count = 1;
    186 
    187       ( *api_mutex_mp_support)( the_thread, id );
    188 
    189     } else
     191    _Thread_Dispatch_disable();
     192
     193    if ( _Objects_Is_local_id( the_thread->Object.id ) )
    190194#endif
    191195    {
    192 
    193196      the_mutex->holder     = the_thread;
    194197      the_mutex->nest_count = 1;
     
    216219      }
    217220    }
     221
     222    _Thread_queue_Unblock_critical(
     223      &the_mutex->Wait_queue,
     224      the_thread,
     225      lock_context
     226    );
     227
     228#if defined(RTEMS_MULTIPROCESSING)
     229    if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
     230
     231      the_mutex->holder     = NULL;
     232      the_mutex->nest_count = 1;
     233
     234      ( *api_mutex_mp_support)( the_thread, id );
     235
     236    }
     237
     238    _Thread_Dispatch_enable( _Per_CPU_Get() );
     239#endif
     240  } else {
     241    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
     242  }
     243
     244  /*
     245   *  Whether or not someone is waiting for the mutex, an
     246   *  inherited priority must be lowered if this is the last
     247   *  mutex (i.e. resource) this task has.
     248   */
     249  if ( !_Thread_Owns_resources( holder ) &&
     250       holder->real_priority != holder->current_priority ) {
     251    Per_CPU_Control *cpu_self;
     252
     253    cpu_self = _Thread_Dispatch_disable();
     254    _Thread_Change_priority( holder, holder->real_priority, true );
     255    _Thread_Dispatch_enable( cpu_self );
    218256  }
    219257
  • cpukit/score/src/debugisownerofallocator.c

    rd12b313 r4438ac25  
    1919#include <rtems/score/assert.h>
    2020#include <rtems/score/apimutex.h>
    21 #include <rtems/score/thread.h>
    22 #include <rtems/score/threaddispatch.h>
     21#include <rtems/score/threadimpl.h>
    2322
    2423#if defined( RTEMS_DEBUG )
     
    2827    bool owner;
    2928
    30     /*
    31      * We have to synchronize with the _CORE_mutex_Surrender() operation,
    32      * otherwise we may observe an outdated mutex holder.
    33      */
    34     _Thread_Disable_dispatch();
    35 
    3629    if ( mutex != NULL ) {
    37       owner = mutex->Mutex.holder == _Thread_Executing;
     30      owner = mutex->Mutex.holder == _Thread_Get_executing();
    3831    } else {
    3932      owner = false;
    4033    }
    4134
    42     _Thread_Enable_dispatch();
    43 
    4435    return owner;
    4536  }
Note: See TracChangeset for help on using the changeset viewer.