diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-11-24 06:38:07 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-02-02 15:01:20 +0100 |
commit | f14a04c6ef5cde3f812aefd9827eddcf4cf2f13e (patch) | |
tree | 149d7e39e4f00b15951aa83699c7ed4ddc95f5ef /cpukit | |
parent | posix: Use one second based CLOCK_MONOTONIC (diff) | |
download | rtems-f14a04c6ef5cde3f812aefd9827eddcf4cf2f13e.tar.bz2 |
Add RTEMS thread API
Update #2843.
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/headers.am | 1 | ||||
-rw-r--r-- | cpukit/include/rtems/thread.h | 289 | ||||
-rw-r--r-- | cpukit/score/src/semaphore.c | 99 |
3 files changed, 386 insertions, 3 deletions
diff --git a/cpukit/headers.am b/cpukit/headers.am index c486c3f51f..379f6afcf4 100644 --- a/cpukit/headers.am +++ b/cpukit/headers.am @@ -210,6 +210,7 @@ include_rtems_HEADERS += include/rtems/termios_printk.h include_rtems_HEADERS += include/rtems/termios_printk_cnf.h include_rtems_HEADERS += include/rtems/termiostypes.h include_rtems_HEADERS += include/rtems/test.h +include_rtems_HEADERS += include/rtems/thread.h include_rtems_HEADERS += include/rtems/timecounter.h include_rtems_HEADERS += include/rtems/timespec.h include_rtems_HEADERS += include/rtems/tm27-default.h diff --git a/cpukit/include/rtems/thread.h b/cpukit/include/rtems/thread.h new file mode 100644 index 0000000000..feee612d22 --- /dev/null +++ b/cpukit/include/rtems/thread.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2017 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. + */ + +#ifndef _RTEMS_THREAD_H +#define _RTEMS_THREAD_H + +#include <sys/lock.h> +#include <errno.h> +#include <stdint.h> + +__BEGIN_DECLS + +/* Temporarily defined, will be shipped with a Newlib update */ +int _Semaphore_Wait_timed_ticks(struct _Semaphore_Control *, __uint32_t); + +/* Temporarily defined, will be shipped with a Newlib update */ +int _Semaphore_Try_wait(struct _Semaphore_Control *); + +/* Temporarily defined, will be shipped with a Newlib update */ +void _Semaphore_Post_binary(struct _Semaphore_Control *); + +typedef struct _Mutex_Control rtems_mutex; + +#define RTEMS_MUTEX_INITIALIZER( name ) _MUTEX_NAMED_INITIALIZER( name ) + +static __inline void rtems_mutex_init( rtems_mutex *mutex, const char *name ) +{ + _Mutex_Initialize_named( mutex, name ); +} + +static __inline const char *rtems_mutex_get_name( const rtems_mutex *mutex ) +{ + return mutex->_Queue._name; +} + +static __inline void rtems_mutex_set_name( rtems_mutex *mutex, const char *name ) +{ + mutex->_Queue._name = name; +} + +static __inline void rtems_mutex_lock( rtems_mutex *mutex ) +{ + _Mutex_Acquire( mutex ); +} + +static __inline void rtems_mutex_unlock( rtems_mutex *mutex ) +{ + _Mutex_Release( mutex ); +} + +static __inline void rtems_mutex_destroy( rtems_mutex *mutex ) +{ + _Mutex_Destroy( mutex ); +} + +typedef struct _Mutex_recursive_Control rtems_recursive_mutex; + +#define RTEMS_RECURSIVE_MUTEX_INITIALIZER( name ) \ + _MUTEX_RECURSIVE_NAMED_INITIALIZER( name ) + +static __inline void rtems_recursive_mutex_init( + rtems_recursive_mutex *mutex, const char *name +) +{ + _Mutex_recursive_Initialize_named( mutex, name ); +} + +static __inline const char *rtems_recursive_mutex_get_name( + const rtems_recursive_mutex *mutex +) +{ + return mutex->_Mutex._Queue._name; +} + +static __inline void rtems_recursive_mutex_set_name( + rtems_recursive_mutex *mutex, const char *name +) +{ + mutex->_Mutex._Queue._name = name; +} + +static __inline void rtems_recursive_mutex_lock( + rtems_recursive_mutex *mutex +) +{ + _Mutex_recursive_Acquire( mutex ); +} + +static __inline void rtems_recursive_mutex_unlock( + rtems_recursive_mutex *mutex +) +{ + _Mutex_recursive_Release( mutex ); +} + +static __inline void rtems_recursive_mutex_destroy( + rtems_recursive_mutex *mutex +) +{ + _Mutex_recursive_Destroy( mutex ); +} + +typedef struct _Condition_Control rtems_condition_variable; + +#define RTEMS_CONDITION_VARIABLE_INITIALIZER( name ) \ + _CONDITION_NAMED_INITIALIZER( name ) + +static __inline void rtems_condition_variable_init( + rtems_condition_variable *condition_variable, + const char *name +) +{ + _Condition_Initialize_named( condition_variable, name ); +} + +static __inline const char *rtems_condition_variable_get_name( + const rtems_condition_variable *condition_variable +) +{ + return condition_variable->_Queue._name; +} + +static __inline void rtems_condition_variable_set_name( + rtems_condition_variable *condition_variable, + const char *name +) +{ + condition_variable->_Queue._name = name; +} + +static __inline void rtems_condition_variable_wait( + rtems_condition_variable *condition_variable, + rtems_mutex *mutex +) +{ + _Condition_Wait( condition_variable, mutex ); +} + +static __inline void rtems_condition_variable_signal( + rtems_condition_variable *condition_variable +) +{ + _Condition_Broadcast( condition_variable ); +} + +static __inline void rtems_condition_variable_broadcast( + rtems_condition_variable *condition_variable +) +{ + _Condition_Broadcast( condition_variable ); +} + +static __inline void rtems_condition_variable_destroy( + rtems_condition_variable *condition_variable +) +{ + _Condition_Destroy( condition_variable ); +} + +typedef struct _Semaphore_Control rtems_counting_semaphore; + +#define RTEMS_COUNTING_SEMAPHORE_INITIALIZER( name, value ) \ + _SEMAPHORE_NAMED_INITIALIZER( name, value ) + +static __inline void rtems_counting_semaphore_init( + rtems_counting_semaphore *counting_semaphore, + const char *name, + unsigned int value +) +{ + _Semaphore_Initialize_named( counting_semaphore, name, value ); +} + +static __inline const char *rtems_counting_semaphore_get_name( + const rtems_counting_semaphore *counting_semaphore +) +{ + return counting_semaphore->_Queue._name; +} + +static __inline void rtems_counting_semaphore_set_name( + rtems_counting_semaphore *counting_semaphore, + const char *name +) +{ + counting_semaphore->_Queue._name = name; +} + +static __inline void rtems_counting_semaphore_wait( + rtems_counting_semaphore *counting_semaphore +) +{ + _Semaphore_Wait( counting_semaphore ); +} + +static __inline void rtems_counting_semaphore_post( + rtems_counting_semaphore *counting_semaphore +) +{ + _Semaphore_Post( counting_semaphore ); +} + +static __inline void rtems_counting_semaphore_destroy( + rtems_counting_semaphore *counting_semaphore +) +{ + _Semaphore_Destroy( counting_semaphore ); +} + +typedef struct { + struct _Semaphore_Control Semaphore; +} rtems_binary_semaphore; + +#define RTEMS_BINARY_SEMAPHORE_INITIALIZER( name ) \ + { _SEMAPHORE_NAMED_INITIALIZER( name, 0 ) } + +static __inline void rtems_binary_semaphore_init( + rtems_binary_semaphore *binary_semaphore, + const char *name +) +{ + _Semaphore_Initialize_named( &binary_semaphore->Semaphore, name, 0 ); +} + +static __inline const char *rtems_binary_semaphore_get_name( + const rtems_binary_semaphore *binary_semaphore +) +{ + return binary_semaphore->Semaphore._Queue._name; +} + +static __inline void rtems_binary_semaphore_set_name( + rtems_binary_semaphore *binary_semaphore, + const char *name +) +{ + binary_semaphore->Semaphore._Queue._name = name; +} + +static __inline void rtems_binary_semaphore_wait( + rtems_binary_semaphore *binary_semaphore +) +{ + _Semaphore_Wait( &binary_semaphore->Semaphore ); +} + +static __inline int rtems_binary_semaphore_wait_timed_ticks( + rtems_binary_semaphore *binary_semaphore, + uint32_t ticks +) +{ + return _Semaphore_Wait_timed_ticks( &binary_semaphore->Semaphore, ticks ); +} + +static __inline int rtems_binary_semaphore_try_wait( + rtems_binary_semaphore *binary_semaphore +) +{ + return _Semaphore_Try_wait( &binary_semaphore->Semaphore ); +} + +static __inline void rtems_binary_semaphore_post( + rtems_binary_semaphore *binary_semaphore +) +{ + _Semaphore_Post_binary( &binary_semaphore->Semaphore ); +} + +static __inline void rtems_binary_semaphore_destroy( + rtems_binary_semaphore *binary_semaphore +) +{ + _Semaphore_Destroy( &binary_semaphore->Semaphore ); +} + +__END_DECLS + +#endif /* _RTEMS_THREAD_H */ diff --git a/cpukit/score/src/semaphore.c b/cpukit/score/src/semaphore.c index 4edd25a387..f76ee332a4 100644 --- a/cpukit/score/src/semaphore.c +++ b/cpukit/score/src/semaphore.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * Copyright (c) 2015, 2017 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -18,8 +18,9 @@ #include <rtems/score/semaphoreimpl.h> #include <rtems/score/statesimpl.h> +#include <rtems/score/threadimpl.h> -#include <limits.h> +#include <errno.h> RTEMS_STATIC_ASSERT( offsetof( Sem_Control, Queue ) @@ -71,6 +72,66 @@ void _Semaphore_Wait( struct _Semaphore_Control *_sem ) } } +int _Semaphore_Wait_timed_ticks( struct _Semaphore_Control *_sem, uint32_t ticks ) +{ + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + Thread_Control *executing; + unsigned int count; + + sem = _Sem_Get( _sem ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + executing = _Sem_Queue_acquire_critical( sem, &queue_context ); + + count = sem->count; + if ( __predict_true( count > 0 ) ) { + sem->count = count - 1; + _Sem_Queue_release( sem, level, &queue_context ); + return 0; + } else { + _Thread_queue_Context_set_thread_state( + &queue_context, + STATES_WAITING_FOR_SEMAPHORE + ); + _Thread_queue_Context_set_enqueue_timeout_ticks( &queue_context, ticks ); + _Thread_queue_Context_set_ISR_level( &queue_context, level ); + _Thread_queue_Enqueue( + &sem->Queue.Queue, + SEMAPHORE_TQ_OPERATIONS, + executing, + &queue_context + ); + return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) ); + } +} + +int _Semaphore_Try_wait( struct _Semaphore_Control *_sem ) +{ + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + unsigned int count; + int eno; + + sem = _Sem_Get( _sem ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + _Sem_Queue_acquire_critical( sem, &queue_context ); + + count = sem->count; + if ( __predict_true( count > 0 ) ) { + sem->count = count - 1; + eno = 0; + } else { + eno = EAGAIN; + } + + _Sem_Queue_release( sem, level, &queue_context ); + return eno; +} + void _Semaphore_Post( struct _Semaphore_Control *_sem ) { Sem_Control *sem; @@ -85,7 +146,6 @@ void _Semaphore_Post( struct _Semaphore_Control *_sem ) heads = sem->Queue.Queue.heads; if ( __predict_true( heads == NULL ) ) { - _Assert( sem->count < UINT_MAX ); ++sem->count; _Sem_Queue_release( sem, level, &queue_context ); } else { @@ -104,3 +164,36 @@ void _Semaphore_Post( struct _Semaphore_Control *_sem ) ); } } + +void _Semaphore_Post_binary( struct _Semaphore_Control *_sem ) +{ + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + Thread_queue_Heads *heads; + + sem = _Sem_Get( _sem ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + _Sem_Queue_acquire_critical( sem, &queue_context ); + + heads = sem->Queue.Queue.heads; + if ( __predict_true( heads == NULL ) ) { + sem->count = 1; + _Sem_Queue_release( sem, level, &queue_context ); + } else { + const Thread_queue_Operations *operations; + Thread_Control *first; + + _Thread_queue_Context_set_ISR_level( &queue_context, level ); + operations = SEMAPHORE_TQ_OPERATIONS; + first = ( *operations->first )( heads ); + + _Thread_queue_Extract_critical( + &sem->Queue.Queue, + operations, + first, + &queue_context + ); + } +} |