LibC: Implement {sig,_,}{longjmp,setjmp}
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
|
||||
28
userspace/libraries/LibC/arch/i686/setjmp.S
Normal file
28
userspace/libraries/LibC/arch/i686/setjmp.S
Normal file
@@ -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
|
||||
23
userspace/libraries/LibC/arch/x86_64/setjmp.S
Normal file
23
userspace/libraries/LibC/arch/x86_64/setjmp.S
Normal file
@@ -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
|
||||
|
||||
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))];
|
||||
|
||||
void longjmp(jmp_buf env, int val);
|
||||
void siglongjmp(sigjmp_buf env, int val);
|
||||
int setjmp(jmp_buf env);
|
||||
int sigsetjmp(sigjmp_buf env, int savemask);
|
||||
#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);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
||||
19
userspace/libraries/LibC/setjmp.cpp
Normal file
19
userspace/libraries/LibC/setjmp.cpp
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user