tobudos-kernel/osal/posix/pthread_prv.c

303 lines
6.6 KiB
C

/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_k.h"
#include "pthread.h"
#include "private/pthread.h"
__STATIC__ k_mutex_t pthread_mutex;
__STATIC__ pthread_ctl_t *thread_ctl_table[PTHREAD_THREADS_MAX] = { 0 };
__STATIC__ pthread_key_ctl_t pthread_key_ctl;
__KNL__ pthread_ctl_t *pthread_ctl_self(void)
{
TOS_CPU_CPSR_ALLOC();
int i = 0;
k_task_t *self_task;
pthread_ctl_t *the_info;
self_task = tos_task_curr_task_get();
TOS_CPU_INT_DISABLE();
for (i = 0; i < TOS_COUNT_OF(thread_ctl_table); ++i) {
the_info = thread_ctl_table[i];
if (the_info && the_info->the_ktask == self_task) {
TOS_CPU_INT_ENABLE();
return the_info;
}
}
TOS_CPU_INT_ENABLE();
return K_NULL;
}
__KNL__ pthread_ctl_t *pthread_ctl_by_id(pthread_t id)
{
pthread_ctl_t *the_ctl;
the_ctl = thread_ctl_table[id];
if (!the_ctl) {
return K_NULL;
}
if (the_ctl->id != id) {
return K_NULL;
}
if (the_ctl->threadstate == PTHREAD_STATE_EXITED) {
return K_NULL;
}
return the_ctl;
}
__KNL__ int pthread_id_add(pthread_t id, pthread_ctl_t *info)
{
TOS_CPU_CPSR_ALLOC();
if (id < 0 ||
id >= TOS_COUNT_OF(thread_ctl_table) ||
thread_ctl_table[id]) {
return -1;
}
TOS_CPU_INT_DISABLE();
thread_ctl_table[id] = info;
TOS_CPU_INT_ENABLE();
return 0;
}
__KNL__ pthread_t pthread_id_alloc(void)
{
TOS_CPU_CPSR_ALLOC();
int i = 0;
TOS_CPU_INT_DISABLE();
for (i = 0; i < TOS_COUNT_OF(thread_ctl_table); ++i) {
if (!thread_ctl_table[i]) {
TOS_CPU_INT_ENABLE();
return (pthread_t)i;
}
}
TOS_CPU_INT_ENABLE();
return -1;
}
__KNL__ int pthread_id_free(pthread_t id)
{
TOS_CPU_CPSR_ALLOC();
if (id < 0 ||
id >= TOS_COUNT_OF(thread_ctl_table) ||
!thread_ctl_table[id]) {
return -1;
}
TOS_CPU_INT_DISABLE();
thread_ctl_table[id] = K_NULL;
TOS_CPU_INT_ENABLE();
return 0;
}
__KNL__ void pthread_data_clear(pthread_key_t key)
{
int i = 0;
pthread_ctl_t *the_ctl;
for (i = 0; i < TOS_COUNT_OF(thread_ctl_table); ++i) {
the_ctl = thread_ctl_table[i];
if (the_ctl && the_ctl->thread_data) {
the_ctl->thread_data[key] = K_NULL;
}
}
}
__STATIC__ int pthread_key_ctl_init(void)
{
int i = 0;
if (tos_bitmap_create_full(&pthread_key_ctl.key_bitmap,
pthread_key_ctl.key_bitmap_tbl,
PTHREAD_KEYS_MAX) != K_ERR_NONE) {
return -1;
}
for (i = 0; i < PTHREAD_KEYS_MAX; ++i) {
pthread_key_ctl.destructors[i] = K_NULL;
}
return 0;
}
__KNL__ pthread_key_t pthread_key_alloc(void)
{
int lsb;
lsb = tos_bitmap_lsb(&pthread_key_ctl.key_bitmap);
if (lsb > PTHREAD_KEYS_MAX) {
return -1;
}
tos_bitmap_reset(&pthread_key_ctl.key_bitmap, lsb);
return (pthread_key_t)lsb;
}
__KNL__ int pthread_key_is_alloc(pthread_key_t key)
{
if (key > PTHREAD_KEYS_MAX || key < 0) {
return K_FALSE;
}
return tos_bitmap_is_reset(&pthread_key_ctl.key_bitmap, key);
}
__KNL__ int pthread_key_free(pthread_key_t key)
{
if (key > PTHREAD_KEYS_MAX || key < 0) {
return -1;
}
if (tos_bitmap_is_set(&pthread_key_ctl.key_bitmap, key)) {
/* what we created is a full bitmap, if the bit is set means it is not used */
return -1;
}
/* make it avaliable again */
tos_bitmap_set(&pthread_key_ctl.key_bitmap, key);
return 0;
}
__KNL__ int pthread_key_destructor_register(pthread_key_t key, key_destructor_t destructor)
{
if (key > PTHREAD_KEYS_MAX || key < 0) {
return -1;
}
if (tos_bitmap_is_set(&pthread_key_ctl.key_bitmap, key)) {
/* what we created is a full bitmap, if the bit is set means it is not used */
return -1;
}
pthread_key_ctl.destructors[key] = destructor;
return 0;
}
__STATIC__ int pthread_key_destructor_is_register(pthread_key_t key)
{
if (key > PTHREAD_KEYS_MAX || key < 0) {
return K_FALSE;
}
if (tos_bitmap_is_set(&pthread_key_ctl.key_bitmap, key)) {
/* what we created is a full bitmap, if the bit is set means it is not used */
return K_FALSE;
}
return pthread_key_ctl.destructors[key] != K_NULL;
}
__KNL__ key_destructor_t pthread_key_destructor_get(pthread_key_t key)
{
if (!pthread_key_destructor_is_register(key)) {
return K_NULL;
}
return pthread_key_ctl.destructors[key];
}
__KNL__ int pthread_ctl_reap(int pthreads_ready2reap)
{
int i = 0;
pthread_ctl_t *the_ctl;
int pthreads_reaped = 0;
if (pthreads_ready2reap == 0) {
return 0;
}
for (i = 0; pthreads_ready2reap && i < TOS_COUNT_OF(thread_ctl_table); ++i) {
the_ctl = thread_ctl_table[i];
if (!the_ctl || the_ctl->threadstate != PTHREAD_STATE_EXITED) {
continue;
}
pthread_id_free((pthread_t)i);
tos_sem_destroy(&the_ctl->joinner_sem);
if (the_ctl->stackaddr) {
/* the_ctl is just on this stack */
tos_mmheap_free(the_ctl->stackaddr);
}
--pthreads_ready2reap;
++pthreads_reaped;
}
return pthreads_reaped;
}
__KNL__ void pthread_lock(void)
{
tos_mutex_pend(&pthread_mutex);
}
__KNL__ void pthread_unlock(void)
{
tos_mutex_post(&pthread_mutex);
}
__STATIC__ int pthread_lock_init(void)
{
if (tos_mutex_create(&pthread_mutex) != K_ERR_NONE) {
return -1;
}
return 0;
}
__KNL__ int pthread_init(void)
{
if (pthread_lock_init() != 0) {
return -1;
}
if (pthread_key_ctl_init() != 0) {
return -1;
}
return 0;
}