Changeset d50f3e5 in mainline for uspace/lib/posix/src/pthread/keys.c
- Timestamp:
- 2025-03-09T20:06:24Z (16 hours ago)
- Children:
- 53e652d
- Parents:
- af28af6
- git-author:
- Matěj Volf <git@…> (2025-03-09 20:05:51)
- git-committer:
- Matěj Volf <git@…> (2025-03-09 20:06:24)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/src/pthread/keys.c
raf28af6 rd50f3e5 40 40 #include "../internal/common.h" 41 41 42 #define DPRINTF(format, ...) ((void) 0) 42 #include <stdio.h> 43 #define DPRINTF(format, ...) printf("pthread_keys: " format, ##__VA_ARGS__) 43 44 44 45 static fibril_local bool fibril_initialized = false; … … 51 52 */ 52 53 #define PTHREAD_KEYS_MAX 100 53 static void (*destructors[PTHREAD_KEYS_MAX])(void *);54 54 55 55 static fibril_local void *key_data[PTHREAD_KEYS_MAX]; … … 58 58 { 59 59 // initialization is done in setspecific -> if not initialized, nothing was set yet 60 if (!fibril_initialized) 60 if (!fibril_initialized) { 61 DPRINTF("pthread_getspecific(%d) = NULL (uninitialized)\n", key); 61 62 return NULL; 63 } 62 64 63 65 assert(key < PTHREAD_KEYS_MAX); … … 65 67 assert(key > 0); 66 68 69 DPRINTF("pthread_getspecific(%d) = %p\n", key, key_data[key]); 67 70 return key_data[key]; 68 }69 70 static void pthread_key_on_fibril_exit(void)71 {72 if (!fibril_initialized)73 return;74 75 for (unsigned i = 0; i < PTHREAD_KEYS_MAX; i++) {76 /*77 * Note that this doesn't cause a race with pthread_key_create:78 * if key `i` has not been assigned yet (it could be just being79 * created), key_data[i] has never been assigned, therefore it80 * is NULL, and the destructor is not checked at all.81 */82 if (key_data[i] != NULL && destructors[i] != NULL)83 destructors[i](key_data[i]);84 }85 71 } 86 72 87 73 int pthread_setspecific(pthread_key_t key, const void *data) 88 74 { 75 DPRINTF("pthread_setspecific(%d, %p)\n", key, data); 89 76 if (!fibril_initialized) { 90 77 DPRINTF("initializing pthread keys\n"); 91 errno_t res = fibril_add_exit_hook(pthread_key_on_fibril_exit);92 if (res != EOK)93 return res;94 95 78 for (unsigned i = 0; i < PTHREAD_KEYS_MAX; i++) { 96 79 key_data[i] = NULL; … … 108 91 int pthread_key_delete(pthread_key_t key) 109 92 { 110 /* 111 * FIXME: this can cause a data race if another fibrill concurrently 112 * runs on_fibril_exit. The obvious solution is to add a rwlock on 113 * the destructors array, which will be needed anyway if we want to 114 * support unlimited number of keys. 115 */ 116 destructors[key] = NULL; 117 key_data[key] = NULL; 118 119 // TODO: the key could also be reused 93 // see https://github.com/HelenOS/helenos/pull/245#issuecomment-2706795848 94 not_implemented(); 120 95 return EOK; 121 96 } … … 124 99 { 125 100 unsigned short k = atomic_fetch_add(&next_key, 1); 101 DPRINTF("pthread_key_create(%p, %p) = %d\n", key, destructor, k); 126 102 if (k >= PTHREAD_KEYS_MAX) { 127 103 atomic_store(&next_key, PTHREAD_KEYS_MAX + 1); 128 104 return ELIMIT; 129 105 } 106 if (destructor != NULL) { 107 static int __counter = 0; 108 if (__counter == 0) { 109 fprintf(stderr, "pthread_key_create: destructors not supported\n"); 110 } 111 __counter++; 112 } 130 113 131 destructors[k] = destructor;132 114 *key = k; 133 115 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.