Changeset d50f3e5 in mainline


Ignore:
Timestamp:
2025-03-09T20:06:24Z (12 hours ago)
Author:
Matěj Volf <git@…>
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)
Message:

decrease scrope of pthread keys support

Location:
uspace/lib
Files:
1 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/libc.c

    raf28af6 rd50f3e5  
    173173void __libc_exit(int status)
    174174{
    175         fibril_run_exit_hooks(&main_fibril);
    176 
    177175        /*
    178176         * GCC extension __attribute__((destructor)),
  • uspace/lib/c/generic/private/fibril.h

    raf28af6 rd50f3e5  
    7070        fibril_owner_info_t *waits_for;
    7171        fibril_event_t *sleep_event;
    72 
    73         list_t exit_hooks;
    7472};
    75 
    76 typedef struct {
    77         link_t link;
    78         void (*func)(void);
    79 } fibril_hook_t;
    8073
    8174extern fibril_t *fibril_alloc(void);
     
    9386extern errno_t fibril_ipc_wait(ipc_call_t *, const struct timespec *);
    9487extern void fibril_ipc_poke(void);
    95 
    96 extern void fibril_run_exit_hooks(fibril_t *);
    9788
    9889/**
  • uspace/lib/c/generic/thread/fibril.c

    raf28af6 rd50f3e5  
    185185void fibril_setup(fibril_t *f)
    186186{
    187         list_initialize(&f->exit_hooks);
    188187        futex_lock(&fibril_futex);
    189188        list_append(&f->all_link, &fibril_list);
     
    846845}
    847846
    848 void fibril_run_exit_hooks(fibril_t *f)
    849 {
    850         list_foreach_safe(f->exit_hooks, cur, _next) {
    851                 fibril_hook_t *hook = list_get_instance(cur, fibril_hook_t, link);
    852                 list_remove(cur);
    853                 hook->func();
    854                 free(hook);
    855         }
    856 }
    857 
    858847/**
    859848 * Exit a fibril. Never returns.
     
    865854        // TODO: implement fibril_join() and remember retval
    866855        (void) retval;
    867 
    868         fibril_run_exit_hooks(fibril_self());
    869856
    870857        fibril_t *f = _ready_list_pop_nonblocking(false);
     
    931918}
    932919
    933 errno_t fibril_add_exit_hook(void (*hook)(void))
    934 {
    935         fibril_hook_t *h = malloc(sizeof(fibril_hook_t));
    936         if (!h)
    937                 return ENOMEM;
    938 
    939         DPRINTF("adding exit hook: function %p (fibril_hook_t structure at %p)\n", hook, h);
    940 
    941         h->func = hook;
    942         list_append(&h->link, &fibril_self()->exit_hooks);
    943         return EOK;
    944 }
    945 
    946920errno_t fibril_ipc_wait(ipc_call_t *call, const struct timespec *expires)
    947921{
  • uspace/lib/c/include/fibril.h

    raf28af6 rd50f3e5  
    7474extern __noreturn void fibril_exit(long);
    7575
    76 /** Add a function to be called after fibril exits, just before it is destroyed */
    77 extern errno_t fibril_add_exit_hook(void (*)(void));
    78 
    7976__HELENOS_DECLS_END;
    8077
  • uspace/lib/c/meson.build

    raf28af6 rd50f3e5  
    177177        'test/double_to_str.c',
    178178        'test/fibril/timer.c',
    179         'test/fibril/exit_hook.c',
    180179        'test/getopt.c',
    181180        'test/gsort.c',
  • uspace/lib/c/test/main.c

    raf28af6 rd50f3e5  
    3838PCUT_IMPORT(double_to_str);
    3939PCUT_IMPORT(fibril_timer);
    40 PCUT_IMPORT(fibril_exit_hook);
    4140PCUT_IMPORT(getopt);
    4241PCUT_IMPORT(gsort);
  • uspace/lib/posix/src/pthread/keys.c

    raf28af6 rd50f3e5  
    4040#include "../internal/common.h"
    4141
    42 #define DPRINTF(format, ...) ((void) 0)
     42#include <stdio.h>
     43#define DPRINTF(format, ...) printf("pthread_keys: " format, ##__VA_ARGS__)
    4344
    4445static fibril_local bool fibril_initialized = false;
     
    5152 */
    5253#define PTHREAD_KEYS_MAX 100
    53 static void (*destructors[PTHREAD_KEYS_MAX])(void *);
    5454
    5555static fibril_local void *key_data[PTHREAD_KEYS_MAX];
     
    5858{
    5959        // 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);
    6162                return NULL;
     63        }
    6264
    6365        assert(key < PTHREAD_KEYS_MAX);
     
    6567        assert(key > 0);
    6668
     69        DPRINTF("pthread_getspecific(%d) = %p\n", key, key_data[key]);
    6770        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         }
    8571}
    8672
    8773int pthread_setspecific(pthread_key_t key, const void *data)
    8874{
     75        DPRINTF("pthread_setspecific(%d, %p)\n", key, data);
    8976        if (!fibril_initialized) {
    9077                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 
    9578                for (unsigned i = 0; i < PTHREAD_KEYS_MAX; i++) {
    9679                        key_data[i] = NULL;
     
    10891int pthread_key_delete(pthread_key_t key)
    10992{
    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();
    12095        return EOK;
    12196}
     
    12499{
    125100        unsigned short k = atomic_fetch_add(&next_key, 1);
     101        DPRINTF("pthread_key_create(%p, %p) = %d\n", key, destructor, k);
    126102        if (k >= PTHREAD_KEYS_MAX) {
    127103                atomic_store(&next_key, PTHREAD_KEYS_MAX + 1);
    128104                return ELIMIT;
    129105        }
     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        }
    130113
    131         destructors[k] = destructor;
    132114        *key = k;
    133115        return EOK;
  • uspace/lib/posix/test/pthread/keys.c

    raf28af6 rd50f3e5  
    3636
    3737pthread_key_t key;
    38 int destructors_executed;
    39 
    40 static void destructor(void *_data)
    41 {
    42         destructors_executed++;
    43 }
    4438
    4539static errno_t simple_fibril(void *_arg)
     
    5751PCUT_TEST(pthread_keys_basic)
    5852{
    59         destructors_executed = 0;
    60         PCUT_ASSERT_INT_EQUALS(0, pthread_key_create(&key, destructor));
     53        PCUT_ASSERT_INT_EQUALS(0, pthread_key_create(&key, NULL));
    6154        PCUT_ASSERT_PTR_EQUALS(NULL, pthread_getspecific(key));
    6255
     
    7164        }
    7265
    73         PCUT_ASSERT_INT_EQUALS(0, destructors_executed);
    7466        PCUT_ASSERT_PTR_EQUALS((void *) 0x42, pthread_getspecific(key));
    7567
     
    7870        }
    7971
    80         PCUT_ASSERT_INT_EQUALS(1, destructors_executed);
    8172        PCUT_ASSERT_PTR_EQUALS((void *) 0x42, pthread_getspecific(key));
    8273}
Note: See TracChangeset for help on using the changeset viewer.