--- /dev/null
+#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
--- /dev/null
+#ifndef REGTEST
+#include <threads.h>
+#include <pthread.h>
+
+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
#include <limits.h>
#ifndef REGTEST
+#include <threads.h>
/* In a POSIX system, stdin / stdout / stderr are equivalent to the (int) file
descriptors 0, 1, and 2 respectively.
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;