diff options
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/libmisc/monitor/mon-prmisc.c | 1 | ||||
-rw-r--r-- | cpukit/score/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/statesimpl.h | 3 | ||||
-rw-r--r-- | cpukit/score/src/semaphore.c | 141 |
4 files changed, 146 insertions, 0 deletions
diff --git a/cpukit/libmisc/monitor/mon-prmisc.c b/cpukit/libmisc/monitor/mon-prmisc.c index ae7f75d350..4656ed297a 100644 --- a/cpukit/libmisc/monitor/mon-prmisc.c +++ b/cpukit/libmisc/monitor/mon-prmisc.c @@ -135,6 +135,7 @@ static const rtems_assoc_t rtems_monitor_state_assoc[] = { { "Wsem", STATES_WAITING_FOR_SEMAPHORE, 0 }, { "Wsig", STATES_WAITING_FOR_SIGNAL, 0 }, { "Wslmtx", STATES_WAITING_FOR_SYS_LOCK_MUTEX, 0 }, + { "Wslsem", STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE, 0 }, { "Wsysev", STATES_WAITING_FOR_SYSTEM_EVENT, 0 }, { "Wterm", STATES_WAITING_FOR_TERMINATION, 0 }, { "Wtime", STATES_WAITING_FOR_TIME, 0 }, diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index c107805a3d..4b4c1f5fce 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -349,6 +349,7 @@ libscore_a_SOURCES += src/profilingisrentryexit.c libscore_a_SOURCES += src/mutex.c libscore_a_SOURCES += src/once.c libscore_a_SOURCES += src/resourceiterate.c +libscore_a_SOURCES += src/semaphore.c libscore_a_SOURCES += src/smpbarrierwait.c libscore_a_SOURCES += src/kern_tc.c diff --git a/cpukit/score/include/rtems/score/statesimpl.h b/cpukit/score/include/rtems/score/statesimpl.h index 4ad8786387..7805ca4c9b 100644 --- a/cpukit/score/include/rtems/score/statesimpl.h +++ b/cpukit/score/include/rtems/score/statesimpl.h @@ -88,6 +88,8 @@ extern "C" { #define STATES_WAITING_FOR_JOIN 0x1000000 /** This macro corresponds to a task waiting for a <sys/lock.h> mutex. */ #define STATES_WAITING_FOR_SYS_LOCK_MUTEX 0x2000000 +/** This macro corresponds to a task waiting for a <sys/lock.h> semaphore. */ +#define STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE 0x4000000 /** This macro corresponds to a task which is in an interruptible * blocking state. @@ -106,6 +108,7 @@ extern "C" { STATES_WAITING_FOR_BARRIER | \ STATES_WAITING_FOR_BSD_WAKEUP | \ STATES_WAITING_FOR_SYS_LOCK_MUTEX | \ + STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE | \ STATES_WAITING_FOR_RWLOCK ) /** This macro corresponds to a task waiting which is blocked. */ diff --git a/cpukit/score/src/semaphore.c b/cpukit/score/src/semaphore.c new file mode 100644 index 0000000000..94e5209fad --- /dev/null +++ b/cpukit/score/src/semaphore.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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 + +#if HAVE_STRUCT__THREAD_QUEUE_QUEUE + +#include <sys/lock.h> + +#include <rtems/score/assert.h> +#include <rtems/score/threadimpl.h> +#include <rtems/score/threadqimpl.h> + +#define SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_priority + +typedef struct { + Thread_queue_Syslock_queue Queue; + unsigned int count; +} Semaphore_Control; + +RTEMS_STATIC_ASSERT( + offsetof( Semaphore_Control, Queue ) + == offsetof( struct _Semaphore_Control, _Queue ), + SEMAPHORE_CONTROL_QUEUE +); + +RTEMS_STATIC_ASSERT( + offsetof( Semaphore_Control, count ) + == offsetof( struct _Semaphore_Control, _count ), + SEMAPHORE_CONTROL_COUNT +); + +RTEMS_STATIC_ASSERT( + sizeof( Semaphore_Control ) == sizeof( struct _Semaphore_Control ), + SEMAPHORE_CONTROL_SIZE +); + +static Semaphore_Control *_Semaphore_Get( + struct _Semaphore_Control *_sem +) +{ + return (Semaphore_Control *) _sem; +} + +static Thread_Control *_Semaphore_Queue_acquire( + Semaphore_Control *sem, + ISR_lock_Context *lock_context +) +{ + Thread_Control *executing; + + _ISR_lock_ISR_disable( lock_context ); + executing = _Thread_Executing; + _Thread_queue_Queue_acquire_critical( + &sem->Queue.Queue, + &executing->Potpourri_stats, + lock_context + ); + + return executing; +} + +static void _Semaphore_Queue_release( + Semaphore_Control *sem, + ISR_lock_Context *lock_context +) +{ + _Thread_queue_Queue_release( &sem->Queue.Queue, lock_context ); +} + +void _Semaphore_Wait( struct _Semaphore_Control *_sem ) +{ + Semaphore_Control *sem ; + ISR_lock_Context lock_context; + Thread_Control *executing; + unsigned int count; + + sem = _Semaphore_Get( _sem ); + executing = _Semaphore_Queue_acquire( sem, &lock_context ); + + count = sem->count; + if ( count > 0 ) { + sem->count = count - 1; + _Semaphore_Queue_release( sem, &lock_context ); + } else { + _Thread_queue_Enqueue_critical( + &sem->Queue.Queue, + SEMAPHORE_TQ_OPERATIONS, + executing, + STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE, + 0, + 0, + &lock_context + ); + } +} + +void _Semaphore_Post( struct _Semaphore_Control *_sem ) +{ + Semaphore_Control *sem; + ISR_lock_Context lock_context; + Thread_queue_Heads *heads; + + sem = _Semaphore_Get( _sem ); + _Semaphore_Queue_acquire( sem, &lock_context ); + + heads = sem->Queue.Queue.heads; + if ( heads == NULL ) { + _Assert( sem->count < UINT_MAX ); + ++sem->count; + _Semaphore_Queue_release( sem, &lock_context ); + } else { + const Thread_queue_Operations *operations; + Thread_Control *first; + + operations = SEMAPHORE_TQ_OPERATIONS; + first = ( *operations->first )( heads ); + + _Thread_queue_Extract_critical( + &sem->Queue.Queue, + operations, + first, + &lock_context + ); + } +} + +#endif /* HAVE_STRUCT__THREAD_QUEUE_QUEUE */ |