forked from Imagelibrary/rtems
RTEMS specific thread support for G++. This implementation
includes RTEMS wrappers invoked by gcc. The beauty of this is that it puts the implementation in our hands. :) It uses a mutex ( semaphore ), and task variables simulating the "keys" for each task. Thanks to Rosimildo da Silva <rdasilva@connectel.com> for submitting this.
This commit is contained in:
@@ -7,7 +7,9 @@ AUTOMAKE_OPTIONS = foreign 1.4
|
|||||||
## RTEMS unistd.h needs to be checked against newlib's and removed
|
## RTEMS unistd.h needs to be checked against newlib's and removed
|
||||||
UNUSED_H_FILES = devctl.h intr.h unistd.h
|
UNUSED_H_FILES = devctl.h intr.h unistd.h
|
||||||
|
|
||||||
H_FILES = pthread.h sched.h aio.h mqueue.h semaphore.h
|
H_FILES = sched.h aio.h mqueue.h semaphore.h
|
||||||
|
|
||||||
|
# H_FILES = pthread.h sched.h aio.h mqueue.h semaphore.h
|
||||||
|
|
||||||
noinst_HEADERS = $(H_FILES)
|
noinst_HEADERS = $(H_FILES)
|
||||||
|
|
||||||
|
|||||||
@@ -1,509 +0,0 @@
|
|||||||
/* pthread.h
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __PTHREAD_h
|
|
||||||
#define __PTHREAD_h
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/features.h>
|
|
||||||
|
|
||||||
#if defined(_POSIX_THREADS)
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/sched.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
|
|
||||||
*
|
|
||||||
* RTEMS does not support processes, so we fall under this and do not
|
|
||||||
* provide this routine:
|
|
||||||
*
|
|
||||||
* "Either the implementation shall support the pthread_atfork() function
|
|
||||||
* as described above or the pthread_atfork() funciton shall not be
|
|
||||||
* provided."
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_mutexattr_init(
|
|
||||||
pthread_mutexattr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutexattr_destroy(
|
|
||||||
pthread_mutexattr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutexattr_getpshared(
|
|
||||||
const pthread_mutexattr_t *attr,
|
|
||||||
int *pshared
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutexattr_setpshared(
|
|
||||||
pthread_mutexattr_t *attr,
|
|
||||||
int pshared
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_mutex_init(
|
|
||||||
pthread_mutex_t *mutex,
|
|
||||||
const pthread_mutexattr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutex_destroy(
|
|
||||||
pthread_mutex_t *mutex
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is used to statically initialize a pthread_mutex_t. Example:
|
|
||||||
*
|
|
||||||
* pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
|
|
||||||
*
|
|
||||||
* NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_mutex_lock(
|
|
||||||
pthread_mutex_t *mutex
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutex_trylock(
|
|
||||||
pthread_mutex_t *mutex
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutex_unlock(
|
|
||||||
pthread_mutex_t *mutex
|
|
||||||
);
|
|
||||||
|
|
||||||
#if defined(_POSIX_TIMEOUTS)
|
|
||||||
|
|
||||||
int pthread_mutex_timedlock(
|
|
||||||
pthread_mutex_t *mutex,
|
|
||||||
const struct timespec *timeout
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* _POSIX_TIMEOUTS */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 11.4.1 Condition Variable Initialization Attributes,
|
|
||||||
* P1003.1c/Draft 10, p. 96
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_condattr_init(
|
|
||||||
pthread_condattr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_condattr_destroy(
|
|
||||||
pthread_condattr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_condattr_getpshared(
|
|
||||||
const pthread_condattr_t *attr,
|
|
||||||
int *pshared
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_condattr_setpshared(
|
|
||||||
pthread_condattr_t *attr,
|
|
||||||
int pshared
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 11.4.2 Initializing and Destroying a Condition Variable,
|
|
||||||
* P1003.1c/Draft 10, p. 87
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_cond_init(
|
|
||||||
pthread_cond_t *cond,
|
|
||||||
const pthread_condattr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_cond_destroy(
|
|
||||||
pthread_cond_t *mutex
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is used to statically initialize a pthread_cond_t. Example:
|
|
||||||
*
|
|
||||||
* pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PTHREAD_COND_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_cond_signal(
|
|
||||||
pthread_cond_t *cond
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_cond_broadcast(
|
|
||||||
pthread_cond_t *cond
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_cond_wait(
|
|
||||||
pthread_cond_t *cond,
|
|
||||||
pthread_mutex_t *mutex
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_cond_timedwait(
|
|
||||||
pthread_cond_t *cond,
|
|
||||||
pthread_mutex_t *mutex,
|
|
||||||
const struct timespec *abstime
|
|
||||||
);
|
|
||||||
|
|
||||||
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_attr_setscope(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
int contentionscope
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getscope(
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
int *contentionscope
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_setinheritsched(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
int inheritsched
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getinheritsched(
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
int *inheritsched
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_setschedpolicy(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
int policy
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getschedpolicy(
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
int *policy
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */
|
|
||||||
|
|
||||||
int pthread_attr_setschedparam(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
const struct sched_param *param
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getschedparam(
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
struct sched_param *param
|
|
||||||
);
|
|
||||||
|
|
||||||
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 13.5.2 Dynamic Thread Scheduling Parameters Access,
|
|
||||||
* P1003.1c/Draft 10, p. 124
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_getschedparam(
|
|
||||||
pthread_t thread,
|
|
||||||
int *policy,
|
|
||||||
struct sched_param *param
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_setschedparam(
|
|
||||||
pthread_t thread,
|
|
||||||
int policy,
|
|
||||||
struct sched_param *param
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */
|
|
||||||
|
|
||||||
#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_mutexattr_setprotocol(
|
|
||||||
pthread_mutexattr_t *attr,
|
|
||||||
int protocol
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutexattr_getprotocol(
|
|
||||||
const pthread_mutexattr_t *attr,
|
|
||||||
int *protocol
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutexattr_setprioceiling(
|
|
||||||
pthread_mutexattr_t *attr,
|
|
||||||
int prioceiling
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutexattr_getprioceiling(
|
|
||||||
const pthread_mutexattr_t *attr,
|
|
||||||
int *prioceiling
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* _POSIX_THREAD_PRIO_INHERIT || _POSIX_THREAD_PRIO_PROTECT */
|
|
||||||
|
|
||||||
#if defined(_POSIX_THREAD_PRIO_PROTECT)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_mutex_setprioceiling(
|
|
||||||
pthread_mutex_t *mutex,
|
|
||||||
int prioceiling,
|
|
||||||
int *old_ceiling
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_mutex_getprioceiling(
|
|
||||||
pthread_mutex_t *mutex,
|
|
||||||
int *prioceiling
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* _POSIX_THREAD_PRIO_PROTECT */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_attr_init(
|
|
||||||
pthread_attr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_destroy(
|
|
||||||
pthread_attr_t *attr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getstacksize(
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
size_t *stacksize
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_setstacksize(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
size_t stacksize
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getstackaddr(
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
void **stackaddr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_setstackaddr(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
void *stackaddr
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getdetachstate(
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
int *detachstate
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_setdetachstate(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
int detachstate
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_create(
|
|
||||||
pthread_t *thread,
|
|
||||||
const pthread_attr_t *attr,
|
|
||||||
void *(*start_routine)( void * ),
|
|
||||||
void *arg
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_join(
|
|
||||||
pthread_t thread,
|
|
||||||
void **value_ptr
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_detach(
|
|
||||||
pthread_t thread
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
|
|
||||||
*/
|
|
||||||
|
|
||||||
void pthread_exit(
|
|
||||||
void *value_ptr
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX
|
|
||||||
*/
|
|
||||||
|
|
||||||
pthread_t pthread_self( void );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_equal(
|
|
||||||
pthread_t t1,
|
|
||||||
pthread_t t2
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16.1.8 Dynamic Package Initialization
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is used to statically initialize a pthread_once_t. Example:
|
|
||||||
*
|
|
||||||
* pthread_once_t once = PTHREAD_ONCE_INIT;
|
|
||||||
*
|
|
||||||
* NOTE: This is named inconsistently -- it should be INITIALIZER.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PTHREAD_ONCE_INIT { 1, 0 } /* is initialized and not run */
|
|
||||||
|
|
||||||
int pthread_once(
|
|
||||||
pthread_once_t *once_control,
|
|
||||||
void (*init_routine)(void)
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_key_create(
|
|
||||||
pthread_key_t *key,
|
|
||||||
void (*destructor)( void * )
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_setspecific(
|
|
||||||
pthread_key_t key,
|
|
||||||
const void *value
|
|
||||||
);
|
|
||||||
|
|
||||||
void *pthread_getspecific(
|
|
||||||
pthread_key_t key
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_key_delete(
|
|
||||||
pthread_key_t key
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 18.2.1 Canceling Execution of a Thread, P1003.1c/Draft 10, p. 181
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PTHREAD_CANCEL_ENABLE 0
|
|
||||||
#define PTHREAD_CANCEL_DISABLE 1
|
|
||||||
|
|
||||||
#define PTHREAD_CANCEL_DEFERRED 0
|
|
||||||
#define PTHREAD_CANCEL_ASYNCHRONOUS 1
|
|
||||||
|
|
||||||
int pthread_cancel(
|
|
||||||
pthread_t thread
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_setcancelstate(
|
|
||||||
int state,
|
|
||||||
int *oldstate
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_setcanceltype(
|
|
||||||
int type,
|
|
||||||
int *oldtype
|
|
||||||
);
|
|
||||||
|
|
||||||
void pthread_testcancel( void );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184
|
|
||||||
*/
|
|
||||||
|
|
||||||
void pthread_cleanup_push(
|
|
||||||
void (*routine)( void * ),
|
|
||||||
void *arg
|
|
||||||
);
|
|
||||||
|
|
||||||
void pthread_cleanup_pop(
|
|
||||||
int execute
|
|
||||||
);
|
|
||||||
|
|
||||||
#if defined(_POSIX_THREAD_CPUTIME)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_getcpuclockid(
|
|
||||||
pthread_t thread_id,
|
|
||||||
clockid_t *clock_id
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pthread_attr_setcputime(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
int clock_allowed
|
|
||||||
);
|
|
||||||
|
|
||||||
int pthread_attr_getcputime(
|
|
||||||
pthread_attr_t *attr,
|
|
||||||
int *clock_allowed
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* defined(_POSIX_THREAD_CPUTIME) */
|
|
||||||
|
|
||||||
#endif /* defined(_POSIX_THREADS) */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/* end of include file */
|
|
||||||
@@ -48,7 +48,7 @@ LIBC_GLUE_C_FILES = __getpid.c __gettod.c __times.c truncate.c access.c \
|
|||||||
|
|
||||||
UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
|
UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
|
||||||
|
|
||||||
COMMON_C_FILES = $(BASE_FS_C_FILES) $(MALLOC_C_FILES) $(TERMIOS_C_FILES) \
|
COMMON_C_FILES = gxx_wrappers.c $(BASE_FS_C_FILES) $(MALLOC_C_FILES) $(TERMIOS_C_FILES) \
|
||||||
$(ERROR_C_FILES) $(ASSOCIATION_C_FILES)
|
$(ERROR_C_FILES) $(ASSOCIATION_C_FILES)
|
||||||
|
|
||||||
UNIX_C_FILES = $(UNIX_LIBC_C_FILES) imfs_unixstub.c
|
UNIX_C_FILES = $(UNIX_LIBC_C_FILES) imfs_unixstub.c
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* RTEMS threads compatibily routines for libgcc2.
|
||||||
|
*
|
||||||
|
* by: Rosimildo da Silva ( rdasilva@connecttel.com
|
||||||
|
*
|
||||||
|
* Used ideas from:
|
||||||
|
* W. Eric Norum
|
||||||
|
* Canadian Light Source
|
||||||
|
* University of Saskatchewan
|
||||||
|
* Saskatoon, Saskatchewan, CANADA
|
||||||
|
* eric@cls.usask.ca
|
||||||
|
*
|
||||||
|
* Eric sent some e-mail in the rtems-list as a start point for this
|
||||||
|
* module implementation.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We might not need, defined just in case */
|
||||||
|
#define __RTEMS_INSIDE__ 1
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/system.h>
|
||||||
|
#include <rtems/rtems/tasks.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These typedefs should match with the ones defined in the file
|
||||||
|
* gcc/gthr-rtems.h in the gcc distribution.
|
||||||
|
*/
|
||||||
|
typedef void *__gthread_key_t;
|
||||||
|
typedef int __gthread_once_t;
|
||||||
|
typedef void *__gthread_mutex_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* uncomment this if you need to debug this interface */
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define DEBUG_GXX_WRAPPERS 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* prototype for the terminate() */
|
||||||
|
extern void __terminate( void );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
/* local function to return the ID of the calling thread */
|
||||||
|
static rtems_id get_tid( void )
|
||||||
|
{
|
||||||
|
rtems_id id = 0;
|
||||||
|
rtems_task_ident( RTEMS_SELF, 0, &id );
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int rtems_gxx_once(__gthread_once_t *once, void (*func) ())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: once=%x, func=%x\n", *once, func );
|
||||||
|
#endif
|
||||||
|
if( *once == 0 )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* NOTE: could not use the call to disable "preemption", it causes
|
||||||
|
* one exception. Somebody might want to investiage it further
|
||||||
|
* sometime later.
|
||||||
|
*/
|
||||||
|
_Thread_Disable_dispatch();
|
||||||
|
*once = 1;
|
||||||
|
(*func)();
|
||||||
|
_Thread_Enable_dispatch();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *))
|
||||||
|
{
|
||||||
|
/* Ok, this can be a bit tricky. We are going to return a "key" as a
|
||||||
|
* pointer to the buffer that will hold the value of the key itself.
|
||||||
|
* We have to to this, becuase the others functions on this interface
|
||||||
|
* deal with the value of the key, as used with the POSIX API.
|
||||||
|
*/
|
||||||
|
/* Do not pull your hair, trust me this works. :-) */
|
||||||
|
__gthread_key_t *new_key = ( __gthread_key_t * )malloc( sizeof( __gthread_key_t ) );
|
||||||
|
*key = ( __gthread_key_t )new_key;
|
||||||
|
*new_key = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key );
|
||||||
|
#endif
|
||||||
|
/* register with RTEMS the buffer that will hold the key values */
|
||||||
|
if( rtems_task_variable_add( RTEMS_SELF, (void **)new_key, NULL ) == RTEMS_SUCCESSFUL )
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtems_gxx_key_dtor (__gthread_key_t key, void *ptr)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: dtor key=%x, ptr=%x\n", key, ptr );
|
||||||
|
#endif
|
||||||
|
*(void **)key = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtems_gxx_key_delete (__gthread_key_t key)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: delete key=%x\n", key );
|
||||||
|
#endif
|
||||||
|
/* register with RTEMS the buffer that will hold the key values */
|
||||||
|
if( rtems_task_variable_delete( RTEMS_SELF, (void **)key ) == RTEMS_SUCCESSFUL )
|
||||||
|
{
|
||||||
|
if( key ) free( (void *)key );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *rtems_gxx_getspecific(__gthread_key_t key)
|
||||||
|
{
|
||||||
|
void *p= 0;
|
||||||
|
|
||||||
|
/* register with RTEMS the buffer that will hold the key values */
|
||||||
|
if( rtems_task_variable_get( RTEMS_SELF, (void **)key, &p ) == RTEMS_SUCCESSFUL )
|
||||||
|
{
|
||||||
|
/* We do not have to do this, but what the heck ! */
|
||||||
|
p= *( void **)key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fisrt time, always set to zero, it is unknown the value that the others
|
||||||
|
* threads are using at the moment of this call
|
||||||
|
*/
|
||||||
|
if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) != RTEMS_SUCCESSFUL )
|
||||||
|
{
|
||||||
|
__terminate ();
|
||||||
|
}
|
||||||
|
*( void ** )key = (void *)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: getspecific key=%x, ptr=%x, id=%x\n", key, p, get_tid() );
|
||||||
|
#endif
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int rtems_gxx_setspecific(__gthread_key_t key, const void *ptr)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n", key, ptr, get_tid() );
|
||||||
|
#endif
|
||||||
|
/* register with RTEMS the buffer that will hold the key values */
|
||||||
|
if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) == RTEMS_SUCCESSFUL )
|
||||||
|
{
|
||||||
|
/* now let's set the proper value */
|
||||||
|
*( void ** )key = (void *)ptr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MUTEX support
|
||||||
|
*/
|
||||||
|
void rtems_gxx_mutex_init (__gthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: mutex init =%X\n", *mutex );
|
||||||
|
#endif
|
||||||
|
if( rtems_semaphore_create( rtems_build_name ('G', 'C', 'C', '2'),
|
||||||
|
1,
|
||||||
|
RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE
|
||||||
|
|RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL,
|
||||||
|
0,
|
||||||
|
(rtems_id *)mutex ) != RTEMS_SUCCESSFUL )
|
||||||
|
{
|
||||||
|
__terminate ();
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: mutex init complete =%X\n", *mutex );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtems_gxx_mutex_lock (__gthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: lock mutex=%X\n", *mutex );
|
||||||
|
#endif
|
||||||
|
return ( rtems_semaphore_obtain( (rtems_id)*mutex,
|
||||||
|
RTEMS_WAIT, RTEMS_NO_TIMEOUT ) == RTEMS_SUCCESSFUL) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtems_gxx_mutex_trylock (__gthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: trylock mutex=%X\n", *mutex );
|
||||||
|
#endif
|
||||||
|
return (rtems_semaphore_obtain ((rtems_id)*mutex,
|
||||||
|
RTEMS_NO_WAIT, 0) == RTEMS_SUCCESSFUL) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtems_gxx_mutex_unlock (__gthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_GXX_WRAPPERS
|
||||||
|
printk( "gxx_wrappers: unlock mutex=%X\n", *mutex );
|
||||||
|
#endif
|
||||||
|
return (rtems_semaphore_release( (rtems_id)*mutex ) == RTEMS_SUCCESSFUL) ? 0 :-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user