Changeset 3fcea34 in mainline for uspace/lib/c


Ignore:
Timestamp:
2024-09-20T12:16:28Z (10 months ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
d3109ff
Parents:
2cf8f994
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-20 11:42:13)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-20 12:16:28)
Message:

Simplify the SYS_THREAD_CREATE syscall interface

Removed the beefy uarg structure. Instead, the syscall gets two
parameters: %pc (program counter) and %sp (stack pointer). It starts
a thread with those values in corresponding registers, with no other
fuss whatsoever.

libc initializes threads by storing any other needed arguments on
the stack and retrieving them in thread_entry. Importantly, this
includes the address of the
thread_main function which is now
called indirectly to fix dynamic linking issues on some archs.

There's a bit of weirdness on SPARC and IA-64, because of their
stacked register handling. The current solution is that we require
some space *above* the stack pointer to be available for those
architectures. I think for SPARC, it can be made more normal.

For the remaining ones, we can (probably) just set the initial
%sp to the top edge of the stack. There's some lingering offsets
on some archs just because I didn't want to accidentally break
anything. The initial thread bringup should be functionally
unchanged from the previous state, and no binaries are currently
multithreaded except thread1 test, so there should be minimal
risk of breakage. Naturally, I tested all available emulator
builds, save for msim.

