123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- * Copyright (c) 2018 Intel Corporation
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <kernel.h>
- #include <posix/pthread.h>
- #include <posix/pthread_key.h>
- struct k_sem pthread_key_sem;
- K_SEM_DEFINE(pthread_key_sem, 1, 1);
- /**
- * @brief Create a key for thread-specific data
- *
- * See IEEE 1003.1
- */
- int pthread_key_create(pthread_key_t *key,
- void (*destructor)(void *))
- {
- pthread_key_obj *new_key;
- *key = NULL;
- new_key = k_malloc(sizeof(pthread_key_obj));
- if (new_key == NULL) {
- return ENOMEM;
- }
- sys_slist_init(&(new_key->key_data_l));
- new_key->destructor = destructor;
- *key = (void *)new_key;
- return 0;
- }
- /**
- * @brief Delete a key for thread-specific data
- *
- * See IEEE 1003.1
- */
- int pthread_key_delete(pthread_key_t key)
- {
- pthread_key_obj *key_obj = (pthread_key_obj *)key;
- pthread_key_data *key_data;
- sys_snode_t *node_l, *next_node_l;
- k_sem_take(&pthread_key_sem, K_FOREVER);
- /* Delete thread-specific elements associated with the key */
- SYS_SLIST_FOR_EACH_NODE_SAFE(&(key_obj->key_data_l),
- node_l, next_node_l) {
- /* Remove the object from the list key_data_l */
- key_data = (pthread_key_data *)
- sys_slist_get(&(key_obj->key_data_l));
- /* Deallocate the object's memory */
- k_free((void *)key_data);
- }
- k_free((void *)key_obj);
- k_sem_give(&pthread_key_sem);
- return 0;
- }
- /**
- * @brief Associate a thread-specific value with a key
- *
- * See IEEE 1003.1
- */
- int pthread_setspecific(pthread_key_t key, const void *value)
- {
- pthread_key_obj *key_obj = (pthread_key_obj *)key;
- struct posix_thread *thread = (struct posix_thread *)pthread_self();
- pthread_key_data *key_data;
- pthread_thread_data *thread_spec_data;
- sys_snode_t *node_l;
- int retval = 0;
- /* Traverse the list of keys set by the thread, looking for key.
- * If the key is already in the list, re-assign its value.
- * Else add the key to the thread's list.
- */
- k_sem_take(&pthread_key_sem, K_FOREVER);
- SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) {
- thread_spec_data = (pthread_thread_data *)node_l;
- if (thread_spec_data->key == key_obj) {
- /* Key is already present so
- * associate thread specific data
- */
- thread_spec_data->spec_data = (void *)value;
- goto out;
- }
- }
- if (node_l == NULL) {
- key_data = k_malloc(sizeof(pthread_key_data));
- if (key_data == NULL) {
- retval = ENOMEM;
- goto out;
- } else {
- /* Associate thread specific data, initialize new key */
- key_data->thread_data.key = key;
- key_data->thread_data.spec_data = (void *)value;
- /* Append new thread key data to thread's key list */
- sys_slist_append((&thread->key_list),
- (sys_snode_t *)(&key_data->thread_data));
- /* Append new key data to the key object's list */
- sys_slist_append(&(key_obj->key_data_l),
- (sys_snode_t *)key_data);
- }
- }
- out:
- k_sem_give(&pthread_key_sem);
- return retval;
- }
- /**
- * @brief Get the thread-specific value associated with the key
- *
- * See IEEE 1003.1
- */
- void *pthread_getspecific(pthread_key_t key)
- {
- pthread_key_obj *key_obj = (pthread_key_obj *)key;
- struct posix_thread *thread = (struct posix_thread *)pthread_self();
- pthread_thread_data *thread_spec_data;
- void *value = NULL;
- sys_snode_t *node_l;
- k_sem_take(&pthread_key_sem, K_FOREVER);
- node_l = sys_slist_peek_head(&(thread->key_list));
- /* Traverse the list of keys set by the thread, looking for key */
- SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) {
- thread_spec_data = (pthread_thread_data *)node_l;
- if (thread_spec_data->key == key_obj) {
- /* Key is present, so get the set thread data */
- value = thread_spec_data->spec_data;
- break;
- }
- }
- k_sem_give(&pthread_key_sem);
- return value;
- }
|