forked from acouzens/open5gs
179 lines
3.8 KiB
C
179 lines
3.8 KiB
C
#include "core.h"
|
|
#include "core_thread.h"
|
|
#include "core_errno.h"
|
|
#include "core_param.h"
|
|
#include "core_general.h"
|
|
#define TRACE_MODULE _thread
|
|
#include "core_debug.h"
|
|
#include "core_pool.h"
|
|
#include "core_semaphore.h"
|
|
|
|
typedef struct _thread_t {
|
|
pthread_t thread;
|
|
void *data;
|
|
thread_start_t func;
|
|
|
|
semaphore_id semaphore;
|
|
} thread_t;
|
|
|
|
struct thread_stop_info {
|
|
pthread_t thread;
|
|
semaphore_id semaphore;
|
|
};
|
|
|
|
struct threadattr_t {
|
|
pthread_attr_t attr;
|
|
};
|
|
|
|
pool_declare(thread_pool, thread_t, MAX_NUM_OF_THREAD);
|
|
pool_declare(threadattr_pool, threadattr_t, MAX_NUM_OF_THREADATTR);
|
|
|
|
static struct thread_stop_info thread_stop_info;
|
|
|
|
int thread_should_stop(void)
|
|
{
|
|
return (thread_stop_info.thread == pthread_self());
|
|
}
|
|
|
|
status_t thread_init(void)
|
|
{
|
|
pool_init(&thread_pool, MAX_NUM_OF_THREAD);
|
|
pool_init(&threadattr_pool, MAX_NUM_OF_THREADATTR);
|
|
|
|
memset(&thread_stop_info, 0, sizeof(thread_stop_info));
|
|
|
|
semaphore_create(&thread_stop_info.semaphore, 0);
|
|
return CORE_OK;
|
|
}
|
|
|
|
status_t thread_final(void)
|
|
{
|
|
pool_final(&thread_pool);
|
|
pool_final(&threadattr_pool);
|
|
|
|
semaphore_delete(thread_stop_info.semaphore);
|
|
return CORE_OK;
|
|
}
|
|
|
|
status_t threadattr_create(threadattr_t **new)
|
|
{
|
|
status_t stat;
|
|
|
|
pool_alloc_node(&threadattr_pool, &(*new));
|
|
d_assert((*new), return CORE_ENOMEM, "threadattr_pool(%d) is not enough\n",
|
|
MAX_NUM_OF_THREADATTR);
|
|
stat = pthread_attr_init(&(*new)->attr);
|
|
|
|
if (stat == 0)
|
|
{
|
|
return CORE_OK;
|
|
}
|
|
|
|
return stat;
|
|
}
|
|
|
|
status_t threadattr_stacksize_set(
|
|
threadattr_t *attr, size_t stacksize)
|
|
{
|
|
int stat;
|
|
|
|
stat = pthread_attr_setstacksize(&attr->attr, stacksize);
|
|
if (stat == 0)
|
|
{
|
|
return CORE_OK;
|
|
}
|
|
|
|
return stat;
|
|
}
|
|
|
|
status_t threadattr_delete(threadattr_t *attr)
|
|
{
|
|
status_t stat;
|
|
|
|
stat = pthread_attr_destroy(&attr->attr);
|
|
pool_free_node(&threadattr_pool, attr);
|
|
|
|
if (stat == 0)
|
|
{
|
|
return CORE_OK;
|
|
}
|
|
|
|
return stat;
|
|
}
|
|
|
|
static void *dummy_worker(void *opaque)
|
|
{
|
|
void *func = NULL;
|
|
thread_t *thread = (thread_t *)opaque;
|
|
|
|
thread->thread = pthread_self();
|
|
semaphore_post(thread->semaphore);
|
|
d_trace(3, "[%d] dummy_worker post semaphore\n", thread->thread);
|
|
|
|
if (!thread_should_stop())
|
|
func = thread->func(thread->data);
|
|
|
|
d_trace(3, "[%d] thread stopped = %d\n",
|
|
thread->thread, thread_should_stop());
|
|
semaphore_post(thread_stop_info.semaphore);
|
|
d_trace(3, "[%d] post semaphore for therad_stop_info.semaphore\n",
|
|
thread->thread);
|
|
|
|
return func;
|
|
}
|
|
|
|
status_t thread_create(thread_id *id,
|
|
threadattr_t *attr, thread_start_t func, void *data)
|
|
{
|
|
status_t stat;
|
|
pthread_attr_t *temp;
|
|
thread_t *new = NULL;
|
|
|
|
pool_alloc_node(&thread_pool, &new);
|
|
d_assert(new, return CORE_ENOMEM, "thread_pool(%d) is not enough\n",
|
|
MAX_NUM_OF_THREAD);
|
|
memset(new, 0, sizeof(thread_id));
|
|
|
|
new->data = data;
|
|
new->func = func;
|
|
|
|
semaphore_create(&new->semaphore, 0);
|
|
|
|
if (attr)
|
|
temp = &attr->attr;
|
|
else
|
|
temp = NULL;
|
|
|
|
if ((stat = pthread_create(&new->thread, temp, dummy_worker, new)) != 0)
|
|
{
|
|
return stat;
|
|
}
|
|
|
|
d_trace(3, "thread_create wait\n");
|
|
semaphore_wait(new->semaphore);
|
|
d_trace(3, "thread_create done\n");
|
|
|
|
*id = (thread_id)new;
|
|
|
|
return CORE_OK;
|
|
}
|
|
|
|
status_t thread_delete(thread_id id)
|
|
{
|
|
thread_t *thread = (thread_t *)id;
|
|
|
|
thread_stop_info.thread = thread->thread;
|
|
d_trace(3, "thread_stop_info.thread for %d\n", thread_stop_info.thread);
|
|
semaphore_wait(thread_stop_info.semaphore);
|
|
d_trace(3, "semaphore_wait done\n");
|
|
thread_stop_info.thread = 0;
|
|
|
|
pthread_join(thread->thread, 0);
|
|
|
|
semaphore_delete(thread->semaphore);
|
|
pool_free_node(&thread_pool, thread);
|
|
d_trace(3, "delete thread-related memory\n");
|
|
|
|
return CORE_OK;
|
|
}
|