#include "xbt/xbt_thread.h" /* This module */
#include "xbt_modinter.h" /* Initialization/finalization of this module */
+
+
+/* ********************************* PTHREAD IMPLEMENTATION ************************************ */
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
typedef struct xbt_thread_ {
pthread_t t;
+ void *param;
+ pvoid_f_pvoid_t *start_routine;
} s_xbt_thread_t ;
+/* thread-specific data containing the xbt_thread_t structure */
+static pthread_key_t xbt_self_thread_key;
+
/* frees the xbt_thread_t corresponding to the current thread */
static void xbt_thread_free_thread_data(void*d){
free(d);
}
-pthread_key_t thread_data; /* thread-specific data containing the xbt_thread_t structure */
void xbt_thread_mod_init(void) {
int errcode;
- if ((errcode=pthread_key_create(&thread_data, &xbt_thread_free_thread_data)))
- THROW0(system_error,errcode,"pthread_key_create failed for thread_data");
+ if ((errcode=pthread_key_create(&xbt_self_thread_key, NULL)))
+ THROW0(system_error,errcode,"pthread_key_create failed for xbt_self_thread_key");
}
void xbt_thread_mod_exit(void) {
- int errcode;
+ /* FIXME: don't try to free our key on shutdown. Valgrind detects no leak if we don't, and whine if we try to */
+// int errcode;
- if ((errcode=pthread_key_delete(thread_data)))
- THROW0(system_error,errcode,"pthread_key_delete failed for thread_data");
+// if ((errcode=pthread_key_delete(xbt_self_thread_key)))
+// THROW0(system_error,errcode,"pthread_key_delete failed for xbt_self_thread_key");
}
+static void * wrapper_start_routine(void *s) {
+ xbt_thread_t t = s;
+ int errcode;
+
+ if ((errcode=pthread_setspecific(xbt_self_thread_key,t)))
+ THROW0(system_error,errcode,"pthread_setspecific failed for xbt_self_thread_key");
+ return t->start_routine(t->param);
+}
xbt_thread_t xbt_thread_create(pvoid_f_pvoid_t start_routine,
void* param) {
- xbt_thread_t res = xbt_new(s_xbt_thread_t,1);
int errcode;
- if ((errcode=pthread_setspecific(thread_data,res)))
- THROW0(system_error,errcode,"pthread_setspecific failed for thread_data");
-
- if ((errcode = pthread_create(&(res->t), NULL, start_routine, param)))
- THROW0(system_error,errcode, "pthread_create failed");
+ xbt_thread_t res_thread=xbt_new(s_xbt_thread_t,1);
+ res_thread->start_routine = start_routine;
+ res_thread->param = param;
+
- return res;
+ if ((errcode = pthread_create(&(res_thread->t), NULL, wrapper_start_routine, res_thread)))
+ THROW0(system_error,errcode, "pthread_create failed");
+
+ return res_thread;
+}
+
+void
+xbt_thread_join(xbt_thread_t thread,void ** thread_return) {
+
+ int errcode;
+
+ if ((errcode = pthread_join(thread->t,thread_return)))
+ THROW0(system_error,errcode, "pthread_join failed");
}
+
void xbt_thread_exit(int *retval) {
pthread_exit(retval);
}
+
xbt_thread_t xbt_thread_self(void) {
- return pthread_getspecific(thread_data);
+ return pthread_getspecific(xbt_self_thread_key);
}
#include <sched.h>
void xbt_mutex_destroy(xbt_mutex_t mutex) {
int errcode;
+ if (!mutex) return;
+
if ((errcode=pthread_mutex_destroy(&(mutex->m))))
THROW1(system_error,errcode,"pthread_mutex_destroy(%p) failed",mutex);
free(mutex);
}
void xbt_thcond_destroy(xbt_thcond_t cond){
int errcode;
+
+ if (!cond) return;
+
if ((errcode=pthread_cond_destroy(&(cond->c))))
THROW1(system_error,errcode,"pthread_cond_destroy(%p) failed",cond);
free(cond);
}
+/* ********************************* WINDOWS IMPLEMENTATION ************************************ */
#elif defined(WIN32)
+
typedef struct xbt_thread_ {
- HANDLE handle; /* the win thread handle */
- unsigned long id; /* the win thread id */
+ HANDLE handle; /* the win thread handle */
+ unsigned long id; /* the win thread id */
+ pvoid_f_pvoid_t *start_routine;
+ void* param;
} s_xbt_thread_t ;
-void xbt_thread_mod_init(void) {}
-void xbt_thread_mod_exit(void) {}
+/* key to the TLS containing the xbt_thread_t structure */
+static unsigned long xbt_self_thread_key;
+
+void xbt_thread_mod_init(void) {
+ xbt_self_thread_key = TlsAlloc();
+}
+void xbt_thread_mod_exit(void) {
+
+ if (!TlsFree(xbt_self_thread_key))
+ THROW0(system_error,(int)GetLastError(),"TlsFree() failed to cleanup the thread submodule");
+}
+
+static DWORD WINAPI wrapper_start_routine(void *s) {
+ xbt_thread_t t = (xbt_thread_t)s;
+
+ if(!TlsSetValue(xbt_self_thread_key,t))
+ THROW0(system_error,(int)GetLastError(),"TlsSetValue of data describing the created thread failed");
+
+ return (DWORD)t->start_routine(t->param);
+}
+
xbt_thread_t xbt_thread_create(pvoid_f_pvoid_t start_routine,
void* param) {
- xbt_thread_t res = xbt_new(s_xbt_thread_t,1);
+ xbt_thread_t t = xbt_new(s_xbt_thread_t,1);
+
+ t->start_routine = start_routine ;
+ t->param = param;
- res->handle = CreateThread(NULL,NULL,start_routine,param,0,&((*thread)->id));
+ t->handle = CreateThread(NULL,0,
+ (LPTHREAD_START_ROUTINE)wrapper_start_routine,
+ t,0,&(t->id));
- if(!res->handle) {
- xbt_free(res);
- THROW0(system_error,errcode,"CreateThread failed");
+ if(!t->handle) {
+ xbt_free(t);
+ THROW0(system_error,(int)GetLastError(),"CreateThread failed");
}
- return res;
+ return t;
+}
+
+void
+xbt_thread_join(xbt_thread_t thread,void ** thread_return) {
+
+ if(WAIT_OBJECT_0 != WaitForSingleObject(thread->handle,INFINITE))
+ THROW0(system_error,(int)GetLastError(), "WaitForSingleObject failed");
+
+ if(thread_return){
+
+ if(!GetExitCodeThread(thread->handle,(DWORD*)(*thread_return)))
+ THROW0(system_error,(int)GetLastError(), "GetExitCodeThread failed");
+ }
+
+ CloseHandle(thread->handle);
}
void xbt_thread_exit(int *retval) {
- xbt_thread_t self = xbt_thread_self();
-
- CloseHandle(self->handle);
- free(self);
-
- ExitThread(*retval);
+ if(retval)
+ ExitThread(*retval);
+ else
+ ExitThread(0);
}
xbt_thread_t xbt_thread_self(void) {
- return GetCurrentThreadId();
+ return TlsGetValue(xbt_self_thread_key);
}
void xbt_thread_yield(void) {
void xbt_mutex_destroy(xbt_mutex_t mutex) {
- DeleteCriticalSection(& mutex->lock);
-
+ if (!mutex) return;
+
+ DeleteCriticalSection(& mutex->lock);
free(mutex);
}
/***** condition related functions *****/
+ enum {
+ SIGNAL = 0,
+ BROADCAST = 1,
+ MAX_EVENTS = 2
+ };
+
typedef struct xbt_thcond_ {
HANDLE events[MAX_EVENTS];
res->events[SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL);
if(!res->events[SIGNAL]){
- DeleteCriticalSection(&((*cond)->waiters_count_lock));
+ DeleteCriticalSection(& res->waiters_count_lock);
free(res);
THROW0(system_error,0,"CreateEvent failed for the signals");
}
void xbt_thcond_destroy(xbt_thcond_t cond){
int error = 0;
+ if (!cond) return;
+
if(!CloseHandle(cond->events[SIGNAL]))
error = 1;