From d293fb98fe80a472ad4d11b4d8a1413d2142064a Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Thu, 27 Dec 2012 21:49:28 +0000 Subject: [PATCH] Add pthreads threading backend and move the POSIX port over to using it --- opt/pthreads/_PDCLIB_threadconfig.h | 23 +++++++++ opt/pthreads/call_once.c | 38 +++++++++++++++ opt/pthreads/mtx_destroy.c | 19 ++++++++ opt/pthreads/mtx_init.c | 44 +++++++++++++++++ opt/pthreads/mtx_lock.c | 21 +++++++++ opt/pthreads/mtx_timedlock.c | 38 +++++++++++++++ opt/pthreads/mtx_trylock.c | 27 +++++++++++ opt/pthreads/mtx_unlock.c | 21 +++++++++ platform/posix/Config.jam | 2 +- platform/posix/functions/_PDCLIB/stdinit.c | 55 ++++++++++++++++++++-- platform/posix/internals/_PDCLIB_config.h | 2 +- 11 files changed, 285 insertions(+), 5 deletions(-) create mode 100644 opt/pthreads/_PDCLIB_threadconfig.h create mode 100644 opt/pthreads/call_once.c create mode 100644 opt/pthreads/mtx_destroy.c create mode 100644 opt/pthreads/mtx_init.c create mode 100644 opt/pthreads/mtx_lock.c create mode 100644 opt/pthreads/mtx_timedlock.c create mode 100644 opt/pthreads/mtx_trylock.c create mode 100644 opt/pthreads/mtx_unlock.c diff --git a/opt/pthreads/_PDCLIB_threadconfig.h b/opt/pthreads/_PDCLIB_threadconfig.h new file mode 100644 index 0000000..75e6f3a --- /dev/null +++ b/opt/pthreads/_PDCLIB_threadconfig.h @@ -0,0 +1,23 @@ +#ifndef _PDCLIB_THREADCONFIG_H +#define _PDCLIB_THREADCONFIG_H +#include <_PDCLIB_aux.h> +#include <_PDCLIB_config.h> + +#ifdef __APPLE__ +#include <_types.h> +#define _PDCLIB_THR_T __darwin_pthread_t +#define _PDCLIB_CND_T __darwin_pthread_cond_t +#define _PDCLIB_MTX_T __darwin_pthread_mutex_t + +#define _PDCLIB_TSS_DTOR_ITERATIONS 5 +#define _PDCLIB_TSS_T __darwin_pthread_key_t + +typedef __darwin_pthread_once_t _PDCLIB_once_flag; +#define _PDCLIB_ONCE_FLAG_INIT {_PTHREAD_ONCE_SIG_init, {0}} + +#else +#error Need to interrogate the C library headers for your platform +#endif + +_PDCLIB_END_EXTERN_C +#endif diff --git a/opt/pthreads/call_once.c b/opt/pthreads/call_once.c new file mode 100644 index 0000000..123ad3a --- /dev/null +++ b/opt/pthreads/call_once.c @@ -0,0 +1,38 @@ +#ifndef REGTEST +#include +#include + +void call_once(once_flag *flag, void (*func)(void)) +{ + pthread_once(flag, func); +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +#ifndef REGTEST +static int count = 0; +static once_flag once = ONCE_FLAG_INIT; + +static void do_once(void) +{ + count++; +} +#endif + +int main( void ) +{ +#ifndef REGTEST + TESTCASE(count == 0); + call_once(&once, do_once); + TESTCASE(count == 1); + call_once(&once, do_once); + TESTCASE(count == 1); + do_once(); + TESTCASE(count == 2); +#endif + return TEST_RESULTS; +} + +#endif diff --git a/opt/pthreads/mtx_destroy.c b/opt/pthreads/mtx_destroy.c new file mode 100644 index 0000000..2d0a2a2 --- /dev/null +++ b/opt/pthreads/mtx_destroy.c @@ -0,0 +1,19 @@ +#ifndef REGTEST +#include +#include + +void mtx_destroy(mtx_t *mtx) +{ + pthread_mutex_destroy(mtx); +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif diff --git a/opt/pthreads/mtx_init.c b/opt/pthreads/mtx_init.c new file mode 100644 index 0000000..90c67e6 --- /dev/null +++ b/opt/pthreads/mtx_init.c @@ -0,0 +1,44 @@ +#ifndef REGTEST +#include +#include + +int mtx_init(mtx_t *mtx, int type) +{ + if(type == mtx_plain || type == mtx_timed) { + if(pthread_mutex_init(mtx, NULL) == 0) + return thrd_success; + else + return thrd_error; + + } else if (type == mtx_recursive || type == (mtx_recursive | mtx_timed)) { + int rc = thrd_error; + pthread_mutexattr_t attr; + + if(pthread_mutexattr_init(&attr)) + goto cleanup1; + + if(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) + goto cleanup2; + + if(pthread_mutex_init(mtx, &attr) == 0) + rc = thrd_success; + + cleanup2: + pthread_mutexattr_destroy(&attr); + cleanup1: + return rc; + } else { + return thrd_error; + } +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif diff --git a/opt/pthreads/mtx_lock.c b/opt/pthreads/mtx_lock.c new file mode 100644 index 0000000..88a1304 --- /dev/null +++ b/opt/pthreads/mtx_lock.c @@ -0,0 +1,21 @@ +#ifndef REGTEST +#include +#include + +int mtx_lock(mtx_t *mtx) +{ + if(pthread_mutex_lock(mtx)) + return thrd_error; + else return thrd_success; +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif diff --git a/opt/pthreads/mtx_timedlock.c b/opt/pthreads/mtx_timedlock.c new file mode 100644 index 0000000..ed490a8 --- /dev/null +++ b/opt/pthreads/mtx_timedlock.c @@ -0,0 +1,38 @@ +#ifndef REGTEST +#include +// On Mac OS X, supress system definition of struct timespec +#ifdef __APPLE__ + #define _STRUCT_TIMESPEC struct timespec +#endif +#include +#include + +/* Can only implement if timeouts are supported. + * + * Namely, Mac OS X does not implement timeouts + */ +#if defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS - 200112L) >= 0L +int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts) +{ + switch(pthread_mutex_timedlock(mtx, ts)) { + case 0: + return thrd_success; + case ETIMEDOUT: + return thrd_timeout; + default: + return thrd_error; + } +} +#endif + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif diff --git a/opt/pthreads/mtx_trylock.c b/opt/pthreads/mtx_trylock.c new file mode 100644 index 0000000..8a095a5 --- /dev/null +++ b/opt/pthreads/mtx_trylock.c @@ -0,0 +1,27 @@ +#ifndef REGTEST +#include +#include +#include + +int mtx_trylock(mtx_t *mtx) +{ + switch(pthread_mutex_trylock(mtx)) { + case 0: + return thrd_success; + case EBUSY: + return thrd_busy; + default: + return thrd_error; + } +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif diff --git a/opt/pthreads/mtx_unlock.c b/opt/pthreads/mtx_unlock.c new file mode 100644 index 0000000..0da592a --- /dev/null +++ b/opt/pthreads/mtx_unlock.c @@ -0,0 +1,21 @@ +#ifndef REGTEST +#include +#include + +int mtx_unlock(mtx_t *mtx) +{ + if(pthread_mutex_unlock(mtx) == 0) + return thrd_success; + return thrd_error; +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif diff --git a/platform/posix/Config.jam b/platform/posix/Config.jam index f068ce6..20fc4ad 100644 --- a/platform/posix/Config.jam +++ b/platform/posix/Config.jam @@ -11,4 +11,4 @@ if $(OS) = "MACOSX" { PDCLIB_TEST_LINKLIBS += -lgcc ; } -PDCLIB_OPTIONS = nothread notime dlmalloc ; \ No newline at end of file +PDCLIB_OPTIONS = pthreads notime dlmalloc ; \ No newline at end of file diff --git a/platform/posix/functions/_PDCLIB/stdinit.c b/platform/posix/functions/_PDCLIB/stdinit.c index 8400ce3..a3c9e8b 100644 --- a/platform/posix/functions/_PDCLIB/stdinit.c +++ b/platform/posix/functions/_PDCLIB/stdinit.c @@ -16,6 +16,7 @@ #include #ifndef REGTEST +#include /* In a POSIX system, stdin / stdout / stderr are equivalent to the (int) file descriptors 0, 1, and 2 respectively. @@ -30,14 +31,62 @@ static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; extern _PDCLIB_fileops_t _PDCLIB_fileops; -static struct _PDCLIB_file_t _PDCLIB_serr = { &_PDCLIB_fileops, { .sval = 2 }, 0, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; -static struct _PDCLIB_file_t _PDCLIB_sout = { &_PDCLIB_fileops, { .sval = 1 }, 0, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; -static struct _PDCLIB_file_t _PDCLIB_sin = { &_PDCLIB_fileops, { .sval = 0 }, 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; + +static struct _PDCLIB_file_t _PDCLIB_serr = { + .ops = &_PDCLIB_fileops, + .handle = { .sval = 2 }, + .buffer = _PDCLIB_serr_buffer, + .bufsize = BUFSIZ, + .bufidx = 0, + .bufend = 0, + .pos = { 0, 0 }, + .ungetidx = 0, + .ungetbuf = _PDCLIB_serr_ungetbuf, + .status = _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, + .filename = NULL, + .next = NULL, +}; +static struct _PDCLIB_file_t _PDCLIB_sout = { + .ops = &_PDCLIB_fileops, + .handle = { .sval = 1 }, + .buffer = _PDCLIB_sout_buffer, + .bufsize = BUFSIZ, + .bufidx = 0, + .bufend = 0, + .pos = { 0, 0 }, + .ungetidx = 0, + .ungetbuf = _PDCLIB_sout_ungetbuf, + .status = _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, + .filename = NULL, + .next = &_PDCLIB_serr +}; +static struct _PDCLIB_file_t _PDCLIB_sin = { + .ops = &_PDCLIB_fileops, + .handle = { .sval = 0 }, + .buffer = _PDCLIB_sin_buffer, + .bufsize = BUFSIZ, + .bufidx = 0, + .bufend = 0, + .pos = { 0, 0 }, + .ungetidx = 0, + .ungetbuf = _PDCLIB_sin_ungetbuf, + .status = _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, + .filename = NULL, + .next = &_PDCLIB_sout +}; struct _PDCLIB_file_t * stdin = &_PDCLIB_sin; struct _PDCLIB_file_t * stdout = &_PDCLIB_sout; struct _PDCLIB_file_t * stderr = &_PDCLIB_serr; +/* Todo: Better solution than this! */ +__attribute__((constructor)) void init_stdio(void) +{ + mtx_init(&stdin->lock, mtx_recursive); + mtx_init(&stdout->lock, mtx_recursive); + mtx_init(&stderr->lock, mtx_recursive); +} + /* FIXME: This approach is a possible attack vector. */ struct _PDCLIB_file_t * _PDCLIB_filelist = &_PDCLIB_sin; diff --git a/platform/posix/internals/_PDCLIB_config.h b/platform/posix/internals/_PDCLIB_config.h index 5cee1ef..099e970 100644 --- a/platform/posix/internals/_PDCLIB_config.h +++ b/platform/posix/internals/_PDCLIB_config.h @@ -186,7 +186,7 @@ struct _PDCLIB_imaxdiv_t * any functions for manipulating more accurate values of time_t, this is * probably not useful. */ -#define _PDCLIB_time unsigned long long +#define _PDCLIB_time long /* : clock_t * -- 2.40.0