diff options
author | H. Peter Anvin <hpa@zytor.com> | 2002-08-13 17:51:30 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2002-08-13 17:51:30 +0000 |
commit | cfaeed5924fdb2bff5efc7412952c4ab12795749 (patch) | |
tree | 3bacb9309cd61d0c9bf230b9ac7247bbe3ea3ff8 | |
parent | ff1b5f868918563dd89dca9e3682494d1e7bff8a (diff) | |
download | klibc-cfaeed5924fdb2bff5efc7412952c4ab12795749.tar.gz |
Special-case socketcalls on i386, esp. since i386 is possibly the onlyklibc-0.32
architecture still using socketcalls. It also lends itself to a particular
optimization.
-rw-r--r-- | include/sys/socketcalls.h | 28 | ||||
-rw-r--r-- | klibc/MCONFIG | 6 | ||||
-rw-r--r-- | klibc/Makefile | 1 | ||||
-rw-r--r-- | klibc/include/sys/socketcalls.h | 28 | ||||
-rw-r--r-- | klibc/socketcall.S | 38 | ||||
-rw-r--r-- | klibc/socketcalls.pl | 58 | ||||
-rw-r--r-- | socketcall.S | 38 | ||||
-rw-r--r-- | socketcalls.pl | 58 |
8 files changed, 215 insertions, 40 deletions
diff --git a/include/sys/socketcalls.h b/include/sys/socketcalls.h new file mode 100644 index 0000000000000..dac9f9aab61fd --- /dev/null +++ b/include/sys/socketcalls.h @@ -0,0 +1,28 @@ +/* + * sys/socketcalls.h + */ + +#ifndef _SYS_SOCKETCALLS_H +#define _SYS_SOCKETCALLS_H + +/* socketcalls by number, since <linux/net.h> isn't usable for assembly */ + +#define SYS_SOCKET 1 /* sys_socket(2) */ +#define SYS_BIND 2 /* sys_bind(2) */ +#define SYS_CONNECT 3 /* sys_connect(2) */ +#define SYS_LISTEN 4 /* sys_listen(2) */ +#define SYS_ACCEPT 5 /* sys_accept(2) */ +#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ +#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ +#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ +#define SYS_SEND 9 /* sys_send(2) */ +#define SYS_RECV 10 /* sys_recv(2) */ +#define SYS_SENDTO 11 /* sys_sendto(2) */ +#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ +#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ +#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ +#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ +#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ +#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ + +#endif /* _SYS_SOCKETCALLS_H */ diff --git a/klibc/MCONFIG b/klibc/MCONFIG index 781e54708b90d..34d21f1538466 100644 --- a/klibc/MCONFIG +++ b/klibc/MCONFIG @@ -44,9 +44,15 @@ include arch/$(ARCH)/MCONFIG .S.o: $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< +.S.s: + $(CC) $(CFLAGS) -D__ASSEMBLY__ -E -o $@ $< + .S.lo: $(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -c -o $@ $< +.S.ls: + $(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $< + .s.o: $(CC) $(CFLAGS) -x assembler -c -o $@ $< diff --git a/klibc/Makefile b/klibc/Makefile index 7579f580ddc75..9af3deb0a5465 100644 --- a/klibc/Makefile +++ b/klibc/Makefile @@ -29,6 +29,7 @@ LIBOBJS = vsnprintf.o snprintf.o vsprintf.o sprintf.o \ getenv.o setenv.o unsetenv.o getopt.o readdir.o \ time.o fdatasync.o llseek.o select.o nice.o getpriority.o \ qsort.o lrand48.o srand48.o seed48.o \ + socketcall.o \ inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \ inet/inet_ntop.o inet/inet_pton.o LIB = libc.a diff --git a/klibc/include/sys/socketcalls.h b/klibc/include/sys/socketcalls.h new file mode 100644 index 0000000000000..dac9f9aab61fd --- /dev/null +++ b/klibc/include/sys/socketcalls.h @@ -0,0 +1,28 @@ +/* + * sys/socketcalls.h + */ + +#ifndef _SYS_SOCKETCALLS_H +#define _SYS_SOCKETCALLS_H + +/* socketcalls by number, since <linux/net.h> isn't usable for assembly */ + +#define SYS_SOCKET 1 /* sys_socket(2) */ +#define SYS_BIND 2 /* sys_bind(2) */ +#define SYS_CONNECT 3 /* sys_connect(2) */ +#define SYS_LISTEN 4 /* sys_listen(2) */ +#define SYS_ACCEPT 5 /* sys_accept(2) */ +#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ +#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ +#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ +#define SYS_SEND 9 /* sys_send(2) */ +#define SYS_RECV 10 /* sys_recv(2) */ +#define SYS_SENDTO 11 /* sys_sendto(2) */ +#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ +#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ +#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ +#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ +#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ +#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ + +#endif /* _SYS_SOCKETCALLS_H */ diff --git a/klibc/socketcall.S b/klibc/socketcall.S new file mode 100644 index 0000000000000..6bac1e6913ef9 --- /dev/null +++ b/klibc/socketcall.S @@ -0,0 +1,38 @@ +# +# socketcall.S +# +# On i386, the main (only?) user of socketcall(2), the memory array +# socketcall(2) needs is conveniently already assembled for us on +# the stack. Capitalize on that to make a common socketcall stub. +# + +#include <asm/unistd.h> + +#ifdef __i386__ + + .text + .align 4 + .globl __socketcall_common + .type __socketcall_common, @function + +__socketcall_common: + pushl %ebx + movzbl %al,%ebx # The socketcall number is passed in in %al + leal 8(%esp),%ecx # Argument pointer + movl $__NR_socketcall, %eax + int $0x80 + cmpl $-125,%eax # Error return? + popl %ebx + jb 1f + neg %eax + movl %eax,errno + xorl %eax,%eax + decl %eax # Return = -1 +1: + ret + + .size __socketcall_common,.-__socketcall_common + +#endif + + diff --git a/klibc/socketcalls.pl b/klibc/socketcalls.pl index 34d1839431cc4..0820b98580d41 100644 --- a/klibc/socketcalls.pl +++ b/klibc/socketcalls.pl @@ -1,4 +1,6 @@ #!/usr/bin/perl +($arch) = @ARGV; + while ( defined($line = <STDIN>) ) { chomp $line; $line =~ s/\s*\#.*$//; # Strip comments and trailing blanks @@ -17,28 +19,44 @@ while ( defined($line = <STDIN>) ) { } $nargs = $i; - open(OUT, "> socketcalls/${name}.c") - or die "$0: Cannot open socketcalls/${name}.c\n"; - print OUT "#include \"socketcommon.h\"\n\n"; - - print OUT "#ifdef __NR_$name\n\n"; - print OUT "_syscall", scalar(@args), "(", $type, ',', $name; - $i = 0; - foreach $arg ( @args ) { - print OUT ",", $arg, ",a",$i++; - } - print OUT ");\n"; - print OUT "\n#else\n\n"; + if ( $arch eq 'i386' ) { + open(OUT, "> socketcalls/${name}.S") + or die "$0: Cannot open socketcalls/${name}.S\n"; - print OUT "$type $name (", join(', ', @cargs), ")\n"; - print OUT "{\n"; - print OUT " unsigned long args[$nargs];\n"; - for ( $i = 0 ; $i < $nargs ; $i++ ) { - print OUT " args[$i] = (unsigned long)a$i;\n"; + print OUT "#include <sys/socketcalls.h>\n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.align 4\n"; + print OUT "\t.globl ${name}\n"; + print OUT "\t.type ${name},\@function\n"; + print OUT "${name}:\n"; + print OUT "\tmovb \$SYS_\U${name}\E,%al\n"; + print OUT "\tjmp __socketcall_common\n"; + print OUT "\t.size ${name},.-${name}\n"; + } else { + open(OUT, "> socketcalls/${name}.c") + or die "$0: Cannot open socketcalls/${name}.c\n"; + print OUT "#include \"socketcommon.h\"\n\n"; + + print OUT "#ifdef __NR_$name\n\n"; + print OUT "_syscall", scalar(@args), "(", $type, ',', $name; + $i = 0; + foreach $arg ( @args ) { + print OUT ",", $arg, ",a",$i++; + } + print OUT ");\n"; + print OUT "\n#else\n\n"; + + print OUT "$type $name (", join(', ', @cargs), ")\n"; + print OUT "{\n"; + print OUT " unsigned long args[$nargs];\n"; + for ( $i = 0 ; $i < $nargs ; $i++ ) { + print OUT " args[$i] = (unsigned long)a$i;\n"; + } + print OUT " return ($type) socketcall(SYS_\U${name}\E, args);\n"; + print OUT "}\n"; + print OUT "\n#endif\n"; } - print OUT " return ($type) socketcall(SYS_\U${name}\E, args);\n"; - print OUT "}\n"; - print OUT "\n#endif\n"; close(OUT); } } diff --git a/socketcall.S b/socketcall.S new file mode 100644 index 0000000000000..6bac1e6913ef9 --- /dev/null +++ b/socketcall.S @@ -0,0 +1,38 @@ +# +# socketcall.S +# +# On i386, the main (only?) user of socketcall(2), the memory array +# socketcall(2) needs is conveniently already assembled for us on +# the stack. Capitalize on that to make a common socketcall stub. +# + +#include <asm/unistd.h> + +#ifdef __i386__ + + .text + .align 4 + .globl __socketcall_common + .type __socketcall_common, @function + +__socketcall_common: + pushl %ebx + movzbl %al,%ebx # The socketcall number is passed in in %al + leal 8(%esp),%ecx # Argument pointer + movl $__NR_socketcall, %eax + int $0x80 + cmpl $-125,%eax # Error return? + popl %ebx + jb 1f + neg %eax + movl %eax,errno + xorl %eax,%eax + decl %eax # Return = -1 +1: + ret + + .size __socketcall_common,.-__socketcall_common + +#endif + + diff --git a/socketcalls.pl b/socketcalls.pl index 34d1839431cc4..0820b98580d41 100644 --- a/socketcalls.pl +++ b/socketcalls.pl @@ -1,4 +1,6 @@ #!/usr/bin/perl +($arch) = @ARGV; + while ( defined($line = <STDIN>) ) { chomp $line; $line =~ s/\s*\#.*$//; # Strip comments and trailing blanks @@ -17,28 +19,44 @@ while ( defined($line = <STDIN>) ) { } $nargs = $i; - open(OUT, "> socketcalls/${name}.c") - or die "$0: Cannot open socketcalls/${name}.c\n"; - print OUT "#include \"socketcommon.h\"\n\n"; - - print OUT "#ifdef __NR_$name\n\n"; - print OUT "_syscall", scalar(@args), "(", $type, ',', $name; - $i = 0; - foreach $arg ( @args ) { - print OUT ",", $arg, ",a",$i++; - } - print OUT ");\n"; - print OUT "\n#else\n\n"; + if ( $arch eq 'i386' ) { + open(OUT, "> socketcalls/${name}.S") + or die "$0: Cannot open socketcalls/${name}.S\n"; - print OUT "$type $name (", join(', ', @cargs), ")\n"; - print OUT "{\n"; - print OUT " unsigned long args[$nargs];\n"; - for ( $i = 0 ; $i < $nargs ; $i++ ) { - print OUT " args[$i] = (unsigned long)a$i;\n"; + print OUT "#include <sys/socketcalls.h>\n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.align 4\n"; + print OUT "\t.globl ${name}\n"; + print OUT "\t.type ${name},\@function\n"; + print OUT "${name}:\n"; + print OUT "\tmovb \$SYS_\U${name}\E,%al\n"; + print OUT "\tjmp __socketcall_common\n"; + print OUT "\t.size ${name},.-${name}\n"; + } else { + open(OUT, "> socketcalls/${name}.c") + or die "$0: Cannot open socketcalls/${name}.c\n"; + print OUT "#include \"socketcommon.h\"\n\n"; + + print OUT "#ifdef __NR_$name\n\n"; + print OUT "_syscall", scalar(@args), "(", $type, ',', $name; + $i = 0; + foreach $arg ( @args ) { + print OUT ",", $arg, ",a",$i++; + } + print OUT ");\n"; + print OUT "\n#else\n\n"; + + print OUT "$type $name (", join(', ', @cargs), ")\n"; + print OUT "{\n"; + print OUT " unsigned long args[$nargs];\n"; + for ( $i = 0 ; $i < $nargs ; $i++ ) { + print OUT " args[$i] = (unsigned long)a$i;\n"; + } + print OUT " return ($type) socketcall(SYS_\U${name}\E, args);\n"; + print OUT "}\n"; + print OUT "\n#endif\n"; } - print OUT " return ($type) socketcall(SYS_\U${name}\E, args);\n"; - print OUT "}\n"; - print OUT "\n#endif\n"; close(OUT); } } |