Changeset 57947f1 in rtems


Ignore:
Timestamp:
Mar 23, 2015, 2:05:32 PM (5 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
3134eb8
Parents:
2e9c3d5
git-author:
Sebastian Huber <sebastian.huber@…> (03/23/15 14:05:32)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/24/15 13:35:04)
Message:

score: Add thread lock

Update #2273.

Location:
cpukit/score
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/include/rtems/score/thread.h

    r2e9c3d5 r57947f1  
    619619}Thread_Capture_control;
    620620
     621#if defined(RTEMS_SMP)
     622/**
     623 * @brief Thread lock control.
     624 *
     625 * The thread lock is either the default lock or the lock of the resource on
     626 * which the thread is currently blocked.  The generation number takes care
     627 * that the up to date lock is used.  Only resources using fine grained locking
     628 * provide their own lock.
     629 *
     630 * The thread lock protects the following thread variables
     631 *  - Thread_Control::current_priority,
     632 *  - Thread_Control::Priority::change_handler, and
     633 *  - Thread_Control::Priority::change_handler_context.
     634 *
     635 * @see _Thread_Lock_acquire(), _Thread_Lock_release(), _Thread_Lock_set() and
     636 * _Thread_Lock_restore_default().
     637 */
     638typedef struct {
     639  /**
     640   * @brief The current thread lock.
     641   */
     642  ISR_lock_Control *current;
     643
     644  /**
     645   * @brief The default thread lock in case the thread is not blocked on a
     646   * resource.
     647   */
     648  ISR_lock_Control Default;
     649
     650  /**
     651   * @brief Generation number to invalidate stale locks.
     652   */
     653  Atomic_Uint generation;
     654} Thread_Lock_control;
     655#endif
     656
    621657/**
    622658 *  This structure defines the Thread Control Block (TCB).
     
    641677  /** This field is the number of mutexes currently held by this thread. */
    642678  uint32_t                 resource_count;
     679
     680#if defined(RTEMS_SMP)
     681  /**
     682   * @brief Thread lock control.
     683   */
     684  Thread_Lock_control Lock;
     685#endif
     686
    643687  /** This field is the blocking information for this thread. */
    644688  Thread_Wait_information  Wait;
  • cpukit/score/include/rtems/score/threadimpl.h

    r2e9c3d5 r57947f1  
    884884}
    885885
     886/**
     887 * @brief Release the thread lock.
     888 *
     889 * @param[in] lock The lock returned by _Thread_Lock_acquire().
     890 * @param[in] lock_context The lock context used for _Thread_Lock_acquire().
     891 */
     892RTEMS_INLINE_ROUTINE void _Thread_Lock_release(
     893  ISR_lock_Control *lock,
     894  ISR_lock_Context *lock_context
     895)
     896{
     897  _ISR_lock_Release_and_ISR_enable( lock, lock_context );
     898}
     899
     900/**
     901 * @brief Acquires the thread lock.
     902 *
     903 * @param[in] the_thread The thread.
     904 * @param[in] lock_context The lock context for _Thread_Lock_release().
     905 *
     906 * @return The lock required by _Thread_Lock_release().
     907 */
     908RTEMS_INLINE_ROUTINE ISR_lock_Control *_Thread_Lock_acquire(
     909  Thread_Control   *the_thread,
     910  ISR_lock_Context *lock_context
     911)
     912{
     913#if defined(RTEMS_SMP)
     914  ISR_lock_Control *lock;
     915
     916  while ( true ) {
     917    uint32_t my_generation;
     918
     919    _ISR_Disable_without_giant( lock_context->Lock_context.isr_level );
     920    my_generation = the_thread->Lock.generation;
     921
     922    /*
     923     * Ensure that we read the initial lock generation before we obtain our
     924     * current lock.
     925     */
     926    _Atomic_Fence( ATOMIC_ORDER_ACQUIRE );
     927
     928    lock = the_thread->Lock.current;
     929    _ISR_lock_Acquire( lock, lock_context );
     930
     931    /*
     932     * Ensure that we read the second lock generation after we obtained our
     933     * current lock.
     934     */
     935    _Atomic_Fence( ATOMIC_ORDER_ACQUIRE );
     936
     937    if ( the_thread->Lock.generation == my_generation ) {
     938      break;
     939    }
     940
     941    _Thread_Lock_release( lock, lock_context );
     942  }
     943
     944  return lock;
     945#else
     946  _ISR_Disable( lock_context->isr_level );
     947
     948  return NULL;
     949#endif
     950}
     951
     952#if defined(RTEMS_SMP)
     953/*
     954 * Internal function, use _Thread_Lock_set() or _Thread_Lock_restore_default()
     955 * instead.
     956 */
     957RTEMS_INLINE_ROUTINE void _Thread_Lock_set_unprotected(
     958  Thread_Control   *the_thread,
     959  ISR_lock_Control *new_lock
     960)
     961{
     962  the_thread->Lock.current = new_lock;
     963
     964  /*
     965   * Ensure that the new lock is visible before we update the generation
     966   * number.  Otherwise someone would be able to read an up to date generation
     967   * number and an old lock.
     968   */
     969  _Atomic_Fence( ATOMIC_ORDER_RELEASE );
     970
     971  /*
     972   * Since we set a new lock right before, this increment is not protected by a
     973   * lock and thus must be an atomic operation.
     974   */
     975  _Atomic_Fetch_add_uint(
     976    &the_thread->Lock.generation,
     977    1,
     978    ATOMIC_ORDER_RELAXED
     979  );
     980}
     981#endif
     982
     983/**
     984 * @brief Sets a new thread lock.
     985 *
     986 * The caller must not be the owner of the default thread lock.  The caller
     987 * must be the owner of the new lock.
     988 *
     989 * @param[in] the_thread The thread.
     990 * @param[in] new_lock The new thread lock.
     991 */
     992#if defined(RTEMS_SMP)
     993RTEMS_INLINE_ROUTINE void _Thread_Lock_set(
     994  Thread_Control   *the_thread,
     995  ISR_lock_Control *new_lock
     996)
     997{
     998  ISR_lock_Control *lock;
     999  ISR_lock_Context  lock_context;
     1000
     1001  lock = _Thread_Lock_acquire( the_thread, &lock_context );
     1002  _Thread_Lock_set_unprotected( the_thread, new_lock );
     1003  _Thread_Lock_release( lock, &lock_context );
     1004}
     1005#else
     1006#define _Thread_Lock_set( the_thread, new_lock ) \
     1007  do { } while ( 0 )
     1008#endif
     1009
     1010/**
     1011 * @brief Restores the default thread lock.
     1012 *
     1013 * The caller must be the owner of the current thread lock.
     1014 *
     1015 * @param[in] the_thread The thread.
     1016 */
     1017#if defined(RTEMS_SMP)
     1018RTEMS_INLINE_ROUTINE void _Thread_Lock_restore_default(
     1019  Thread_Control *the_thread
     1020)
     1021{
     1022  _Atomic_Fence( ATOMIC_ORDER_RELEASE );
     1023
     1024  _Thread_Lock_set_unprotected( the_thread, &the_thread->Lock.Default );
     1025}
     1026#else
     1027#define _Thread_Lock_restore_default( the_thread ) \
     1028  do { } while ( 0 )
     1029#endif
     1030
    8861031void _Thread_Priority_change_do_nothing(
    8871032  Thread_Control   *the_thread,
  • cpukit/score/src/threadchangepriority.c

    r2e9c3d5 r57947f1  
    3030)
    3131{
    32   ISR_Level level;
     32  ISR_lock_Context  lock_context;
     33  ISR_lock_Control *lock;
    3334
    34   _ISR_Disable( level );
     35  lock = _Thread_Lock_acquire( the_thread, &lock_context );
    3536
    3637  /*
     
    3940   */
    4041  if ( the_thread->current_priority != new_priority ) {
    41     uint32_t my_generation = the_thread->Priority.generation + 1;
     42    uint32_t  my_generation;
     43    ISR_Level level;
    4244
     45    my_generation = the_thread->Priority.generation + 1;
    4346    the_thread->current_priority = new_priority;
    4447    the_thread->Priority.generation = my_generation;
     
    5053    );
    5154
    52     _ISR_Flash( level );
     55    _Thread_Lock_release( lock, &lock_context );
     56
     57    _ISR_Disable( level );
    5358
    5459    if ( the_thread->Priority.generation == my_generation ) {
     
    6368      }
    6469    }
     70
     71    _ISR_Enable( level );
     72  } else {
     73    _Thread_Lock_release( lock, &lock_context );
    6574  }
    66 
    67   _ISR_Enable( level );
    6875}
  • cpukit/score/src/threadinitialize.c

    r2e9c3d5 r57947f1  
    197197  _Resource_Node_initialize( &the_thread->Resource_node );
    198198  _CPU_Context_Set_is_executing( &the_thread->Registers, false );
     199  the_thread->Lock.current = &the_thread->Lock.Default;
     200  _ISR_lock_Initialize( &the_thread->Lock.Default, "Thread Lock Default");
     201  _Atomic_Init_uint(&the_thread->Lock.generation, 0);
    199202#endif
    200203
  • cpukit/score/src/threadrestart.c

    r2e9c3d5 r57947f1  
    9898
    9999  _Workspace_Free( the_thread->Start.tls_area );
     100
     101#if defined(RTEMS_SMP)
     102  _ISR_lock_Destroy( &the_thread->Lock.Default );
     103#endif
    100104
    101105  _Objects_Free(
Note: See TracChangeset for help on using the changeset viewer.