diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-03-19 18:51:42 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-03-19 18:51:42 -0400 |
commit | d00ff2950eacc375d57e44d65c7697f636c67625 (patch) | |
tree | 33949c7eb7e75251b3a598f964db558604caf7c6 /src | |
parent | 56fd65e861e0ad0ea7677211f8258a8f64233f26 (diff) | |
download | musl-d00ff2950eacc375d57e44d65c7697f636c67625.tar.gz musl-d00ff2950eacc375d57e44d65c7697f636c67625.tar.bz2 musl-d00ff2950eacc375d57e44d65c7697f636c67625.tar.xz musl-d00ff2950eacc375d57e44d65c7697f636c67625.zip |
overhaul syscall interface
this commit shuffles around the location of syscall definitions so
that we can make a syscall() library function with both SYS_* and
__NR_* style syscall names available to user applications, provides
the syscall() library function, and optimizes the code that performs
the actual inline syscalls in the library itself.
previously on i386 when built as PIC (shared library), syscalls were
incurring bus lock (lock prefix) overhead at entry and exit, due to
the way the ebx register was being loaded (xchg instruction with a
memory operand). now the xchg takes place between two registers.
further cleanup to arch/$(ARCH)/syscall.h is planned.
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/i386/syscall.s | 21 | ||||
-rw-r--r-- | src/internal/syscall.c | 11 | ||||
-rw-r--r-- | src/internal/syscall_ret.c | 11 | ||||
-rw-r--r-- | src/internal/x86_64/syscall.s | 14 | ||||
-rw-r--r-- | src/linux/syscall.c | 19 | ||||
-rw-r--r-- | src/thread/pthread_create.c | 4 |
6 files changed, 67 insertions, 13 deletions
diff --git a/src/internal/i386/syscall.s b/src/internal/i386/syscall.s new file mode 100644 index 00000000..5b19a1b8 --- /dev/null +++ b/src/internal/i386/syscall.s @@ -0,0 +1,21 @@ +.global __syscall +.type __syscall,%function +__syscall: + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + movl 20(%esp),%eax + movl 24(%esp),%ebx + movl 28(%esp),%ecx + movl 32(%esp),%edx + movl 36(%esp),%esi + movl 40(%esp),%edi + movl 44(%esp),%ebp + int $128 + popl %ebp + popl %edi + popl %esi + popl %ebx + ret +.size __syscall,.-__syscall diff --git a/src/internal/syscall.c b/src/internal/syscall.c index 4f159e0b..e69de29b 100644 --- a/src/internal/syscall.c +++ b/src/internal/syscall.c @@ -1,11 +0,0 @@ -#include <errno.h> -#include <unistd.h> - -long __syscall_ret(unsigned long r) -{ - if (r >= (unsigned long)-1 - 4096) { - errno = -(long)r; - return -1; - } - return (long)r; -} diff --git a/src/internal/syscall_ret.c b/src/internal/syscall_ret.c new file mode 100644 index 00000000..4f159e0b --- /dev/null +++ b/src/internal/syscall_ret.c @@ -0,0 +1,11 @@ +#include <errno.h> +#include <unistd.h> + +long __syscall_ret(unsigned long r) +{ + if (r >= (unsigned long)-1 - 4096) { + errno = -(long)r; + return -1; + } + return (long)r; +} diff --git a/src/internal/x86_64/syscall.s b/src/internal/x86_64/syscall.s new file mode 100644 index 00000000..7bec7291 --- /dev/null +++ b/src/internal/x86_64/syscall.s @@ -0,0 +1,14 @@ +.global __syscall +.type __syscall,%function +__syscall: +di,si,dx,cx,r8,r9 + movq %rdi,%rax + movq %rsi,%rdi + movq %rdx,%rsi + movq %rcx,%rdx + movq %r8,%r10 + movq %r9,%r8 + movq 8(%rsp),%r9 + syscall + ret +.size __syscall,.-__syscall diff --git a/src/linux/syscall.c b/src/linux/syscall.c new file mode 100644 index 00000000..15355609 --- /dev/null +++ b/src/linux/syscall.c @@ -0,0 +1,19 @@ +#include "syscall.h" +#include <stdarg.h> + +#undef syscall + +long syscall(long n, ...) +{ + va_list ap; + long a,b,c,d,e,f; + va_start(ap, n); + a=va_arg(ap, long); + b=va_arg(ap, long); + c=va_arg(ap, long); + d=va_arg(ap, long); + e=va_arg(ap, long); + f=va_arg(ap, long); + va_end(ap); + return __syscall_ret(__syscall(n,a,b,c,d,e,f)); +} diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 7494a486..fccfa191 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -91,7 +91,7 @@ static void rsyscall_handler(int sig, siginfo_t *si, void *ctx) return; } - if (syscall6(rs.nr, rs.arg[0], rs.arg[1], rs.arg[2], + if (__syscall(rs.nr, rs.arg[0], rs.arg[1], rs.arg[2], rs.arg[3], rs.arg[4], rs.arg[5]) < 0 && !rs.err) rs.err=errno; a_inc(&rs.cnt); @@ -140,7 +140,7 @@ static int rsyscall(int nr, long a, long b, long c, long d, long e, long f) while((i=rs.cnt)) __wait(&rs.cnt, 0, i, 1); if (rs.err) errno = rs.err, ret = -1; - else ret = syscall6(nr, a, b, c, d, e, f); + else ret = __syscall(nr, a, b, c, d, e, f); UNLOCK(&rs.lock); return ret; |