diff --git a/libs/libks/src/include/ks_threadmutex.h b/libs/libks/src/include/ks_threadmutex.h index 0739efe5db..fea6184200 100644 --- a/libs/libks/src/include/ks_threadmutex.h +++ b/libs/libks/src/include/ks_threadmutex.h @@ -53,6 +53,16 @@ typedef #endif ks_pid_t; +typedef enum { + KS_THREAD_INIT, + KS_THREAD_RUNNING, + KS_THREAD_FAIL, + KS_THREAD_SHUTDOWN, + KS_THREAD_STOPPED +} ks_thread_state_t; + +#define KS_THREAD_IS_RUNNING(_thread) _thread->state == KS_THREAD_RUNNING + struct ks_thread { ks_pool_t *pool; #ifdef WIN32 @@ -65,7 +75,7 @@ struct ks_thread { ks_thread_function_t function; size_t stack_size; uint32_t flags; - uint8_t running; + ks_thread_state_t state; uint8_t priority; void *return_data; }; @@ -79,7 +89,7 @@ struct ks_thread { typedef enum { KS_THREAD_FLAG_DEFAULT = 0, - KS_THREAD_FLAG_DETATCHED = (1 << 0) + KS_THREAD_FLAG_DETACHED = (1 << 0) } ks_thread_flags_t; KS_DECLARE(int) ks_thread_set_priority(int nice_val); diff --git a/libs/libks/src/ks_thread.c b/libs/libks/src/ks_thread.c index e450fb22da..25b08184a6 100644 --- a/libs/libks/src/ks_thread.c +++ b/libs/libks/src/ks_thread.c @@ -85,18 +85,23 @@ static void ks_thread_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, switch(action) { case KS_MPCL_ANNOUNCE: - thread->running = 0; + if (thread->state == KS_THREAD_RUNNING) { + thread->state = KS_THREAD_SHUTDOWN; + } break; case KS_MPCL_TEARDOWN: - if (!(thread->flags & KS_THREAD_FLAG_DETATCHED)) { + while(thread->state == KS_THREAD_SHUTDOWN) { + ks_sleep(10000); + } + + if (!(thread->flags & KS_THREAD_FLAG_DETACHED)) { ks_thread_join(thread); } break; case KS_MPCL_DESTROY: + #ifdef WIN32 - //if (!(thread->flags & KS_THREAD_FLAG_DETATCHED)) { - CloseHandle(thread->handle); - //} + CloseHandle(thread->handle); #endif break; } @@ -118,8 +123,9 @@ static void *KS_THREAD_CALLING_CONVENTION thread_launch(void *args) pthread_setschedparam(tt, policy, ¶m); } #endif - + thread->state = KS_THREAD_RUNNING; thread->return_data = thread->function(thread, thread->private_data); + thread->state = KS_THREAD_STOPPED; #ifndef WIN32 pthread_attr_destroy(&thread->attribute); #endif @@ -205,6 +211,7 @@ KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **rthread, ks_thread_fun { ks_thread_t *thread = NULL; ks_status_t status = KS_STATUS_FAIL; + int sanity = 1000; if (!rthread) goto done; @@ -219,7 +226,6 @@ KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **rthread, ks_thread_fun thread->private_data = data; thread->function = func; thread->stack_size = stack_size; - thread->running = 1; thread->flags = flags; thread->priority = priority; thread->pool = pool; @@ -241,7 +247,7 @@ KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **rthread, ks_thread_fun SetThreadPriority(thread->handle, THREAD_PRIORITY_LOWEST); } - if (flags & KS_THREAD_FLAG_DETATCHED) { + if (flags & KS_THREAD_FLAG_DETACHED) { //CloseHandle(thread->handle); } @@ -252,7 +258,7 @@ KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **rthread, ks_thread_fun if (pthread_attr_init(&thread->attribute) != 0) goto fail; - if ((flags & KS_THREAD_FLAG_DETATCHED) && pthread_attr_setdetachstate(&thread->attribute, PTHREAD_CREATE_DETACHED) != 0) + if ((flags & KS_THREAD_FLAG_DETACHED) && pthread_attr_setdetachstate(&thread->attribute, PTHREAD_CREATE_DETACHED) != 0) goto failpthread; if (thread->stack_size && pthread_attr_setstacksize(&thread->attribute, thread->stack_size) != 0) @@ -265,19 +271,28 @@ KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **rthread, ks_thread_fun goto done; failpthread: - + thread->state = KS_THREAD_FAIL; pthread_attr_destroy(&thread->attribute); #endif fail: if (thread) { - thread->running = 0; + thread->state = KS_THREAD_FAIL; if (pool) { ks_pool_free(pool, &thread); } } done: if (status == KS_STATUS_SUCCESS) { + while(thread->state < KS_THREAD_RUNNING && --sanity > 0) { + ks_sleep(1000); + } + + if (!sanity) { + status = KS_STATUS_FAIL; + goto fail; + } + *rthread = thread; ks_pool_set_cleanup(pool, thread, NULL, 0, ks_thread_cleanup); } diff --git a/libs/libks/src/ks_thread_pool.c b/libs/libks/src/ks_thread_pool.c index 0ce9fdff84..9840b47944 100644 --- a/libs/libks/src/ks_thread_pool.c +++ b/libs/libks/src/ks_thread_pool.c @@ -94,7 +94,7 @@ static int check_queue(ks_thread_pool_t *tp, ks_bool_t adding) ks_mutex_unlock(tp->mutex); while(need > 0) { - if (ks_thread_create_ex(&thread, worker_thread, tp, KS_THREAD_FLAG_DETATCHED, tp->stack_size, tp->priority, tp->pool) != KS_STATUS_SUCCESS) { + if (ks_thread_create_ex(&thread, worker_thread, tp, KS_THREAD_FLAG_DETACHED, tp->stack_size, tp->priority, tp->pool) != KS_STATUS_SUCCESS) { ks_mutex_lock(tp->mutex); tp->thread_count--; ks_mutex_unlock(tp->mutex); diff --git a/libs/libks/test/testhash.c b/libs/libks/test/testhash.c index 51526fc7eb..82146518b2 100644 --- a/libs/libks/test/testhash.c +++ b/libs/libks/test/testhash.c @@ -49,14 +49,14 @@ static void *test2_thread(ks_thread_t *thread, void *data) ks_hash_iterator_t *itt; ks_hash_t *hash = (ks_hash_t *) data; - while(thread->running) { + while(KS_THREAD_IS_RUNNING(thread)) { for (itt = ks_hash_first(hash, KS_READLOCKED); itt; itt = ks_hash_next(&itt)) { const void *key; void *val; ks_hash_this(itt, &key, NULL, &val); - printf("%d ITT %s=%s\n", (int)ks_thread_self_id(), (char *)key, (char *)val); + printf("%u ITT %s=%s\n", (int)ks_thread_self_id(), (char *)key, (char *)val); } ks_sleep(100000); } @@ -109,7 +109,7 @@ int test2(void) } for (i = 0; i < ttl; i++) { - threads[i]->running = 0; + threads[i]->state = KS_THREAD_SHUTDOWN; ks_thread_join(threads[i]); } diff --git a/libs/libks/test/testthreadmutex.c b/libs/libks/test/testthreadmutex.c index ce28af07d6..02e666db73 100644 --- a/libs/libks/test/testthreadmutex.c +++ b/libs/libks/test/testthreadmutex.c @@ -23,8 +23,8 @@ static int cpu_count = 0; static void *thread_priority(ks_thread_t *thread, void *data) { - while (thread->running) { - ks_sleep(1000000); + while (KS_THREAD_IS_RUNNING(thread)) { + ks_sleep(100000); } return NULL; @@ -145,8 +145,8 @@ static void *thread_test_function_cleanup(ks_thread_t *thread, void *data) { int d = (int)(intptr_t)data; - while (thread->running) { - ks_sleep(1000000); + while (KS_THREAD_IS_RUNNING(thread)) { + ks_sleep(100000); } if ( d == 1 ) { @@ -229,7 +229,7 @@ static void create_threads_detatched(void) int i; for(i = 0; i < cpu_count; i++) { - status = ks_thread_create_ex(&threads[i], thread_test_function_detatched, d, KS_THREAD_FLAG_DETATCHED, KS_THREAD_DEFAULT_STACK, KS_PRI_NORMAL, pool); + status = ks_thread_create_ex(&threads[i], thread_test_function_detatched, d, KS_THREAD_FLAG_DETACHED, KS_THREAD_DEFAULT_STACK, KS_PRI_NORMAL, pool); ok( status == KS_STATUS_SUCCESS ); } } @@ -239,9 +239,9 @@ static void check_thread_priority(void) ks_status_t status; void *d = (void *)(intptr_t)1; - status = ks_thread_create_ex(&thread_p, thread_priority, d, KS_THREAD_FLAG_DETATCHED, KS_THREAD_DEFAULT_STACK, KS_PRI_IMPORTANT, pool); + status = ks_thread_create_ex(&thread_p, thread_priority, d, KS_THREAD_FLAG_DETACHED, KS_THREAD_DEFAULT_STACK, KS_PRI_IMPORTANT, pool); ok( status == KS_STATUS_SUCCESS ); - ks_sleep(1000000); + ks_sleep(100000); todo("Add check to see if has permission to set thread priority\n"); ok( ks_thread_priority(thread_p) == KS_PRI_IMPORTANT ); end_todo;