Location:
uspace/lib/c
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/abs32le/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3636#define _LIBC_abs32le_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     44
     45        sp[-1] = (uintptr_t) arg;
     46        sp[-2] = (uintptr_t) main;
     47
     48        return (uintptr_t) sp;
     49}
     50
    3851#endif
    3952
  • uspace/lib/c/arch/abs32le/src/thread_entry.c

    r2cf8f994 r3fcea34  
    3030 */
    3131
     32#include <stdbool.h>
    3233#include <stddef.h>
    3334#include "../../../generic/private/thread.h"
     
    3536void __thread_entry(void)
    3637{
    37         __thread_main(NULL);
     38        while (true)
     39                ;
    3840}
    3941
  • uspace/lib/c/arch/amd64/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3636#define _LIBC_amd64_THREAD_H_
    3737
     38#include <align.h>
     39#include <stddef.h>
     40#include <stdint.h>
     41
     42static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     43    void (*main)(void *), void *arg)
     44{
     45        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     46
     47        *--sp = (uintptr_t) arg;
     48        *--sp = (uintptr_t) main;
     49
     50        return (uintptr_t) sp;
     51}
     52
    3853#endif
    3954
  • uspace/lib/c/arch/amd64/src/thread_entry.S

    r2cf8f994 r3fcea34  
    3535#
    3636SYMBOL_BEGIN(__thread_entry)
     37        # Pop libc thread entry function and argument
     38        popq %rax
     39        popq %rdi
     40
    3741        #
    3842        # Create the first stack frame.
     
    4246        movq %rsp, %rbp
    4347
    44         #
    45         # RAX contains address of uarg
    46         #
    47         movq %rax, %rdi
    48         call FUNCTION_REF(__thread_main)
     48        call *%rax
    4949SYMBOL_END(__thread_entry)
  • uspace/lib/c/arch/arm32/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3737#define _LIBC_arm32_THREAD_H_
    3838
     39#include <align.h>
     40
     41static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     42    void (*main)(void *), void *arg)
     43{
     44        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     45
     46        *--sp = (uintptr_t) main;
     47        *--sp = (uintptr_t) arg;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3952#endif
    4053
  • uspace/lib/c/arch/arm32/src/thread_entry.S

    r2cf8f994 r3fcea34  
    3535#
    3636SYMBOL(__thread_entry)
     37        # Pop libc entry function and its argument.
     38        pop { r0, r4 }
     39
    3740        #
    3841        # Create the first stack frame.
     
    4346        sub fp, ip, #4
    4447
    45         b __thread_main
     48        bx r4
  • uspace/lib/c/arch/arm64/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3636#define _LIBC_arm64_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     44
     45        *--sp = (uintptr_t) arg;
     46        *--sp = (uintptr_t) main;
     47
     48        return (uintptr_t) sp;
     49}
     50
    3851#endif
    3952
  • uspace/lib/c/arch/arm64/src/thread_entry.S

    r2cf8f994 r3fcea34  
    3535#
    3636SYMBOL(__thread_entry)
    37         #
     37        # Load entry function and argument from stack.
     38        ldp x1, x0, [sp], #16
     39
    3840        # Create the first stack frame.
    39         #
    4041        mov x29, #0
    4142        stp x29, x30, [sp, #-16]!
    4243        mov x29, sp
    4344
    44         b __thread_main
     45        br x1
  • uspace/lib/c/arch/ia32/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3636#define _LIBC_ia32_THREAD_H_
    3737
     38#include <align.h>
     39#include <stddef.h>
     40#include <stdint.h>
     41
     42static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     43    void (*main)(void *), void *arg)
     44{
     45        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     46
     47        *--sp = (uintptr_t) arg;
     48        *--sp = (uintptr_t) main;
     49
     50        return (uintptr_t) sp;
     51}
     52
    3853#endif
    3954
  • uspace/lib/c/arch/ia32/src/syscall.S

    r2cf8f994 r3fcea34  
    7777        pushl %ebp
    7878        mov %esp, %ebp
    79         lea ra, %edi
    8079        movl 20(%esp), %edx     # First argument.
    8180        movl 24(%esp), %ecx     # Second argument.
     
    8382        movl 32(%esp), %esi     # Fourth argument.
    8483        movl 44(%esp), %eax     # Syscall number.
    85         sysenter
    86 ra:
     84        call 1f
    8785        movw %cs, %cx
    8886        addw $8, %cx
     
    9593        popl %ebx
    9694        ret
     95
     96        /* Trampoline for entering kernel */
     971:
     98        pop %edi
     99        sysenter
    97100FUNCTION_END(__syscall_fast)
  • uspace/lib/c/arch/ia32/src/thread_entry.S

    r2cf8f994 r3fcea34  
    4141        # Do not set %gs, it contains descriptor that can see TLS
    4242
     43        # Pop libc thread main function.
     44        popl %eax
     45        # Pop argument.
     46        popl %ebx
     47
    4348        #
    4449        # Create the first stack frame.
     
    4853        mov %esp, %ebp
    4954
    50         #
    51         # EAX contains address of uarg.
    52         #
    53         pushl %eax
    54         call __thread_main
     55        pushl %ebx
     56        call *%eax
    5557
    5658        #
  • uspace/lib/c/arch/ia64/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3636#define _LIBC_ia64_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) (ALIGN_DOWN((uintptr_t) stack + stack_size / 2, 16));
     44
     45        /* Store data under stack pointer */
     46        sp[-1] = (uintptr_t) arg;
     47        sp[-2] = (uintptr_t) main;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3852#endif
    3953
  • uspace/lib/c/arch/ia64/src/thread_entry.S

    r2cf8f994 r3fcea34  
    3737        alloc loc0 = ar.pfs, 0, 1, 1, 0
    3838
    39 #ifndef CONFIG_RTLD
    40         # XXX This does not work in a shared library
    41         movl gp = __gp
    42 #endif
     39        add r8 = -8, sp ;;
     40        # Entry function argument
     41        ld8 out0 = [r8], -8 ;;
    4342
    44         #
    45         # r8 contains address of uarg structure.
    46         #
     43        # Entry function descriptor
     44        ld8 r8 = [r8] ;;
     45        # Entry function address
     46        ld8 r9 = [r8], 8 ;;
     47        # Entry function global pointer
     48        ld8 gp = [r8] ;;
    4749
    48         mov out0 = r8 ;;
    49         # XXX br.call.sptk.many b0 = FUNCTION_REF(__thread_main)
    50         br.call.sptk.many b0 = __thread_main
     50        mov b1 = r9 ;;
     51
     52        br.call.sptk.many b0 = b1 ;;
    5153
    5254        #
  • uspace/lib/c/arch/mips32/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3737#define _LIBC_mips32_THREAD_H_
    3838
     39#include <align.h>
     40
     41static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     42    void (*main)(void *), void *arg)
     43{
     44        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     45
     46        sp[-1] = (uintptr_t) arg;
     47        sp[-2] = (uintptr_t) main;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3952#endif
    4053
  • uspace/lib/c/arch/mips32/src/thread_entry.S

    r2cf8f994 r3fcea34  
    4040#
    4141SYMBOL(__thread_entry)
    42         .ent __thread_entry
    43         .frame $sp, ABI_STACK_FRAME, $ra
    44         .cpload $t9
     42        # All registers should be zero, including $fp and $ra.
     43        # Instead of setting up a stack frame here, we leave it for __thread_main.
    4544
    46         #
    47         # v0 contains address of uarg.
    48         #
    49         add $a0, $v0, 0
     45        # Function argument.
     46        lw $a0, -4($sp)
     47        # Function pointer.
     48        lw $t0, -8($sp)
    5049
    51         # Allocate the stack frame.
    52         addiu $sp, -ABI_STACK_FRAME
    53 
    54         # Allow PIC code
    55         .cprestore 16
    56 
    57         jal __thread_main
     50        j $t0
    5851        nop
    59 
    60         #
    61         # Not reached.
    62         #
    63         addiu $sp, ABI_STACK_FRAME
    64         .end __thread_entry
  • uspace/lib/c/arch/ppc32/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3636#define _LIBC_ppc32_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size - sizeof(void *), 16);
     44
     45        sp[0] = 0;
     46        sp[-1] = (uintptr_t) arg;
     47        sp[-2] = (uintptr_t) main;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3852#endif
    3953
  • uspace/lib/c/arch/ppc32/src/thread_entry.S

    r2cf8f994 r3fcea34  
    3535#
    3636SYMBOL(__thread_entry)
    37         #
    38         # Create the first stack frame.
    39         #
    40         li %r4, 0
    41         stw %r4, 0(%r1)
    42         stwu %r1, -16(%r1)
     37        # Load function and argument.
     38        lwz %r3, -4(%r1)
     39        lwz %r4, -8(%r1)
    4340
    44         b __thread_main
     41        # Clear LR
     42        li %r0, 0
     43        mtlr %r0
    4544
     45        mtctr %r4
     46        bctr
  • uspace/lib/c/arch/riscv64/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3636#define _LIBC_riscv64_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     44
     45        sp[-1] = (uintptr_t) arg;
     46        sp[-2] = (uintptr_t) main;
     47
     48        return (uintptr_t) sp;
     49}
     50
    3851#endif
    3952
  • uspace/lib/c/arch/riscv64/src/thread_entry.c

    r2cf8f994 r3fcea34  
    3535void __thread_entry(void)
    3636{
    37         __thread_main((void *) 0);
     37        // TODO
     38        while (true)
     39                ;
    3840}
    3941
  • uspace/lib/c/arch/sparc64/include/libarch/thread.h

    r2cf8f994 r3fcea34  
    3535#define _LIBC_sparc64_THREAD_H_
    3636
     37#include <assert.h>
     38#include <align.h>
     39#include <libarch/stack.h>
     40
     41static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     42    void (*main)(void *), void *arg)
     43{
     44        /* We must leave space above the stack pointer for initial register spill area. */
     45        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size - STACK_WINDOW_SAVE_AREA_SIZE - STACK_ARG_SAVE_AREA_SIZE, 16);
     46
     47        sp[-1] = (uintptr_t) arg;
     48        sp[-2] = (uintptr_t) main;
     49
     50        return ((uintptr_t) sp) - STACK_BIAS;
     51}
     52
    3753#endif
    3854
  • uspace/lib/c/arch/sparc64/src/thread_entry.S

    r2cf8f994 r3fcea34  
    3535#
    3636SYMBOL(__thread_entry)
     37        add %sp, 0x7ff, %g1
     38
    3739        #
    3840        # Create the first stack frame.
     
    4345
    4446        #
    45         # Propagate the input arguments to the new window.
     47        # Load libc entry point address and argument from stack
    4648        #
     49        ldn [%g1 - 8], %o0
     50        ldn [%g1 - 16], %g1
    4751
    48         call __thread_main              ! %o0 contains address of uarg
    49         mov %i0, %o0
     52        jmpl %g1, %r0
     53        # Wipe link register
     54        xor %o7, %o7, %o7
    5055
    5156        ! not reached
  • uspace/lib/c/generic/private/fibril.h

    r2cf8f994 r3fcea34  
    3333#include <context.h>
    3434#include <tls.h>
    35 #include <abi/proc/uarg.h>
    3635#include <fibril.h>
    3736#include <ipc/common.h>
     
    5049        context_t ctx;
    5150
    52         uspace_arg_t uarg;
    5351        link_t link;
    5452        void *stack;
  • uspace/lib/c/generic/private/thread.h

    r2cf8f994 r3fcea34  
    3737
    3838#include <time.h>
    39 #include <abi/proc/uarg.h>
    4039#include <libarch/thread.h>
    4140#include <abi/proc/thread.h>
    4241
    4342extern void __thread_entry(void);
    44 extern void __thread_main(uspace_arg_t *);
    4543
    46 extern errno_t thread_create(void (*)(void *), void *, const char *,
    47     thread_id_t *);
     44extern errno_t thread_create(errno_t (*)(void *), void *, const char *);
    4845extern void thread_exit(int) __attribute__((noreturn));
    49 extern void thread_detach(thread_id_t);
    5046extern thread_id_t thread_get_id(void);
    5147extern void thread_usleep(usec_t);
  • uspace/lib/c/generic/thread/fibril.c

    r2cf8f994 r3fcea34  
    781781}
    782782
    783 static void _runner_fn(void *arg)
     783static errno_t _runner_fn(void *arg)
    784784{
    785785        _helper_fibril_fn(arg);
     786        return EOK;
    786787}
    787788
     
    808809
    809810        for (int i = 0; i < n; i++) {
    810                 thread_id_t tid;
    811                 rc = thread_create(_runner_fn, NULL, "fibril runner", &tid);
     811                rc = thread_create(_runner_fn, NULL, "fibril runner");
    812812                if (rc != EOK)
    813813                        return i;
    814                 thread_detach(tid);
    815814        }
    816815
  • uspace/lib/c/generic/thread/thread.c

    r2cf8f994 r3fcea34  
    3737#include <stdlib.h>
    3838#include <libarch/faddr.h>
    39 #include <abi/proc/uarg.h>
    4039#include <fibril.h>
    4140#include <stack.h>
     
    5453 * and exit when thread returns back.
    5554 *
    56  * @param uarg Pointer to userspace argument structure.
     55 * @param arg Fibril pointer.
    5756 *
    5857 */
    59 void __thread_main(uspace_arg_t *uarg)
     58static void __thread_main(void *arg)
    6059{
     60        fibril_t *fibril = arg;
     61
    6162        assert(!__tcb_is_set());
    62 
    63         fibril_t *fibril = uarg->uspace_thread_arg;
    6463        assert(fibril);
    6564
    6665        __tcb_set(fibril->tcb);
    6766
    68         uarg->uspace_thread_function(fibril->arg);
     67        fibril->func(fibril->arg);
    6968        /*
    7069         * XXX: we cannot free the userspace stack while running on it
     
    9089 * @return Zero on success or a code from @ref errno.h on failure.
    9190 */
    92 errno_t thread_create(void (*function)(void *), void *arg, const char *name,
    93     thread_id_t *tid)
     91errno_t thread_create(errno_t (*func)(void *), void *arg, const char *name)
    9492{
    95         uspace_arg_t *uarg = calloc(1, sizeof(uspace_arg_t));
    96         if (!uarg)
     93        fibril_t *fibril = fibril_alloc();
     94        if (!fibril)
    9795                return ENOMEM;
    9896
    99         fibril_t *fibril = fibril_alloc();
    100         if (!fibril) {
    101                 free(uarg);
    102                 return ENOMEM;
    103         }
     97        fibril->func = func;
     98        fibril->arg = arg;
    10499
    105100        size_t stack_size = stack_size_get();
     
    109104        if (stack == AS_MAP_FAILED) {
    110105                fibril_teardown(fibril);
    111                 free(uarg);
    112106                return ENOMEM;
    113107        }
    114108
    115         fibril->arg = arg;
    116         uarg->uspace_entry = (void *) FADDR(__thread_entry);
    117         uarg->uspace_stack = stack;
    118         uarg->uspace_stack_size = stack_size;
    119         uarg->uspace_thread_function = function;
    120         uarg->uspace_thread_arg = fibril;
    121         uarg->uspace_uarg = uarg;
     109        uintptr_t sp = arch_thread_prepare(stack, stack_size, __thread_main,
     110            fibril);
    122111
    123         errno_t rc = (errno_t) __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg,
    124             (sysarg_t) name, (sysarg_t) str_size(name), (sysarg_t) tid);
     112        errno_t rc = (errno_t) __SYSCALL4(SYS_THREAD_CREATE,
     113            (sysarg_t) FADDR(__thread_entry), sp,
     114            (sysarg_t) name, (sysarg_t) str_size(name));
    125115
    126116        if (rc != EOK) {
     
    130120                 */
    131121                as_area_destroy(stack);
    132                 free(uarg);
    133122        }
    134123
     
    148137        while (true)
    149138                ;
    150 }
    151 
    152 /** Detach thread.
    153  *
    154  * Currently not implemented.
    155  *
    156  * @param thread TID.
    157  */
    158 void thread_detach(thread_id_t thread)
    159 {
    160139}
    161140
Note: See TracChangeset for help on using the changeset viewer.