diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-11-15 14:12:12 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-11-15 14:12:12 +0000 |
commit | 82a975f2f2671f0fb54ccc56d3cc621dad8b645b (patch) | |
tree | 39ad2c87c1a4da6419ddc49638f3c599882e79b4 | |
parent | 80b0b55af2faa2e314d61d2f17fc24c9cfa94a34 (diff) |
This draws from an old patch by David Blythe for the now-dead
unified syscall interface. I reworked his old patch considerably
and cleaned up his version of bits/syscalls.h with some sneaky macro
magic. And I implemented a powerpc correct version of pread/pwrite
-Erik
-rw-r--r-- | libc/sysdeps/linux/powerpc/Makefile | 4 | ||||
-rw-r--r-- | libc/sysdeps/linux/powerpc/__uClibc_syscall.S | 14 | ||||
-rw-r--r-- | libc/sysdeps/linux/powerpc/_mmap.c | 7 | ||||
-rw-r--r-- | libc/sysdeps/linux/powerpc/bits/syscalls.h | 99 | ||||
-rw-r--r-- | libc/sysdeps/linux/powerpc/pread_write.c | 193 | ||||
-rw-r--r-- | libc/sysdeps/linux/powerpc/vfork.c | 7 |
6 files changed, 276 insertions, 48 deletions
diff --git a/libc/sysdeps/linux/powerpc/Makefile b/libc/sysdeps/linux/powerpc/Makefile index 2cf67849d..d765c78e9 100644 --- a/libc/sysdeps/linux/powerpc/Makefile +++ b/libc/sysdeps/linux/powerpc/Makefile @@ -37,10 +37,10 @@ CRT0=crt0.S CRT0_OBJ=$(patsubst %.S,%.o, $(CRT0)) endif -SSRC=__longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S brk.S clone.S +SSRC=__longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S brk.S clone.S __uClibc_syscall.S SOBJS=$(patsubst %.S,%.o, $(SSRC)) -CSRC=_mmap.c vfork.c __syscall_error.c +CSRC=_mmap.c vfork.c __syscall_error.c pread_write.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(SOBJS) $(MOBJ) $(COBJS) diff --git a/libc/sysdeps/linux/powerpc/__uClibc_syscall.S b/libc/sysdeps/linux/powerpc/__uClibc_syscall.S new file mode 100644 index 000000000..09bfb89cc --- /dev/null +++ b/libc/sysdeps/linux/powerpc/__uClibc_syscall.S @@ -0,0 +1,14 @@ +.section ".text" + .align 2 +.globl __uClibc_syscall + .type __uClibc_syscall,@function +__uClibc_syscall: +.Lsize: + sc + bnslr +#ifdef __PIC__ + b __syscall_error@plt +#else + b __syscall_error +#endif + .size __uClibc_syscall,.Lsize-__uClibc_syscall diff --git a/libc/sysdeps/linux/powerpc/_mmap.c b/libc/sysdeps/linux/powerpc/_mmap.c index a229181e0..350f4c49e 100644 --- a/libc/sysdeps/linux/powerpc/_mmap.c +++ b/libc/sysdeps/linux/powerpc/_mmap.c @@ -1,9 +1,14 @@ #include <unistd.h> #include <sys/mman.h> -#include <sys/syscall.h> #include <errno.h> +#include <sys/syscall.h> +#define __syscall_clobbers \ + "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" +#define __syscall_return(type) \ + return (__sc_err & 0x10000000 ? errno = __sc_ret, __sc_ret = -1 : 0), \ + (type) __sc_ret void * mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) diff --git a/libc/sysdeps/linux/powerpc/bits/syscalls.h b/libc/sysdeps/linux/powerpc/bits/syscalls.h index 6b11315e2..f2a1b6da4 100644 --- a/libc/sysdeps/linux/powerpc/bits/syscalls.h +++ b/libc/sysdeps/linux/powerpc/bits/syscalls.h @@ -1,60 +1,71 @@ #ifndef _BITS_SYSCALLS_H #define _BITS_SYSCALLS_H + #ifndef _SYSCALL_H # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead." #endif -#include <features.h> - -/* Do something very evil for now. Until we create our own syscall - * macros, short circuit bits/sysnum.h and use asm/unistd.h instead */ -#include <asm/unistd.h> - /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel * header files. It also defines the traditional `SYS_<name>' macros for older * programs. */ #include <bits/sysnum.h> -/* The kernel includes don't provide _syscall6, so provide our own */ -#undef _syscall6 -#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ -type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ -{ \ - unsigned long __sc_ret, __sc_err; \ - { \ - register unsigned long __sc_0 __asm__ ("r0"); \ - register unsigned long __sc_3 __asm__ ("r3"); \ - register unsigned long __sc_4 __asm__ ("r4"); \ - register unsigned long __sc_5 __asm__ ("r5"); \ - register unsigned long __sc_6 __asm__ ("r6"); \ - register unsigned long __sc_7 __asm__ ("r7"); \ - register unsigned long __sc_8 __asm__ ("r8"); \ - \ - __sc_3 = (unsigned long) (arg1); \ - __sc_4 = (unsigned long) (arg2); \ - __sc_5 = (unsigned long) (arg3); \ - __sc_6 = (unsigned long) (arg4); \ - __sc_7 = (unsigned long) (arg5); \ - __sc_8 = (unsigned long) (arg6); \ - __sc_0 = __NR_##name; \ - __asm__ __volatile__ \ - ("sc \n\t" \ - "mfcr %1 " \ - : "=&r" (__sc_3), "=&r" (__sc_0) \ - : "0" (__sc_3), "1" (__sc_0), \ - "r" (__sc_4), \ - "r" (__sc_5), \ - "r" (__sc_6), \ - "r" (__sc_7), \ - "r" (__sc_8) \ - : __syscall_clobbers); \ - __sc_ret = __sc_3; \ - __sc_err = __sc_0; \ - } \ - __syscall_return (type); \ -} +#define STRINGIFY(s) STRINGIFY2 (s) +#define STRINGIFY2(s) #s + +#ifdef __PIC__ +#define JUMPTARGET(name) STRINGIFY(name##@plt) +#else +#define JUMPTARGET(name) STRINGIFY(name) +#endif + +#define unified_syscall_body(name) \ + __asm__ ( \ + ".section \".text\"\n\t" \ + ".align 2\n\t" \ + ".globl "###name"\n\t" \ + ".type "###name",@function\n" \ + #name":\n\tli 0," STRINGIFY(__NR_##name) "\n\t" \ + "b "JUMPTARGET(__uClibc_syscall)"\n" \ + ".Lfe1"###name":\n\t" \ + ".size\t"###name ",.Lfe1"###name"-"###name"\n" \ + ) +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void); \ +unified_syscall_body(name) + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1); \ +unified_syscall_body(name) + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1, type2 arg2); \ +unified_syscall_body(name) + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1, type2 arg2, type3 arg3); \ +unified_syscall_body(name) + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \ +unified_syscall_body(name) + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \ +unified_syscall_body(name) + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6); \ +unified_syscall_body(name) #endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/powerpc/pread_write.c b/libc/sysdeps/linux/powerpc/pread_write.c new file mode 100644 index 000000000..e9dd36680 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/pread_write.c @@ -0,0 +1,193 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2002 by Erik Andersen <andersen@uclibc.org> + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define _GNU_SOURCE +#define _LARGEFILE64_SOURCE +#include <features.h> +#undef __OPTIMIZE__ +/* We absolutely do _NOT_ want interfaces silently + * * * renamed under us or very bad things will happen... */ +#ifdef __USE_FILE_OFFSET64 +# undef __USE_FILE_OFFSET64 +#endif + + +#include <errno.h> +#include <sys/types.h> +#include <sys/syscall.h> +#include <unistd.h> + +#ifdef __NR_pread +#define __NR___syscall_pread __NR_pread +static inline _syscall4(ssize_t, __syscall_pread, int, fd, + void *, buf, size_t, count, off64_t, offset); + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd, buf, count, (off64_t)offset)); +} +weak_alias (__libc_pread, pread) + +#if defined __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return(__syscall_pread(fd, buf, count, offset)); +} +weak_alias (__libc_pread64, pread64) +#endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pread */ + + +#ifdef __NR_pwrite +#define __NR___syscall_pwrite __NR_pwrite +static inline _syscall4(ssize_t, __syscall_pwrite, int, fd, + const void *, buf, size_t, count, off64_t, offset); + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__syscall_pwrite(fd, buf, count, (off64_t)offset)); +} +weak_alias (__libc_pwrite, pwrite) + +#if defined __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return(__syscall_pwrite(fd, buf, count, offset)); +} +weak_alias (__libc_pwrite64, pwrite64) +#endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ + + + +#if ! defined __NR_pread || ! defined __NR_pwrite +static ssize_t __fake_pread_write(int fd, void *buf, + size_t count, off_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek (fd, offset, SEEK_SET) == (off_t) -1) + return -1; + + if (do_pwrite==1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. If this fails we + * have to return this as an error. */ + save_errno = errno; + if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1) + { + if (result == -1) + __set_errno(save_errno); + return -1; + } + __set_errno(save_errno); + return(result); +} + +#if defined __UCLIBC_HAS_LFS__ +static ssize_t __fake_pread_write64(int fd, void *buf, + size_t count, off64_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off64_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) + return -1; + + if (do_pwrite==1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. */ + save_errno = errno; + if (lseek64 (fd, old_offset, SEEK_SET) == (off64_t) -1) { + if (result == -1) + __set_errno (save_errno); + return -1; + } + __set_errno (save_errno); + return result; +} +#endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! defined __NR_pread || ! defined __NR_pwrite */ + +#ifndef __NR_pread +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__fake_pread_write(fd, buf, count, offset, 0)); +} +weak_alias (__libc_pread, pread) + +#if defined __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return(__fake_pread_write64(fd, buf, count, offset, 0)); +} +weak_alias (__libc_pread64, pread64) +#endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pread */ + + +#ifndef __NR_pwrite +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__fake_pread_write(fd, buf, count, offset, 1)); +} +weak_alias (__libc_pwrite, pwrite) + +#if defined __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return(__fake_pread_write64(fd, (void*)buf, count, offset, 1)); +} +weak_alias (__libc_pwrite64, pwrite64) +#endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pwrite */ + diff --git a/libc/sysdeps/linux/powerpc/vfork.c b/libc/sysdeps/linux/powerpc/vfork.c index fcf020804..750255be9 100644 --- a/libc/sysdeps/linux/powerpc/vfork.c +++ b/libc/sysdeps/linux/powerpc/vfork.c @@ -1,9 +1,14 @@ #include <unistd.h> -#include <sys/syscall.h> #include <sys/types.h> #include <errno.h> +#include <sys/syscall.h> +#define __syscall_clobbers \ + "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" +#define __syscall_return(type) \ + return (__sc_err & 0x10000000 ? errno = __sc_ret, __sc_ret = -1 : 0), \ + (type) __sc_ret int vfork(void) { |