diff options
Diffstat (limited to 'nptl/sysdeps/unix/sysv')
41 files changed, 2287 insertions, 1 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/close.c b/nptl/sysdeps/unix/sysv/linux/close.c new file mode 100644 index 0000000000..e5cac953f3 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/close.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include <unistd.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +__libc_close (int fd) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (close, 1, fd); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (close, 1, fd); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__libc_close, __close) +libc_hidden_weak (__close) +weak_alias (__libc_close, close) diff --git a/nptl/sysdeps/unix/sysv/linux/connect.S b/nptl/sysdeps/unix/sysv/linux/connect.S new file mode 100644 index 0000000000..ce6a038fa5 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/connect.S @@ -0,0 +1,6 @@ +#define socket connect +#define __socket __libc_connect +#define NARGS 3 +#include <pt-socket.S> +strong_alias (__libc_connect, __connect_internal) +weak_alias (__libc_connect, __connect) diff --git a/nptl/sysdeps/unix/sysv/linux/creat.c b/nptl/sysdeps/unix/sysv/linux/creat.c new file mode 100644 index 0000000000..c21c8bb9a4 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/creat.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sysdep.h> +#include <unistd.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +creat (const char *pathname, mode_t mode) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + { +#ifdef __NR_creat + return INLINE_SYSCALL (creat, 2, pathname, mode); +#else + return __libc_open (pathname, O_WRONLY|O_CREAT|O_TRUNC, mode); +#endif + } + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + +#ifdef __NR_creat + int result = INLINE_SYSCALL (creat, 2, pathname, mode); +#else + int result = __libc_open (pathname, O_WRONLY|O_CREAT|O_TRUNC, mode); +#endif + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} diff --git a/nptl/sysdeps/unix/sysv/linux/fsync.c b/nptl/sysdeps/unix/sysv/linux/fsync.c new file mode 100644 index 0000000000..b132a75ee9 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/fsync.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include <unistd.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +__libc_fsync (int fd) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (fsync, 1, fd); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (fsync, 1, fd); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_fsync, fsync) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/fcntl.c b/nptl/sysdeps/unix/sysv/linux/i386/fcntl.c new file mode 100644 index 0000000000..89b8084693 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/i386/fcntl.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> + +#include <nptl/pthreadP.h> +#include <tls.h> +#include <sysdep.h> +#include <sys/syscall.h> +#include "../kernel-features.h" + +extern int __syscall_fcntl64 (int __fd, int __cmd, ...); + + +int +__libc_fcntl (int fd, int cmd, ...) +{ + va_list ap; + + va_start (ap, cmd); + void *arg = va_arg (ap, void *); + va_end (ap); + +#ifndef NOT_IN_libc + if (cmd != F_SETLKW + || __builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, + 1)) + return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +libc_hidden_def (__libc_fcntl) + +weak_alias (__libc_fcntl, __fcntl) +libc_hidden_weak (__fcntl) +weak_alias (__libc_fcntl, fcntl) diff --git a/nptl/sysdeps/unix/sysv/linux/i386/pt-socket.S b/nptl/sysdeps/unix/sysv/linux/i386/pt-socket.S index 0b8523bd86..d9140edcc5 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/pt-socket.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/pt-socket.S @@ -18,6 +18,7 @@ #include <sysdep.h> #include <socketcall.h> +#include <tls.h> #define P(a, b) P2(a, b) #define P2(a, b) a##b @@ -37,8 +38,34 @@ .globl __socket ENTRY (__socket) + cmpl $0, %gs:MULTIPLE_THREADS_OFFSET + jne 1f + + /* Save registers. */ + movl %ebx, %edx + + movl $SYS_ify(socketcall), %eax /* System call number in %eax. */ + + /* Use ## so `socket' is a separate token that might be #define'd. */ + movl $P(SOCKOP_,socket), %ebx /* Subcode is first arg to syscall. */ + lea 4(%esp), %ecx /* Address of args is 2nd arg. */ + + /* Do the system call trap. */ + int $0x80 + + /* Restore registers. */ + movl %edx, %ebx + + /* %eax is < 0 if there was an error. */ + cmpl $-125, %eax + jae SYSCALL_ERROR_LABEL + + /* Successful; return the syscall's value. */ + ret + + /* We need one more register. */ - pushl %esi +1: pushl %esi /* Enable asynchronous cancellation. */ call __libc_enable_asynccancel /* No @plt */ diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c index 80b6dbcb4f..bf0551a7e4 100644 --- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c +++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -17,8 +17,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <unistd.h> #include <list.h> #include "fork.h" +#include <tls.h> #include <bits/libc-lock.h> @@ -38,4 +40,15 @@ __libc_pthread_init (ptr, reclaim) /* The fork handler needed by libpthread. */ list_add_tail (&pthread_child_handler.list, &__fork_child_list); + + /* We have a macro which is used in asm code describing data layout. + Make sure it does not get out of date. */ + if (offsetof (struct pthread, header.data.multiple_threads) + != MULTIPLE_THREADS_OFFSET) + { +#define str_n_len(str) str, sizeof (str) - 1 + __libc_write (STDERR_FILENO, + str_n_len ("*** MULTIPLE_THREADS_OFFSET out of date\n")); + _exit (1); + } } diff --git a/nptl/sysdeps/unix/sysv/linux/llseek.c b/nptl/sysdeps/unix/sysv/linux/llseek.c new file mode 100644 index 0000000000..e807bcfec2 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/llseek.c @@ -0,0 +1,68 @@ +/* Long-long seek operation. + Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +extern int __syscall__llseek (int fd, off_t offset_hi, off_t offset_lo, + loff_t *__unbounded result, int whence); + +/* Seek to OFFSET on FD, starting from WHENCE. */ +extern loff_t __llseek (int fd, loff_t offset, int whence); + +loff_t +__llseek (int fd, loff_t offset, int whence) +{ + loff_t result; + +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return (loff_t) (INLINE_SYSCALL (_llseek, 5, fd, (off_t) (offset >> 32), + (off_t) (offset & 0xffffffff), + __ptrvalue (&result), whence) ?: result); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int retval = INLINE_SYSCALL (_llseek, 5, fd, (off_t) (offset >> 32), + (off_t) (offset & 0xffffffff), + __ptrvalue (&result), whence); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return (loff_t) (retval ?: result); +} +weak_alias (__llseek, llseek) +strong_alias (__llseek, __libc_lseek64) +strong_alias (__llseek, __lseek64) +weak_alias (__llseek, lseek64) + +/* llseek doesn't have a prototype. Since the second parameter is a + 64bit type, this results in wrong behaviour if no prototype is + provided. */ +link_warning (llseek, "\ +the `llseek' function may be dangerous; use `lseek64' instead.") diff --git a/nptl/sysdeps/unix/sysv/linux/lseek.c b/nptl/sysdeps/unix/sysv/linux/lseek.c new file mode 100644 index 0000000000..5229216122 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/lseek.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include <unistd.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +off_t +__libc_lseek (int fd, off_t offset, int whence) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (lseek, 3, fd, offset, whence); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + off_t result = INLINE_SYSCALL (lseek, 3, fd, offset, whence); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__libc_lseek, __lseek) +weak_alias (__libc_lseek, lseek) diff --git a/nptl/sysdeps/unix/sysv/linux/msgrcv.c b/nptl/sysdeps/unix/sysv/linux/msgrcv.c new file mode 100644 index 0000000000..af1953f5a0 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/msgrcv.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1995, 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sys/msg.h> +#include <ipc_priv.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +#include <bp-checks.h> + +/* Kludge to work around Linux' restriction of only up to five + arguments to a system call. */ +struct ipc_kludge + { + void *__unbounded msgp; + long int msgtyp; + }; + + +int +__libc_msgrcv (msqid, msgp, msgsz, msgtyp, msgflg) + int msqid; + void *msgp; + size_t msgsz; + long int msgtyp; + int msgflg; +{ + /* The problem here is that Linux' calling convention only allows up to + fives parameters to a system call. */ + struct ipc_kludge tmp; + + tmp.msgp = CHECK_N (msgp, msgsz); + tmp.msgtyp = msgtyp; + +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg, + __ptrvalue (&tmp)); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg, + __ptrvalue (&tmp)); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_msgrcv, msgrcv) diff --git a/nptl/sysdeps/unix/sysv/linux/msgsnd.c b/nptl/sysdeps/unix/sysv/linux/msgsnd.c new file mode 100644 index 0000000000..1f3e40a0c6 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/msgsnd.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1995,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sys/msg.h> +#include <ipc_priv.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +#include <bp-checks.h> + +int +__libc_msgsnd (msqid, msgp, msgsz, msgflg) + int msqid; + const void *msgp; + size_t msgsz; + int msgflg; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (ipc, 5, IPCOP_msgsnd, msqid, msgsz, + msgflg, (void *) CHECK_N (msgp, msgsz)); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (ipc, 5, IPCOP_msgsnd, msqid, msgsz, + msgflg, (void *) CHECK_N (msgp, msgsz)); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_msgsnd, msgsnd) diff --git a/nptl/sysdeps/unix/sysv/linux/msync.c b/nptl/sysdeps/unix/sysv/linux/msync.c new file mode 100644 index 0000000000..9edd56c024 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/msync.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include <sys/mman.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +__libc_msync (void *start, size_t length, int flags) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (msync, 3, start, length, flags); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (msync, 3, start, length, flags); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_msync, msync) diff --git a/nptl/sysdeps/unix/sysv/linux/nanosleep.c b/nptl/sysdeps/unix/sysv/linux/nanosleep.c new file mode 100644 index 0000000000..d43f9eb9da --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/nanosleep.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include <time.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +__libc_nanosleep (const struct timespec *req, struct timespec *rem) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (nanosleep, 2, req, rem); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (nanosleep, 2, req, rem); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__libc_nanosleep, __nanosleep) +weak_alias (__libc_nanosleep, nanosleep) diff --git a/nptl/sysdeps/unix/sysv/linux/open.c b/nptl/sysdeps/unix/sysv/linux/open.c new file mode 100644 index 0000000000..f0f95c1b60 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/open.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sysdep.h> +#include <stdarg.h> +#include <unistd.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +__libc_open (const char *file, int oflag, ...) +{ + int mode = 0; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, int); + va_end (arg); + } + +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (open, 3, file, oflag, mode); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (open, 3, file, oflag, mode); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +libc_hidden_def (__libc_open) +strong_alias (__libc_open, __open) +libc_hidden_weak (__open) +weak_alias (__libc_open, open) diff --git a/nptl/sysdeps/unix/sysv/linux/open64.c b/nptl/sysdeps/unix/sysv/linux/open64.c new file mode 100644 index 0000000000..0fac91609c --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/open64.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sysdep.h> +#include <stdarg.h> +#include <unistd.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +__libc_open64 (const char *file, int oflag, ...) +{ + int mode = 0; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, int); + va_end (arg); + } + +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__libc_open64, __open64) +libc_hidden_weak (__open64) +weak_alias (__libc_open64, open64) diff --git a/nptl/sysdeps/unix/sysv/linux/pause.c b/nptl/sysdeps/unix/sysv/linux/pause.c new file mode 100644 index 0000000000..6348974031 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/pause.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include <unistd.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +int +__libc_pause (void) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (pause, 0); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (pause, 0); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_pause, pause) diff --git a/nptl/sysdeps/unix/sysv/linux/poll.c b/nptl/sysdeps/unix/sysv/linux/poll.c new file mode 100644 index 0000000000..e44db71d61 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/poll.c @@ -0,0 +1,59 @@ +/* Poll system call, with emulation if it is not available. + Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sys/poll.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +extern int __syscall_poll (struct pollfd *__unbounded fds, + unsigned int nfds, int timeout); + + +/* The real implementation. */ +int +__poll (fds, nfds, timeout) + struct pollfd *fds; + nfds_t nfds; + int timeout; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (poll, 3, CHECK_N (fds, nfds), nfds, timeout); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (poll, 3, CHECK_N (fds, nfds), nfds, timeout); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +libc_hidden_def (__poll) +weak_alias (__poll, poll) +strong_alias (__poll, __libc_poll) diff --git a/nptl/sysdeps/unix/sysv/linux/pread.c b/nptl/sysdeps/unix/sysv/linux/pread.c new file mode 100644 index 0000000000..ec792693b0 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/pread.c @@ -0,0 +1,70 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <endian.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +#ifndef __NR_pread64 /* Newer kernels renamed but it's the same. */ +# error "__NR_pread64 must be defined" +#endif + + +/* The order of hi, lo depends on endianness. */ +extern ssize_t __syscall_pread64 (int fd, void *__unbounded buf, size_t count, + off_t offset_hi, off_t offset_lo); + + +ssize_t +__libc_pread (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off_t offset; +{ + assert (sizeof (offset) == 4); +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (pread64, 5, fd, CHECK_N (buf, count), count, + __LONG_LONG_PAIR (offset >> 31, offset)); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + ssize_t result = INLINE_SYSCALL (pread64, 5, fd, CHECK_N (buf, count), count, + __LONG_LONG_PAIR (offset >> 31, offset)); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} + +strong_alias (__libc_pread, __pread) +weak_alias (__libc_pread, pread) diff --git a/nptl/sysdeps/unix/sysv/linux/pread64.c b/nptl/sysdeps/unix/sysv/linux/pread64.c new file mode 100644 index 0000000000..5abe5d1813 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/pread64.c @@ -0,0 +1,71 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <endian.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +#ifndef __NR_pread64 /* Newer kernels renamed but it's the same. */ +# error "__NR_pread64 must be defined" +#endif + + +/* The order of hi, lo depends on endianness. */ +extern ssize_t __syscall_pread64 (int fd, void *__unbounded buf, size_t count, + off_t offset_hi, off_t offset_lo); + + +ssize_t +__libc_pread64 (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off64_t offset; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (pread64, 5, fd, CHECK_N (buf, count), count, + __LONG_LONG_PAIR ((off_t) (offset >> 32), + (off_t) (offset & 0xffffffff))); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + ssize_t result = INLINE_SYSCALL (pread64, 5, fd, CHECK_N (buf, count), count, + __LONG_LONG_PAIR ((off_t) (offset >> 32), + (off_t) (offset + & 0xffffffff))); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} + +weak_alias (__libc_pread64, __pread64) +weak_alias (__libc_pread64, pread64) diff --git a/nptl/sysdeps/unix/sysv/linux/pselect.c b/nptl/sysdeps/unix/sysv/linux/pselect.c new file mode 100644 index 0000000000..bb5daa8768 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/pselect.c @@ -0,0 +1,91 @@ +/* Copyright (C) 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <stddef.h> /* For NULL. */ +#include <sys/time.h> +#include <sys/select.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Additionally set the sigmask + SIGMASK for this call. Returns the number of ready descriptors, or -1 for + errors. */ +static int +do_pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + struct timeval tval; + int retval; + sigset_t savemask; + + /* Change nanosecond number to microseconds. This might mean losing + precision and therefore the `pselect` should be available. But + for now it is hardly found. */ + if (timeout != NULL) + TIMESPEC_TO_TIMEVAL (&tval, timeout); + + /* The setting and restoring of the signal mask and the select call + should be an atomic operation. This can't be done without kernel + help. */ + if (sigmask != NULL) + __sigprocmask (SIG_SETMASK, sigmask, &savemask); + + retval = __select (nfds, readfds, writefds, exceptfds, + timeout != NULL ? &tval : NULL); + + if (sigmask != NULL) + __sigprocmask (SIG_SETMASK, &savemask, NULL); + + return retval; +} + + +int +__pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask) + int nfds; + fd_set *readfds; + fd_set *writefds; + fd_set *exceptfds; + const struct timespec *timeout; + const sigset_t *sigmask; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return do_pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = do_pselect (nfds, readfds, writefds, exceptfds, timeout, + sigmask); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__pselect, pselect) +strong_alias (__pselect, __libc_pselect) diff --git a/nptl/sysdeps/unix/sysv/linux/pwrite.c b/nptl/sysdeps/unix/sysv/linux/pwrite.c new file mode 100644 index 0000000000..d13fe5a4a3 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/pwrite.c @@ -0,0 +1,72 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <endian.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +#ifndef __NR_pwrite64 +# error "__NR_pwrite64 must be defined" +#endif + + +/* The order of hi, lo depends on endianness. */ +extern ssize_t __syscall_pwrite64 (int fd, const void *__unbounded buf, + size_t count, off_t offset_hi, + off_t offset_lo); + + +ssize_t +__libc_pwrite (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off_t offset; +{ + /* First try the syscall. */ + assert (sizeof (offset) == 4); +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (pwrite64, 5, fd, CHECK_N (buf, count), count, + __LONG_LONG_PAIR (offset >> 31, offset)); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + ssize_t result = INLINE_SYSCALL (pwrite64, 5, fd, CHECK_N (buf, count), + count, + __LONG_LONG_PAIR (offset >> 31, offset)); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} + +strong_alias (__libc_pwrite, __pwrite) +weak_alias (__libc_pwrite, pwrite) diff --git a/nptl/sysdeps/unix/sysv/linux/pwrite64.c b/nptl/sysdeps/unix/sysv/linux/pwrite64.c new file mode 100644 index 0000000000..37c2b9c6f1 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/pwrite64.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <endian.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +#ifndef __NR_pwrite64 +# error "__NR_pwrite64 must be defined" +#endif + + +/* The order of hi, lo depends on endianness. */ +extern ssize_t __syscall_pwrite64 (int fd, const void *__unbounded buf, + size_t count, off_t offset_hi, + off_t offset_lo); + + +ssize_t +__libc_pwrite64 (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off64_t offset; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (pwrite64, 5, fd, CHECK_N (buf, count), count, + __LONG_LONG_PAIR ((off_t) (offset >> 32), + (off_t) (offset & 0xffffffff))); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + ssize_t result = INLINE_SYSCALL (pwrite64, 5, fd, CHECK_N (buf, count), + count, + __LONG_LONG_PAIR ((off_t) (offset >> 32), + (off_t) (offset + & 0xffffffff))); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} + +weak_alias (__libc_pwrite64, __pwrite64) +libc_hidden_weak (__pwrite64) +weak_alias (__libc_pwrite64, pwrite64) diff --git a/nptl/sysdeps/unix/sysv/linux/readv.c b/nptl/sysdeps/unix/sysv/linux/readv.c new file mode 100644 index 0000000000..3bf83ba6a6 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/readv.c @@ -0,0 +1,58 @@ +/* readv supports all Linux kernels >= 2.0. + Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stddef.h> +#include <sys/param.h> +#include <sys/uio.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +extern ssize_t __syscall_readv (int, __const struct iovec *__unbounded, int); + + +ssize_t +__libc_readv (fd, vector, count) + int fd; + const struct iovec *vector; + int count; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (readv, 3, fd, CHECK_N (vector, count), count); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + ssize_t result = INLINE_SYSCALL (readv, 3, fd, CHECK_N (vector, count), + count); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__libc_readv, __readv) +weak_alias (__libc_readv, readv) diff --git a/nptl/sysdeps/unix/sysv/linux/recv.S b/nptl/sysdeps/unix/sysv/linux/recv.S new file mode 100644 index 0000000000..2f8bc3339a --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/recv.S @@ -0,0 +1,5 @@ +#define socket recv +#define __socket __libc_recv +#define NARGS 4 +#include <pt-socket.S> +weak_alias (__libc_recv, __recv) diff --git a/nptl/sysdeps/unix/sysv/linux/recvfrom.S b/nptl/sysdeps/unix/sysv/linux/recvfrom.S new file mode 100644 index 0000000000..0b938e3bb4 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/recvfrom.S @@ -0,0 +1,5 @@ +#define socket recvfrom +#define __socket __libc_recvfrom +#define NARGS 6 +#include <pt-socket.S> +weak_alias (__libc_recvfrom, __recvfrom) diff --git a/nptl/sysdeps/unix/sysv/linux/recvmsg.S b/nptl/sysdeps/unix/sysv/linux/recvmsg.S new file mode 100644 index 0000000000..64e44ac151 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/recvmsg.S @@ -0,0 +1,5 @@ +#define socket recvmsg +#define __socket __libc_recvmsg +#define NARGS 3 +#include <pt-socket.S> +weak_alias (__libc_recvmsg, __recvmsg) diff --git a/nptl/sysdeps/unix/sysv/linux/select.c b/nptl/sysdeps/unix/sysv/linux/select.c new file mode 100644 index 0000000000..b1c46595be --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/select.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include <sys/select.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +#ifdef __NR__newselect +# undef __NR_select +# define __NR_select __NR__newselect +#endif + + +int +__libc_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (select, 5, n, readfds, writefds, exceptfds, + timeout); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (select, 5, n, readfds, writefds, exceptfds, + timeout); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__libc_select, __select) +libc_hidden_weak(__select) +weak_alias (__libc_select, select) diff --git a/nptl/sysdeps/unix/sysv/linux/send.S b/nptl/sysdeps/unix/sysv/linux/send.S new file mode 100644 index 0000000000..f20c54321b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/send.S @@ -0,0 +1,6 @@ +#define socket send +#define __socket __libc_send +#define NARGS 4 +#include <pt-socket.S> +weak_alias (__libc_send, __send) +libc_hidden_def (__send) diff --git a/nptl/sysdeps/unix/sysv/linux/sendmsg.S b/nptl/sysdeps/unix/sysv/linux/sendmsg.S new file mode 100644 index 0000000000..f83bb58331 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sendmsg.S @@ -0,0 +1,5 @@ +#define socket sendmsg +#define __socket __libc_sendmsg +#define NARGS 3 +#include <pt-socket.S> +weak_alias (__libc_sendmsg, __sendmsg) diff --git a/nptl/sysdeps/unix/sysv/linux/sendto.S b/nptl/sysdeps/unix/sysv/linux/sendto.S new file mode 100644 index 0000000000..10bcc6742b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sendto.S @@ -0,0 +1,5 @@ +#define socket sendto +#define __socket __libc_sendto +#define NARGS 6 +#include <pt-socket.S> +weak_alias (__libc_sendto, __sendto) diff --git a/nptl/sysdeps/unix/sysv/linux/sigpause.c b/nptl/sysdeps/unix/sysv/linux/sigpause.c new file mode 100644 index 0000000000..bd7756c89b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sigpause.c @@ -0,0 +1,100 @@ +/* Copyright (C) 1991,92,94-98,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <stddef.h> /* For NULL. */ +#include <nptl/pthreadP.h> +#include <tls.h> + +#include <sigset-cvt-mask.h> + +/* Set the mask of blocked signals to MASK, + wait for a signal to arrive, and then restore the mask. */ +int +__sigpause (int sig_or_mask, int is_sig) +{ + sigset_t set; + + if (is_sig != 0) + { + /* The modern X/Open implementation is requested. */ + if (__sigprocmask (0, NULL, &set) < 0 + /* Yes, we call `sigdelset' and not `__sigdelset'. */ + || __sigdelset (&set, sig_or_mask) < 0) + return -1; + } + else if (sigset_set_old_mask (&set, sig_or_mask) < 0) + return -1; + + return __sigsuspend (&set); +} +libc_hidden_def (__sigpause) + +/* We have to provide a default version of this function since the + standards demand it. The version which is a bit more reasonable is + the BSD version. So make this the default. */ +int +__attribute__ ((weak)) +__default_sigpause (int mask) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return __sigpause (mask, 0); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = __sigpause (mask, 0); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +#undef sigpause +weak_alias (__default_sigpause, sigpause) +strong_alias (__default_sigpause, __libc_sigpause) + + +/* We have to provide a default version of this function since the + standards demand it. The version which is a bit more reasonable is + the BSD version. So make this the default. */ +int +__attribute__ ((weak)) +__xpg_sigpause (int sig) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return __sigpause (sig, 1); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = __sigpause (sig, 1); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__xpg_sigpause, __libc___xpg_sigpause) diff --git a/nptl/sysdeps/unix/sysv/linux/sigsuspend.c b/nptl/sysdeps/unix/sysv/linux/sigsuspend.c new file mode 100644 index 0000000000..2a7dfef49f --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sigsuspend.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +extern int __syscall_rt_sigsuspend (const sigset_t *__unbounded, size_t); + + +/* Change the set of blocked signals to SET, + wait until a signal arrives, and restore the set of blocked signals. */ +int +__sigsuspend (set) + const sigset_t *set; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), _NSIG / 8); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), + _NSIG / 8); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +libc_hidden_def (__sigsuspend) +weak_alias (__sigsuspend, sigsuspend) +strong_alias (__sigsuspend, __libc_sigsuspend) diff --git a/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c b/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c new file mode 100644 index 0000000000..90f739c9b9 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +extern int __syscall_rt_sigtimedwait (const sigset_t *__unbounded, siginfo_t *__unbounded, + const struct timespec *__unbounded, size_t); + + +/* Return any pending signal or wait for one for the given time. */ +int +__sigtimedwait (set, info, timeout) + const sigset_t *set; + siginfo_t *info; + const struct timespec *timeout; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + return INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + CHECK_1 (info), timeout, _NSIG / 8); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + CHECK_1 (info), timeout, _NSIG / 8); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +libc_hidden_def (__sigtimedwait) +weak_alias (__sigtimedwait, sigtimedwait) diff --git a/nptl/sysdeps/unix/sysv/linux/sigwait.c b/nptl/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 0000000000..540ca57182 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,91 @@ +/* Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#define __need_NULL +#include <stddef.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +extern int __syscall_rt_sigtimedwait (const sigset_t *__unbounded, siginfo_t *__unbounded, + const struct timespec *__unbounded, size_t); + + +/* Return any pending signal or wait for one for the given time. */ +static int +do_sigwait (const sigset_t *set, int *sig) +{ + int ret; + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ +#ifdef INTERNAL_SYSCALL + ret = INTERNAL_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + NULL, NULL, _NSIG / 8); + if (! INTERNAL_SYSCALL_ERROR_P (ret)) + { + *sig = ret; + ret = 0; + } + else + ret = INTERNAL_SYSCALL_ERRNO (ret); +#else + ret = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + NULL, NULL, _NSIG / 8); + if (ret != -1) + { + *sig = ret; + ret = 0; + } + else + ret = errno; +#endif + + return ret; +} + + +int +__sigwait (set, sig) + const sigset_t *set; + int *sig; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return do_sigwait (set, sig); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = do_sigwait (set, sig); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +libc_hidden_def (__sigwait) +weak_alias (__sigwait, sigwait) +strong_alias (__sigwait, __libc_sigwait) diff --git a/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c b/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c new file mode 100644 index 0000000000..f79f4ba366 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#define __need_NULL +#include <stddef.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +extern int __syscall_rt_sigtimedwait (const sigset_t *__unbounded, siginfo_t *__unbounded, + const struct timespec *__unbounded, size_t); + + +/* Return any pending signal or wait for one for the given time. */ +int +__sigwaitinfo (set, info) + const sigset_t *set; + siginfo_t *info; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + return INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + CHECK_1 (info), NULL, _NSIG / 8); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + CHECK_1 (info), NULL, _NSIG / 8); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +libc_hidden_def (__sigwaitinfo) +weak_alias (__sigwaitinfo, sigwaitinfo) +strong_alias (__sigwaitinfo, __libc_sigwaitinfo) diff --git a/nptl/sysdeps/unix/sysv/linux/system.c b/nptl/sysdeps/unix/sysv/linux/system.c new file mode 100644 index 0000000000..638967e2cb --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/system.c @@ -0,0 +1,209 @@ +/* Copyright (C) 1991-99,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <bits/libc-lock.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +#ifndef HAVE_GNU_LD +#define __environ environ +#endif + +#define SHELL_PATH "/bin/sh" /* Path of the shell. */ +#define SHELL_NAME "sh" /* Name to give it. */ + + +#ifdef _LIBC_REENTRANT +static struct sigaction intr, quit; +static int sa_refcntr; +__libc_lock_define_initialized (static, lock); + +# define DO_LOCK() __libc_lock_lock (lock) +# define DO_UNLOCK() __libc_lock_unlock (lock) +# define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; }) +# define ADD_REF() sa_refcntr++ +# define SUB_REF() --sa_refcntr +#else +# define DO_LOCK() +# define DO_UNLOCK() +# define INIT_LOCK() +# define ADD_REF() (void) 0 +# define SUB_REF() 0 +#endif + + +/* Execute LINE as a shell command, returning its status. */ +static int +do_system (const char *line) +{ + int status, save; + pid_t pid; + struct sigaction sa; +#ifndef _LIBC_REENTRANT + struct sigaction intr, quit; +#endif +#ifndef WAITPID_CANNOT_BLOCK_SIGCHLD + sigset_t block, omask; +#endif + + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + __sigemptyset (&sa.sa_mask); + + DO_LOCK (); + if (ADD_REF () == 0) + { + if (__sigaction (SIGINT, &sa, &intr) < 0) + { + SUB_REF (); + DO_UNLOCK (); + return -1; + } + if (__sigaction (SIGQUIT, &sa, &quit) < 0) + { + save = errno; + goto out_restore_sigint; + } + } + DO_UNLOCK (); + + __sigemptyset (&block); + __sigaddset (&block, SIGCHLD); + save = errno; + if (__sigprocmask (SIG_BLOCK, &block, &omask) < 0) + { + if (errno == ENOSYS) + __set_errno (save); + else + { + save = errno; + DO_LOCK (); + if (SUB_REF () == 0) + { + (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); + out_restore_sigint: + (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); + } + DO_UNLOCK (); + __set_errno (save); + return -1; + } + } + + pid = __fork (); + if (pid == (pid_t) 0) + { + /* Child side. */ + const char *new_argv[4]; + new_argv[0] = SHELL_NAME; + new_argv[1] = "-c"; + new_argv[2] = line; + new_argv[3] = NULL; + + /* Restore the signals. */ + (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); + (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); + (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL); + INIT_LOCK (); + + /* Exec the shell. */ + (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ); + _exit (127); + } + else if (pid < (pid_t) 0) + /* The fork failed. */ + status = -1; + else + /* Parent side. */ + { +#ifdef NO_WAITPID + pid_t child; + do + { + child = __wait (&status); + if (child <= -1 && errno != EINTR) + { + status = -1; + break; + } + /* Note that pid cannot be <= -1 and therefore the loop continues + when __wait returned with EINTR. */ + } + while (child != pid); +#else + if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid) + status = -1; +#endif + } + + save = errno; + DO_LOCK (); + if ((SUB_REF () == 0 + && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL) + | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0) + || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0) + { +#ifndef _LIBC + /* glibc cannot be used on systems without waitpid. */ + if (errno == ENOSYS) + __set_errno (save); + else +#endif + status = -1; + } + DO_UNLOCK (); + + return status; +} + + +int +__libc_system (const char *line) +{ + if (line == NULL) + /* Check that we have a command processor available. It might + not be available after a chroot(), for example. */ + return do_system ("exit 0") == 0; + +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return do_system (line); + + /* XXX We have to install a cancellation handler to kill the child + process. */ + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = do_system (line); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_system, system) diff --git a/nptl/sysdeps/unix/sysv/linux/tcdrain.c b/nptl/sysdeps/unix/sysv/linux/tcdrain.c new file mode 100644 index 0000000000..df0c969d11 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/tcdrain.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <termios.h> +#include <sys/ioctl.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +/* Wait for pending output to be written on FD. */ +int +__libc_tcdrain (int fd) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + /* With an argument of 1, TCSBRK for output to be drain. */ + return __ioctl (fd, TCSBRK, 1); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + /* With an argument of 1, TCSBRK for output to be drain. */ + int result = __ioctl (fd, TCSBRK, 1); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_tcdrain, tcdrain) diff --git a/nptl/sysdeps/unix/sysv/linux/wait.c b/nptl/sysdeps/unix/sysv/linux/wait.c new file mode 100644 index 0000000000..5846075563 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/wait.c @@ -0,0 +1,52 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/wait.h> +#include <errno.h> +#include <sys/resource.h> +#include <stddef.h> +#include <sysdep.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +/* Wait for a child to die. When one does, put its status in *STAT_LOC + and return its process ID. For errors, return (pid_t) -1. */ +__pid_t +__libc_wait (__WAIT_STATUS_DEFN stat_loc) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0, + (struct rusage *) NULL); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0, + (struct rusage *) NULL); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} + +weak_alias (__libc_wait, __wait) +weak_alias (__libc_wait, wait) diff --git a/nptl/sysdeps/unix/sysv/linux/waitid.c b/nptl/sysdeps/unix/sysv/linux/waitid.c new file mode 100644 index 0000000000..589f421845 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/waitid.c @@ -0,0 +1,145 @@ +/* Pseudo implementation of waitid. + Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#define __need_NULL +#include <stddef.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <nptl/pthreadP.h> +#include <tls.h> + + +static int +do_waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options) +{ + pid_t pid, child; + int status; + + switch (idtype) + { + case P_PID: + if(id <= 0) + goto invalid; + pid = (pid_t) id; + break; + case P_PGID: + if (id < 0 || id == 1) + goto invalid; + pid = (pid_t) -id; + break; + case P_ALL: + pid = -1; + break; + default: + invalid: + __set_errno (EINVAL); + return -1; + } + + /* Technically we're supposed to return EFAULT if infop is bogus, + but that would involve mucking with signals, which is + too much hassle. User will have to deal with SIGSEGV/SIGBUS. + We just check for a null pointer. */ + + if (infop == NULL) + { + __set_errno (EFAULT); + return -1; + } + + child = __waitpid (pid, &status, options); + + if (child == -1) + /* `waitpid' set `errno' for us. */ + return -1; + + if (child == 0) + { + /* The WHOHANG bit in OPTIONS is set and there are children available + but none has a status for us. The XPG docs do not mention this + case so we clear the `siginfo_t' struct and return successfully. */ + infop->si_signo = 0; + infop->si_code = 0; + return 0; + } + + /* Decode the status field and set infop members... */ + infop->si_signo = SIGCHLD; + infop->si_pid = child; + infop->si_errno = 0; + + if (WIFEXITED (status)) + { + infop->si_code = CLD_EXITED; + infop->si_status = WEXITSTATUS (status); + } + else if (WIFSIGNALED (status)) + { + infop->si_code = WCOREDUMP (status) ? CLD_DUMPED : CLD_KILLED; + infop->si_status = WTERMSIG (status); + } + else if (WIFSTOPPED (status)) + { + infop->si_code = CLD_STOPPED; + infop->si_status = WSTOPSIG (status); + } +#ifdef WIFCONTINUED + else if (WIFCONTINUED (status)) + { + infop->si_code = CLD_CONTINUED; + infop->si_status = SIGCONT; + } +#endif + else + /* Can't happen. */ + assert (! "What?"); + + return 0; +} + + +int +__waitid (idtype, id, infop, options) + idtype_t idtype; + id_t id; + siginfo_t *infop; + int options; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return do_waitid (idtype, id, infop, options); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = do_waitid (idtype, id, infop, options); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__waitid, waitid) +strong_alias (__waitid, __libc_waitid) diff --git a/nptl/sysdeps/unix/sysv/linux/waitpid.c b/nptl/sysdeps/unix/sysv/linux/waitpid.c new file mode 100644 index 0000000000..ab4bd67127 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/waitpid.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991,92,95,96,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +__pid_t +__libc_waitpid (__pid_t pid, int *stat_loc, int options) +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + int result = INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +weak_alias (__libc_waitpid, __waitpid) +libc_hidden_weak (__waitpid) +weak_alias (__libc_waitpid, waitpid) diff --git a/nptl/sysdeps/unix/sysv/linux/writev.c b/nptl/sysdeps/unix/sysv/linux/writev.c new file mode 100644 index 0000000000..d32a1749b1 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/writev.c @@ -0,0 +1,58 @@ +/* writev supports all Linux kernels >= 2.0. + Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stddef.h> +#include <sys/param.h> +#include <sys/uio.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <nptl/pthreadP.h> +#include <tls.h> + +extern ssize_t __syscall_writev (int, const struct iovec *__unbounded, int); + + +ssize_t +__libc_writev (fd, vector, count) + int fd; + const struct iovec *vector; + int count; +{ +#ifndef NOT_IN_libc + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, + header.data.multiple_threads) == 0, 1)) + return INLINE_SYSCALL (writev, 3, fd, CHECK_N (vector, count), count); + + int oldtype = LIBC_CANCEL_ASYNC (); +#endif + + ssize_t result = INLINE_SYSCALL (writev, 3, fd, CHECK_N (vector, count), + count); + +#ifndef NOT_IN_libc + LIBC_CANCEL_RESET (oldtype); +#endif + + return result; +} +strong_alias (__libc_writev, __writev) +weak_alias (__libc_writev, writev) |