Changeset 5222488 in rtems for cpukit/posix


Ignore:
Timestamp:
Sep 26, 2017, 5:49:17 AM (2 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
de59c065
Parents:
89fc9345
git-author:
Sebastian Huber <sebastian.huber@…> (09/26/17 05:49:17)
git-committer:
Sebastian Huber <sebastian.huber@…> (10/05/17 12:29:02)
Message:

posix: Implement self-contained POSIX condvar

POSIX condition variables are now available in all configurations and no
longer depend on --enable-posix.

Update #2514.
Update #3113.

Location:
cpukit/posix
Files:
3 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • cpukit/posix/Makefile.am

    r89fc9345 r5222488  
    1818## Some POSIX threads features are needed all the time
    1919include_rtems_posix_HEADERS += include/rtems/posix/barrierimpl.h
     20include_rtems_posix_HEADERS += include/rtems/posix/condimpl.h
    2021include_rtems_posix_HEADERS += include/rtems/posix/key.h
    2122include_rtems_posix_HEADERS += include/rtems/posix/keyimpl.h
     
    3536# include/rtems/posix
    3637include_rtems_posix_HEADERS += include/rtems/posix/aio_misc.h
    37 include_rtems_posix_HEADERS += include/rtems/posix/cond.h
    38 include_rtems_posix_HEADERS += include/rtems/posix/condimpl.h
    3938include_rtems_posix_HEADERS += include/rtems/posix/mmanimpl.h
    4039include_rtems_posix_HEADERS += include/rtems/posix/mqueue.h
     
    7372    src/pbarrierwait.c
    7473
    75 if HAS_PTHREADS
    76 libposix_a_SOURCES +=  src/pthreadatfork.c
    77 
    78 ## CANCEL_C_FILES
    79 libposix_a_SOURCES += src/cancel.c \
    80     src/cleanuppush.c src/setcancelstate.c \
    81     src/setcanceltype.c src/testcancel.c
    82 
    8374## CONDITION_VARIABLE_C_FILES
    84 libposix_a_SOURCES += src/cond.c src/condattrdestroy.c \
     75libposix_a_SOURCES += src/condattrdestroy.c \
    8576    src/condattrinit.c  \
    8677    src/condattrgetpshared.c src/condattrsetpshared.c \
     
    8879    src/condbroadcast.c src/conddefaultattributes.c src/conddestroy.c \
    8980    src/condinit.c src/condsignal.c src/condsignalsupp.c \
    90     src/condtimedwait.c src/condwait.c src/condwaitsupp.c src/condget.c
     81    src/condtimedwait.c src/condwait.c src/condwaitsupp.c
     82
     83if HAS_PTHREADS
     84libposix_a_SOURCES +=  src/pthreadatfork.c
     85
     86## CANCEL_C_FILES
     87libposix_a_SOURCES += src/cancel.c \
     88    src/cleanuppush.c src/setcancelstate.c \
     89    src/setcanceltype.c src/testcancel.c
    9190
    9291## MEMORY_C_FILES
  • cpukit/posix/include/rtems/posix/condimpl.h

    r89fc9345 r5222488  
    1717#ifndef _RTEMS_POSIX_CONDIMPL_H
    1818#define _RTEMS_POSIX_CONDIMPL_H
    19  
    20 #include <rtems/posix/cond.h>
    21 #include <rtems/score/objectimpl.h>
    22 #include <rtems/score/threadqimpl.h>
    2319
    2420#include <errno.h>
     21#include <pthread.h>
     22
     23#include <rtems/score/percpu.h>
     24#include <rtems/score/threadqimpl.h>
    2525
    2626#ifdef __cplusplus
    2727extern "C" {
    2828#endif
     29
     30typedef struct {
     31  unsigned long flags;
     32  Thread_queue_Syslock_queue Queue;
     33  pthread_mutex_t *mutex;
     34} POSIX_Condition_variables_Control;
     35
     36#define POSIX_CONDITION_VARIABLES_CLOCK_MONOTONIC 0x1UL
     37
     38#define POSIX_CONDITION_VARIABLES_FLAGS_MASK 0x1UL
     39
     40#define POSIX_CONDITION_VARIABLES_MAGIC 0x18dfb1feUL
    2941
    3042/**
     
    3850#define POSIX_CONDITION_VARIABLE_OF_THREAD_QUEUE_QUEUE( queue ) \
    3951  RTEMS_CONTAINER_OF( \
    40     queue, POSIX_Condition_variables_Control, Wait_queue.Queue )
    41 
    42 /**
    43  *  The following defines the information control block used to manage
    44  *  this class of objects.
    45  */
    46 extern Objects_Information _POSIX_Condition_variables_Information;
     52    queue, POSIX_Condition_variables_Control, Queue.Queue )
    4753
    4854/**
     
    5157extern const pthread_condattr_t _POSIX_Condition_variables_Default_attributes;
    5258
     59static inline POSIX_Condition_variables_Control *_POSIX_Condition_variables_Get(
     60  pthread_cond_t *cond
     61)
     62{
     63  return (POSIX_Condition_variables_Control *) cond;
     64}
     65
    5366RTEMS_INLINE_ROUTINE void _POSIX_Condition_variables_Initialize(
    5467  POSIX_Condition_variables_Control *the_cond,
     
    5669)
    5770{
    58   _Thread_queue_Object_initialize( &the_cond->Wait_queue );
     71  unsigned long flags;
     72
     73  _Thread_queue_Queue_initialize( &the_cond->Queue.Queue, NULL );
    5974  the_cond->mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
    60   the_cond->clock = the_attr->clock;
     75
     76  flags = (uintptr_t) the_cond ^ POSIX_CONDITION_VARIABLES_MAGIC;
     77  flags &= ~POSIX_CONDITION_VARIABLES_FLAGS_MASK;
     78
     79  if ( the_attr->clock == CLOCK_MONOTONIC ) {
     80    flags |= POSIX_CONDITION_VARIABLES_CLOCK_MONOTONIC;
     81  }
     82
     83  the_cond->flags = flags;
    6184}
    6285
     
    6588)
    6689{
    67   _Thread_queue_Destroy( &the_cond->Wait_queue );
     90  the_cond->flags = ~the_cond->flags;
    6891}
    6992
    70 RTEMS_INLINE_ROUTINE void _POSIX_Condition_variables_Acquire_critical(
     93RTEMS_INLINE_ROUTINE clockid_t _POSIX_Condition_variables_Get_clock(
     94  unsigned long flags
     95)
     96{
     97  if ( ( flags & POSIX_CONDITION_VARIABLES_CLOCK_MONOTONIC ) != 0 ) {
     98    return CLOCK_MONOTONIC;
     99  }
     100
     101  return CLOCK_REALTIME;
     102}
     103
     104RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Condition_variables_Acquire(
    71105  POSIX_Condition_variables_Control *the_cond,
    72106  Thread_queue_Context              *queue_context
    73107)
    74108{
    75   _Thread_queue_Acquire_critical( &the_cond->Wait_queue, queue_context );
     109  ISR_Level       level;
     110  Thread_Control *executing;
     111
     112  _Thread_queue_Context_ISR_disable( queue_context, level );
     113  _Thread_queue_Context_set_ISR_level( queue_context, level );
     114  executing = _Thread_Executing;
     115  _Thread_queue_Queue_acquire_critical(
     116    &the_cond->Queue.Queue,
     117    &executing->Potpourri_stats,
     118    &queue_context->Lock_context.Lock_context
     119  );
     120
     121  return executing;
    76122}
    77123
     
    81127)
    82128{
    83   _Thread_queue_Release( &the_cond->Wait_queue, queue_context );
    84 }
    85 
    86 /**
    87  *  @brief POSIX Condition Variable Allocate
    88  *
    89  *  This function allocates a condition variable control block from
    90  *  the inactive chain of free condition variable control blocks.
    91  */
    92 RTEMS_INLINE_ROUTINE POSIX_Condition_variables_Control *
    93   _POSIX_Condition_variables_Allocate( void )
    94 {
    95   return (POSIX_Condition_variables_Control *)
    96     _Objects_Allocate( &_POSIX_Condition_variables_Information );
    97 }
    98 
    99 /**
    100  *  @brief POSIX Condition Variable Free
    101  *
    102  *  This routine frees a condition variable control block to the
    103  *  inactive chain of free condition variable control blocks.
    104  */
    105 RTEMS_INLINE_ROUTINE void _POSIX_Condition_variables_Free (
    106   POSIX_Condition_variables_Control *the_condition_variable
    107 )
    108 {
    109   _Objects_Free(
    110     &_POSIX_Condition_variables_Information,
    111     &the_condition_variable->Object
     129  _Thread_queue_Queue_release(
     130    &the_cond->Queue.Queue,
     131    &queue_context->Lock_context.Lock_context
    112132  );
    113133}
    114 
    115 POSIX_Condition_variables_Control *_POSIX_Condition_variables_Get(
    116   pthread_cond_t       *cond,
    117   Thread_queue_Context *queue_context
    118 );
    119134
    120135/**
     
    141156);
    142157
     158bool _POSIX_Condition_variables_Auto_initialization(
     159  POSIX_Condition_variables_Control *the_cond
     160);
     161
     162#define POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags ) \
     163  do { \
     164    if ( ( the_cond ) == NULL ) { \
     165      return EINVAL; \
     166    } \
     167    flags = ( the_cond )->flags; \
     168    if ( \
     169      ( ( (uintptr_t) ( the_cond ) ^ POSIX_CONDITION_VARIABLES_MAGIC ) \
     170          & ~POSIX_CONDITION_VARIABLES_FLAGS_MASK ) \
     171        != ( flags & ~POSIX_CONDITION_VARIABLES_FLAGS_MASK ) \
     172    ) { \
     173      if ( !_POSIX_Condition_variables_Auto_initialization( the_cond ) ) { \
     174        return EINVAL; \
     175      } \
     176    } \
     177  } while ( 0 )
     178
    143179#ifdef __cplusplus
    144180}
  • cpukit/posix/include/rtems/posix/config.h

    r89fc9345 r5222488  
    7171  /**
    7272   * This field contains the maximum number of POSIX API
    73    * condition variables which are configured for this application.
    74    */
    75   uint32_t                            maximum_condition_variables;
    76 
    77   /**
    78    * This field contains the maximum number of POSIX API
    7973   * timers which are configured for this application.
    8074   */
  • cpukit/posix/preinstall.am

    r89fc9345 r5222488  
    3131        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/barrierimpl.h
    3232PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/barrierimpl.h
     33
     34$(PROJECT_INCLUDE)/rtems/posix/condimpl.h: include/rtems/posix/condimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
     35        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
     36PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
    3337
    3438$(PROJECT_INCLUDE)/rtems/posix/key.h: include/rtems/posix/key.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
     
    8084        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/aio_misc.h
    8185PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/aio_misc.h
    82 
    83 $(PROJECT_INCLUDE)/rtems/posix/cond.h: include/rtems/posix/cond.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
    84         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/cond.h
    85 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/cond.h
    86 
    87 $(PROJECT_INCLUDE)/rtems/posix/condimpl.h: include/rtems/posix/condimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
    88         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
    89 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
    9086
    9187$(PROJECT_INCLUDE)/rtems/posix/mmanimpl.h: include/rtems/posix/mmanimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
  • cpukit/posix/src/conddestroy.c

    r89fc9345 r5222488  
    2525 *         P1003.1c/Draft 10, p. 87
    2626 */
    27 int pthread_cond_destroy(
    28   pthread_cond_t           *cond
    29 )
     27int pthread_cond_destroy( pthread_cond_t *cond )
    3028{
    3129  POSIX_Condition_variables_Control *the_cond;
     30  unsigned long                      flags;
    3231  Thread_queue_Context               queue_context;
    3332
    34   _Objects_Allocator_lock();
    35   the_cond = _POSIX_Condition_variables_Get( cond, &queue_context );
     33  the_cond = _POSIX_Condition_variables_Get( cond );
     34  POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags );
    3635
    37   if ( the_cond == NULL ) {
    38     _Objects_Allocator_unlock();
    39     return EINVAL;
    40   }
     36  _Thread_queue_Context_initialize( &queue_context );
     37  _POSIX_Condition_variables_Acquire( the_cond, &queue_context );
    4138
    42   _POSIX_Condition_variables_Acquire_critical( the_cond, &queue_context );
    43 
    44   if ( !_Thread_queue_Is_empty( &the_cond->Wait_queue.Queue ) ) {
     39  if ( !_Thread_queue_Is_empty( &the_cond->Queue.Queue ) ) {
    4540    _POSIX_Condition_variables_Release( the_cond, &queue_context );
    46     _Objects_Allocator_unlock();
    4741    return EBUSY;
    4842  }
    4943
    50   _Objects_Close(
    51     &_POSIX_Condition_variables_Information,
    52     &the_cond->Object
    53   );
    5444  _POSIX_Condition_variables_Release( the_cond, &queue_context );
    5545  _POSIX_Condition_variables_Destroy( the_cond );
    56   _POSIX_Condition_variables_Free( the_cond );
    57   _Objects_Allocator_unlock();
    5846  return 0;
    5947}
  • cpukit/posix/src/condinit.c

    r89fc9345 r5222488  
    2222#include <rtems/posix/posixapi.h>
    2323
     24RTEMS_STATIC_ASSERT(
     25  offsetof( POSIX_Condition_variables_Control, flags )
     26    == offsetof( pthread_cond_t, _flags ),
     27  POSIX_CONDITION_VARIABLES_CONTROL_FLAGS
     28);
     29
     30RTEMS_STATIC_ASSERT(
     31  offsetof( POSIX_Condition_variables_Control, mutex )
     32    == offsetof( pthread_cond_t, _mutex ),
     33  POSIX_CONDITION_VARIABLES_CONTROL_COUNT
     34);
     35
     36RTEMS_STATIC_ASSERT(
     37  offsetof( POSIX_Condition_variables_Control, Queue )
     38    == offsetof( pthread_cond_t, _Queue ),
     39  POSIX_CONDITION_VARIABLES_CONTROL_QUEUE
     40);
     41
     42RTEMS_STATIC_ASSERT(
     43  sizeof( POSIX_Condition_variables_Control ) == sizeof( pthread_cond_t ),
     44  POSIX_CONDITION_VARIABLES_CONTROL_SIZE
     45);
     46
    2447/**
    2548 *  11.4.2 Initializing and Destroying a Condition Variable,
     
    3154)
    3255{
    33   POSIX_Condition_variables_Control   *the_cond;
    34   const pthread_condattr_t            *the_attr;
     56  POSIX_Condition_variables_Control *the_cond;
    3557
    36   if ( attr ) the_attr = attr;
    37   else        the_attr = &_POSIX_Condition_variables_Default_attributes;
     58  the_cond = _POSIX_Condition_variables_Get( cond );
    3859
    39   /*
    40    *  Be careful about attributes when global!!!
    41    */
    42 
    43   if ( !the_attr->is_initialized )
    44     return EINVAL;
    45 
    46   if ( !_POSIX_Is_valid_pshared( the_attr->process_shared ) ) {
     60  if ( the_cond == NULL ) {
    4761    return EINVAL;
    4862  }
    4963
    50   the_cond = _POSIX_Condition_variables_Allocate();
    51 
    52   if ( !the_cond ) {
    53     _Objects_Allocator_unlock();
    54     return ENOMEM;
     64  if ( attr == NULL ) {
     65    attr = &_POSIX_Condition_variables_Default_attributes;
    5566  }
    5667
    57   _POSIX_Condition_variables_Initialize( the_cond, the_attr );
     68  if ( !attr->is_initialized ) {
     69    return EINVAL;
     70  }
    5871
    59   _Objects_Open_u32(
    60     &_POSIX_Condition_variables_Information,
    61     &the_cond->Object,
    62     0
    63   );
     72  if ( !_POSIX_Is_valid_pshared( attr->process_shared ) ) {
     73    return EINVAL;
     74  }
    6475
    65   *cond = the_cond->Object.id;
    66 
    67   _Objects_Allocator_unlock();
    68 
     76  _POSIX_Condition_variables_Initialize( the_cond, attr );
    6977  return 0;
    7078}
  • cpukit/posix/src/condsignalsupp.c

    r89fc9345 r5222488  
    3333)
    3434{
    35   Thread_Control *the_thread;
     35  POSIX_Condition_variables_Control *the_cond;
     36  unsigned long                      flags;
     37  const Thread_queue_Operations     *operations;
     38  Thread_queue_Heads                *heads;
     39
     40  the_cond = _POSIX_Condition_variables_Get( cond );
     41  POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags );
     42  operations = POSIX_CONDITION_VARIABLES_TQ_OPERATIONS;
    3643
    3744  do {
    38     POSIX_Condition_variables_Control *the_cond;
    39     Thread_queue_Context               queue_context;
     45    Thread_queue_Context queue_context;
    4046
    41     the_cond = _POSIX_Condition_variables_Get( cond, &queue_context );
     47    _Thread_queue_Context_initialize( &queue_context );
     48    _POSIX_Condition_variables_Acquire( the_cond, &queue_context );
    4249
    43     if ( the_cond == NULL ) {
    44       return EINVAL;
    45     }
     50    heads = the_cond->Queue.Queue.heads;
    4651
    47     _POSIX_Condition_variables_Acquire_critical( the_cond, &queue_context );
     52    if ( heads != NULL ) {
     53      Thread_Control *the_thread;
    4854
    49     the_thread = _Thread_queue_First_locked(
    50       &the_cond->Wait_queue,
    51       POSIX_CONDITION_VARIABLES_TQ_OPERATIONS
    52     );
    53 
    54     if ( the_thread != NULL ) {
     55      the_thread = ( *operations->first )( heads );
    5556      _Thread_queue_Extract_critical(
    56         &the_cond->Wait_queue.Queue,
    57         POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
     57        &the_cond->Queue.Queue,
     58        operations,
    5859        the_thread,
    5960        &queue_context
     
    6364      _POSIX_Condition_variables_Release( the_cond, &queue_context );
    6465    }
    65   } while ( is_broadcast && the_thread != NULL );
     66  } while ( is_broadcast && heads != NULL );
    6667
    6768  return 0;
  • cpukit/posix/src/condwait.c

    r89fc9345 r5222488  
    2121#include <rtems/posix/condimpl.h>
    2222
     23#include <string.h>
     24
     25bool _POSIX_Condition_variables_Auto_initialization(
     26  POSIX_Condition_variables_Control *the_cond
     27)
     28{
     29  POSIX_Condition_variables_Control zero;
     30  unsigned long                     flags;
     31
     32  memset( &zero, 0, sizeof( zero ) );
     33
     34  if ( memcmp( the_cond, &zero, sizeof( *the_cond ) ) != 0 ) {
     35    return false;
     36  }
     37
     38  flags = (uintptr_t) the_cond ^ POSIX_CONDITION_VARIABLES_MAGIC;
     39  flags &= ~POSIX_CONDITION_VARIABLES_FLAGS_MASK;
     40  the_cond->flags = flags;
     41  return true;
     42}
     43
    2344/*
    2445 *  11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105
  • cpukit/posix/src/condwaitsupp.c

    r89fc9345 r5222488  
    2525#include <rtems/score/status.h>
    2626#include <rtems/score/threaddispatch.h>
    27 
    28 THREAD_QUEUE_OBJECT_ASSERT( POSIX_Condition_variables_Control, Wait_queue );
    2927
    3028static void _POSIX_Condition_variables_Enqueue_callout(
     
    5957{
    6058  POSIX_Condition_variables_Control *the_cond;
     59  unsigned long                      flags;
    6160  Thread_queue_Context               queue_context;
    6261  int                                error;
     
    6766  TOD_Absolute_timeout_conversion_results  status;
    6867
    69   if ( mutex == NULL ) {
    70     return EINVAL;
    71   }
     68  the_cond = _POSIX_Condition_variables_Get( cond );
     69  POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags );
    7270
    73   the_cond = _POSIX_Condition_variables_Get( cond, &queue_context );
    74 
    75   if ( the_cond == NULL ) {
    76     return EINVAL;
    77   }
    78 
     71  _Thread_queue_Context_initialize( &queue_context );
    7972  already_timedout = false;
    8073
     
    8982     *  status into the appropriate error.
    9083     */
    91     _Assert( the_cond->clock );
    92     status = _TOD_Absolute_timeout_to_ticks(abstime, the_cond->clock, &timeout);
     84    status = _TOD_Absolute_timeout_to_ticks(
     85      abstime,
     86      _POSIX_Condition_variables_Get_clock( flags ),
     87      &timeout
     88    );
    9389    if ( status == TOD_ABSOLUTE_TIMEOUT_INVALID )
    9490      return EINVAL;
     
    104100  }
    105101
    106   _POSIX_Condition_variables_Acquire_critical( the_cond, &queue_context );
     102  executing = _POSIX_Condition_variables_Acquire( the_cond, &queue_context );
    107103
    108104  if (
     
    115111
    116112  the_cond->mutex = mutex;
    117   executing = _Thread_Executing;
    118113
    119114  if ( !already_timedout ) {
     
    127122    );
    128123    _Thread_queue_Enqueue(
    129       &the_cond->Wait_queue.Queue,
     124      &the_cond->Queue.Queue,
    130125      POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
    131126      executing,
Note: See TracChangeset for help on using the changeset viewer.