Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/src/pthread/keys.c

    r25ee7ec5 r9b8be79  
    3636#include <pthread.h>
    3737#include <errno.h>
    38 #include <fibril.h>
    39 #include <stdatomic.h>
    4038#include "../internal/common.h"
    41 
    42 #define DPRINTF(format, ...) ((void) 0)
    43 
    44 static fibril_local bool fibril_initialized = false;
    45 static atomic_ushort next_key = 1; // skip the key 'zero'
    46 
    47 /*
    48  * For now, we just support maximum of 100 keys. This can be improved
    49  * in the future by implementing a dynamically growing array with
    50  * reallocations, but that will require more synchronization.
    51  */
    52 #define PTHREAD_KEYS_MAX 100
    53 static void (*destructors[PTHREAD_KEYS_MAX])(void *);
    54 
    55 static fibril_local void *key_data[PTHREAD_KEYS_MAX];
    5639
    5740void *pthread_getspecific(pthread_key_t key)
    5841{
    59         // initialization is done in setspecific -> if not initialized, nothing was set yet
    60         if (!fibril_initialized)
    61                 return NULL;
    62 
    63         assert(key < PTHREAD_KEYS_MAX);
    64         assert(key < next_key);
    65         assert(key > 0);
    66 
    67         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 being
    79                  * created), key_data[i] has never been assigned, therefore it
    80                  * 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         }
     42        not_implemented();
     43        return NULL;
    8544}
    8645
    8746int pthread_setspecific(pthread_key_t key, const void *data)
    8847{
    89         if (!fibril_initialized) {
    90                 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                 for (unsigned i = 0; i < PTHREAD_KEYS_MAX; i++) {
    96                         key_data[i] = NULL;
    97                 }
    98                 fibril_initialized = true;
    99         }
    100         assert(key < PTHREAD_KEYS_MAX);
    101         assert(key < next_key);
    102         assert(key > 0);
    103 
    104         key_data[key] = (void *) data;
    105         return EOK;
     48        not_implemented();
     49        return ENOTSUP;
    10650}
    10751
    10852int pthread_key_delete(pthread_key_t key)
    10953{
    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
    120         return EOK;
     54        not_implemented();
     55        return ENOTSUP;
    12156}
    12257
    12358int pthread_key_create(pthread_key_t *key, void (*destructor)(void *))
    12459{
    125         unsigned short k = atomic_fetch_add(&next_key, 1);
    126         if (k >= PTHREAD_KEYS_MAX) {
    127                 atomic_store(&next_key, PTHREAD_KEYS_MAX + 1);
    128                 return ELIMIT;
    129         }
    130 
    131         destructors[k] = destructor;
    132         *key = k;
    133         return EOK;
     60        not_implemented();
     61        return ENOTSUP;
    13462}
    13563
Note: See TracChangeset for help on using the changeset viewer.