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.
This commit is contained in:
Rich Felker 2011-03-19 18:51:42 -04:00
commit d00ff2950e
11 changed files with 1582 additions and 754 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

19
src/linux/syscall.c Normal file
View file

@ -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));
}

View file

@ -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;