Changeset a35a3d8 in mainline


Ignore:
Timestamp:
2018-03-12T17:13:46Z (6 years ago)
Author:
GitHub <noreply@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b127e4af
Parents:
f3d47c97
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-12 17:13:46)
git-committer:
GitHub <noreply@…> (2018-03-12 17:13:46)
Message:

Turn context_save/context_restore into standard setjmp/longjmp. (#24)

Turn context_save()/context_restore() into semi-standard __setjmp()/__longjmp().

The original context_* functions are similar to setjmp()/longjmp(), except that the return value is more restricted for the former, and with inverted meaning. This commit adopts the standard return value semantics and acknowledges that these functions are "standard setjmp()/longjmp() with additional implementation-specific properties" by changing the name. The only divergence from the standard is that __longjmp() causes __setjmp() to return its value unchanged, even if it is zero. This is just to avoid extra assembly, and longjmp() checks this in C.

Note that the original use of context_save()/context_restore() to implement context switching in fibril implementation has already been delegated to context_create()/context_swap(), which provide more natural control flow.

Location:
uspace/lib/c
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/abs32le/src/fibril.c

    rf3d47c97 ra35a3d8  
    3030 */
    3131
    32 #include <fibril.h>
     32#include <setjmp.h>
    3333#include <stdbool.h>
    3434
    35 int context_save(context_t *ctx)
     35int __setjmp(context_t *ctx)
    3636{
    37         return 1;
     37        return 0;
    3838}
    3939
    40 void context_restore(context_t *ctx)
     40void __longjmp(context_t *ctx, int val)
    4141{
    4242        while (true);
  • uspace/lib/c/arch/amd64/src/fibril.S

    rf3d47c97 ra35a3d8  
    3535#
    3636# Save CPU context to context_t variable
    37 # pointed by the 1st argument. Returns 1 in EAX.
     37# pointed by the 1st argument. Returns 0 in RAX.
    3838#
    39 FUNCTION_BEGIN(context_save)
     39FUNCTION_BEGIN(__setjmp)
    4040        movq (%rsp), %rdx     # the caller's return %eip
    4141
     
    5454        movq %rax, CONTEXT_OFFSET_TLS(%rdi)
    5555
    56         xorl %eax, %eax                      # context_save returns 1
    57         incl %eax
     56        xorq %rax, %rax                      # __setjmp returns 0
    5857        ret
    59 FUNCTION_END(context_save)
     58FUNCTION_END(__setjmp)
    6059
    6160## Restore current CPU context
    6261#
    6362# Restore CPU context from context_t variable
    64 # pointed by the 1st argument. Returns 0 in EAX.
     63# pointed by the 1st argument. Returns second argument in RAX.
    6564#
    66 FUNCTION_BEGIN(context_restore)
     65FUNCTION_BEGIN(__longjmp)
    6766        movq CONTEXT_OFFSET_R15(%rdi), %r15
    6867        movq CONTEXT_OFFSET_R14(%rdi), %r14
     
    8180        movq %rdi, %fs:0
    8281
    83         xorl %eax, %eax                      # context_restore returns 0
     82        movq %rsi, %rax                      # __longjmp returns second argument
    8483        ret
    85 FUNCTION_END(context_restore)
     84FUNCTION_END(__longjmp)
    8685
  • uspace/lib/c/arch/arm32/src/fibril.S

    rf3d47c97 ra35a3d8  
    3131.text
    3232
    33 FUNCTION_BEGIN(context_save)
     33FUNCTION_BEGIN(__setjmp)
    3434        stmia r0!, {sp, lr}
    3535        stmia r0!, {r4-r11}
    36 
    37         # return 1
    38         mov r0, #1
    39         mov pc, lr
    40 FUNCTION_END(context_save)
    41 
    42 FUNCTION_BEGIN(context_restore)
    43         ldmia r0!, {sp, lr}
    44         ldmia r0!, {r4-r11}
    4536
    4637        # return 0
    4738        mov r0, #0
    4839        mov pc, lr
    49 FUNCTION_END(context_restore)
     40FUNCTION_END(__setjmp)
    5041
     42FUNCTION_BEGIN(__longjmp)
     43        ldmia r0!, {sp, lr}
     44        ldmia r0!, {r4-r11}
     45
     46        # return second argument
     47        mov r0, r1
     48        mov pc, lr
     49FUNCTION_END(__longjmp)
     50
  • uspace/lib/c/arch/ia32/src/fibril.S

    rf3d47c97 ra35a3d8  
    3535#
    3636# Save CPU context to the context_t variable
    37 # pointed by the 1st argument. Returns 1 in EAX.
     37# pointed by the 1st argument. Returns 0 in EAX.
    3838#
    39 FUNCTION_BEGIN(context_save)
     39FUNCTION_BEGIN(__setjmp)
    4040        movl 0(%esp), %eax  # the caller's return %eip
    4141        movl 4(%esp), %edx  # address of the context variable to save context to
     
    5353        movl %eax, CONTEXT_OFFSET_TLS(%edx)     # tls -> ctx->tls
    5454
    55         xorl %eax, %eax         # context_save returns 1
    56         incl %eax
     55        xorl %eax, %eax         # __setjmp returns 0
    5756        ret
    58 FUNCTION_END(context_save)
     57FUNCTION_END(__setjmp)
    5958
    6059## Restore saved CPU context
    6160#
    6261# Restore CPU context from context_t variable
    63 # pointed by the 1st argument. Returns 0 in EAX.
     62# pointed by the 1st argument. Returns second argument in EAX.
    6463#
    65 FUNCTION_BEGIN(context_restore)
     64FUNCTION_BEGIN(__longjmp)
    6665        movl 4(%esp), %eax  # address of the context variable to restore context from
     66        movl 8(%esp), %ecx  # return value
    6767
    6868        # restore registers from the context structure
     
    8080        movl %edx, %gs:0
    8181
    82         xorl %eax, %eax         # context_restore returns 0
     82        movl %ecx, %eax
    8383        ret
    84 FUNCTION_END(context_restore)
     84FUNCTION_END(__longjmp)
    8585
  • uspace/lib/c/arch/ia64/include/libarch/fibril.h

    rf3d47c97 ra35a3d8  
    4343
    4444/*
    45  * context_save() and context_restore() are both leaf procedures.
     45 * __setjmp() and __longjmp() are both leaf procedures.
    4646 * No need to allocate scratch area.
    4747 */
  • uspace/lib/c/arch/ia64/src/fibril.S

    rf3d47c97 ra35a3d8  
    3232.text
    3333
    34 FUNCTION_BEGIN(context_save)
     34FUNCTION_BEGIN(__setjmp)
    3535        alloc loc0 = ar.pfs, 1, 49, 0, 0
    3636        mov loc1 = ar.unat ;;
     
    178178        mov ar.unat = loc1
    179179
    180         add r8 = r0, r0, 1      /* context_save returns 1 */
     180        mov r8 = 0      /* __setjmp returns 0 */
    181181        br.ret.sptk.many b0
    182 FUNCTION_END(context_save)
    183 
    184 FUNCTION_BEGIN(context_restore)
    185         alloc loc0 = ar.pfs, 1, 50, 0, 0        ;;
     182FUNCTION_END(__setjmp)
     183
     184FUNCTION_BEGIN(__longjmp)
     185        alloc loc0 = ar.pfs, 2, 51, 0, 0        ;;
    186186
    187187        add loc9 = CONTEXT_OFFSET_AR_PFS, in0
     
    230230        add loc47 = CONTEXT_OFFSET_F29, in0
    231231        add loc48 = CONTEXT_OFFSET_F30, in0
    232         add loc49 = CONTEXT_OFFSET_F31, in0 ;;
     232        add loc49 = CONTEXT_OFFSET_F31, in0
     233        mov loc50 = in1 ;;
    233234
    234235        ld8 loc0 = [loc9]       /* load ar.pfs */
     
    335336        mov ar.unat = loc1
    336337
    337         mov r8 = r0                     /* context_restore returns 0 */
     338        mov r8 = loc50                  /* __longjmp returns second argument */
    338339        br.ret.sptk.many b0
    339 FUNCTION_END(context_restore)
     340FUNCTION_END(__longjmp)
  • uspace/lib/c/arch/mips32/src/fibril.S

    rf3d47c97 ra35a3d8  
    3535#include <libarch/fibril_context.h>
    3636
    37 FUNCTION_BEGIN(context_save)
     37FUNCTION_BEGIN(__setjmp)
    3838        sw $s0, CONTEXT_OFFSET_S0($a0)
    3939        sw $s1, CONTEXT_OFFSET_S1($a0)
     
    8787        sw $sp, CONTEXT_OFFSET_SP($a0)
    8888
    89         # context_save returns 1
     89        # __setjmp returns 0
    9090        j $ra
    91         li $v0, 1
    92 FUNCTION_END(context_save)
     91        li $v0, 0
     92FUNCTION_END(__setjmp)
    9393
    94 FUNCTION_BEGIN(context_restore)
     94FUNCTION_BEGIN(__longjmp)
    9595        lw $s0, CONTEXT_OFFSET_S0($a0)
    9696        lw $s1, CONTEXT_OFFSET_S1($a0)
     
    147147        move $t9, $ra
    148148
    149         # context_restore returns 0
     149        # __longjmp returns second argument
    150150        j $ra
    151         xor $v0, $v0
    152 FUNCTION_END(context_restore)
     151        move $v0, $a1
     152FUNCTION_END(__longjmp)
  • uspace/lib/c/arch/ppc32/src/fibril.S

    rf3d47c97 ra35a3d8  
    3333#include <libarch/fibril_context.h>
    3434
    35 FUNCTION_BEGIN(context_save)
     35FUNCTION_BEGIN(__setjmp)
    3636        stw sp, CONTEXT_OFFSET_SP(r3)
    3737        stw r2, CONTEXT_OFFSET_TLS(r3)
     
    6262        stw r4, CONTEXT_OFFSET_CR(r3)
    6363
    64         # context_save returns 1
    65         li r3, 1
     64        # __setjmp returns 0
     65        li r3, 0
    6666        blr
    67 FUNCTION_END(context_save)
     67FUNCTION_END(__setjmp)
    6868
    69 FUNCTION_BEGIN(context_restore)
     69FUNCTION_BEGIN(__longjmp)
    7070        lwz sp, CONTEXT_OFFSET_SP(r3)
    7171        lwz r2, CONTEXT_OFFSET_TLS(r3)
     
    9090        lwz r31, CONTEXT_OFFSET_R31(r3)
    9191
    92         lwz r4, CONTEXT_OFFSET_CR(r3)
    93         mtcr r4
     92        lwz r5, CONTEXT_OFFSET_CR(r3)
     93        mtcr r5
    9494
    95         lwz r4, CONTEXT_OFFSET_PC(r3)
    96         mtlr r4
     95        lwz r5, CONTEXT_OFFSET_PC(r3)
     96        mtlr r5
    9797
    98         # context_restore returns 0
    99         li r3, 0
     98        # __longjmp returns second argument
     99        mr r3, r4
    100100        blr
    101 FUNCTION_END(context_restore)
     101FUNCTION_END(__longjmp)
  • uspace/lib/c/arch/riscv64/src/fibril.c

    rf3d47c97 ra35a3d8  
    3333#include <stdbool.h>
    3434
    35 int context_save(context_t *ctx)
     35int __setjmp(context_t *ctx)
    3636{
    37         return 1;
     37        return 0;
    3838}
    3939
    40 void context_restore(context_t *ctx)
     40void __longjmp(context_t *ctx, int ret)
    4141{
    4242        while (true);
  • uspace/lib/c/arch/sparc64/src/fibril.S

    rf3d47c97 ra35a3d8  
    3232.text
    3333
    34 FUNCTION_BEGIN(context_save)
     34FUNCTION_BEGIN(__setjmp)
    3535        #
    3636        # We rely on the kernel to flush our active register windows to memory
     
    5757        stx %g7, [%o0 + CONTEXT_OFFSET_TP]
    5858        retl
    59         mov 1, %o0              ! context_save_arch returns 1
    60 FUNCTION_END(context_save)
     59        mov 0, %o0              ! __setjmp returns 0
     60FUNCTION_END(__setjmp)
    6161
    62 FUNCTION_BEGIN(context_restore)
     62FUNCTION_BEGIN(__longjmp)
    6363        #
    6464        # Flush all active windows.
     
    8989        ldx [%o0 + CONTEXT_OFFSET_TP], %g7
    9090        retl
    91         xor %o0, %o0, %o0       ! context_restore_arch returns 0
    92 FUNCTION_END(context_restore)
     91        mov %o1, %o0    ! __longjmp returns second argument
     92FUNCTION_END(__longjmp)
  • uspace/lib/c/generic/context.c

    rf3d47c97 ra35a3d8  
    2828
    2929#include <context.h>
     30#include <setjmp.h>
    3031#include <libarch/tls.h>
    3132#include <libarch/fibril.h>
     
    4243void context_swap(context_t *self, context_t *other)
    4344{
    44         if (context_save(self))
    45                 context_restore(other);
     45        if (!__setjmp(self))
     46                __longjmp(other, 1);
    4647}
    4748
    4849void context_create(context_t *context, const context_create_t *arg)
    4950{
    50         context_save(context);
     51        __setjmp(context);
    5152        context_set(context, FADDR(arg->fn), arg->stack_base,
    5253            arg->stack_size, arg->tls);
  • uspace/lib/c/generic/setjmp.c

    rf3d47c97 ra35a3d8  
    11/*
    22 * Copyright (c) 2013 Vojtech Horky
     3 * Copyright (c) 2018 CZ.NIC, z.s.p.o.
    34 * All rights reserved.
    45 *
     
    3031 * @{
    3132 */
    32 /** @file Long jump implementation.
    33  *
    34  * Implementation inspired by Jiri Zarevucky's code from
    35  * http://bazaar.launchpad.net/~zarevucky-jiri/helenos/stdc/revision/1544/uspace/lib/posix/setjmp.h
    36  */
    3733
    3834#include <setjmp.h>
    3935#include <context.h>
    4036
    41 // TODO: setjmp/longjmp are basically a stronger version of
    42 // context_save/context_restore. It would be preferable to turn
    43 // those two into setjmp/longjmp (all it would need is preserving the
    44 // return value).
    45 
    46 /**
    47  * Restore environment previously stored by setjmp.
    48  *
    49  * This function never returns.
    50  *
    51  * @param env Variable with the environment previously stored by call
    52  * to setjmp.
    53  * @param val Value to fake when returning from setjmp (0 is transformed to 1).
    54  */
    55 void longjmp(jmp_buf env, int val) {
    56         env[0].return_value = (val == 0) ? 1 : val;
    57         context_restore(&env[0].context);
     37/** Standard function implementation. */
     38void longjmp(jmp_buf env, int val)
     39{
     40        /* __longjmp defined in assembly doesn't "correct" the value. */
     41        __longjmp(env, val == 0 ? 1 : val);
    5842}
    5943
  • uspace/lib/c/include/context.h

    rf3d47c97 ra35a3d8  
    4646extern uintptr_t context_get_pc(context_t *ctx);
    4747
    48 // TODO: These should go away.
    49 
    50 extern int context_save(context_t *ctx) __attribute__((returns_twice));
    51 extern void context_restore(context_t *ctx) __attribute__((noreturn));
    52 
    5348#endif
    5449
  • uspace/lib/c/include/setjmp.h

    rf3d47c97 ra35a3d8  
    11/*
    2  * Copyright (c) 2008 Josef Cejka
    3  * Copyright (c) 2013 Vojtech Horky
     2 * Copyright (c) 2018 CZ.NIC, z.s.p.o.
    43 * All rights reserved.
    54 *
     
    3130 * @{
    3231 */
    33 /** @file Long jump implementation.
    34  *
    35  * Implementation inspired by Jiri Zarevucky's code from
    36  * http://bazaar.launchpad.net/~zarevucky-jiri/helenos/stdc/revision/1544/uspace/lib/posix/setjmp.h
    37  */
    3832
    3933#ifndef LIBC_SETJMP_H_
    4034#define LIBC_SETJMP_H_
    4135
    42 #include <libarch/fibril.h>
     36#include <libarch/fibril_context.h>
    4337
    44 struct jmp_buf_interal {
    45         context_t context;
    46         int return_value;
    47 };
    48 typedef struct jmp_buf_interal jmp_buf[1];
     38typedef context_t jmp_buf[1];
    4939
    50 /*
    51  * Specified as extern to minimize number of included headers
    52  * because this file is used as is in libposix too.
    53  */
    54 extern int context_save(context_t *ctx) __attribute__((returns_twice));
     40extern int __setjmp(jmp_buf) __attribute__((returns_twice));
     41extern _Noreturn void __longjmp(jmp_buf, int);
    5542
    56 /**
    57  * Save current environment (registers).
    58  *
    59  * This function may return twice.
    60  *
    61  * @param env Variable where to save the environment (of type jmp_buf).
    62  * @return Whether the call returned after longjmp.
    63  * @retval 0 Environment was saved, normal execution.
    64  * @retval other longjmp was executed and returned here.
    65  */
    66 #define setjmp(env) \
    67         ((env)[0].return_value = 0, \
    68         context_save(&(env)[0].context), \
    69         (env)[0].return_value)
    70 
    71 extern void longjmp(jmp_buf env, int val) __attribute__((noreturn));
     43#define setjmp __setjmp
     44extern _Noreturn void longjmp(jmp_buf, int);
    7245
    7346#endif
Note: See TracChangeset for help on using the changeset viewer.