diff --git a/configure.ac b/configure.ac index 6e5c27f0a..e7cf3fa6e 100644 --- a/configure.ac +++ b/configure.ac @@ -235,6 +235,8 @@ AC_CHECK_FUNCS(\ utime \ utimes \ sem_timedwait \ + pthread_yield \ + sched_yield \ ) AC_CHECK_LIB([pthread], [pthread_mutex_init], [LIBS="${LIBS} -lpthread"]) diff --git a/lib/core/include/core.h.in b/lib/core/include/core.h.in index ec9a26e3c..a9345b5c1 100644 --- a/lib/core/include/core.h.in +++ b/lib/core/include/core.h.in @@ -253,7 +253,7 @@ typedef c_int32_t c_intptr_t; * so that they follow the platform's calling convention. *
* - * void* THREAD_FUNC my_thread_entry_fn(core_thread_t *thd, void *data); + * void* THREAD_FUNC my_thread_entry_fn(thread_id id, void *data); * **/ diff --git a/lib/core/include/core_thread.h b/lib/core/include/core_thread.h index c9df0afb3..f88cdc8ec 100644 --- a/lib/core/include/core_thread.h +++ b/lib/core/include/core_thread.h @@ -14,7 +14,7 @@ typedef c_uintptr_t thread_id; /** Opaque Thread attributes structure. */ typedef struct threadattr_t threadattr_t; -typedef void *(THREAD_FUNC *thread_start_t)(void*); +typedef void *(THREAD_FUNC *thread_start_t)(thread_id id, void*); /** * Check if Thread Should Stop @@ -67,11 +67,32 @@ CORE_DECLARE(status_t) thread_create(thread_id *id, */ CORE_DECLARE(status_t) thread_delete(thread_id id); +/** + * detach a thread + * @param thd The thread to detach + */ +CORE_DECLARE(status_t) thread_detach(thread_id id); + +/** + * stop the current thread + * @param thd The thread to stop + * @param retval The return value to pass back to any thread that cares + */ +CORE_DECLARE(status_t) thread_exit(thread_id id, status_t retval); + +/** + * block until the desired thread stops executing. + * @param retval The return value from the dead thread. + * @param thd The thread to join + */ +CORE_DECLARE(status_t) thread_join(status_t *retval, thread_id id); + /** * force the current thread to yield the processor */ CORE_DECLARE(void) thread_yield(void); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lib/core/src/unix/thread.c b/lib/core/src/unix/thread.c index e0c1c043d..3df8eca99 100644 --- a/lib/core/src/unix/thread.c +++ b/lib/core/src/unix/thread.c @@ -12,6 +12,7 @@ typedef struct _thread_t { pthread_t thread; void *data; thread_start_t func; + status_t exitval; semaphore_id semaphore; } thread_t; @@ -111,7 +112,7 @@ static void *dummy_worker(void *opaque) d_trace(3, "[%d] dummy_worker post semaphore\n", thread->thread); if (!thread_should_stop()) - func = thread->func(thread->data); + func = thread->func((thread_id)thread, thread->data); d_trace(3, "[%d] thread stopped = %d\n", thread->thread, thread_should_stop()); @@ -176,3 +177,56 @@ status_t thread_delete(thread_id id) return CORE_OK; } + +status_t thread_join(status_t *retval, thread_id id) +{ + thread_t *thread = (thread_t *)id; + + status_t stat; + status_t *thread_stat; + + if ((stat = pthread_join(thread->thread, (void *)&thread_stat)) == 0) + { + *retval = thread->exitval; + return CORE_OK; + } + else + { + return stat; + } +} + +status_t thread_exit(thread_id id, status_t retval) +{ + thread_t *thread = (thread_t *)id; + + thread->exitval = retval; + pthread_exit(NULL); + return CORE_OK; +} + +status_t thread_detach(thread_id id) +{ + thread_t *thread = (thread_t *)id; + status_t stat; + + if ((stat = pthread_detach(thread->thread)) == 0) + { + return CORE_OK; + } + else + { + return stat; + } +} + +void thread_yield(void) +{ +#ifdef HAVE_PTHREAD_YIELD + pthread_yield(NULL); +#else +#ifdef HAVE_SCHED_YIELD + sched_yield(); +#endif +#endif +} diff --git a/lib/core/test/testlock.c b/lib/core/test/testlock.c index 5df5dd2c9..f93929294 100644 --- a/lib/core/test/testlock.c +++ b/lib/core/test/testlock.c @@ -10,10 +10,10 @@ #define MAX_COUNTER 10000 #define MAX_RETRY 3 -static void *THREAD_FUNC thread_rwlock_func(void *data); -static void *THREAD_FUNC thread_mutex_function(void *data); -static void *THREAD_FUNC thread_cond_producer(void *data); -static void *THREAD_FUNC thread_cond_consumer(void *data); +static void *THREAD_FUNC thread_rwlock_func(thread_id id, void *data); +static void *THREAD_FUNC thread_mutex_function(thread_id id, void *data); +static void *THREAD_FUNC thread_cond_producer(thread_id id, void *data); +static void *THREAD_FUNC thread_cond_consumer(thread_id id, void *data); static mutex_id mutex; static rwlock_id rwlock; @@ -37,7 +37,7 @@ struct { static mutex_id timeout_mutex; static cond_id timeout_cond; -static void *THREAD_FUNC thread_rwlock_func(void *data) +static void *THREAD_FUNC thread_rwlock_func(thread_id id, void *data) { int exitLoop = 1; @@ -62,7 +62,7 @@ static void *THREAD_FUNC thread_rwlock_func(void *data) return NULL; } -static void *THREAD_FUNC thread_mutex_function(void *data) +static void *THREAD_FUNC thread_mutex_function(thread_id id, void *data) { int exitLoop = 1; @@ -87,7 +87,7 @@ static void *THREAD_FUNC thread_mutex_function(void *data) return NULL; } -static void *THREAD_FUNC thread_cond_producer(void *data) +static void *THREAD_FUNC thread_cond_producer(thread_id id, void *data) { for (;;) { @@ -114,7 +114,7 @@ static void *THREAD_FUNC thread_cond_producer(void *data) return NULL; } -static void *THREAD_FUNC thread_cond_consumer(void *data) +static void *THREAD_FUNC thread_cond_consumer(thread_id id, void *data) { int i; @@ -133,7 +133,7 @@ static void *THREAD_FUNC thread_cond_consumer(void *data) return NULL; } -static void *THREAD_FUNC thread_semaphore_function(void *data) +static void *THREAD_FUNC thread_semaphore_function(thread_id id, void *data) { int exitLoop = 1; diff --git a/lib/core/test/testmsgq.c b/lib/core/test/testmsgq.c index 474fead62..9552d292d 100644 --- a/lib/core/test/testmsgq.c +++ b/lib/core/test/testmsgq.c @@ -1,24 +1,6 @@ #include "core_msgq.h" #include "testutil.h" -#if 0 -static thread_id *s1; -static thread_id *r1; - -static void *THREAD_FUNC thread_send(void *data); -static void *THREAD_FUNC thread_recv(void *data); - -static void *THREAD_FUNC thread_send(void *data) -{ - -} - -static void *THREAD_FUNC thread_recv(void *data) -{ - -} -#endif - char msg[16][24] = { {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28}, diff --git a/lib/core/test/testthread.c b/lib/core/test/testthread.c index 9a022a040..0cea893d1 100644 --- a/lib/core/test/testthread.c +++ b/lib/core/test/testthread.c @@ -5,12 +5,14 @@ static mutex_id lock; static int x = 0; +static status_t exit_ret_val = 123; + static thread_id t1; static thread_id t2; static thread_id t3; static thread_id t4; -static void *THREAD_FUNC thread_func1(void *data) +static void *THREAD_FUNC thread_func1(thread_id id, void *data) { int i; @@ -20,6 +22,7 @@ static void *THREAD_FUNC thread_func1(void *data) x++; mutex_unlock(lock); } + thread_exit(id, exit_ret_val); return NULL; } @@ -45,18 +48,18 @@ static void create_threads(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, CORE_OK, rv); } -static void delete_threads(abts_case *tc, void *data) +static void join_threads(abts_case *tc, void *data) { status_t s; - s = thread_delete(t1); - ABTS_INT_EQUAL(tc, CORE_OK, s); - s = thread_delete(t2); - ABTS_INT_EQUAL(tc, CORE_OK, s); - s = thread_delete(t3); - ABTS_INT_EQUAL(tc, CORE_OK, s); - s = thread_delete(t4); - ABTS_INT_EQUAL(tc, CORE_OK, s); + thread_join(&s, t1); + ABTS_INT_EQUAL(tc, exit_ret_val, s); + thread_join(&s, t2); + ABTS_INT_EQUAL(tc, exit_ret_val, s); + thread_join(&s, t3); + ABTS_INT_EQUAL(tc, exit_ret_val, s); + thread_join(&s, t4); + ABTS_INT_EQUAL(tc, exit_ret_val, s); } static void check_locks(abts_case *tc, void *data) @@ -70,7 +73,7 @@ abts_suite *testthread(abts_suite *suite) abts_run_test(suite, init_thread, NULL); abts_run_test(suite, create_threads, NULL); - abts_run_test(suite, delete_threads, NULL); + abts_run_test(suite, join_threads, NULL); abts_run_test(suite, check_locks, NULL); return suite; diff --git a/src/init.c b/src/init.c index fec87aa28..4b6b47147 100644 --- a/src/init.c +++ b/src/init.c @@ -16,7 +16,7 @@ static pid_t logger_pid; static thread_id net_thread; static int check_signal(int signum); -void *THREAD_FUNC net_main(void *data); +void *THREAD_FUNC net_main(thread_id id, void *data); status_t cellwire_initialize(char *config_path, char *log_path) { @@ -104,7 +104,7 @@ static int check_signal(int signum) return 0; } -void *THREAD_FUNC net_main(void *data) +void *THREAD_FUNC net_main(thread_id id, void *data) { while (!thread_should_stop()) { diff --git a/src/mme/init.c b/src/mme/init.c index 74757cb1d..5c154f437 100644 --- a/src/mme/init.c +++ b/src/mme/init.c @@ -11,7 +11,7 @@ #define EVENT_WAIT_TIMEOUT 10000 /* 10 msec */ static thread_id mme_sm_thread; -void *THREAD_FUNC mme_sm_main(void *data); +void *THREAD_FUNC mme_sm_main(thread_id id, void *data); status_t mme_initialize() { @@ -39,7 +39,7 @@ void mme_terminate(void) mme_ctx_final(); } -void *THREAD_FUNC mme_sm_main(void *data) +void *THREAD_FUNC mme_sm_main(thread_id id, void *data) { event_t event; mme_sm_t mme_sm; @@ -93,7 +93,7 @@ void *THREAD_FUNC mme_sm_main(void *data) return NULL; } -void *THREAD_FUNC mme_net_main(void *data) +void *THREAD_FUNC mme_net_main(thread_id id, void *data) { while (!thread_should_stop()) {