LibC: Implement {sig,_,}{longjmp,setjmp}
This commit is contained in:
parent
91d513a672
commit
6fedf06150
|
@ -13,6 +13,7 @@ set(LIBC_SOURCES
|
||||||
printf_impl.cpp
|
printf_impl.cpp
|
||||||
pwd.cpp
|
pwd.cpp
|
||||||
scanf_impl.cpp
|
scanf_impl.cpp
|
||||||
|
setjmp.cpp
|
||||||
signal.cpp
|
signal.cpp
|
||||||
stdio.cpp
|
stdio.cpp
|
||||||
stdlib.cpp
|
stdlib.cpp
|
||||||
|
@ -32,6 +33,8 @@ set(LIBC_SOURCES
|
||||||
unistd.cpp
|
unistd.cpp
|
||||||
icxxabi.cpp
|
icxxabi.cpp
|
||||||
|
|
||||||
|
arch/${BANAN_ARCH}/setjmp.S
|
||||||
|
|
||||||
../../../BAN/BAN/Assert.cpp
|
../../../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,13 +7,16 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
typedef int jmp_buf[1];
|
typedef long jmp_buf[2];
|
||||||
typedef int sigjmp_buf[1];
|
typedef long sigjmp_buf[2 + 1 + (sizeof(long long) / sizeof(long))];
|
||||||
|
|
||||||
void longjmp(jmp_buf env, int val);
|
#define _longjmp longjmp
|
||||||
void siglongjmp(sigjmp_buf env, int val);
|
void longjmp(jmp_buf env, int val);
|
||||||
int setjmp(jmp_buf env);
|
void siglongjmp(sigjmp_buf env, int val);
|
||||||
int sigsetjmp(sigjmp_buf env, int savemask);
|
|
||||||
|
#define _setjmp setjmp
|
||||||
|
int setjmp(jmp_buf env);
|
||||||
|
int sigsetjmp(sigjmp_buf env, int savemask);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -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-mmap-shared
|
||||||
test-mouse
|
test-mouse
|
||||||
test-popen
|
test-popen
|
||||||
|
test-setjmp
|
||||||
test-sort
|
test-sort
|
||||||
test-tcp
|
test-tcp
|
||||||
test-udp
|
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