diff options
Diffstat (limited to 'rts/posix/OSThreads.c')
-rw-r--r-- | rts/posix/OSThreads.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/rts/posix/OSThreads.c b/rts/posix/OSThreads.c new file mode 100644 index 0000000000..07bd762130 --- /dev/null +++ b/rts/posix/OSThreads.c @@ -0,0 +1,166 @@ +/* --------------------------------------------------------------------------- + * + * (c) The GHC Team, 2001-2005 + * + * Accessing OS threads functionality in a (mostly) OS-independent + * manner. + * + * --------------------------------------------------------------------------*/ + +#if defined(DEBUG) && defined(__linux__) +/* We want GNU extensions in DEBUG mode for mutex error checking */ +#define _GNU_SOURCE +#endif + +#include "Rts.h" +#if defined(THREADED_RTS) +#include "OSThreads.h" +#include "RtsUtils.h" + +#if HAVE_STRING_H +#include <string.h> +#endif + +#if !defined(HAVE_PTHREAD_H) +#error pthreads.h is required for the threaded RTS on Posix platforms +#endif + +/* + * This (allegedly) OS threads independent layer was initially + * abstracted away from code that used Pthreads, so the functions + * provided here are mostly just wrappers to the Pthreads API. + * + */ + +void +initCondition( Condition* pCond ) +{ + pthread_cond_init(pCond, NULL); + return; +} + +void +closeCondition( Condition* pCond ) +{ + pthread_cond_destroy(pCond); + return; +} + +rtsBool +broadcastCondition ( Condition* pCond ) +{ + return (pthread_cond_broadcast(pCond) == 0); +} + +rtsBool +signalCondition ( Condition* pCond ) +{ + return (pthread_cond_signal(pCond) == 0); +} + +rtsBool +waitCondition ( Condition* pCond, Mutex* pMut ) +{ + return (pthread_cond_wait(pCond,pMut) == 0); +} + +void +yieldThread() +{ + sched_yield(); + return; +} + +void +shutdownThread() +{ + pthread_exit(NULL); +} + +int +createOSThread (OSThreadId* pId, OSThreadProc *startProc, void *param) +{ + int result = pthread_create(pId, NULL, (void *(*)(void *))startProc, param); + if(!result) + pthread_detach(*pId); + return result; +} + +OSThreadId +osThreadId() +{ + return pthread_self(); +} + +void +initMutex(Mutex* pMut) +{ +#if defined(DEBUG) && defined(linux_HOST_OS) + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK_NP); + pthread_mutex_init(pMut,&attr); +#else + pthread_mutex_init(pMut,NULL); +#endif + return; +} + +void +newThreadLocalKey (ThreadLocalKey *key) +{ + int r; + if ((r = pthread_key_create(key, NULL)) != 0) { + barf("newThreadLocalKey: %s", strerror(r)); + } +} + +void * +getThreadLocalVar (ThreadLocalKey *key) +{ + return pthread_getspecific(*key); + // Note: a return value of NULL can indicate that either the key + // is not valid, or the key is valid and the data value has not + // yet been set. We need to use the latter case, so we cannot + // detect errors here. +} + +void +setThreadLocalVar (ThreadLocalKey *key, void *value) +{ + int r; + if ((r = pthread_setspecific(*key,value)) != 0) { + barf("setThreadLocalVar: %s", strerror(r)); + } +} + +static void * +forkOS_createThreadWrapper ( void * entry ) +{ + Capability *cap; + cap = rts_lock(); + cap = rts_evalStableIO(cap, (HsStablePtr) entry, NULL); + rts_unlock(cap); + return NULL; +} + +int +forkOS_createThread ( HsStablePtr entry ) +{ + pthread_t tid; + int result = pthread_create(&tid, NULL, + forkOS_createThreadWrapper, (void*)entry); + if(!result) + pthread_detach(tid); + return result; +} + +#else /* !defined(THREADED_RTS) */ + +int +forkOS_createThread ( HsStablePtr entry STG_UNUSED ) +{ + return -1; +} + +#endif /* !defined(THREADED_RTS) */ |