diff --git a/src/monitor.h b/src/monitor.h index ebd714c8..c082e75d 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -18,16 +18,16 @@ #ifndef HAVE_PTHREADS_MONITOR_H #define HAVE_PTHREADS_MONITOR_H -typedef unsigned long pthreads_monitor_state_t; +typedef volatile unsigned long pthreads_monitor_state_t; typedef struct _pthreads_monitor_t pthreads_monitor_t; -#define PTHREADS_MONITOR_NOTHING (0) -#define PTHREADS_MONITOR_READY (1<<0) -#define PTHREADS_MONITOR_STARTED (1<<1) -#define PTHREADS_MONITOR_RUNNING (1<<2) -#define PTHREADS_MONITOR_JOINED (1<<3) -#define PTHREADS_MONITOR_ERROR (1<<4) +#define PTHREADS_MONITOR_NOTHING (0) +#define PTHREADS_MONITOR_STARTED (1<<0) +#define PTHREADS_MONITOR_RUNNING (1<<1) +#define PTHREADS_MONITOR_JOINED (1<<2) +#define PTHREADS_MONITOR_ERROR (1<<3) +#define PTHREADS_MONITOR_READY (1<<4) pthreads_monitor_t* pthreads_monitor_alloc(); zend_bool pthreads_monitor_lock(pthreads_monitor_t *m); diff --git a/src/object.c b/src/object.c index ec8c55ea..7ec622ee 100644 --- a/src/object.c +++ b/src/object.c @@ -41,7 +41,7 @@ extern zend_module_entry pthreads_module_entry; /* }}} */ static void pthreads_base_ctor(pthreads_object_t* base, zend_class_entry *entry); /* }}} */ /* {{{ */ -static void * pthreads_routine(void *arg); /* }}} */ +static void * pthreads_routine(pthreads_routine_arg_t *arg); /* }}} */ static inline void pthreads_object_iterator_dtor(pthreads_iterator_t* iterator) { if (Z_TYPE(iterator->zit.data) != IS_UNDEF) @@ -203,7 +203,6 @@ int pthreads_connect(pthreads_object_t* source, pthreads_object_t* destination) pthreads_stack_free(destination->stack); } - pthreads_monitor_free(destination->ready); pthreads_monitor_free(destination->monitor); destination->scope |= PTHREADS_SCOPE_CONNECTION; @@ -215,7 +214,6 @@ int pthreads_connect(pthreads_object_t* source, pthreads_object_t* destination) destination->local.id = source->local.id; destination->local.ls = source->local.ls; destination->monitor = source->monitor; - destination->ready = source->ready; destination->store = source->store; destination->stack = source->stack; @@ -267,7 +265,6 @@ static void pthreads_base_ctor(pthreads_object_t* base, zend_class_entry *entry) if (PTHREADS_IS_NOT_CONNECTION(base)) { base->monitor = pthreads_monitor_alloc(); - base->ready = pthreads_monitor_alloc(); base->store = pthreads_store_alloc(); if (PTHREADS_IS_WORKER(base)) { @@ -322,6 +319,7 @@ HashTable* pthreads_base_gc(zval *object, zval **table, int *n) { /* {{{ */ zend_bool pthreads_start(pthreads_object_t* thread) { + pthreads_routine_arg_t routine; if (!PTHREADS_IN_CREATOR(thread) || PTHREADS_IS_CONNECTION(thread)) { zend_throw_exception_ex(spl_ce_RuntimeException, @@ -336,11 +334,11 @@ zend_bool pthreads_start(pthreads_object_t* thread) { return 0; } - pthreads_monitor_add(thread->monitor, PTHREADS_MONITOR_STARTED); + pthreads_routine_init(&routine, thread); - switch (pthread_create(&thread->thread, NULL, pthreads_routine, (void*)thread)) { + switch (pthread_create(&thread->thread, NULL, (void* (*) (void*)) pthreads_routine, (void*)&routine)) { case SUCCESS: - pthreads_monitor_wait_until(thread->ready, PTHREADS_MONITOR_READY); + pthreads_routine_wait(&routine); return 1; case EAGAIN: @@ -353,8 +351,8 @@ zend_bool pthreads_start(pthreads_object_t* thread) { 0, "cannot start %s, unknown error", thread->std.ce->name->val); } - pthreads_monitor_remove(thread->monitor, PTHREADS_MONITOR_STARTED); - + pthreads_routine_free(&routine); + return 0; } /* }}} */ @@ -433,10 +431,11 @@ static inline zend_bool pthreads_routine_run_function(pthreads_object_t* object, } /* }}} */ /* {{{ */ -static void * pthreads_routine(void *arg) { - pthreads_object_t* thread = (pthreads_object_t*) arg; +static void * pthreads_routine(pthreads_routine_arg_t *routine) { + pthreads_object_t* thread = routine->thread; + pthreads_monitor_t* ready = routine->ready; - pthreads_prepared_startup(thread); + pthreads_prepared_startup(thread, ready); zend_first_try { ZVAL_UNDEF(&PTHREADS_ZG(this)); diff --git a/src/prepare.c b/src/prepare.c index e9a5b71b..2851562b 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -589,7 +589,7 @@ static inline void pthreads_kill_handler(int signo) /* {{{ */ #endif /* {{{ */ -int pthreads_prepared_startup(pthreads_object_t* thread) { +int pthreads_prepared_startup(pthreads_object_t* thread, pthreads_monitor_t *ready) { #ifdef PTHREADS_KILL_SIGNAL #ifdef ZEND_SIGNAL zend_signal(PTHREADS_KILL_SIGNAL, pthreads_kill_handler); @@ -629,7 +629,7 @@ int pthreads_prepared_startup(pthreads_object_t* thread) { pthreads_prepare_exception_handler(thread); pthreads_prepare_resource_destructor(thread); - pthreads_monitor_add(thread->ready, PTHREADS_MONITOR_READY); + pthreads_monitor_add(ready, PTHREADS_MONITOR_READY); return SUCCESS; } /* }}} */ diff --git a/src/prepare.h b/src/prepare.h index 83cd8aff..12507a1a 100644 --- a/src/prepare.h +++ b/src/prepare.h @@ -26,7 +26,7 @@ zend_class_entry* pthreads_prepared_entry(pthreads_object_t* thread, zend_class_entry *candidate); /* }}} */ /* {{{ */ -int pthreads_prepared_startup(pthreads_object_t* thread); /* }}} */ +int pthreads_prepared_startup(pthreads_object_t* thread, pthreads_monitor_t *ready); /* }}} */ /* {{{ */ int pthreads_prepared_shutdown(pthreads_object_t* thread); /* }}} */ diff --git a/src/thread.h b/src/thread.h index 27ea582a..4effbc7b 100644 --- a/src/thread.h +++ b/src/thread.h @@ -31,19 +31,43 @@ typedef struct _pthreads_ident_t { void*** ls; } pthreads_ident_t; -/* {{{ threaded structure */ +/* {{{ */ typedef struct _pthreads_object_t { pthread_t thread; uint scope; zend_ulong options; pthreads_monitor_t *monitor; - pthreads_monitor_t *ready; pthreads_store_t *store; pthreads_stack_t *stack; pthreads_ident_t creator; pthreads_ident_t local; zend_object std; -} pthreads_object_t; +} pthreads_object_t; /* }}} */ + +/* {{{ */ +typedef struct _pthreads_routine_arg_t { + pthreads_object_t *thread; + pthreads_monitor_t *ready; +} pthreads_routine_arg_t; + +static inline void pthreads_routine_init(pthreads_routine_arg_t *r, pthreads_object_t *thread) { + r->thread = thread; + r->ready = pthreads_monitor_alloc(); + pthreads_monitor_add( + r->thread->monitor, PTHREADS_MONITOR_STARTED); +} + +static inline void pthreads_routine_wait(pthreads_routine_arg_t *r) { + pthreads_monitor_wait_until( + r->ready, PTHREADS_MONITOR_READY); + pthreads_monitor_free(r->ready); +} + +static inline void pthreads_routine_free(pthreads_routine_arg_t *r) { + pthreads_monitor_remove( + r->thread->monitor, PTHREADS_MONITOR_STARTED); + pthreads_monitor_free(r->ready); +} /* }}} */ /* {{{ object iterator structure */ typedef struct _pthreads_iterator_t { @@ -116,3 +140,4 @@ static inline ulong pthreads_self() { #define PTHREADS_IN_THREAD(t) ((t)->local.ls == TSRMLS_CACHE) /* }}} */ #endif /* HAVE_PTHREADS_THREAD_H */ +