#include "xbt/sysdep.h"
#include "xbt/ex.h"
#include "portable.h"
+#include "xbt/xbt_os_time.h" /* Portable time facilities */
#include "xbt/xbt_os_thread.h" /* This module */
#include "xbt_modinter.h" /* Initialization/finalization of this module */
#include <pthread.h>
typedef struct xbt_os_thread_ {
- /* KEEP IT IN SYNC WITH xbt_thread.c */
pthread_t t;
void *param;
pvoid_f_pvoid_t *start_routine;
/* thread-specific data containing the xbt_os_thread_t structure */
static pthread_key_t xbt_self_thread_key;
+static int thread_mod_inited = 0;
/* frees the xbt_os_thread_t corresponding to the current thread */
static void xbt_os_thread_free_thread_data(void*d){
void xbt_os_thread_mod_init(void) {
int errcode;
+ if (thread_mod_inited)
+ return;
+
if ((errcode=pthread_key_create(&xbt_self_thread_key, NULL)))
THROW0(system_error,errcode,"pthread_key_create failed for xbt_self_thread_key");
+
+ thread_mod_inited = 1;
}
void xbt_os_thread_mod_exit(void) {
/* FIXME: don't try to free our key on shutdown. Valgrind detects no leak if we don't, and whine if we try to */
THROW0(system_error,errcode,"pthread_setspecific failed for xbt_self_thread_key");
return t->start_routine(t->param);
}
-
xbt_os_thread_t xbt_os_thread_create(pvoid_f_pvoid_t start_routine,
void* param) {
int errcode;
}
xbt_os_thread_t xbt_os_thread_self(void) {
- return pthread_getspecific(xbt_self_thread_key);
+ return thread_mod_inited ? pthread_getspecific(xbt_self_thread_key):NULL;
}
#include <sched.h>
void xbt_os_thread_yield(void) {
sched_yield();
}
+void xbt_os_thread_cancel(xbt_os_thread_t t) {
+ pthread_cancel(t->t);
+}
/****** mutex related functions ******/
typedef struct xbt_os_mutex_ {
/* KEEP IT IN SYNC WITH xbt_thread.c */
cond,mutex, strerror(errcode));
}
+#include <time.h>
+#include <math.h>
+void xbt_os_cond_timedwait(xbt_os_cond_t cond, xbt_os_mutex_t mutex, double delay) {
+ int errcode;
+ struct timespec ts_end;
+ double end = delay + xbt_os_time();
+ ts_end.tv_sec = (time_t) floor(end);
+ ts_end.tv_nsec = (long) ( ( end - ts_end.tv_sec) * 1000000000);
+ switch ( (errcode=pthread_cond_timedwait(&(cond->c),&(mutex->m), &ts_end)) ) {
+ case ETIMEDOUT:
+ THROW3(timeout_error,errcode,"condition %p (mutex %p) wasn't signaled before timeout (%f)",
+ cond,mutex, delay);
+ default:
+ THROW4(system_error,errcode,"pthread_cond_timedwait(%p,%p,%f) failed: %s",
+ cond,mutex, delay, strerror(errcode));
+ }
+}
+
void xbt_os_cond_signal(xbt_os_cond_t cond) {
int errcode;
if ((errcode=pthread_cond_signal(&(cond->c))))
free(cond);
}
+void *xbt_os_thread_getparam(void) {
+ xbt_os_thread_t t = xbt_os_thread_self();
+ return t?t->param:NULL;
+}
+
/* ********************************* WINDOWS IMPLEMENTATION ************************************ */
#elif defined(WIN32)
typedef struct xbt_os_thread_ {
- /* KEEP IT IN SYNC WITH xbt_thread */
HANDLE handle; /* the win thread handle */
unsigned long id; /* the win thread id */
pvoid_f_pvoid_t *start_routine;
return TlsGetValue(xbt_self_thread_key);
}
+void *xbt_os_thread_getparam(void) {
+ xbt_os_thread_t t = xbt_os_thread_self();
+ return t->param;
+}
+
+
void xbt_os_thread_yield(void) {
Sleep(0);
}
+void xbt_os_thread_cancel(xbt_os_thread_t t) {
+ THROW_UNIMPLEMENTED;
+}
/****** mutex related functions ******/
typedef struct xbt_os_mutex_ {
/* relock the mutex associated with the condition in accordance with the posix thread specification */
EnterCriticalSection (& mutex->lock);
}
+void xbt_os_cond_timedwait(xbt_os_cond_t cond, xbt_os_mutex_t mutex, double delay) {
+ THROW_UNIMPLEMENTED;
+}
void xbt_os_cond_signal(xbt_os_cond_t cond) {
int have_waiters;