aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-08-13 17:51:30 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-08-13 17:51:30 +0000
commitcfaeed5924fdb2bff5efc7412952c4ab12795749 (patch)
tree3bacb9309cd61d0c9bf230b9ac7247bbe3ea3ff8
parentff1b5f868918563dd89dca9e3682494d1e7bff8a (diff)
downloadklibc-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.h28
-rw-r--r--klibc/MCONFIG6
-rw-r--r--klibc/Makefile1
-rw-r--r--klibc/include/sys/socketcalls.h28
-rw-r--r--klibc/socketcall.S38
-rw-r--r--klibc/socketcalls.pl58
-rw-r--r--socketcall.S38
-rw-r--r--socketcalls.pl58
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);
}
}