LibC: Implement {sig,_,}{longjmp,setjmp}
This commit is contained in:
parent
91d513a672
commit
6fedf06150
|
@ -13,6 +13,7 @@ set(LIBC_SOURCES
|
|||
printf_impl.cpp
|
||||
pwd.cpp
|
||||
scanf_impl.cpp
|
||||
setjmp.cpp
|
||||
signal.cpp
|
||||
stdio.cpp
|
||||
stdlib.cpp
|
||||
|
@ -32,6 +33,8 @@ set(LIBC_SOURCES
|
|||
unistd.cpp
|
||||
icxxabi.cpp
|
||||
|
||||
arch/${BANAN_ARCH}/setjmp.S
|
||||
|
||||
../../../BAN/BAN/Assert.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// int setjmp(jmp_buf env)
|
||||
.global setjmp
|
||||
setjmp:
|
||||
movl 4(%esp), %edx
|
||||
|
||||
leal 4(%esp), %eax
|
||||
movl %eax, 0(%edx)
|
||||
|
||||
movl (%esp), %eax
|
||||
movl %eax, 4(%edx)
|
||||
|
||||
xorl %eax, %eax
|
||||
|
||||
ret
|
||||
|
||||
// void longjmp(jmp_buf env, int val)
|
||||
.global longjmp
|
||||
longjmp:
|
||||
movl 4(%esp), %edx
|
||||
|
||||
movl 8(%esp), %ecx
|
||||
movl $1, %eax
|
||||
testl %ecx, %ecx
|
||||
cmovnzl %ecx, %eax
|
||||
|
||||
movl 0(%edx), %esp
|
||||
movl 4(%edx), %ecx
|
||||
jmp *%ecx
|
|
@ -0,0 +1,23 @@
|
|||
// int setjmp(jmp_buf env)
|
||||
.global setjmp
|
||||
setjmp:
|
||||
leaq 8(%rsp), %rax
|
||||
movq %rax, 0(%rdi)
|
||||
|
||||
movq (%rsp), %rax
|
||||
movq %rax, 8(%rdi)
|
||||
|
||||
xorq %rax, %rax
|
||||
|
||||
ret
|
||||
|
||||
// void longjmp(jmp_buf env, int val)
|
||||
.global longjmp
|
||||
longjmp:
|
||||
movq $1, %rax
|
||||
testq %rsi, %rsi
|
||||
cmovnzq %rsi, %rax
|
||||
|
||||
movq 0(%rdi), %rsp
|
||||
movq 8(%rdi), %rcx
|
||||
jmp *%rcx
|
|
@ -7,11 +7,14 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
typedef int jmp_buf[1];
|
||||
typedef int sigjmp_buf[1];
|
||||
typedef long jmp_buf[2];
|
||||
typedef long sigjmp_buf[2 + 1 + (sizeof(long long) / sizeof(long))];
|
||||
|
||||
#define _longjmp longjmp
|
||||
void longjmp(jmp_buf env, int val);
|
||||
void siglongjmp(sigjmp_buf env, int val);
|
||||
|
||||
#define _setjmp setjmp
|
||||
int setjmp(jmp_buf env);
|
||||
int sigsetjmp(sigjmp_buf env, int savemask);
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
||||
static_assert(sizeof(sigjmp_buf) == sizeof(jmp_buf) + sizeof(long) + sizeof(sigset_t));
|
||||
|
||||
void siglongjmp(sigjmp_buf env, int val)
|
||||
{
|
||||
if (env[2])
|
||||
pthread_sigmask(SIG_SETMASK, reinterpret_cast<sigset_t*>(&env[3]), nullptr);
|
||||
return longjmp(env, val);
|
||||
}
|
||||
|
||||
int sigsetjmp(sigjmp_buf env, int savemask)
|
||||
{
|
||||
env[2] = savemask;
|
||||
if (savemask)
|
||||
pthread_sigmask(0, nullptr, reinterpret_cast<sigset_t*>(&env[3]));
|
||||
return setjmp(env);
|
||||
}
|
|
@ -5,6 +5,7 @@ set(USERSPACE_TESTS
|
|||
test-mmap-shared
|
||||
test-mouse
|
||||
test-popen
|
||||
test-setjmp
|
||||
test-sort
|
||||
test-tcp
|
||||
test-udp
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-setjmp ${SOURCES})
|
||||
banan_link_library(test-setjmp libc)
|
||||
|
||||
install(TARGETS test-setjmp OPTIONAL)
|
|
@ -0,0 +1,22 @@
|
|||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
|
||||
jmp_buf env;
|
||||
|
||||
void iterate()
|
||||
{
|
||||
static volatile int count = 0;
|
||||
if (count < 10)
|
||||
{
|
||||
count = count + 1;
|
||||
longjmp(env, count);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("start\n");
|
||||
if (int ret = setjmp(env))
|
||||
printf("longjmp %d\n", ret);
|
||||
iterate();
|
||||
}
|
Loading…
Reference in New Issue