Changeset d30e067 in mainline for uspace/lib/c


Ignore:
Timestamp:
2025-03-02T20:02:33Z (5 months ago)
Author:
Miroslav Cimerman <mc@…>
Children:
8cdf360
Parents:
7debda3 (diff), 4285f384 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge 'upstream/master' into helenraid-para

Location:
uspace/lib/c
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/arm32/src/atomic.c

    r7debda3 rd30e067  
    8686}
    8787
     88unsigned char __atomic_exchange_1(volatile void *mem0, unsigned char val,
     89    int model)
     90{
     91        volatile unsigned char *mem = mem0;
     92
     93        (void) model;
     94
     95        unsigned ret;
     96
     97        /*
     98         * The following instructions between labels 1 and 2 constitute a
     99         * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
     100         * the kernel will restart it.
     101         */
     102        asm volatile (
     103            "1:\n"
     104            "   adr %[ret], 1b\n"
     105            "   str %[ret], %[rp0]\n"
     106            "   adr %[ret], 2f\n"
     107            "   str %[ret], %[rp1]\n"
     108            "   ldrb %[ret], %[addr]\n"
     109            "   strb %[imm], %[addr]\n"
     110            "2:\n"
     111            : [ret] "=&r" (ret),
     112              [rp0] "=m" (ras_page[0]),
     113              [rp1] "=m" (ras_page[1]),
     114              [addr] "+m" (*mem)
     115            : [imm] "r" (val)
     116        );
     117
     118        ras_page[0] = 0;
     119        ras_page[1] = 0xffffffff;
     120
     121        return ret;
     122}
     123
     124unsigned short __atomic_exchange_2(volatile void *mem0, unsigned short val,
     125    int model)
     126{
     127        volatile unsigned short *mem = mem0;
     128
     129        (void) model;
     130
     131        unsigned ret;
     132
     133        /*
     134         * The following instructions between labels 1 and 2 constitute a
     135         * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
     136         * the kernel will restart it.
     137         */
     138        asm volatile (
     139            "1:\n"
     140            "   adr %[ret], 1b\n"
     141            "   str %[ret], %[rp0]\n"
     142            "   adr %[ret], 2f\n"
     143            "   str %[ret], %[rp1]\n"
     144            "   ldrh %[ret], %[addr]\n"
     145            "   strh %[imm], %[addr]\n"
     146            "2:\n"
     147            : [ret] "=&r" (ret),
     148              [rp0] "=m" (ras_page[0]),
     149              [rp1] "=m" (ras_page[1]),
     150              [addr] "+m" (*mem)
     151            : [imm] "r" (val)
     152        );
     153
     154        ras_page[0] = 0;
     155        ras_page[1] = 0xffffffff;
     156
     157        return ret;
     158}
     159
     160unsigned __atomic_exchange_4(volatile void *mem0, unsigned val, int model)
     161{
     162        volatile unsigned *mem = mem0;
     163
     164        (void) model;
     165
     166        unsigned ret;
     167
     168        /*
     169         * The following instructions between labels 1 and 2 constitute a
     170         * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
     171         * the kernel will restart it.
     172         */
     173        asm volatile (
     174            "1:\n"
     175            "   adr %[ret], 1b\n"
     176            "   str %[ret], %[rp0]\n"
     177            "   adr %[ret], 2f\n"
     178            "   str %[ret], %[rp1]\n"
     179            "   ldr %[ret], %[addr]\n"
     180            "   str %[imm], %[addr]\n"
     181            "2:\n"
     182            : [ret] "=&r" (ret),
     183              [rp0] "=m" (ras_page[0]),
     184              [rp1] "=m" (ras_page[1]),
     185              [addr] "+m" (*mem)
     186            : [imm] "r" (val)
     187        );
     188
     189        ras_page[0] = 0;
     190        ras_page[1] = 0xffffffff;
     191
     192        return ret;
     193}
     194
    88195unsigned short __atomic_fetch_add_2(volatile void *mem0, unsigned short val,
    89196    int model)
     
    164271}
    165272
     273bool __atomic_test_and_set(volatile void *ptr, int memorder)
     274{
     275        volatile unsigned char *b = ptr;
     276
     277        unsigned char orig = __atomic_exchange_n(b, (unsigned char) true, memorder);
     278        return orig != 0;
     279}
     280
    166281void __sync_synchronize(void)
    167282{
  • uspace/lib/c/generic/device/hw_res.c

    r7debda3 rd30e067  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * Copyright (c) 2010 Lenka Trochtova
    44 * All rights reserved.
     
    162162}
    163163
    164 /** Get bus flags.
     164/** Query legacy IO claims.
    165165 *
    166166 * @param sess HW res session
    167  * @param rflags Place to store the flags
    168  *
    169  * @return Error code.
    170  *
    171  */
    172 errno_t hw_res_get_flags(async_sess_t *sess, hw_res_flags_t *rflags)
    173 {
    174         async_exch_t *exch = async_exchange_begin(sess);
    175 
    176         sysarg_t flags;
     167 * @param rclaims Place to store the claims
     168 *
     169 * @return Error code.
     170 *
     171 */
     172errno_t hw_res_query_legacy_io(async_sess_t *sess, hw_res_claims_t *rclaims)
     173{
     174        async_exch_t *exch = async_exchange_begin(sess);
     175
     176        sysarg_t claims;
    177177        const errno_t ret = async_req_1_1(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
    178             HW_RES_GET_FLAGS, &flags);
     178            HW_RES_QUERY_LEGACY_IO, &claims);
    179179
    180180        async_exchange_end(exch);
    181181
    182182        if (ret == EOK)
    183                 *rflags = flags;
     183                *rclaims = claims;
     184
     185        return ret;
     186}
     187
     188/** Claim legacy IO devices.
     189 *
     190 * @param sess HW res session
     191 * @param claims Claims
     192 *
     193 * @return Error code.
     194 *
     195 */
     196errno_t hw_res_claim_legacy_io(async_sess_t *sess, hw_res_claims_t claims)
     197{
     198        async_exch_t *exch = async_exchange_begin(sess);
     199
     200        const errno_t ret = async_req_2_0(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
     201            HW_RES_CLAIM_LEGACY_IO, claims);
     202
     203        async_exchange_end(exch);
    184204
    185205        return ret;
  • uspace/lib/c/generic/elf/elf_load.c

    r7debda3 rd30e067  
    6060        rtld_t *env;
    6161#endif
    62         errno_t rc;
     62        errno_t rc = EOK;
     63        elf_finfo_t *finfo = &info->finfo;
    6364
    64         rc = elf_load_file(file, 0, &info->finfo);
     65        rc = elf_load_file(file, 0, finfo);
    6566        if (rc != EOK) {
    66                 DPRINTF("Failed to load executable '%s'.\n", file_name);
     67                DPRINTF("Failed to load executable.\n");
    6768                return rc;
    6869        }
    6970
     71#ifdef CONFIG_RTLD
     72        DPRINTF("- prog dynamic: %p\n", finfo->dynamic);
     73        rc = rtld_prog_process(finfo, &env);
     74        if (rc != EOK) {
     75                DPRINTF("Failed to process executable.\n");
     76                return rc;
     77        }
     78        info->env = env;
     79        return EOK;
     80#else
    7081        if (info->finfo.dynamic == NULL) {
    71                 /* Statically linked program */
    72                 DPRINTF("Binary is statically linked.\n");
    7382                info->env = NULL;
    7483                return EOK;
    7584        }
    7685
    77         DPRINTF("Binary is dynamically linked.\n");
    78 #ifdef CONFIG_RTLD
    79         DPRINTF("- prog dynamic: %p\n", info->finfo.dynamic);
    80 
    81         rc = rtld_prog_process(&info->finfo, &env);
    82         info->env = env;
    83 #else
    84         rc = ENOTSUP;
     86        DPRINTF("Error: trying to run a dynamically-linked executable with CONFIG_RTLD disabled.\n");
     87        return ENOTSUP;
    8588#endif
    86         return rc;
    8789}
    8890
  • uspace/lib/c/generic/libc.c

    r7debda3 rd30e067  
    9696
    9797#ifdef CONFIG_RTLD
    98         if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
     98        if (__pcb == NULL) {
     99                /*
     100                 * A binary loaded by kernel, not the loader.
     101                 * Noop - code loaded by kernel doesn't need RTLD.
     102                 */
     103        } else {
     104                assert(__pcb->rtld_runtime != NULL);
    99105                runtime_env = (rtld_t *) __pcb->rtld_runtime;
    100         } else {
    101                 if (rtld_init_static() != EOK)
    102                         abort();
    103106        }
    104107#endif
  • uspace/lib/c/generic/rtld/module.c

    r7debda3 rd30e067  
    5555#include "../private/libc.h"
    5656
    57 /** Create module for static executable.
    58  *
     57/** Create the "entrypoint" module, of the program executable
     58 *
     59 * @param p_info Program ELF file info
    5960 * @param rtld Run-time dynamic linker
    6061 * @param rmodule Place to store pointer to new module or @c NULL
    6162 * @return EOK on success, ENOMEM if out of memory
    6263 */
    63 errno_t module_create_static_exec(rtld_t *rtld, module_t **rmodule)
     64errno_t module_create_entrypoint(elf_finfo_t *p_info, rtld_t *rtld, module_t **rmodule)
    6465{
    6566        module_t *module;
     67        bool is_dynamic = p_info->dynamic != NULL;
     68        DPRINTF("module_create_entrypoint\n");
    6669
    6770        module = calloc(1, sizeof(module_t));
    68         if (module == NULL) {
    69                 DPRINTF("malloc failed\n");
     71        if (module == NULL)
    7072                return ENOMEM;
    71         }
    72 
     73
     74        uintptr_t bias = elf_get_bias(p_info->base);
     75
     76        /*
     77         * First we need to process dynamic sections of the executable
     78         * program and insert it into the module graph.
     79         */
     80        if (is_dynamic) {
     81                DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
     82                dynamic_parse(p_info->dynamic, bias, &module->dyn);
     83        } else {
     84                DPRINTF("Executable is not dynamically linked\n");
     85        }
     86
     87        module->bias = bias;
    7388        module->id = rtld_get_next_id(rtld);
    7489        module->dyn.soname = "[program]";
     
    7691        module->rtld = rtld;
    7792        module->exec = true;
    78         module->local = true;
    79 
    80         const elf_segment_header_t *tls =
    81             elf_get_phdr(__progsymbols.elfstart, PT_TLS);
    82 
    83         if (tls) {
    84                 uintptr_t bias = elf_get_bias(__progsymbols.elfstart);
    85                 module->tdata = (void *) (tls->p_vaddr + bias);
    86                 module->tdata_size = tls->p_filesz;
    87                 module->tbss_size = tls->p_memsz - tls->p_filesz;
    88                 module->tls_align = tls->p_align;
    89         } else {
    90                 module->tdata = NULL;
    91                 module->tdata_size = 0;
    92                 module->tbss_size = 0;
    93                 module->tls_align = 1;
    94         }
     93        module->local = !is_dynamic;
     94
     95        module->tdata = p_info->tls.tdata;
     96        module->tdata_size = p_info->tls.tdata_size;
     97        module->tbss_size = p_info->tls.tbss_size;
     98        module->tls_align = p_info->tls.tls_align;
     99
     100        DPRINTF("prog tdata at %p size %zu, tbss size %zu\n",
     101        module->tdata, module->tdata_size, module->tbss_size);
    95102
    96103        list_append(&module->modules_link, &rtld->modules);
     
    398405         * be correct, "zero" offset (i.e. the total size) must be aligned
    399406         * to the strictest alignment present.
    400          * Note that the padding is actually in front of the TLS data,
    401          * not after it.
    402407         */
    403408        rtld->tls_size = ALIGN_UP(rtld->tls_size, rtld->tls_align);
    404409
    405         /* Space for the TCB. */
     410        /*
     411         * Space for the TCB.
     412         * Later, the TLS zero offset is equal to the pointer to tcb_t, so
     413         * adding the sizeof(tcb_t) block AFTER we calculated the alignment
     414         * of the remainder above is correct.
     415         */
    406416        rtld->tls_size += sizeof(tcb_t);
    407417#endif
  • uspace/lib/c/generic/rtld/rtld.c

    r7debda3 rd30e067  
    4343
    4444rtld_t *runtime_env;
    45 static rtld_t rt_env_static;
    46 
    47 /** Initialize the runtime linker for use in a statically-linked executable. */
    48 errno_t rtld_init_static(void)
    49 {
    50         errno_t rc;
    51 
    52         runtime_env = &rt_env_static;
    53         list_initialize(&runtime_env->modules);
    54         list_initialize(&runtime_env->imodules);
    55         runtime_env->program = NULL;
    56         runtime_env->next_id = 1;
    57 
    58         rc = module_create_static_exec(runtime_env, NULL);
    59         if (rc != EOK)
    60                 return rc;
    61 
    62         modules_process_tls(runtime_env);
    63 
    64         return EOK;
    65 }
    66 
    67 /** Initialize and process a dynamically linked executable.
     45
     46/** Initialize and process an executable.
    6847 *
    6948 * @param p_info Program info
     
    7352{
    7453        rtld_t *env;
    75         module_t *prog;
    76 
    77         DPRINTF("Load dynamically linked program.\n");
     54        bool is_dynamic = p_info->dynamic != NULL;
     55        DPRINTF("rtld_prog_process\n");
    7856
    7957        /* Allocate new RTLD environment to pass to the loaded program */
     
    8260                return ENOMEM;
    8361
    84         env->next_id = 1;
    85 
    86         prog = calloc(1, sizeof(module_t));
    87         if (prog == NULL) {
    88                 free(env);
    89                 return ENOMEM;
    90         }
    91 
    92         /*
    93          * First we need to process dynamic sections of the executable
    94          * program and insert it into the module graph.
    95          */
    96 
    97         DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
    98         dynamic_parse(p_info->dynamic, 0, &prog->dyn);
    99         prog->bias = 0;
    100         prog->dyn.soname = "[program]";
    101         prog->rtld = env;
    102         prog->id = rtld_get_next_id(env);
    103         prog->exec = true;
    104         prog->local = false;
    105 
    106         prog->tdata = p_info->tls.tdata;
    107         prog->tdata_size = p_info->tls.tdata_size;
    108         prog->tbss_size = p_info->tls.tbss_size;
    109         prog->tls_align = p_info->tls.tls_align;
    110 
    111         DPRINTF("prog tdata at %p size %zu, tbss size %zu\n",
    112             prog->tdata, prog->tdata_size, prog->tbss_size);
    113 
    114         /* Initialize list of loaded modules */
    11562        list_initialize(&env->modules);
    11663        list_initialize(&env->imodules);
    117         list_append(&prog->modules_link, &env->modules);
     64        env->next_id = 1;
     65
     66        module_t *module;
     67        errno_t rc = module_create_entrypoint(p_info, env, &module);
     68        if (rc != EOK) {
     69                free(env);
     70                return rc;
     71        }
    11872
    11973        /* Pointer to program module. Used as root of the module graph. */
    120         env->program = prog;
     74        env->program = module;
    12175
    12276        /*
     
    12478         */
    12579
    126         DPRINTF("Load all program dependencies\n");
    127         errno_t rc = module_load_deps(prog, 0);
    128         if (rc != EOK) {
    129                 return rc;
     80        if (is_dynamic) {
     81                DPRINTF("Load all program dependencies\n");
     82                rc = module_load_deps(module, 0);
     83                if (rc != EOK) {
     84                        free(module);
     85                        free(env);
     86                        return rc;
     87                }
    13088        }
    13189
     
    13795         */
    13896
    139         /* Process relocations in all modules */
    140         DPRINTF("Relocate all modules\n");
    141         modules_process_relocs(env, prog);
    142 
    143         *rre = env;
     97        if (is_dynamic) {
     98                /* Process relocations in all modules */
     99                DPRINTF("Relocate all modules\n");
     100                modules_process_relocs(env, module);
     101        }
     102
     103        if (rre != NULL)
     104                *rre = env;
    144105        return EOK;
    145106}
  • uspace/lib/c/generic/thread/fibril_synch.c

    r7debda3 rd30e067  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2009 Jakub Jermar
    34 * All rights reserved.
     
    112113#define AWAITER_INIT { .fid = fibril_get_id() }
    113114
    114 static void print_deadlock(fibril_owner_info_t *oi)
     115/** Print deadlock message nad blocking chain.
     116 *
     117 * @param oi Owner info for the resource being acquired
     118 * @param f Fibril that is trying to acquire the resource
     119 */
     120static void print_deadlock(fibril_owner_info_t *oi, fibril_t *f)
    115121{
    116122        // FIXME: Print to stderr.
    117 
    118         fibril_t *f = (fibril_t *) fibril_get_id();
    119123
    120124        if (deadlocked) {
     
    143147}
    144148
    145 static void check_fibril_for_deadlock(fibril_owner_info_t *oi, fibril_t *fib)
    146 {
     149/** Check whether fibril trying to acquire a resource will cause deadlock.
     150 *
     151 * @param wanted_oi Owner info for the primitive that the fibril wants
     152 * @param fib Fibril that wants to aquire the primitive
     153 */
     154static void check_fibril_for_deadlock(fibril_owner_info_t *wanted_oi,
     155    fibril_t *fib)
     156{
     157        fibril_owner_info_t *oi;
     158
    147159        futex_assert_is_locked(&fibril_synch_futex);
    148160
     161        oi = wanted_oi;
    149162        while (oi && oi->owned_by) {
    150163                if (oi->owned_by == fib) {
    151164                        futex_unlock(&fibril_synch_futex);
    152                         print_deadlock(oi);
     165                        print_deadlock(wanted_oi, fib);
    153166                        abort();
    154167                }
     
    157170}
    158171
     172/** Check whether trying to acquire a resource will cause deadlock.
     173 *
     174 * @param oi Owner info for the primitive that the current fibril wants
     175 */
    159176static void check_for_deadlock(fibril_owner_info_t *oi)
    160177{
     
    246263        futex_lock(&fibril_synch_futex);
    247264
    248         if (!frw->writers) {
     265        if (!frw->writers && list_empty(&frw->waiters)) {
    249266                /* Consider the first reader the owner. */
    250267                if (frw->readers++ == 0)
  • uspace/lib/c/generic/thread/tls.c

    r7debda3 rd30e067  
    5959#endif
    6060
    61 static ptrdiff_t _tcb_data_offset(void)
     61static ptrdiff_t _tcb_data_offset(const void *elf)
    6262{
    6363        const elf_segment_header_t *tls =
    64             elf_get_phdr(__progsymbols.elfstart, PT_TLS);
     64            elf_get_phdr(elf, PT_TLS);
    6565
    6666        size_t tls_align = tls ? tls->p_align : 1;
     
    7474}
    7575
    76 /** Get address of static TLS block */
     76/** Get address of static TLS block - only when RTLD is not initialized  */
    7777void *tls_get(void)
    7878{
     
    8080        assert(runtime_env == NULL);
    8181#endif
    82         return (uint8_t *)__tcb_get() + _tcb_data_offset();
     82        return (uint8_t *)__tcb_get() + _tcb_data_offset(__progsymbols.elfstart);
    8383}
    8484
    8585static tcb_t *tls_make_generic(const void *elf, void *(*alloc)(size_t, size_t))
    8686{
     87        /*
     88         * See also rtld/module.c -> modules_process_tls(), where we have less
     89         * messy code for the dynamic-linking version of this.
     90         */
    8791        assert(!elf_get_phdr(elf, PT_DYNAMIC));
    8892#ifdef CONFIG_RTLD
     
    100104        assert(tls_align <= PAGE_SIZE);
    101105
     106        /*
     107         * FIXME: the calculation of alloc_size shouldn't include the alignment
     108         * of tcb_t (at least in Variant II)
     109         * See https://github.com/HelenOS/helenos/pull/240/files/4ef27ebf98a0656e09889b7d00efdec03343f1aa#r1929592924
     110         * (you will also need to fix _tcb_data_offset)
     111         */
     112
    102113#ifdef CONFIG_TLS_VARIANT_1
    103114        size_t alloc_size =
     
    114125#ifdef CONFIG_TLS_VARIANT_1
    115126        tcb_t *tcb = area;
    116         uint8_t *data = (uint8_t *)tcb + _tcb_data_offset();
     127        uint8_t *data = (uint8_t *)tcb + _tcb_data_offset(elf);
    117128        memset(tcb, 0, sizeof(*tcb));
    118129#else
    119130        uint8_t *data = area;
    120         tcb_t *tcb = (tcb_t *) (data - _tcb_data_offset());
     131        tcb_t *tcb = (tcb_t *) (data - _tcb_data_offset(elf));
    121132        memset(tcb, 0, sizeof(tcb_t));
    122133        tcb->self = tcb;
  • uspace/lib/c/include/device/hw_res.h

    r7debda3 rd30e067  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * Copyright (c) 2010 Lenka Trochtova
    44 * All rights reserved.
     
    5757        HW_RES_DMA_CHANNEL_SETUP,
    5858        HW_RES_DMA_CHANNEL_REMAIN,
    59         HW_RES_GET_FLAGS
     59        HW_RES_QUERY_LEGACY_IO,
     60        HW_RES_CLAIM_LEGACY_IO
    6061} hw_res_method_t;
    6162
     
    118119}
    119120
     121/** Claims to legacy devices */
    120122typedef enum {
    121         /** This is an PCI/ISA bridge, not 'classic' ISA bus */
    122         hwf_isa_bridge = 0x1
    123 } hw_res_flags_t;
     123        /** 'Legacy' ISA IDE I/O ranges */
     124        hwc_isa_ide = 0x1
     125} hw_res_claims_t;
    124126
    125127extern errno_t hw_res_get_resource_list(async_sess_t *, hw_resource_list_t *);
     
    131133    uint32_t, uint8_t);
    132134extern errno_t hw_res_dma_channel_remain(async_sess_t *, unsigned, size_t *);
    133 extern errno_t hw_res_get_flags(async_sess_t *, hw_res_flags_t *);
     135extern errno_t hw_res_query_legacy_io(async_sess_t *, hw_res_claims_t *);
     136extern errno_t hw_res_claim_legacy_io(async_sess_t *, hw_res_claims_t);
    134137
    135138#endif
  • uspace/lib/c/include/rtld/module.h

    r7debda3 rd30e067  
    4141#include <types/rtld/rtld.h>
    4242
    43 extern errno_t module_create_static_exec(rtld_t *, module_t **);
     43extern errno_t module_create_entrypoint(elf_finfo_t *, rtld_t *, module_t **);
    4444extern void module_process_relocs(module_t *);
    4545extern module_t *module_find(rtld_t *, const char *);
  • uspace/lib/c/include/rtld/rtld.h

    r7debda3 rd30e067  
    4545extern rtld_t *runtime_env;
    4646
    47 extern errno_t rtld_init_static(void);
    4847extern errno_t rtld_prog_process(elf_finfo_t *, rtld_t **);
    4948extern tcb_t *rtld_tls_make(rtld_t *);
Note: See TracChangeset for help on using the changeset viewer.