aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2004-02-22 01:01:12 +0000
committerH. Peter Anvin <hpa@zytor.com>2004-02-22 01:01:12 +0000
commit80a6119e6d7bee9709a7a632983a4e06e94a7401 (patch)
tree69560423ed6ab1f7c10c1ab27990cf8c89e9bce3
parent28fe3b9fdfe50384461193ba3fded999978d0256 (diff)
downloadklibc-80a6119e6d7bee9709a7a632983a4e06e94a7401.tar.gz
open() is a weird function; treat it with care.klibc-0.115
-rw-r--r--include/klibc/compiler.h4
-rw-r--r--include/unistd.h4
-rw-r--r--klibc/Makefile1
-rw-r--r--klibc/SYSCALLS1
-rw-r--r--klibc/include/klibc/compiler.h4
-rw-r--r--klibc/include/unistd.h4
-rw-r--r--klibc/open.c17
7 files changed, 30 insertions, 5 deletions
diff --git a/include/klibc/compiler.h b/include/klibc/compiler.h
index 49872b89d4c24..6c01474cc1add 100644
--- a/include/klibc/compiler.h
+++ b/include/klibc/compiler.h
@@ -8,12 +8,16 @@
#define _KLIBC_COMPILER_H
/* Specific calling conventions */
+/* __cdecl is used when we want varadic and non-varadic functions to have
+ the same binary calling convention. */
#ifdef __i386__
# ifdef __GNUC__
# define __cdecl __attribute__((cdecl,regparm(0)))
# else
/* Most other C compilers have __cdecl as a keyword */
# endif
+#else
+# define __cdecl /* Meaningless on non-i386 */
#endif
/* How to declare a function that *must* be inlined */
diff --git a/include/unistd.h b/include/unistd.h
index 0b61d1afc6c07..13ff03b012cb9 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -77,8 +77,8 @@ __extern int sync(void);
__extern ssize_t read(int, void *, size_t);
__extern ssize_t write(int, const void *, size_t);
-#ifndef __IN_SYS_COMMON
-__extern int open(const char *, int, ...);
+#ifndef __IN_OPEN_C
+__extern __cdecl int open(const char *, int, ...);
#endif
__extern int close(int);
__extern off_t lseek(int, off_t, int);
diff --git a/klibc/Makefile b/klibc/Makefile
index 2ddd753353874..d0689f67bcbc7 100644
--- a/klibc/Makefile
+++ b/klibc/Makefile
@@ -18,6 +18,7 @@ LIBOBJS = vsnprintf.o snprintf.o vsprintf.o sprintf.o \
globals.o exitc.o atexit.o onexit.o \
execl.o execle.o execv.o execvpe.o execvp.o execlp.o execlpe.o \
fork.o wait.o wait3.o waitpid.o system.o setpgrp.o getpgrp.o \
+ open.o \
printf.o vprintf.o fprintf.o vfprintf.o perror.o \
fopen.o fread.o fread2.o fgetc.o fgets.o \
fwrite.o fwrite2.o fputc.o fputs.o puts.o \
diff --git a/klibc/SYSCALLS b/klibc/SYSCALLS
index 809a36425dee9..f206ddf01b4eb 100644
--- a/klibc/SYSCALLS
+++ b/klibc/SYSCALLS
@@ -91,7 +91,6 @@ int lchown(const char *, uid_t, gid_t)
#
ssize_t read(int, void *, size_t)
ssize_t write(int, const void *, size_t)
-int open(const char *, int, mode_t)
int close(int)
off_t lseek(int, off_t, int)
int dup(int)
diff --git a/klibc/include/klibc/compiler.h b/klibc/include/klibc/compiler.h
index 49872b89d4c24..6c01474cc1add 100644
--- a/klibc/include/klibc/compiler.h
+++ b/klibc/include/klibc/compiler.h
@@ -8,12 +8,16 @@
#define _KLIBC_COMPILER_H
/* Specific calling conventions */
+/* __cdecl is used when we want varadic and non-varadic functions to have
+ the same binary calling convention. */
#ifdef __i386__
# ifdef __GNUC__
# define __cdecl __attribute__((cdecl,regparm(0)))
# else
/* Most other C compilers have __cdecl as a keyword */
# endif
+#else
+# define __cdecl /* Meaningless on non-i386 */
#endif
/* How to declare a function that *must* be inlined */
diff --git a/klibc/include/unistd.h b/klibc/include/unistd.h
index 0b61d1afc6c07..13ff03b012cb9 100644
--- a/klibc/include/unistd.h
+++ b/klibc/include/unistd.h
@@ -77,8 +77,8 @@ __extern int sync(void);
__extern ssize_t read(int, void *, size_t);
__extern ssize_t write(int, const void *, size_t);
-#ifndef __IN_SYS_COMMON
-__extern int open(const char *, int, ...);
+#ifndef __IN_OPEN_C
+__extern __cdecl int open(const char *, int, ...);
#endif
__extern int close(int);
__extern off_t lseek(int, off_t, int);
diff --git a/klibc/open.c b/klibc/open.c
new file mode 100644
index 0000000000000..0d7db10c4a3d7
--- /dev/null
+++ b/klibc/open.c
@@ -0,0 +1,17 @@
+/*
+ * open.c
+ *
+ * The open syscall is weird, because it's defined as a varadic
+ * function, but implementing it as such generally sucks for
+ * performance. Thus we generate it as a 3-argument function,
+ * but with explicit __cdecl assuming the __cdecl convention is
+ * independent of being varadic.
+ */
+
+#define __IN_OPEN_C
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+
+__cdecl _syscall3(int,open,const char *,file,int,flags,mode_t,mode)