From 291996a60567617f17aeb5e96159290b1ba22340 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 10 Oct 2002 23:05:06 +0000 Subject: Import libpthread. --- .cvsignore | 1 + lockfile.c | 65 +++++++ not-in-libc.h | 11 ++ pthread/Versions | 15 ++ pthread/cthreads-compat.c | 100 ++++++++++ pthread/pt-alloc.c | 215 +++++++++++++++++++++ pthread/pt-cancel.c | 40 ++++ pthread/pt-cleanup.c | 28 +++ pthread/pt-create.c | 194 +++++++++++++++++++ pthread/pt-dealloc.c | 63 +++++++ pthread/pt-detach.c | 84 +++++++++ pthread/pt-exit.c | 115 ++++++++++++ pthread/pt-initialize.c | 33 ++++ pthread/pt-internal.h | 260 ++++++++++++++++++++++++++ pthread/pt-join.c | 79 ++++++++ pthread/pt-self.c | 29 +++ pthread/pt-setcancelstate.c | 42 +++++ pthread/pt-setcanceltype.c | 42 +++++ pthread/pt-sigmask.c | 33 ++++ pthread/pt-spin-inlines.c | 34 ++++ pthread/pt-testcancel.c | 31 +++ sysdeps/generic/bits/barrier-attr.h | 30 +++ sysdeps/generic/bits/barrier.h | 39 ++++ sysdeps/generic/bits/cancelation.h | 54 ++++++ sysdeps/generic/bits/condition-attr.h | 32 ++++ sysdeps/generic/bits/condition.h | 40 ++++ sysdeps/generic/bits/mutex-attr.h | 33 ++++ sysdeps/generic/bits/mutex.h | 139 ++++++++++++++ sysdeps/generic/bits/once.h | 34 ++++ sysdeps/generic/bits/pthread.h | 33 ++++ sysdeps/generic/bits/rwlock-attr.h | 30 +++ sysdeps/generic/bits/rwlock.h | 73 ++++++++ sysdeps/generic/bits/thread-attr.h | 39 ++++ sysdeps/generic/bits/thread-barrier.h | 30 +++ sysdeps/generic/bits/thread-specific.h | 25 +++ sysdeps/generic/pt-atfork.c | 29 +++ sysdeps/generic/pt-attr-destroy.c | 27 +++ sysdeps/generic/pt-attr-getdetachstate.c | 29 +++ sysdeps/generic/pt-attr-getguardsize.c | 29 +++ sysdeps/generic/pt-attr-getinheritsched.c | 29 +++ sysdeps/generic/pt-attr-getschedparam.c | 31 +++ sysdeps/generic/pt-attr-getschedpolicy.c | 29 +++ sysdeps/generic/pt-attr-getscope.c | 29 +++ sysdeps/generic/pt-attr-getstack.c | 31 +++ sysdeps/generic/pt-attr-getstackaddr.c | 29 +++ sysdeps/generic/pt-attr-getstacksize.c | 29 +++ sysdeps/generic/pt-attr-init.c | 28 +++ sysdeps/generic/pt-attr-setdetachstate.c | 38 ++++ sysdeps/generic/pt-attr-setguardsize.c | 29 +++ sysdeps/generic/pt-attr-setinheritsched.c | 38 ++++ sysdeps/generic/pt-attr-setschedparam.c | 38 ++++ sysdeps/generic/pt-attr-setschedpolicy.c | 42 +++++ sysdeps/generic/pt-attr-setscope.c | 41 ++++ sysdeps/generic/pt-attr-setstack.c | 51 +++++ sysdeps/generic/pt-attr-setstackaddr.c | 29 +++ sysdeps/generic/pt-attr-setstacksize.c | 41 ++++ sysdeps/generic/pt-attr.c | 41 ++++ sysdeps/generic/pt-barrier-destroy.c | 27 +++ sysdeps/generic/pt-barrier-init.c | 43 +++++ sysdeps/generic/pt-barrier-wait.c | 61 ++++++ sysdeps/generic/pt-barrier.c | 26 +++ sysdeps/generic/pt-barrierattr-destroy.c | 27 +++ sysdeps/generic/pt-barrierattr-getpshared.c | 29 +++ sysdeps/generic/pt-barrierattr-init.c | 28 +++ sysdeps/generic/pt-barrierattr-setpshared.c | 39 ++++ sysdeps/generic/pt-cond-brdcast.c | 42 +++++ sysdeps/generic/pt-cond-destroy.c | 27 +++ sysdeps/generic/pt-cond-init.c | 34 ++++ sysdeps/generic/pt-cond-signal.c | 54 ++++++ sysdeps/generic/pt-cond-timedwait.c | 86 +++++++++ sysdeps/generic/pt-cond-wait.c | 37 ++++ sysdeps/generic/pt-cond.c | 29 +++ sysdeps/generic/pt-condattr-destroy.c | 27 +++ sysdeps/generic/pt-condattr-getclock.c | 31 +++ sysdeps/generic/pt-condattr-getpshared.c | 29 +++ sysdeps/generic/pt-condattr-init.c | 28 +++ sysdeps/generic/pt-condattr-setclock.c | 33 ++++ sysdeps/generic/pt-condattr-setpshared.c | 39 ++++ sysdeps/generic/pt-destroy-specific.c | 28 +++ sysdeps/generic/pt-equal.c | 29 +++ sysdeps/generic/pt-getconcurrency.c | 27 +++ sysdeps/generic/pt-getcpuclockid.c | 34 ++++ sysdeps/generic/pt-getschedparam.c | 28 +++ sysdeps/generic/pt-getspecific.c | 27 +++ sysdeps/generic/pt-init-specific.c | 27 +++ sysdeps/generic/pt-key-create.c | 27 +++ sysdeps/generic/pt-key-delete.c | 27 +++ sysdeps/generic/pt-key.h | 22 +++ sysdeps/generic/pt-mutex-destroy.c | 35 ++++ sysdeps/generic/pt-mutex-getprioceiling.c | 28 +++ sysdeps/generic/pt-mutex-init.c | 48 +++++ sysdeps/generic/pt-mutex-lock.c | 37 ++++ sysdeps/generic/pt-mutex-setprioceiling.c | 28 +++ sysdeps/generic/pt-mutex-timedlock.c | 148 +++++++++++++++ sysdeps/generic/pt-mutex-trylock.c | 89 +++++++++ sysdeps/generic/pt-mutex-unlock.c | 82 ++++++++ sysdeps/generic/pt-mutexattr-destroy.c | 27 +++ sysdeps/generic/pt-mutexattr-getprioceiling.c | 28 +++ sysdeps/generic/pt-mutexattr-getprotocol.c | 29 +++ sysdeps/generic/pt-mutexattr-getpshared.c | 29 +++ sysdeps/generic/pt-mutexattr-gettype.c | 28 +++ sysdeps/generic/pt-mutexattr-init.c | 28 +++ sysdeps/generic/pt-mutexattr-setprioceiling.c | 28 +++ sysdeps/generic/pt-mutexattr-setprotocol.c | 42 +++++ sysdeps/generic/pt-mutexattr-setpshared.c | 39 ++++ sysdeps/generic/pt-mutexattr-settype.c | 37 ++++ sysdeps/generic/pt-mutexattr.c | 29 +++ sysdeps/generic/pt-once.c | 43 +++++ sysdeps/generic/pt-rwlock-attr.c | 26 +++ sysdeps/generic/pt-rwlock-destroy.c | 29 +++ sysdeps/generic/pt-rwlock-init.c | 31 +++ sysdeps/generic/pt-rwlock-rdlock.c | 32 ++++ sysdeps/generic/pt-rwlock-timedrdlock.c | 110 +++++++++++ sysdeps/generic/pt-rwlock-timedwrlock.c | 92 +++++++++ sysdeps/generic/pt-rwlock-tryrdlock.c | 56 ++++++ sysdeps/generic/pt-rwlock-trywrlock.c | 46 +++++ sysdeps/generic/pt-rwlock-unlock.c | 90 +++++++++ sysdeps/generic/pt-rwlock-wrlock.c | 34 ++++ sysdeps/generic/pt-rwlockattr-destroy.c | 27 +++ sysdeps/generic/pt-rwlockattr-getpshared.c | 29 +++ sysdeps/generic/pt-rwlockattr-init.c | 28 +++ sysdeps/generic/pt-rwlockattr-setpshared.c | 39 ++++ sysdeps/generic/pt-setconcurrency.c | 34 ++++ sysdeps/generic/pt-setschedparam.c | 28 +++ sysdeps/generic/pt-setschedprio.c | 27 +++ sysdeps/generic/pt-setspecific.c | 27 +++ sysdeps/hurd/pt-destroy-specific.c | 77 ++++++++ sysdeps/hurd/pt-getspecific.c | 37 ++++ sysdeps/hurd/pt-init-specific.c | 30 +++ sysdeps/hurd/pt-key-create.c | 109 +++++++++++ sysdeps/hurd/pt-key-delete.c | 45 +++++ sysdeps/hurd/pt-key.h | 76 ++++++++ sysdeps/hurd/pt-kill.c | 49 +++++ sysdeps/hurd/pt-setspecific.c | 43 +++++ sysdeps/i386/bits/atomic.h | 66 +++++++ sysdeps/i386/bits/memory.h | 40 ++++ sysdeps/i386/bits/spin-lock.h | 103 ++++++++++ sysdeps/i386/machine-sp.h | 31 +++ sysdeps/i386/pt-machdep.h | 29 +++ sysdeps/l4/hurd/i386/pt-machdep.c | 20 ++ sysdeps/l4/hurd/i386/pt-setup.c | 72 +++++++ sysdeps/l4/hurd/pt-sysdep.c | 58 ++++++ sysdeps/l4/hurd/pt-sysdep.h | 50 +++++ sysdeps/l4/pt-block.c | 29 +++ sysdeps/l4/pt-docancel.c | 51 +++++ sysdeps/l4/pt-stack-alloc.c | 70 +++++++ sysdeps/l4/pt-start.c | 103 ++++++++++ sysdeps/l4/pt-thread-alloc.c | 52 ++++++ sysdeps/l4/pt-thread-halt.c | 38 ++++ sysdeps/l4/pt-thread-start.c | 92 +++++++++ sysdeps/l4/pt-wakeup.c | 29 +++ sysdeps/mach/bits/spin-lock.h | 97 ++++++++++ sysdeps/mach/hurd/i386/pt-machdep.c | 54 ++++++ sysdeps/mach/hurd/i386/pt-setup.c | 99 ++++++++++ sysdeps/mach/hurd/pt-attr-setstackaddr.c | 35 ++++ sysdeps/mach/hurd/pt-attr-setstacksize.c | 35 ++++ sysdeps/mach/hurd/pt-docancel.c | 57 ++++++ sysdeps/mach/hurd/pt-sigstate-destroy.c | 28 +++ sysdeps/mach/hurd/pt-sigstate-init.c | 37 ++++ sysdeps/mach/hurd/pt-sigstate.c | 69 +++++++ sysdeps/mach/hurd/pt-sysdep.c | 72 +++++++ sysdeps/mach/hurd/pt-sysdep.h | 65 +++++++ sysdeps/mach/pt-block.c | 39 ++++ sysdeps/mach/pt-spin.c | 35 ++++ sysdeps/mach/pt-stack-alloc.c | 74 ++++++++ sysdeps/mach/pt-start.c | 106 +++++++++++ sysdeps/mach/pt-thread-alloc.c | 98 ++++++++++ sysdeps/mach/pt-thread-halt.c | 39 ++++ sysdeps/mach/pt-thread-start.c | 45 +++++ sysdeps/mach/pt-timedblock.c | 60 ++++++ sysdeps/mach/pt-wakeup.c | 38 ++++ sysdeps/posix/pt-spin.c | 53 ++++++ tests/.cvsignore | 1 + tests/Makefile | 29 +++ tests/test-1.c | 49 +++++ tests/test-10.c | 46 +++++ tests/test-11.c | 143 ++++++++++++++ tests/test-12.c | 29 +++ tests/test-13.c | 66 +++++++ tests/test-14.c | 44 +++++ tests/test-15.c | 87 +++++++++ tests/test-16.c | 71 +++++++ tests/test-2.c | 39 ++++ tests/test-3.c | 55 ++++++ tests/test-4.c | 86 +++++++++ tests/test-5.c | 75 ++++++++ tests/test-6.c | 95 ++++++++++ tests/test-7.c | 66 +++++++ tests/test-8.c | 60 ++++++ tests/test-9.c | 88 +++++++++ 190 files changed, 9364 insertions(+) create mode 100644 .cvsignore create mode 100644 lockfile.c create mode 100644 not-in-libc.h create mode 100644 pthread/Versions create mode 100644 pthread/cthreads-compat.c create mode 100644 pthread/pt-alloc.c create mode 100644 pthread/pt-cancel.c create mode 100644 pthread/pt-cleanup.c create mode 100644 pthread/pt-create.c create mode 100644 pthread/pt-dealloc.c create mode 100644 pthread/pt-detach.c create mode 100644 pthread/pt-exit.c create mode 100644 pthread/pt-initialize.c create mode 100644 pthread/pt-internal.h create mode 100644 pthread/pt-join.c create mode 100644 pthread/pt-self.c create mode 100644 pthread/pt-setcancelstate.c create mode 100644 pthread/pt-setcanceltype.c create mode 100644 pthread/pt-sigmask.c create mode 100644 pthread/pt-spin-inlines.c create mode 100644 pthread/pt-testcancel.c create mode 100644 sysdeps/generic/bits/barrier-attr.h create mode 100644 sysdeps/generic/bits/barrier.h create mode 100644 sysdeps/generic/bits/cancelation.h create mode 100644 sysdeps/generic/bits/condition-attr.h create mode 100644 sysdeps/generic/bits/condition.h create mode 100644 sysdeps/generic/bits/mutex-attr.h create mode 100644 sysdeps/generic/bits/mutex.h create mode 100644 sysdeps/generic/bits/once.h create mode 100644 sysdeps/generic/bits/pthread.h create mode 100644 sysdeps/generic/bits/rwlock-attr.h create mode 100644 sysdeps/generic/bits/rwlock.h create mode 100644 sysdeps/generic/bits/thread-attr.h create mode 100644 sysdeps/generic/bits/thread-barrier.h create mode 100644 sysdeps/generic/bits/thread-specific.h create mode 100644 sysdeps/generic/pt-atfork.c create mode 100644 sysdeps/generic/pt-attr-destroy.c create mode 100644 sysdeps/generic/pt-attr-getdetachstate.c create mode 100644 sysdeps/generic/pt-attr-getguardsize.c create mode 100644 sysdeps/generic/pt-attr-getinheritsched.c create mode 100644 sysdeps/generic/pt-attr-getschedparam.c create mode 100644 sysdeps/generic/pt-attr-getschedpolicy.c create mode 100644 sysdeps/generic/pt-attr-getscope.c create mode 100644 sysdeps/generic/pt-attr-getstack.c create mode 100644 sysdeps/generic/pt-attr-getstackaddr.c create mode 100644 sysdeps/generic/pt-attr-getstacksize.c create mode 100644 sysdeps/generic/pt-attr-init.c create mode 100644 sysdeps/generic/pt-attr-setdetachstate.c create mode 100644 sysdeps/generic/pt-attr-setguardsize.c create mode 100644 sysdeps/generic/pt-attr-setinheritsched.c create mode 100644 sysdeps/generic/pt-attr-setschedparam.c create mode 100644 sysdeps/generic/pt-attr-setschedpolicy.c create mode 100644 sysdeps/generic/pt-attr-setscope.c create mode 100644 sysdeps/generic/pt-attr-setstack.c create mode 100644 sysdeps/generic/pt-attr-setstackaddr.c create mode 100644 sysdeps/generic/pt-attr-setstacksize.c create mode 100644 sysdeps/generic/pt-attr.c create mode 100644 sysdeps/generic/pt-barrier-destroy.c create mode 100644 sysdeps/generic/pt-barrier-init.c create mode 100644 sysdeps/generic/pt-barrier-wait.c create mode 100644 sysdeps/generic/pt-barrier.c create mode 100644 sysdeps/generic/pt-barrierattr-destroy.c create mode 100644 sysdeps/generic/pt-barrierattr-getpshared.c create mode 100644 sysdeps/generic/pt-barrierattr-init.c create mode 100644 sysdeps/generic/pt-barrierattr-setpshared.c create mode 100644 sysdeps/generic/pt-cond-brdcast.c create mode 100644 sysdeps/generic/pt-cond-destroy.c create mode 100644 sysdeps/generic/pt-cond-init.c create mode 100644 sysdeps/generic/pt-cond-signal.c create mode 100644 sysdeps/generic/pt-cond-timedwait.c create mode 100644 sysdeps/generic/pt-cond-wait.c create mode 100644 sysdeps/generic/pt-cond.c create mode 100644 sysdeps/generic/pt-condattr-destroy.c create mode 100644 sysdeps/generic/pt-condattr-getclock.c create mode 100644 sysdeps/generic/pt-condattr-getpshared.c create mode 100644 sysdeps/generic/pt-condattr-init.c create mode 100644 sysdeps/generic/pt-condattr-setclock.c create mode 100644 sysdeps/generic/pt-condattr-setpshared.c create mode 100644 sysdeps/generic/pt-destroy-specific.c create mode 100644 sysdeps/generic/pt-equal.c create mode 100644 sysdeps/generic/pt-getconcurrency.c create mode 100644 sysdeps/generic/pt-getcpuclockid.c create mode 100644 sysdeps/generic/pt-getschedparam.c create mode 100644 sysdeps/generic/pt-getspecific.c create mode 100644 sysdeps/generic/pt-init-specific.c create mode 100644 sysdeps/generic/pt-key-create.c create mode 100644 sysdeps/generic/pt-key-delete.c create mode 100644 sysdeps/generic/pt-key.h create mode 100644 sysdeps/generic/pt-mutex-destroy.c create mode 100644 sysdeps/generic/pt-mutex-getprioceiling.c create mode 100644 sysdeps/generic/pt-mutex-init.c create mode 100644 sysdeps/generic/pt-mutex-lock.c create mode 100644 sysdeps/generic/pt-mutex-setprioceiling.c create mode 100644 sysdeps/generic/pt-mutex-timedlock.c create mode 100644 sysdeps/generic/pt-mutex-trylock.c create mode 100644 sysdeps/generic/pt-mutex-unlock.c create mode 100644 sysdeps/generic/pt-mutexattr-destroy.c create mode 100644 sysdeps/generic/pt-mutexattr-getprioceiling.c create mode 100644 sysdeps/generic/pt-mutexattr-getprotocol.c create mode 100644 sysdeps/generic/pt-mutexattr-getpshared.c create mode 100644 sysdeps/generic/pt-mutexattr-gettype.c create mode 100644 sysdeps/generic/pt-mutexattr-init.c create mode 100644 sysdeps/generic/pt-mutexattr-setprioceiling.c create mode 100644 sysdeps/generic/pt-mutexattr-setprotocol.c create mode 100644 sysdeps/generic/pt-mutexattr-setpshared.c create mode 100644 sysdeps/generic/pt-mutexattr-settype.c create mode 100644 sysdeps/generic/pt-mutexattr.c create mode 100644 sysdeps/generic/pt-once.c create mode 100644 sysdeps/generic/pt-rwlock-attr.c create mode 100644 sysdeps/generic/pt-rwlock-destroy.c create mode 100644 sysdeps/generic/pt-rwlock-init.c create mode 100644 sysdeps/generic/pt-rwlock-rdlock.c create mode 100644 sysdeps/generic/pt-rwlock-timedrdlock.c create mode 100644 sysdeps/generic/pt-rwlock-timedwrlock.c create mode 100644 sysdeps/generic/pt-rwlock-tryrdlock.c create mode 100644 sysdeps/generic/pt-rwlock-trywrlock.c create mode 100644 sysdeps/generic/pt-rwlock-unlock.c create mode 100644 sysdeps/generic/pt-rwlock-wrlock.c create mode 100644 sysdeps/generic/pt-rwlockattr-destroy.c create mode 100644 sysdeps/generic/pt-rwlockattr-getpshared.c create mode 100644 sysdeps/generic/pt-rwlockattr-init.c create mode 100644 sysdeps/generic/pt-rwlockattr-setpshared.c create mode 100644 sysdeps/generic/pt-setconcurrency.c create mode 100644 sysdeps/generic/pt-setschedparam.c create mode 100644 sysdeps/generic/pt-setschedprio.c create mode 100644 sysdeps/generic/pt-setspecific.c create mode 100644 sysdeps/hurd/pt-destroy-specific.c create mode 100644 sysdeps/hurd/pt-getspecific.c create mode 100644 sysdeps/hurd/pt-init-specific.c create mode 100644 sysdeps/hurd/pt-key-create.c create mode 100644 sysdeps/hurd/pt-key-delete.c create mode 100644 sysdeps/hurd/pt-key.h create mode 100644 sysdeps/hurd/pt-kill.c create mode 100644 sysdeps/hurd/pt-setspecific.c create mode 100644 sysdeps/i386/bits/atomic.h create mode 100644 sysdeps/i386/bits/memory.h create mode 100644 sysdeps/i386/bits/spin-lock.h create mode 100644 sysdeps/i386/machine-sp.h create mode 100644 sysdeps/i386/pt-machdep.h create mode 100644 sysdeps/l4/hurd/i386/pt-machdep.c create mode 100644 sysdeps/l4/hurd/i386/pt-setup.c create mode 100644 sysdeps/l4/hurd/pt-sysdep.c create mode 100644 sysdeps/l4/hurd/pt-sysdep.h create mode 100644 sysdeps/l4/pt-block.c create mode 100644 sysdeps/l4/pt-docancel.c create mode 100644 sysdeps/l4/pt-stack-alloc.c create mode 100644 sysdeps/l4/pt-start.c create mode 100644 sysdeps/l4/pt-thread-alloc.c create mode 100644 sysdeps/l4/pt-thread-halt.c create mode 100644 sysdeps/l4/pt-thread-start.c create mode 100644 sysdeps/l4/pt-wakeup.c create mode 100644 sysdeps/mach/bits/spin-lock.h create mode 100644 sysdeps/mach/hurd/i386/pt-machdep.c create mode 100644 sysdeps/mach/hurd/i386/pt-setup.c create mode 100644 sysdeps/mach/hurd/pt-attr-setstackaddr.c create mode 100644 sysdeps/mach/hurd/pt-attr-setstacksize.c create mode 100644 sysdeps/mach/hurd/pt-docancel.c create mode 100644 sysdeps/mach/hurd/pt-sigstate-destroy.c create mode 100644 sysdeps/mach/hurd/pt-sigstate-init.c create mode 100644 sysdeps/mach/hurd/pt-sigstate.c create mode 100644 sysdeps/mach/hurd/pt-sysdep.c create mode 100644 sysdeps/mach/hurd/pt-sysdep.h create mode 100644 sysdeps/mach/pt-block.c create mode 100644 sysdeps/mach/pt-spin.c create mode 100644 sysdeps/mach/pt-stack-alloc.c create mode 100644 sysdeps/mach/pt-start.c create mode 100644 sysdeps/mach/pt-thread-alloc.c create mode 100644 sysdeps/mach/pt-thread-halt.c create mode 100644 sysdeps/mach/pt-thread-start.c create mode 100644 sysdeps/mach/pt-timedblock.c create mode 100644 sysdeps/mach/pt-wakeup.c create mode 100644 sysdeps/posix/pt-spin.c create mode 100644 tests/.cvsignore create mode 100644 tests/Makefile create mode 100644 tests/test-1.c create mode 100644 tests/test-10.c create mode 100644 tests/test-11.c create mode 100644 tests/test-12.c create mode 100644 tests/test-13.c create mode 100644 tests/test-14.c create mode 100644 tests/test-15.c create mode 100644 tests/test-16.c create mode 100644 tests/test-2.c create mode 100644 tests/test-3.c create mode 100644 tests/test-4.c create mode 100644 tests/test-5.c create mode 100644 tests/test-6.c create mode 100644 tests/test-7.c create mode 100644 tests/test-8.c create mode 100644 tests/test-9.c diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 00000000..70845e08 --- /dev/null +++ b/.cvsignore @@ -0,0 +1 @@ +Makefile.in diff --git a/lockfile.c b/lockfile.c new file mode 100644 index 00000000..040cbfb4 --- /dev/null +++ b/lockfile.c @@ -0,0 +1,65 @@ +/* lockfile - Handle locking and unlocking of streams. Hurd cthreads version. + Copyright (C) 2000,01,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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include /* Must come before ! */ +#include + +#ifdef _STDIO_USES_IOSTREAM + +void +_cthreads_flockfile (_IO_FILE *fp) +{ + _IO_lock_lock (*fp->_lock); +} + +void +_cthreads_funlockfile (_IO_FILE *fp) +{ + _IO_lock_unlock (*fp->_lock); +} + +int +_cthreads_ftrylockfile (_IO_FILE *fp) +{ + return __libc_lock_trylock_recursive (*fp->_lock); +} + +# undef _IO_flockfile +# undef _IO_funlockfile +# undef _IO_ftrylockfile +# undef flockfile +# undef funlockfile +# undef ftrylockfile + +void _IO_flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void _IO_funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int _IO_ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +void flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +#endif /* _STDIO_USES_IOSTREAM */ diff --git a/not-in-libc.h b/not-in-libc.h new file mode 100644 index 00000000..516d4d13 --- /dev/null +++ b/not-in-libc.h @@ -0,0 +1,11 @@ +#define __mach_port_insert_right mach_port_insert_right +#define __mach_port_allocate mach_port_allocate +#define __mig_init mig_init +#define __thread_create thread_create +#define __thread_get_state thread_get_state +#define __thread_resume thread_resume +#define __thread_set_state thread_set_state +#define __thread_terminate thread_terminate +#define __vm_allocate vm_allocate +#define __vm_deallocate vm_deallocate +#define __sched_yield sched_yield diff --git a/pthread/Versions b/pthread/Versions new file mode 100644 index 00000000..e4b4e8bf --- /dev/null +++ b/pthread/Versions @@ -0,0 +1,15 @@ +libc { + GLIBC_2.2 { + # XXX + __vm_deallocate; __mach_port_insert_right; __mach_reply_port; + __mig_init; __vm_allocate; + + # functions used in inline functions or macros + __pthread_spin_destroy; __pthread_spin_init; __pthread_spin_lock; + _pthread_spin_lock; __pthread_spin_trylock; __pthread_spin_unlock; + + # p* + pthread_spin_destroy; pthread_spin_init; pthread_spin_lock; + pthread_spin_trylock; pthread_spin_unlock; + } +} diff --git a/pthread/cthreads-compat.c b/pthread/cthreads-compat.c new file mode 100644 index 00000000..ccea03c9 --- /dev/null +++ b/pthread/cthreads-compat.c @@ -0,0 +1,100 @@ +/* Compatibility routines for cthreads. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +void +cthread_detach (cthread_t thread) +{ + int err; + + err = pthread_detach ((pthread_t) thread); + assert_perror (err); +} + +cthread_t +cthread_fork (cthread_fn_t func, void *arg) +{ + pthread_t thread; + int err; + + err = pthread_create (&thread, NULL, func, arg); + assert_perror (err); + + return (cthread_t) thread; +} + +int +cthread_keycreate (cthread_key_t *key) +{ + error_t err; + + err = pthread_key_create (key, 0); + if (err) + { + errno = err; + *key = CTHREAD_KEY_INVALID; + err = -1; + } + + return err; +} + +int +cthread_getspecific (cthread_key_t key, void **val) +{ + *val = pthread_getspecific (key); + return 0; +} + +void * +__libc_getspecific (cthread_key_t key) +{ + return pthread_getspecific (key); +} + +int +cthread_setspecific (cthread_key_t key, void *val) +{ + error_t err; + + err = pthread_setspecific (key, (const void *) val); + if (err) + { + errno = err; + err = -1; + } + + return err; +} + +void +__mutex_lock_solid (void *lock) +{ + __pthread_mutex_lock (lock); +} + +void +__mutex_unlock_solid (void *lock) +{ + __pthread_mutex_unlock (lock); +} diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c new file mode 100644 index 00000000..5cdc85df --- /dev/null +++ b/pthread/pt-alloc.c @@ -0,0 +1,215 @@ +/* Allocate a new thread structure. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#include + +#include + +/* This braindamage is necessary because the standard says that some + of the threads functions "shall fail" if "No thread could be found + corresponding to that specified by the given thread ID." */ + +/* Thread ID lookup table. */ +struct __pthread **__pthread_threads; + +/* The size of the thread ID lookup table. */ +int __pthread_max_threads; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +int __pthread_num_threads; + +/* A lock for the table, and the other variables above. */ +pthread_rwlock_t __pthread_threads_lock; + + +/* List of thread structures corresponding to free thread IDs. */ +__atomicptr_t __pthread_free_threads; + +static inline error_t +initialize_pthread (struct __pthread *new, int recycling) +{ + error_t err; + + err = __pthread_init_specific (new); + if (err) + return err; + + new->cancel_state = PTHREAD_CANCEL_ENABLE; + new->cancel_type = PTHREAD_CANCEL_DEFERRED; + new->cancel_pending = 0; + + if (recycling) + /* Since we are recycling PTHREAD, we can assume certains things + about PTHREAD's current state and save some cycles by not + rewriting the memory. */ + return 0; + + new->stack = 0; + + new->state_lock = PTHREAD_MUTEX_INITIALIZER; + new->state_cond = PTHREAD_COND_INITIALIZER; + + new->cancelation_handlers = 0; + + new->next = 0; + new->prevp = 0; + + return 0; +} + + +/* Allocate a new thread structure and its pthread thread ID (but not + a kernel thread). */ +int +__pthread_alloc (struct __pthread **pthread) +{ + error_t err; + + struct __pthread *new; + struct __pthread **threads; + struct __pthread **old_threads; + int max_threads; + int new_max_threads; + + /* Try to re-use a thread structure before creating a new one. */ + while ((new = (struct __pthread *)__pthread_free_threads)) + { + if (__atomicptr_compare_and_swap (&__pthread_free_threads, + new, new->next)) + { + /* Yes, we managed to get one. The thread number in the + thread structure still refers to the correct slot. */ + err = initialize_pthread (new, 1); + if (err) + /* An error occured, however, we cannot just free NEW as + there may be resources attached to it. We must return + it to the free list. */ + while (1) + { + new->next = (struct __pthread *)__pthread_free_threads; + if (__atomicptr_compare_and_swap (&__pthread_free_threads, + new->next, new)) + break; + } + + if (! err) + *pthread = new; + + return err; + } + } + + /* Allocate a new thread structure. */ + new = malloc (sizeof (struct __pthread)); + if (new == NULL) + return ENOMEM; + + err = initialize_pthread (new, 0); + if (err) + { + free (new); + return err; + } + + retry: + pthread_rwlock_wrlock (&__pthread_threads_lock); + + if (__pthread_num_threads < __pthread_max_threads) + { + /* We have a free slot. Use the slot number as + the thread ID for the new thread. */ + new->thread = __pthread_num_threads++; + __pthread_threads[new->thread] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + *pthread = new; + return 0; + } +#ifdef PTHREAD_THREADS_MAX + else if (__pthread_num_threads >= PTHREAD_THREADS_MAX) + { + /* We have reached the limit on the number of threads per process. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (new); + return EAGAIN; + } +#endif + + /* We are going to enlarge the threads table. Save its current + size. We're going to release the lock before doing the necessary + memory allocation, since that's a potentially blocking operation. */ + max_threads = __pthread_max_threads; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Allocate a new lookup table that's twice as large. */ + new_max_threads + = max_threads > 0 ? max_threads * 2 : _POSIX_THREAD_THREADS_MAX; + threads = malloc (new_max_threads * sizeof (struct __pthread *)); + if (threads == NULL) + { + free (new); + return ENOMEM; + } + + pthread_rwlock_wrlock (&__pthread_threads_lock); + + /* Check if nobody else has already enlarged the table. */ + if (max_threads != __pthread_max_threads) + { + /* Yep, they did. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Free the newly allocated table and try again to allocate a slot. */ + free (threads); + goto retry; + } + + /* Copy over the contents of the old table. */ + memcpy (threads, __pthread_threads, + __pthread_max_threads * sizeof (struct __pthread *)); + + /* Save the location of the old table. We want to deallocate its + storage after we released the lock. */ + old_threads = __pthread_threads; + + /* Replace the table with the new one. */ + __pthread_max_threads = new_max_threads; + __pthread_threads = threads; + + /* And allocate ourselves one of the newly created slots. */ + new->thread = __pthread_num_threads++; + __pthread_threads[new->thread] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (old_threads); + + *pthread = new; + return 0; +} diff --git a/pthread/pt-cancel.c b/pthread/pt-cancel.c new file mode 100644 index 00000000..d19c557d --- /dev/null +++ b/pthread/pt-cancel.c @@ -0,0 +1,40 @@ +/* Cancel a thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_cancel (pthread_t t) +{ + int err = 0; + struct __pthread *p; + + p = __pthread_getid (t); + if (! p) + return ESRCH; + + p->cancel_pending = 1; + if (p->cancel_state == PTHREAD_CANCEL_ENABLE + && p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS) + err = __pthread_do_cancel (p); + + return err; +} diff --git a/pthread/pt-cleanup.c b/pthread/pt-cleanup.c new file mode 100644 index 00000000..58865aa4 --- /dev/null +++ b/pthread/pt-cleanup.c @@ -0,0 +1,28 @@ +/* Add a cancelation handler to the stack. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +struct __pthread_cancelation_handler ** +__pthread_get_cleanup_stack (void) +{ + return &_pthread_self ()->cancelation_handlers; +} diff --git a/pthread/pt-create.c b/pthread/pt-create.c new file mode 100644 index 00000000..bbfc6606 --- /dev/null +++ b/pthread/pt-create.c @@ -0,0 +1,194 @@ +/* Thread creation. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +#include + +/* The total number of pthreads currently active. This is defined + here since it would be really stupid to have a threads-using + program that doesn't call `pthread_create'. */ +__atomic_t __pthread_total; + + +/* The entry-point for new threads. */ +static void +entry_point (void *(*start_routine)(void *), void *arg) +{ + pthread_exit (start_routine (arg)); +} + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. */ +int +pthread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + + err = __pthread_create_internal (&pthread, attr, start_routine, arg); + if (! err) + *thread = pthread->thread; + + return err; +} + +/* Internal version of pthread_create. See comment in + pt-internal.h. */ +int +__pthread_create_internal (struct __pthread **thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + const struct __pthread_attr *setup; + sigset_t sigset; + + /* Allocate a new thread structure. */ + err = __pthread_alloc (&pthread); + if (err) + goto failed; + + /* Use the default attributes if ATTR is NULL. */ + setup = attr ? attr : &__pthread_default_attr; + + /* Initialize the thread state. */ + pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED + ? PTHREAD_DETACHED : PTHREAD_JOINABLE); + + /* If the user supplied a stack, it is not our responsibility to + setup a stack guard. */ + if (setup->stackaddr) + pthread->guardsize = 0; + else + pthread->guardsize = (setup->guardsize <= setup->stacksize + ? setup->guardsize : setup->stacksize); + + /* Find a stack. There are several scenarios: if a detached thread + kills itself, it has no way to deallocate its stack, thus it + leaves PTHREAD->stack set to true. We try to reuse it here, + however, if the user supplied a stack, we cannot use the old one. + Right now, we simply deallocate it. */ + if (pthread->stack) + { + if (setup->stackaddr != __pthread_default_attr.stackaddr) + { + __pthread_stack_dealloc (pthread->stackaddr, + pthread->stacksize); + pthread->stackaddr = setup->stackaddr; + pthread->stacksize = setup->stacksize; + } + } + else + { + err = __pthread_stack_alloc (&pthread->stackaddr, + setup->stacksize); + if (err) + goto failed_stack_alloc; + + pthread->stacksize = setup->stacksize; + pthread->stack = 1; + } + + /* Allocate the kernel thread and other required resources. */ + err = __pthread_thread_alloc (pthread); + if (err) + goto failed_thread_alloc; + + /* And initialize the rest of the machine context. This may include + additional machine- and system-specific initializations that + prove convenient. */ + err = __pthread_setup (pthread, entry_point, start_routine, arg); + if (err) + goto failed_setup; + + /* Initialize the system-specific signal state for the new + thread. */ + err = __pthread_sigstate_init (pthread); + if (err) + goto failed_sigstate; + + /* Set the new thread's signal mask and set the pending signals to + empty. POSIX says: "The signal mask shall be inherited from the + creating thread. The set of signals pending for the new thread + shall be empty." If the currnet thread is not a pthread then we + just inherit the process' sigmask. */ + if (__pthread_num_threads == 1) + err = sigprocmask (0, 0, &sigset); + else + err = __pthread_sigstate (_pthread_self (), 0, 0, &sigset, 0); + assert_perror (err); + + err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 1); + assert_perror (err); + + /* Increase the total number of threads. We do this before actually + starting the new thread, since the new thread might immediately + call `pthread_exit' which decreases the number of threads and + calls `exit' if the number of threads reaches zero. Increasing + the number of threads from within the new thread isn't an option + since this thread might return and call `pthread_exit' before the + new thread runs. */ + __atomic_inc (&__pthread_total); + + /* Store a pointer to this thread in the thread ID lookup table. We + could use __thread_setid, however, we only lock for reading as no + other thread should be using this entry (we also assume that the + store is atomic). */ + pthread_rwlock_rdlock (&__pthread_threads_lock); + __pthread_threads[pthread->thread] = pthread; + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* At this point it is possible to guess our pthread ID. We have to + make sure that all functions taking a pthread_t argument can + handle the fact that this thread isn't really running yet. */ + + /* Schedule the new thread. */ + err = __pthread_thread_start (pthread); + if (err) + goto failed_starting; + + /* At this point the new thread is up and running. */ + + *thread = pthread; + + return 0; + + failed_starting: + __pthread_setid (pthread->thread, NULL); + __atomic_dec (&__pthread_total); + failed_sigstate: + __pthread_sigstate_destroy (pthread); + failed_setup: + __pthread_thread_halt (pthread); + failed_thread_alloc: + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + failed_stack_alloc: + __pthread_dealloc (pthread); + failed: + return err; +} diff --git a/pthread/pt-dealloc.c b/pthread/pt-dealloc.c new file mode 100644 index 00000000..1fc7a7b3 --- /dev/null +++ b/pthread/pt-dealloc.c @@ -0,0 +1,63 @@ +/* Deallocate a thread structure. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +#include + +/* List of thread structures corresponding to free thread IDs. */ +extern __atomicptr_t __pthread_free_threads; + +/* Deallocate the thread structure for PTHREAD and the resources + associated with it. */ +void +__pthread_dealloc (struct __pthread *pthread) +{ + assert (pthread->state != PTHREAD_TERMINATED); + + /* Withdraw this thread from the thread ID lookup table. */ + __pthread_setid (pthread->thread, NULL); + + /* Mark the thread as terminated. We broadcast the condition + here to prevent pthread_join from waiting for this thread to + exit where it was never really started. Such a call to + pthread_join is completely bogus, but unfortunately allowed + by the standards. */ + __pthread_mutex_lock (&pthread->state_lock); + pthread->state = PTHREAD_TERMINATED; + if (pthread->state != PTHREAD_EXITED) + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + + /* We do not actually deallocate the thread structure, but add it to + a list of re-usable thread structures. */ + while (1) + { + pthread->next = (struct __pthread *)__pthread_free_threads; + if (__atomicptr_compare_and_swap (&__pthread_free_threads, + pthread->next, pthread)) + return; + } + + /* NOTREACHED */ +} diff --git a/pthread/pt-detach.c b/pthread/pt-detach.c new file mode 100644 index 00000000..c22f6a03 --- /dev/null +++ b/pthread/pt-detach.c @@ -0,0 +1,84 @@ +/* Detach a thread. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Indicate that the storage for THREAD can be reclaimed when it + terminates. */ +int +pthread_detach (pthread_t thread) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + + switch (pthread->state) + { + case PTHREAD_JOINABLE: + /* THREAD still running. Mark it as detached such that its + resources can be reclaimed as soon as the thread exits. */ + pthread->state = PTHREAD_DETACHED; + + /* Broadcast the condition. This will make threads that are + waiting to join THREAD continue with hopefully disastrous + consequences instead of blocking indefinitely. */ + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + break; + + case PTHREAD_EXITED: + /* THREAD has already exited. Make sure that nobody can + reference it anymore, and mark it as terminated. */ + + __pthread_mutex_unlock (&pthread->state_lock); + + __pthread_thread_halt (pthread); + + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not detach non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c new file mode 100644 index 00000000..fb9e97c0 --- /dev/null +++ b/pthread/pt-exit.c @@ -0,0 +1,115 @@ +/* Thread termination. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +#include + + +/* Terminate the current thread and make STATUS available to any + thread that might join us. */ +void +pthread_exit (void *status) +{ + struct __pthread *self = _pthread_self (); + struct __pthread_cancelation_handler **handlers; + int oldstate; + + /* Run any cancelation handlers. According to POSIX, the + cancellation cleanup handlers should be called with cancellation + disabled. */ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); + + for (handlers = __pthread_get_cleanup_stack (); + *handlers; + *handlers = (*handlers)->next) + (*handlers)->handler ((*handlers)->arg); + + pthread_setcancelstate (oldstate, &oldstate); + + /* Destory any thread specific data. */ + __pthread_destroy_specific (self); + + /* Destroy any signal state. */ + __pthread_sigstate_destroy (self); + + /* Decrease the number of threads. We use an atomic operation to + make sure that only the last thread calls `exit'. */ + if (__atomic_dec_and_test (&__pthread_total)) + /* We are the last thread. */ + exit (0); + + /* Note that after this point the process can be terminated at any + point if another thread calls `pthread_exit' and happens to be + the last thread. */ + + __pthread_mutex_lock (&self->state_lock); + + if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) + status = PTHREAD_CANCELED; + + switch (self->state) + { + default: + assert (! "This cannot happen!"); + break; + + case PTHREAD_DETACHED: + /* Make sure that nobody can reference this thread anymore, and + mark it as terminated. Our thread ID will immediately become + available for re-use. For obvious reasons, we cannot + deallocate our own stack. However, it will eventually be + reused when this thread structure is recycled. */ + __pthread_mutex_unlock (&self->state_lock); + __pthread_dealloc (self); + + break; + + case PTHREAD_JOINABLE: + /* We need to stay around for a while since another thread + might want to join us. */ + self->state = PTHREAD_EXITED; + + /* We need to remember the exit status. A thread joining us + might ask for it. */ + self->status = status; + + /* Broadcast the condition. This will wake up threads that are + waiting to join us. */ + pthread_cond_broadcast (&self->state_cond); + __pthread_mutex_unlock (&self->state_lock); + + break; + } + + /* Note that after this point the resources used by this thread can + be freed at any moment if another thread joins or detaches us. + This means that before freeing any resources, such a thread + should make sure that this thread is really halted. */ + + __pthread_thread_halt (self); + + /* NOTREACHED */ + abort (); +} diff --git a/pthread/pt-initialize.c b/pthread/pt-initialize.c new file mode 100644 index 00000000..cf32b8b5 --- /dev/null +++ b/pthread/pt-initialize.c @@ -0,0 +1,33 @@ +/* Initialize pthreads library. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +DEFINE_HOOK (__pthread_init, (void)); + +/* Initialize the pthreads library. */ +void +__pthread_initialize (void) +{ + RUN_HOOK (__pthread_init, ()); +} diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h new file mode 100644 index 00000000..a32345c4 --- /dev/null +++ b/pthread/pt-internal.h @@ -0,0 +1,260 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_INTERNAL_H +#define _PT_INTERNAL_H 1 + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +/* Thread state. */ +enum pthread_state +{ + PTHREAD_JOINABLE = 0, + PTHREAD_DETACHED, + PTHREAD_EXITED, + PTHREAD_TERMINATED +}; + +#ifndef PTHREAD_KEY_MEMBERS +# define PTHREAD_KEY_MEMBERS +#endif + +#ifndef PTHREAD_SYSDEP_MEMBERS +# define PTHREAD_SYSDEP_MEMBERS +#endif + +/* This structure describes a POSIX thread. */ +struct __pthread +{ + /* Thread ID. */ + pthread_t thread; + + /* Cancellation. */ + int cancel_state; + int cancel_type; + int cancel_pending; + struct __pthread_cancelation_handler *cancelation_handlers; + + /* Thread stack. */ + void *stackaddr; + size_t stacksize; + size_t guardsize; /* Included in STACKSIZE (i.e. total + stack memory is STACKSIZE, not + STACKSIZE + GUARDSIZE). */ + int stack; /* Nonzero if the stack was allocated. */ + + /* Exit status. */ + void *status; + + /* Thread state. */ + enum pthread_state state; + pthread_mutex_t state_lock; /* Locks the state. */ + pthread_cond_t state_cond; /* Signalled when the state changes. */ + + /* Thread context. */ + struct pthread_mcontext mcontext; + + PTHREAD_KEY_MEMBERS + + PTHREAD_SYSDEP_MEMBERS + + struct __pthread *next, **prevp; +}; + +/* Enqueue an element THREAD on the queue *HEAD. */ +static inline void +__pthread_enqueue (struct __pthread **head, struct __pthread *thread) +{ + assert (thread->prevp == 0); + + thread->next = *head; + thread->prevp = head; + if (*head) + (*head)->prevp = &thread->next; + *head = thread; +} + +/* Dequeue the element THREAD from the queue it is connected to. */ +static inline void +__pthread_dequeue (struct __pthread *thread) +{ + assert (thread); + + if (thread->next) + thread->next->prevp = thread->prevp; + *thread->prevp = thread->next; + thread->prevp = 0; +} + +/* Iterate over QUEUE storing each element in ELEMENT. */ +#define __pthread_queue_iterate(queue, element) \ + for (element = queue; element; element = element->next) + +/* Iterate over QUEUE dequeuing each element, storing it in + ELEMENT. */ +#define __pthread_dequeuing_iterate(queue, element) \ + for (element = queue; \ + element && ((element->prevp = 0), 1); \ + element = element->next) + +/* The total number of threads currently active. */ +extern __atomic_t __pthread_total; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +extern int __pthread_num_threads; + +/* Concurrency hint. */ +extern int __pthread_concurrency; + +/* Array of __pthread structures and its lock. */ +extern struct __pthread **__pthread_threads; +extern pthread_rwlock_t __pthread_threads_lock; + +#define __pthread_getid(thread) \ + ({ struct __pthread *__t; \ + pthread_rwlock_rdlock (&__pthread_threads_lock); \ + __t = __pthread_threads[thread]; \ + pthread_rwlock_unlock (&__pthread_threads_lock); \ + __t; }) + +#define __pthread_setid(thread, pthread) \ + pthread_rwlock_wrlock (&__pthread_threads_lock); \ + __pthread_threads[thread] = pthread; \ + pthread_rwlock_unlock (&__pthread_threads_lock); + +/* Similar to pthread_self, but returns the thread descriptor instead + of the thread ID. */ +#ifndef _pthread_self +extern struct __pthread *_pthread_self (void); +#endif + + +/* Initialize the pthreads library. */ +extern void __pthread_initialize (void); + +/* Internal version of pthread_create. Rather than return the new + tid, we return the whole __pthread structure in *PTHREAD. */ +extern int __pthread_create_internal (struct __pthread **pthread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg); + +/* Allocate a new thread structure and a pthread thread ID (but not a + kernel thread or a stack). */ +extern int __pthread_alloc (struct __pthread **thread); + +/* Deallocate the thread structure. This is the dual of + __pthread_alloc (N.B. it does not call __pthread_stack_alloc nor + __pthread_thread_halt). */ +extern void __pthread_dealloc (struct __pthread *thread); + + +/* Allocate a stack of size STACKSIZE. The stack base shall be + returned in *STACKADDR. */ +extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize); + +/* Deallocate the stack STACKADDR of size STACKSIZE. */ +extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize); + + +/* Setup thread THREAD's context. */ +extern int __pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), + void *), + void *(*start_routine)(void *), void *arg); + + +/* Allocate a kernel thread for THREAD; it must not be placed on the + run queue. */ +extern int __pthread_thread_alloc (struct __pthread *thread); + +/* Start THREAD making it eligible to run. */ +extern int __pthread_thread_start (struct __pthread *thread); + +/* Stop thread thread and deallocate any kernel resources associated + with THREAD. */ +extern void __pthread_thread_halt (struct __pthread *thread); + + +/* Block THREAD. */ +extern void __pthread_block (struct __pthread *thread); + +/* Block THREAD until *ABSTIME is reached. */ +extern error_t __pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime); + +/* Wakeup THREAD. */ +extern void __pthread_wakeup (struct __pthread *thread); + + +/* Perform a cancelation. */ +extern int __pthread_do_cancel (struct __pthread *thread); + + +/* Initialize the thread specific data structures. THREAD must be the + calling thread. */ +extern error_t __pthread_init_specific (struct __pthread *thread); + +/* Call the destructors on all of the thread specific data in THREAD. + THREAD must be the calling thread. */ +extern void __pthread_destroy_specific (struct __pthread *thread); + + +/* Initialize newly create thread *THREAD's signal state data + structures. */ +extern error_t __pthread_sigstate_init (struct __pthread *thread); + +/* Destroy the signal state data structures associcated with thread + *THREAD. */ +extern void __pthread_sigstate_destroy (struct __pthread *thread); + +/* Modify thread *THREAD's signal state. */ +extern error_t __pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending); + + +/* Default thread attributes. */ +extern const struct __pthread_attr __pthread_default_attr; + +/* Default barrier attributes. */ +extern const struct __pthread_barrierattr __pthread_default_barrierattr; + +/* Default mutex attributes. */ +extern const struct __pthread_mutexattr __pthread_default_mutexattr; + +/* Default rdlock attributes. */ +const struct __pthread_rwlockattr __pthread_default_rwlockattr; + +/* Default condition attributes. */ +const struct __pthread_condattr __pthread_default_condattr; + +#endif /* pt-internal.h */ diff --git a/pthread/pt-join.c b/pthread/pt-join.c new file mode 100644 index 00000000..698b6c9f --- /dev/null +++ b/pthread/pt-join.c @@ -0,0 +1,79 @@ +/* Wait for thread termination. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Make calling thread wait for termination of thread THREAD. Return + the exit status of the thread in *STATUS. */ +int +pthread_join (pthread_t thread, void **status) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + pthread_cleanup_push (__pthread_mutex_unlock, &pthread->state_lock); + + while (pthread->state == PTHREAD_JOINABLE) + pthread_cond_wait (&pthread->state_cond, &pthread->state_lock); + + pthread_cleanup_pop (0); + + switch (pthread->state) + { + case PTHREAD_EXITED: + __pthread_mutex_unlock (&pthread->state_lock); + + /* THREAD has already exited. Salvage its exit status. */ + if (status) + *status = pthread->status; + + /* Make sure nobody can reference it anymore, and mark it as + terminated. */ + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not join non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/pthread/pt-self.c b/pthread/pt-self.c new file mode 100644 index 00000000..e14fe1eb --- /dev/null +++ b/pthread/pt-self.c @@ -0,0 +1,29 @@ +/* Get calling thread's ID. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Return the thread ID of the calling thread. */ +pthread_t +pthread_self (void) +{ + return _pthread_self()->thread; +} diff --git a/pthread/pt-setcancelstate.c b/pthread/pt-setcancelstate.c new file mode 100644 index 00000000..ded58922 --- /dev/null +++ b/pthread/pt-setcancelstate.c @@ -0,0 +1,42 @@ +/* Set the cancel state for the calling thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_setcancelstate (int state, int *oldstate) +{ + struct __pthread *p = _pthread_self (); + + switch (state) + { + default: + return EINVAL; + case PTHREAD_CANCEL_ENABLE: + case PTHREAD_CANCEL_DISABLE: + break; + } + + *oldstate = p->cancel_state; + p->cancel_state = state; + + return 0; +} diff --git a/pthread/pt-setcanceltype.c b/pthread/pt-setcanceltype.c new file mode 100644 index 00000000..9511c991 --- /dev/null +++ b/pthread/pt-setcanceltype.c @@ -0,0 +1,42 @@ +/* Set the cancel type for the calling thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_setcanceltype (int type, int *oldtype) +{ + struct __pthread *p = _pthread_self (); + + switch (type) + { + default: + return EINVAL; + case PTHREAD_CANCEL_DEFERRED: + case PTHREAD_CANCEL_ASYNCHRONOUS: + break; + } + + *oldtype = p->cancel_type; + p->cancel_type = type; + + return 0; +} diff --git a/pthread/pt-sigmask.c b/pthread/pt-sigmask.c new file mode 100644 index 00000000..1b53873e --- /dev/null +++ b/pthread/pt-sigmask.c @@ -0,0 +1,33 @@ +/* Get or set a thread's signal mask. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_sigmask (int how, const sigset_t *set, + sigset_t *oset) +{ + struct __pthread *self = _pthread_self (); + + /* Do not clear SELF's pending signals. */ + return __pthread_sigstate (self, how, set, oset, 0); +} diff --git a/pthread/pt-spin-inlines.c b/pthread/pt-spin-inlines.c new file mode 100644 index 00000000..cfb21dd3 --- /dev/null +++ b/pthread/pt-spin-inlines.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* declares some extern inline functions. These + functions are declared additionally here for use when inlining is + not possible. */ + +#define _FORCE_INLINES +#define __PT_SPIN_INLINE /* empty */ + +#include + +/* Weak aliases for the spin lock functions. Note that + pthread_spin_lock is left out deliberately. We already provide an + implementation for it in pt-spin.c. */ +weak_alias (__pthread_spin_destroy, pthread_spin_destroy); +weak_alias (__pthread_spin_init, pthread_spin_init); +weak_alias (__pthread_spin_trylock, pthread_spin_trylock); +weak_alias (__pthread_spin_unlock, pthread_spin_unlock); diff --git a/pthread/pt-testcancel.c b/pthread/pt-testcancel.c new file mode 100644 index 00000000..01f1ac9c --- /dev/null +++ b/pthread/pt-testcancel.c @@ -0,0 +1,31 @@ +/* Add an explicit cancelation point. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +void +pthread_testcancel (void) +{ + struct __pthread *p = _pthread_self (); + + if (p->cancel_state == PTHREAD_CANCEL_ENABLE && p->cancel_pending) + pthread_exit (PTHREAD_CANCELED); +} diff --git a/sysdeps/generic/bits/barrier-attr.h b/sysdeps/generic/bits/barrier-attr.h new file mode 100644 index 00000000..86f3cb02 --- /dev/null +++ b/sysdeps/generic/bits/barrier-attr.h @@ -0,0 +1,30 @@ +/* Thread barrier attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_BARRIER_ATTR_H +#define _BITS_BARRIER_ATTR_H 1 + +/* This structure describes the attributes of a POSIX thread barrier. + Note that not all of them are supported on all systems. */ +struct __pthread_barrierattr +{ + enum __pthread_process_shared pshared; +}; + +#endif /* bits/barrier-attr.h */ diff --git a/sysdeps/generic/bits/barrier.h b/sysdeps/generic/bits/barrier.h new file mode 100644 index 00000000..5e559312 --- /dev/null +++ b/sysdeps/generic/bits/barrier.h @@ -0,0 +1,39 @@ +/* Thread barrier attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_BARRIER_H +#define _BITS_BARRIER_H 1 + +#include + +/* This structure describes the attributes of a POSIX barrier. */ +struct __pthread_barrier +{ + __pthread_spinlock_t lock; + struct __pthread *queue; /* List of waiters. */ + unsigned pending; /* Number of that still need to wait on + barrier. */ + unsigned count; /* Number of threads that must wait before + barrier is passed. */ + struct __pthread_barrierattr *attr; + void *data; +}; + + +#endif /* bits/barrier.h */ diff --git a/sysdeps/generic/bits/cancelation.h b/sysdeps/generic/bits/cancelation.h new file mode 100644 index 00000000..bb6b58a1 --- /dev/null +++ b/sysdeps/generic/bits/cancelation.h @@ -0,0 +1,54 @@ +/* Cancelation. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_CANCELATION_H +#define _BITS_CANCELATION_H 1 + +#include + +struct __pthread_cancelation_handler +{ + void (*handler)(void *); + void *arg; + struct __pthread_cancelation_handler *next; +}; + +/* Returns the thread local location of the cleanup handler stack. */ +struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); + +#define pthread_cleanup_push(rt, rtarg) \ + { \ + struct __pthread_cancelation_handler **__handlers \ + = __pthread_get_cleanup_stack (); \ + struct __pthread_cancelation_handler __handler = \ + { \ + handler: (rt), \ + arg: (rtarg), \ + next: *__handlers \ + }; \ + *__handlers = &__handler; + +#define pthread_cleanup_pop(execute) \ + if (execute) \ + __handler.handler (__handler.arg); \ + assert (*__handlers == &__handler); \ + *__handlers = __handler.next; \ + } + +#endif /* _BITS_CANCELATION_H */ diff --git a/sysdeps/generic/bits/condition-attr.h b/sysdeps/generic/bits/condition-attr.h new file mode 100644 index 00000000..2d48dfb6 --- /dev/null +++ b/sysdeps/generic/bits/condition-attr.h @@ -0,0 +1,32 @@ +/* Condition attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_CONDITION_ATTR_H +#define _BITS_CONDITION_ATTR_H 1 + +#include + +/* User visible part of a condition attribute variable. */ +struct __pthread_condattr + { + enum __pthread_process_shared pshared; + clockid_t clock; + }; + +#endif /* bits/condition.h */ diff --git a/sysdeps/generic/bits/condition.h b/sysdeps/generic/bits/condition.h new file mode 100644 index 00000000..cb7e935c --- /dev/null +++ b/sysdeps/generic/bits/condition.h @@ -0,0 +1,40 @@ +/* Condition type. Generic version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_CONDITION_H +#define _BITS_CONDITION_H 1 + +#include + +/* User visible part of a condition variable. */ +struct __pthread_cond + { + __pthread_spinlock_t __lock; + struct __pthread *__queue; + struct __pthread_condattr *__attr; + struct __pthread_condimpl *__impl; + void *__data; + }; + +/* Initializer for a condition variable. */ +#define __PTHREAD_COND_INITIALIZER \ + ((struct __pthread_cond) \ + { __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL }) + +#endif /* bits/condition.h */ diff --git a/sysdeps/generic/bits/mutex-attr.h b/sysdeps/generic/bits/mutex-attr.h new file mode 100644 index 00000000..883b0746 --- /dev/null +++ b/sysdeps/generic/bits/mutex-attr.h @@ -0,0 +1,33 @@ +/* Mutex attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MUTEX_ATTR_H +#define _BITS_MUTEX_ATTR_H 1 + +/* This structure describes the attributes of a POSIX mutex + attribute. */ +struct __pthread_mutexattr +{ + int prioceiling; + enum __pthread_mutex_protocol protocol; + enum __pthread_process_shared pshared; + enum __pthread_mutex_type mutex_type; +}; + +#endif /* bits/mutex-attr.h */ diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h new file mode 100644 index 00000000..2baf0408 --- /dev/null +++ b/sysdeps/generic/bits/mutex.h @@ -0,0 +1,139 @@ +/* Mutex type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MUTEX_H + +#ifndef __need_pthread_mutex +# define _BITS_MUTEX_H 1 +#endif + +#ifndef __pthread_mutex_defined +# if defined __need_pthread_mutex || defined _BITS_MUTEX_H +# undef __need_pthread_mutex +# define __pthread_mutex_defined + +# include +# include + +/* User visible part of a mutex. */ +struct __pthread_mutex + { + __pthread_spinlock_t __held; + __pthread_spinlock_t __lock; + /* In cthreads, mutex_init does not initialized thre third + pointer, as such, we cannot rely on its value for anything. */ + char *cthreadscompat1; + struct __pthread *__queue; + struct __pthread_mutexattr *attr; + void *data; + /* Up to this point, we are completely compatible with cthreads + and what libc expects. */ + void *owner; + unsigned locks; + /* If NULL then the default attributes apply. */ + }; + +/* Initializer for a mutex. N.B. this also happens to be compatible + with the cthread mutex initializer. */ +# define __PTHREAD_MUTEX_INITIALIZER \ + ((struct __pthread_mutex) \ + { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, \ + NULL, 0, 0 }) + +# endif +#endif /* Not __pthread_mutex_defined. */ + +#ifdef _BITS_MUTEX_H + +#include +#include + +#ifdef __USE_EXTERN_INLINES + +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif + +_EXTERN_INLINE int +pthread_mutex_init (struct __pthread_mutex *__mutex, + const pthread_mutexattr_t *attr) +{ + extern int _pthread_mutex_init (struct __pthread_mutex *, + const pthread_mutexattr_t *); + + if (attr) + return _pthread_mutex_init (__mutex, attr); + + *__mutex = __PTHREAD_MUTEX_INITIALIZER; + return 0; +} + +_EXTERN_INLINE int +pthread_mutex_destroy (struct __pthread_mutex *__mutex) +{ + extern int _pthread_mutex_destroy (struct __pthread_mutex *); + + if (__mutex->attr || __mutex->data) + return _pthread_mutex_destroy (__mutex); + + return 0; +} + +_EXTERN_INLINE int +__pthread_mutex_lock (struct __pthread_mutex *__mutex) +{ + extern int _pthread_mutex_lock (struct __pthread_mutex *); + + if (__mutex->attr == NULL + && __mutex->data == NULL + && __pthread_spin_trylock (&__mutex->__held) == 0) + return 0; + + return _pthread_mutex_lock (__mutex); +} + +extern inline int +__pthread_mutex_trylock (struct __pthread_mutex *__mutex) +{ + extern int _pthread_mutex_trylock (struct __pthread_mutex *); + + if (__mutex->attr == NULL + && __mutex->data == NULL) + return __pthread_spin_trylock (&__mutex->__held); + + return _pthread_mutex_trylock (__mutex); +} + +extern inline int +pthread_mutex_lock (struct __pthread_mutex *__mutex) +{ + return __pthread_mutex_lock (__mutex); +} + +extern inline int +pthread_mutex_trylock (struct __pthread_mutex *__mutex) +{ + return __pthread_mutex_trylock (__mutex); +} + +#endif /* Use extern inlines. */ + +#endif + +#endif /* bits/mutex.h */ diff --git a/sysdeps/generic/bits/once.h b/sysdeps/generic/bits/once.h new file mode 100644 index 00000000..7f572faf --- /dev/null +++ b/sysdeps/generic/bits/once.h @@ -0,0 +1,34 @@ +/* Dynamic package initialization data structures. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_ONCE_H +#define _BITS_ONCE_H 1 + +#include + +struct __pthread_once +{ + int run; + __pthread_spinlock_t lock; +}; + +#define __PTHREAD_ONCE_INIT \ + { 0, __SPIN_LOCK_INITIALIZER } + +#endif /* bits/once.h */ diff --git a/sysdeps/generic/bits/pthread.h b/sysdeps/generic/bits/pthread.h new file mode 100644 index 00000000..740325d0 --- /dev/null +++ b/sysdeps/generic/bits/pthread.h @@ -0,0 +1,33 @@ +/* Pthread data structures. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_PTHREAD_H +#define _BITS_PTHREAD_H 1 + +typedef int pthread_t; + +/* Return true if __T1 and __T2 both name the same thread. Otherwise, + false. */ +extern inline int +pthread_equal (pthread_t __t1, pthread_t __t2) +{ + return __t1 == __t2; +} + +#endif /* bits/pthread.h */ diff --git a/sysdeps/generic/bits/rwlock-attr.h b/sysdeps/generic/bits/rwlock-attr.h new file mode 100644 index 00000000..44765bd6 --- /dev/null +++ b/sysdeps/generic/bits/rwlock-attr.h @@ -0,0 +1,30 @@ +/* Thread rwlock attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_RWLOCK_ATTR_H +#define _BITS_RWLOCK_ATTR_H 1 + +/* This structure describes the attributes of a POSIX thread rwlock. + Note that not all of them are supported on all systems. */ +struct __pthread_rwlockattr +{ + enum __pthread_process_shared pshared; +}; + +#endif /* bits/rwlock-attr.h */ diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h new file mode 100644 index 00000000..d089b0c6 --- /dev/null +++ b/sysdeps/generic/bits/rwlock.h @@ -0,0 +1,73 @@ +/* rwlock type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_RWLOCK_H +#define _BITS_RWLOCK_H + +#include + +/* User visible part of a rwlock. If __held is not held and readers + is 0, then the lock is unlocked. If __held is held and readers is + 0, then the lock is held by a writer. If __held is held and + readers is greater than 0, then the lock is held by READERS + readers. */ +struct __pthread_rwlock + { + __pthread_spinlock_t __held; + __pthread_spinlock_t __lock; + int readers; + struct __pthread *readerqueue; + struct __pthread *writerqueue; + struct __pthread_rwlockattr *__attr; + void *__data; + }; + +/* Initializer for a rwlock. */ +#define __PTHREAD_RWLOCK_INITIALIZER \ + ((struct __pthread_rwlock) \ + { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 }) + + +_EXTERN_INLINE int +pthread_rwlock_init (struct __pthread_rwlock *__rwlock, + const struct __pthread_rwlockattr *__attr) +{ + extern int _pthread_rwlock_init (struct __pthread_rwlock *, + const struct __pthread_rwlockattr *); + + if (__attr) + return _pthread_rwlock_init (__rwlock, __attr); + + *__rwlock = __PTHREAD_RWLOCK_INITIALIZER; + return 0; +} + +_EXTERN_INLINE int +pthread_rwlock_destroy (struct __pthread_rwlock *__rwlock) +{ + extern int _pthread_rwlock_destroy (struct __pthread_rwlock *); + + if (__rwlock->__attr + || __rwlock->__data) + return _pthread_rwlock_destroy (__rwlock); + + return 0; +} + +#endif /* bits/rwlock.h */ diff --git a/sysdeps/generic/bits/thread-attr.h b/sysdeps/generic/bits/thread-attr.h new file mode 100644 index 00000000..31630221 --- /dev/null +++ b/sysdeps/generic/bits/thread-attr.h @@ -0,0 +1,39 @@ +/* Thread attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_THREAD_ATTR_H +#define _BITS_THREAD_ATTR_H 1 + +#include + +/* This structure describes the attributes of a POSIX thread. Note + that not all of them are supported on all systems. */ +struct __pthread_attr +{ + struct sched_param schedparam; + void *stackaddr; + size_t stacksize; + size_t guardsize; + enum __pthread_detachstate detachstate; + enum __pthread_inheritsched inheritsched; + enum __pthread_contentionscope contentionscope; + int schedpolicy; +}; + +#endif /* bits/thread-attr.h */ diff --git a/sysdeps/generic/bits/thread-barrier.h b/sysdeps/generic/bits/thread-barrier.h new file mode 100644 index 00000000..23d51ae5 --- /dev/null +++ b/sysdeps/generic/bits/thread-barrier.h @@ -0,0 +1,30 @@ +/* Thread barrier attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_THREAD_BARRIER_H +#define _BITS_THREAD_BARRIER_H 1 + +/* This structure describes the attributes of a POSIX thread barrier. + Note that not all of them are supported on all systems. */ +struct __pthread_attr +{ + enum __ +}; + +#endif /* bits/thread-barrier.h */ diff --git a/sysdeps/generic/bits/thread-specific.h b/sysdeps/generic/bits/thread-specific.h new file mode 100644 index 00000000..b42d99e7 --- /dev/null +++ b/sysdeps/generic/bits/thread-specific.h @@ -0,0 +1,25 @@ +/* Thread specific data. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_THREAD_SPECIFIC_H +#define _BITS_THREAD_SPECIFIC_H 1 + +typedef int __pthread_key; + +#endif /* bits/thread-specific.h */ diff --git a/sysdeps/generic/pt-atfork.c b/sysdeps/generic/pt-atfork.c new file mode 100644 index 00000000..32e1e78c --- /dev/null +++ b/sysdeps/generic/pt-atfork.c @@ -0,0 +1,29 @@ +/* Register fork handlers. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_atfork (void (*prepare) (void), + void (*parent) (void), + void (*child) (void)) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-attr-destroy.c b/sysdeps/generic/pt-attr-destroy.c new file mode 100644 index 00000000..c4b9aa54 --- /dev/null +++ b/sysdeps/generic/pt-attr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_attr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_destroy (pthread_attr_t *attr) +{ + return 0; +} diff --git a/sysdeps/generic/pt-attr-getdetachstate.c b/sysdeps/generic/pt-attr-getdetachstate.c new file mode 100644 index 00000000..be406f1d --- /dev/null +++ b/sysdeps/generic/pt-attr-getdetachstate.c @@ -0,0 +1,29 @@ +/* pthread_attr_getdetachstate. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate) +{ + *detachstate = attr->detachstate; + return 0; +} diff --git a/sysdeps/generic/pt-attr-getguardsize.c b/sysdeps/generic/pt-attr-getguardsize.c new file mode 100644 index 00000000..c1d9f13e --- /dev/null +++ b/sysdeps/generic/pt-attr-getguardsize.c @@ -0,0 +1,29 @@ +/* pthread_attr_getguardsize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getguardsize (const pthread_attr_t *attr, + size_t *guardsize) +{ + *guardsize = attr->guardsize; + return 0; +} diff --git a/sysdeps/generic/pt-attr-getinheritsched.c b/sysdeps/generic/pt-attr-getinheritsched.c new file mode 100644 index 00000000..cca4e3d7 --- /dev/null +++ b/sysdeps/generic/pt-attr-getinheritsched.c @@ -0,0 +1,29 @@ +/* pthread_attr_getinheritsched. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inheritsched) +{ + *inheritsched = attr->inheritsched; + return 0; +} diff --git a/sysdeps/generic/pt-attr-getschedparam.c b/sysdeps/generic/pt-attr-getschedparam.c new file mode 100644 index 00000000..25afebd0 --- /dev/null +++ b/sysdeps/generic/pt-attr-getschedparam.c @@ -0,0 +1,31 @@ +/* pthread_attr_getschedparam. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param) +{ + *param = attr->schedparam; + return 0; +} diff --git a/sysdeps/generic/pt-attr-getschedpolicy.c b/sysdeps/generic/pt-attr-getschedpolicy.c new file mode 100644 index 00000000..4349a238 --- /dev/null +++ b/sysdeps/generic/pt-attr-getschedpolicy.c @@ -0,0 +1,29 @@ +/* pthread_attr_getschedpolicy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy) +{ + *policy = attr->schedpolicy; + return 0; +} diff --git a/sysdeps/generic/pt-attr-getscope.c b/sysdeps/generic/pt-attr-getscope.c new file mode 100644 index 00000000..97198fa5 --- /dev/null +++ b/sysdeps/generic/pt-attr-getscope.c @@ -0,0 +1,29 @@ +/* pthread_attr_getscope. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getscope (const pthread_attr_t *attr, + int *contentionscope) +{ + *contentionscope = attr->contentionscope; + return 0; +} diff --git a/sysdeps/generic/pt-attr-getstack.c b/sysdeps/generic/pt-attr-getstack.c new file mode 100644 index 00000000..7beb79f0 --- /dev/null +++ b/sysdeps/generic/pt-attr-getstack.c @@ -0,0 +1,31 @@ +/* pthread_attr_getstack. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getstack (const pthread_attr_t *attr, + void **stackaddr, + size_t *stacksize) +{ + pthread_attr_getstackaddr (attr, stackaddr); + pthread_attr_getstacksize (attr, stacksize); + return 0; +} diff --git a/sysdeps/generic/pt-attr-getstackaddr.c b/sysdeps/generic/pt-attr-getstackaddr.c new file mode 100644 index 00000000..d43eeff7 --- /dev/null +++ b/sysdeps/generic/pt-attr-getstackaddr.c @@ -0,0 +1,29 @@ +/* pthread_attr_getstackaddr. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getstackaddr (const pthread_attr_t *attr, + void **stackaddr) +{ + *stackaddr = attr->stackaddr; + return 0; +} diff --git a/sysdeps/generic/pt-attr-getstacksize.c b/sysdeps/generic/pt-attr-getstacksize.c new file mode 100644 index 00000000..c1bc6617 --- /dev/null +++ b/sysdeps/generic/pt-attr-getstacksize.c @@ -0,0 +1,29 @@ +/* pthread_attr_getstacksize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getstacksize (const pthread_attr_t *attr, + size_t *stacksize) +{ + *stacksize = attr->stacksize; + return 0; +} diff --git a/sysdeps/generic/pt-attr-init.c b/sysdeps/generic/pt-attr-init.c new file mode 100644 index 00000000..6a930e30 --- /dev/null +++ b/sysdeps/generic/pt-attr-init.c @@ -0,0 +1,28 @@ +/* pthread_attr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_init (pthread_attr_t *attr) +{ + *attr = __pthread_default_attr; + return 0; +} diff --git a/sysdeps/generic/pt-attr-setdetachstate.c b/sysdeps/generic/pt-attr-setdetachstate.c new file mode 100644 index 00000000..688ba5d6 --- /dev/null +++ b/sysdeps/generic/pt-attr-setdetachstate.c @@ -0,0 +1,38 @@ +/* pthread_attr_setdetachstate. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate) +{ + switch (detachstate) + { + case PTHREAD_CREATE_DETACHED: + case PTHREAD_CREATE_JOINABLE: + attr->detachstate = detachstate; + break; + default: + return EINVAL; + } + + return 0; +} diff --git a/sysdeps/generic/pt-attr-setguardsize.c b/sysdeps/generic/pt-attr-setguardsize.c new file mode 100644 index 00000000..b2ba0f0f --- /dev/null +++ b/sysdeps/generic/pt-attr-setguardsize.c @@ -0,0 +1,29 @@ +/* pthread_attr_setguardsize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setguardsize (pthread_attr_t *attr, + size_t guardsize) +{ + attr->guardsize = guardsize; + return 0; +} diff --git a/sysdeps/generic/pt-attr-setinheritsched.c b/sysdeps/generic/pt-attr-setinheritsched.c new file mode 100644 index 00000000..e9012c58 --- /dev/null +++ b/sysdeps/generic/pt-attr-setinheritsched.c @@ -0,0 +1,38 @@ +/* pthread_attr_setinheritsched. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setinheritsched (pthread_attr_t *attr, + int inheritsched) +{ + switch (inheritsched) + { + case PTHREAD_INHERIT_SCHED: + case PTHREAD_EXPLICIT_SCHED: + attr->inheritsched = inheritsched; + break; + default: + return EINVAL; + } + + return 0; +} diff --git a/sysdeps/generic/pt-attr-setschedparam.c b/sysdeps/generic/pt-attr-setschedparam.c new file mode 100644 index 00000000..18a575ec --- /dev/null +++ b/sysdeps/generic/pt-attr-setschedparam.c @@ -0,0 +1,38 @@ +/* pthread_attr_getschedparam. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param) +{ + if (memcmp (param, &__pthread_default_attr.schedparam, + sizeof *param) == 0) + { + attr->schedparam = *param; + return 0; + } + + return ENOTSUP; +} diff --git a/sysdeps/generic/pt-attr-setschedpolicy.c b/sysdeps/generic/pt-attr-setschedpolicy.c new file mode 100644 index 00000000..e481d04c --- /dev/null +++ b/sysdeps/generic/pt-attr-setschedpolicy.c @@ -0,0 +1,42 @@ +/* pthread_attr_getschedpolicy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setschedpolicy (pthread_attr_t *attr, + int policy) +{ + switch (policy) + { + case SCHED_OTHER: + attr->schedpolicy = policy; + break; + + case SCHED_FIFO: + case SCHED_RR: + return ENOTSUP; + + default: + return EINVAL; + } + + return 0; +} diff --git a/sysdeps/generic/pt-attr-setscope.c b/sysdeps/generic/pt-attr-setscope.c new file mode 100644 index 00000000..c74a4f67 --- /dev/null +++ b/sysdeps/generic/pt-attr-setscope.c @@ -0,0 +1,41 @@ +/* pthread_attr_setscope. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setscope (pthread_attr_t *attr, + int contentionscope) +{ + if (contentionscope == __pthread_default_attr.contentionscope) + { + attr->contentionscope = contentionscope; + return 0; + } + + switch (contentionscope) + { + case PTHREAD_SCOPE_PROCESS: + case PTHREAD_SCOPE_SYSTEM: + return ENOTSUP; + default: + return EINVAL; + } +} diff --git a/sysdeps/generic/pt-attr-setstack.c b/sysdeps/generic/pt-attr-setstack.c new file mode 100644 index 00000000..360d27a3 --- /dev/null +++ b/sysdeps/generic/pt-attr-setstack.c @@ -0,0 +1,51 @@ +/* pthread_attr_setstack. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_attr_setstack (pthread_attr_t *attr, + void *stackaddr, + size_t stacksize) +{ + int err; + size_t s; + + /* pthread_attr_setstack should always succeed, thus we set the size + first as it is more discriminating. */ + pthread_attr_getstacksize (attr, &s); + + err = pthread_attr_setstacksize (attr, stacksize); + if (err) + return err; + + err = pthread_attr_setstackaddr (attr, stackaddr); + if (err) + { + int e = pthread_attr_setstacksize (attr, s); + assert_perror (e); + + return err; + } + + return 0; +} diff --git a/sysdeps/generic/pt-attr-setstackaddr.c b/sysdeps/generic/pt-attr-setstackaddr.c new file mode 100644 index 00000000..431f2d0c --- /dev/null +++ b/sysdeps/generic/pt-attr-setstackaddr.c @@ -0,0 +1,29 @@ +/* pthread_attr_setstackaddr. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr) +{ + attr->stackaddr = stackaddr; + return 0; +} diff --git a/sysdeps/generic/pt-attr-setstacksize.c b/sysdeps/generic/pt-attr-setstacksize.c new file mode 100644 index 00000000..d0e51022 --- /dev/null +++ b/sysdeps/generic/pt-attr-setstacksize.c @@ -0,0 +1,41 @@ +/* pthread_attr_setstacksize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + if (stacksize == __pthread_default_attr.stacksize) + { + attr->stacksize = stacksize; + + /* The guard size cannot be larger than the stack itself, as + such, if the new stack size is smaller than the guard size, + we squash the guard size. */ + if (attr->guardsize > attr->stacksize) + attr->guardsize = attr->stacksize; + + return 0; + } + + return ENOTSUP; +} diff --git a/sysdeps/generic/pt-attr.c b/sysdeps/generic/pt-attr.c new file mode 100644 index 00000000..769f292a --- /dev/null +++ b/sysdeps/generic/pt-attr.c @@ -0,0 +1,41 @@ +/* Default attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +const struct __pthread_attr __pthread_default_attr = +{ + schedparam: { sched_priority: 0 }, + stacksize: PTHREAD_STACK_DEFAULT, + stackaddr: NULL, +#ifdef PAGESIZE + guardsize: PAGESIZE, +#else + guardsize: 0, +#endif /* PAGESIZE */ + detachstate: PTHREAD_CREATE_JOINABLE, + inheritsched: PTHREAD_EXPLICIT_SCHED, + contentionscope: PTHREAD_SCOPE_SYSTEM, + schedpolicy: SCHED_OTHER +}; diff --git a/sysdeps/generic/pt-barrier-destroy.c b/sysdeps/generic/pt-barrier-destroy.c new file mode 100644 index 00000000..01b938b4 --- /dev/null +++ b/sysdeps/generic/pt-barrier-destroy.c @@ -0,0 +1,27 @@ +/* pthread_barrier_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrier_destroy (pthread_barrier_t *barrier) +{ + return 0; +} diff --git a/sysdeps/generic/pt-barrier-init.c b/sysdeps/generic/pt-barrier-init.c new file mode 100644 index 00000000..57911d51 --- /dev/null +++ b/sysdeps/generic/pt-barrier-init.c @@ -0,0 +1,43 @@ +/* pthread_barrier_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +pthread_barrier_init (pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned count) +{ + assert (attr->pshared == PTHREAD_PROCESS_PRIVATE); + + if (count == 0) + return EINVAL; + + memset (barrier, 0, sizeof *barrier); + + barrier->lock = PTHREAD_SPINLOCK_INITIALIZER; + barrier->pending = count; + barrier->count = count; + + return 0; +} diff --git a/sysdeps/generic/pt-barrier-wait.c b/sysdeps/generic/pt-barrier-wait.c new file mode 100644 index 00000000..f1de250a --- /dev/null +++ b/sysdeps/generic/pt-barrier-wait.c @@ -0,0 +1,61 @@ +/* pthread_barrier_wait. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_barrier_wait (pthread_barrier_t *barrier) +{ + __pthread_spin_lock (&barrier->lock); + if (-- barrier->pending == 0) + { + barrier->pending = barrier->count; + + if (barrier->count > 1) + { + struct __pthread *wakeup; + + wakeup = barrier->queue; + barrier->queue = NULL; + __pthread_spin_unlock (&barrier->lock); + + /* We can safely walk the list of waiting threads without + holding the lock since it is decoupled from the barrier + variable now. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + } + + return PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + struct __pthread *self = _pthread_self (); + + /* Add ourselves to the list of waiters. */ + __pthread_enqueue (&barrier->queue, self); + __pthread_spin_unlock (&barrier->lock); + + __pthread_block (self); + return 0; + } +} diff --git a/sysdeps/generic/pt-barrier.c b/sysdeps/generic/pt-barrier.c new file mode 100644 index 00000000..d772719f --- /dev/null +++ b/sysdeps/generic/pt-barrier.c @@ -0,0 +1,26 @@ +/* Default barrier attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +const struct __pthread_barrierattr __pthread_default_barrierattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE +}; diff --git a/sysdeps/generic/pt-barrierattr-destroy.c b/sysdeps/generic/pt-barrierattr-destroy.c new file mode 100644 index 00000000..eb396347 --- /dev/null +++ b/sysdeps/generic/pt-barrierattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_barrierattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_destroy (pthread_barrierattr_t *attr) +{ + return 0; +} diff --git a/sysdeps/generic/pt-barrierattr-getpshared.c b/sysdeps/generic/pt-barrierattr-getpshared.c new file mode 100644 index 00000000..ed2cdd24 --- /dev/null +++ b/sysdeps/generic/pt-barrierattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_barrierattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_getpshared (const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/sysdeps/generic/pt-barrierattr-init.c b/sysdeps/generic/pt-barrierattr-init.c new file mode 100644 index 00000000..45f16cc8 --- /dev/null +++ b/sysdeps/generic/pt-barrierattr-init.c @@ -0,0 +1,28 @@ +/* pthread_barrierattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_init (pthread_barrierattr_t *attr) +{ + *attr = __pthread_default_barrierattr; + return 0; +} diff --git a/sysdeps/generic/pt-barrierattr-setpshared.c b/sysdeps/generic/pt-barrierattr-setpshared.c new file mode 100644 index 00000000..84ef2df8 --- /dev/null +++ b/sysdeps/generic/pt-barrierattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_barrierattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/sysdeps/generic/pt-cond-brdcast.c b/sysdeps/generic/pt-cond-brdcast.c new file mode 100644 index 00000000..3f55e33e --- /dev/null +++ b/sysdeps/generic/pt-cond-brdcast.c @@ -0,0 +1,42 @@ +/* Broadcast a condition. Generic version. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Unblock all threads that are blocked on condition variable COND. */ +int +pthread_cond_broadcast (pthread_cond_t *cond) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&cond->__lock); + + wakeup = cond->__queue; + cond->__queue = NULL; + __pthread_spin_unlock (&cond->__lock); + + /* We can safely walk the list of waiting threads without holding + the lock since it is now decoupled from the condition. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + + return 0; +} diff --git a/sysdeps/generic/pt-cond-destroy.c b/sysdeps/generic/pt-cond-destroy.c new file mode 100644 index 00000000..eba47784 --- /dev/null +++ b/sysdeps/generic/pt-cond-destroy.c @@ -0,0 +1,27 @@ +/* pthread_cond_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_cond_destroy (pthread_cond_t *cond) +{ + return 0; +} diff --git a/sysdeps/generic/pt-cond-init.c b/sysdeps/generic/pt-cond-init.c new file mode 100644 index 00000000..4afcc94e --- /dev/null +++ b/sysdeps/generic/pt-cond-init.c @@ -0,0 +1,34 @@ +/* pthread_cond_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *attr) +{ + if (attr) + assert (attr->pshared == PTHREAD_PROCESS_PRIVATE); + + *cond = __PTHREAD_COND_INITIALIZER; + return 0; +} diff --git a/sysdeps/generic/pt-cond-signal.c b/sysdeps/generic/pt-cond-signal.c new file mode 100644 index 00000000..c5e1bc1d --- /dev/null +++ b/sysdeps/generic/pt-cond-signal.c @@ -0,0 +1,54 @@ +/* Signal a condition. Generic version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +static int +cond_signal (struct __pthread_cond *cond, int *unblocked) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&cond->__lock); + wakeup = cond->__queue; + if (wakeup) + __pthread_dequeue (wakeup); + __pthread_spin_unlock (&cond->__lock); + + if (wakeup) + { + /* We found a thread waiting for the condition to be signalled. + Wake it up! */ + __pthread_wakeup (wakeup); + *unblocked = 1; + } + + return 0; +} + +/* Unblock at least one of the threads that are blocked on condition + variable COND. */ +int +pthread_cond_signal (pthread_cond_t *cond) +{ + int unblocked = 0; + + return cond_signal (cond, &unblocked); +} diff --git a/sysdeps/generic/pt-cond-timedwait.c b/sysdeps/generic/pt-cond-timedwait.c new file mode 100644 index 00000000..99761f3a --- /dev/null +++ b/sysdeps/generic/pt-cond-timedwait.c @@ -0,0 +1,86 @@ +/* Wait on a condition. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + +int +pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + return __pthread_cond_timedwait_internal (cond, mutex, abstime); +} + +/* Block on condition variable COND until ABSTIME. As a GNU + extension, if ABSTIME is NULL, then wait forever. MUTEX should be + held by the calling thread. On return, MUTEX will be held by the + calling thread. */ +int +__pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + error_t err; + int canceltype; + + void cleanup (void *arg) + { + struct __pthread *self = _pthread_self (); + + __pthread_spin_lock (&cond->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&cond->__lock); + + pthread_setcanceltype (canceltype, &canceltype); + __pthread_mutex_lock (mutex); + } + + struct __pthread *self = _pthread_self (); + + /* Add ourselves to the list of waiters. */ + __pthread_spin_lock (&cond->__lock); + __pthread_enqueue (&cond->__queue, self); + __pthread_spin_unlock (&cond->__lock); + + __pthread_mutex_unlock (mutex); + + /* Enter async cancelation mode. If cancelation is disabled, then + this does not change anything which is exactly what we want. */ + pthread_cleanup_push (cleanup, 0); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &canceltype); + + if (abstime) + err = __pthread_timedblock (self, abstime); + else + { + err = 0; + __pthread_block (self); + } + + pthread_cleanup_pop (1); + + return err; +} diff --git a/sysdeps/generic/pt-cond-wait.c b/sysdeps/generic/pt-cond-wait.c new file mode 100644 index 00000000..a03476df --- /dev/null +++ b/sysdeps/generic/pt-cond-wait.c @@ -0,0 +1,37 @@ +/* Wait on a condition. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Implemented in pt-cond-timedwait.c. */ +extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + + +/* Block on condition variable COND. MUTEX should be held by the + calling thread. On return, MUTEX will be held by the calling + thread. */ +int +pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + return __pthread_cond_timedwait_internal (cond, mutex, 0); +} diff --git a/sysdeps/generic/pt-cond.c b/sysdeps/generic/pt-cond.c new file mode 100644 index 00000000..033e767f --- /dev/null +++ b/sysdeps/generic/pt-cond.c @@ -0,0 +1,29 @@ +/* Default condition attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +const struct __pthread_condattr __pthread_default_condattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE, + clock: CLOCK_REALTIME +}; diff --git a/sysdeps/generic/pt-condattr-destroy.c b/sysdeps/generic/pt-condattr-destroy.c new file mode 100644 index 00000000..c8fd71b9 --- /dev/null +++ b/sysdeps/generic/pt-condattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_condattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_destroy (pthread_condattr_t *cond) +{ + return 0; +} diff --git a/sysdeps/generic/pt-condattr-getclock.c b/sysdeps/generic/pt-condattr-getclock.c new file mode 100644 index 00000000..5b9f8893 --- /dev/null +++ b/sysdeps/generic/pt-condattr-getclock.c @@ -0,0 +1,31 @@ +/* pthread_condattr_getclock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_condattr_getclock (const pthread_condattr_t *attr, + clockid_t *clock) +{ + *clock = attr->clock; + return 0; +} diff --git a/sysdeps/generic/pt-condattr-getpshared.c b/sysdeps/generic/pt-condattr-getpshared.c new file mode 100644 index 00000000..c072a507 --- /dev/null +++ b/sysdeps/generic/pt-condattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_condattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_getpshared (const pthread_condattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/sysdeps/generic/pt-condattr-init.c b/sysdeps/generic/pt-condattr-init.c new file mode 100644 index 00000000..cf9e1989 --- /dev/null +++ b/sysdeps/generic/pt-condattr-init.c @@ -0,0 +1,28 @@ +/* pthread_condattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_init (pthread_condattr_t *attr) +{ + *attr = __pthread_default_condattr; + return 0; +} diff --git a/sysdeps/generic/pt-condattr-setclock.c b/sysdeps/generic/pt-condattr-setclock.c new file mode 100644 index 00000000..984c17e2 --- /dev/null +++ b/sysdeps/generic/pt-condattr-setclock.c @@ -0,0 +1,33 @@ +/* pthread_condattr_setclock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock) +{ + if (__pthread_default_condattr.clock == clock) + { + attr->clock = clock; + return 0; + } + + return EINVAL; +} diff --git a/sysdeps/generic/pt-condattr-setpshared.c b/sysdeps/generic/pt-condattr-setpshared.c new file mode 100644 index 00000000..b9f0af83 --- /dev/null +++ b/sysdeps/generic/pt-condattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_condattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_setpshared (pthread_condattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/sysdeps/generic/pt-destroy-specific.c b/sysdeps/generic/pt-destroy-specific.c new file mode 100644 index 00000000..b627f872 --- /dev/null +++ b/sysdeps/generic/pt-destroy-specific.c @@ -0,0 +1,28 @@ +/* __pthread_destory_specific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +void +__pthread_destory_specifc (struct __pthread *thread) +{ + /* Not support, thus there cannot be any. */ + return; +} diff --git a/sysdeps/generic/pt-equal.c b/sysdeps/generic/pt-equal.c new file mode 100644 index 00000000..8fbc519c --- /dev/null +++ b/sysdeps/generic/pt-equal.c @@ -0,0 +1,29 @@ +/* Default attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* Return true if __T1 and __T2 both name the same thread. Otherwise, + false. */ +int +pthread_equal (pthread_t __t1, pthread_t __t2) +{ + return __t1 == __t2; +} diff --git a/sysdeps/generic/pt-getconcurrency.c b/sysdeps/generic/pt-getconcurrency.c new file mode 100644 index 00000000..b55c8eef --- /dev/null +++ b/sysdeps/generic/pt-getconcurrency.c @@ -0,0 +1,27 @@ +/* Get the current level of desired concurrency. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_getconcurrency (void) +{ + return __pthread_concurrency; +} diff --git a/sysdeps/generic/pt-getcpuclockid.c b/sysdeps/generic/pt-getcpuclockid.c new file mode 100644 index 00000000..81f6aabd --- /dev/null +++ b/sysdeps/generic/pt-getcpuclockid.c @@ -0,0 +1,34 @@ +/* Return a thread's cpu clockid. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_getcpuclockid (pthread_t thread, clockid_t *clock) +{ +#ifdef CLOCK_THREAD_CPUTIME_ID + *clock = CLOCK_THREAD_CPUTIME_ID; + return 0; +#else + return ENOSYS; +#endif +} diff --git a/sysdeps/generic/pt-getschedparam.c b/sysdeps/generic/pt-getschedparam.c new file mode 100644 index 00000000..c128d02e --- /dev/null +++ b/sysdeps/generic/pt-getschedparam.c @@ -0,0 +1,28 @@ +/* Get the scheduling parameters for a thread. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-getspecific.c b/sysdeps/generic/pt-getspecific.c new file mode 100644 index 00000000..2a7c4a9e --- /dev/null +++ b/sysdeps/generic/pt-getspecific.c @@ -0,0 +1,27 @@ +/* pthread_getspecific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_getspecific (pthread_key_t key) +{ + return EINVAL; +} diff --git a/sysdeps/generic/pt-init-specific.c b/sysdeps/generic/pt-init-specific.c new file mode 100644 index 00000000..00744fb6 --- /dev/null +++ b/sysdeps/generic/pt-init-specific.c @@ -0,0 +1,27 @@ +/* __pthread_init_specific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +error_t +__pthread_init_specific (struct __pthread *thread) +{ + return 0; +} diff --git a/sysdeps/generic/pt-key-create.c b/sysdeps/generic/pt-key-create.c new file mode 100644 index 00000000..7ef4b991 --- /dev/null +++ b/sysdeps/generic/pt-key-create.c @@ -0,0 +1,27 @@ +/* pthread_key_create. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-key-delete.c b/sysdeps/generic/pt-key-delete.c new file mode 100644 index 00000000..2e36f044 --- /dev/null +++ b/sysdeps/generic/pt-key-delete.c @@ -0,0 +1,27 @@ +/* pthread_key_delete. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_key_destory (pthread_key_t key) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-key.h b/sysdeps/generic/pt-key.h new file mode 100644 index 00000000..544eb20f --- /dev/null +++ b/sysdeps/generic/pt-key.h @@ -0,0 +1,22 @@ +/* pthread_key internal declatations. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#define PTHREAD_KEY_MEMBERS diff --git a/sysdeps/generic/pt-mutex-destroy.c b/sysdeps/generic/pt-mutex-destroy.c new file mode 100644 index 00000000..d9fb59ce --- /dev/null +++ b/sysdeps/generic/pt-mutex-destroy.c @@ -0,0 +1,35 @@ +/* Destroy a mutex. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +_pthread_mutex_destroy (pthread_mutex_t *mutex) +{ + if (mutex->attr) + free (mutex->attr); + + return 0; +} + +weak_alias (_pthread_mutex_destroy, pthread_mutex_destroy); diff --git a/sysdeps/generic/pt-mutex-getprioceiling.c b/sysdeps/generic/pt-mutex-getprioceiling.c new file mode 100644 index 00000000..eb51639b --- /dev/null +++ b/sysdeps/generic/pt-mutex-getprioceiling.c @@ -0,0 +1,28 @@ +/* Get a mutex' priority ceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, + int *prioceiling) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c new file mode 100644 index 00000000..2902f6e4 --- /dev/null +++ b/sysdeps/generic/pt-mutex-init.c @@ -0,0 +1,48 @@ +/* Initialize a mutex. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +int +_pthread_mutex_init (pthread_mutex_t *mutex, + const pthread_mutexattr_t *attr) +{ + *mutex = __PTHREAD_MUTEX_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_mutexattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + mutex->attr = malloc (sizeof *attr); + if (! mutex->attr) + return ENOMEM; + + *mutex->attr = *attr; + return 0; +} + +weak_alias (_pthread_mutex_init, pthread_mutex_init); diff --git a/sysdeps/generic/pt-mutex-lock.c b/sysdeps/generic/pt-mutex-lock.c new file mode 100644 index 00000000..58d3827c --- /dev/null +++ b/sysdeps/generic/pt-mutex-lock.c @@ -0,0 +1,37 @@ +/* Lock a mutex. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Implemented in pt-mutex-timedlock.c. */ +extern int __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, + const struct timespec *abstime); + +/* Lock MUTEX, block if we can't get it. */ +int +__pthread_mutex_lock (struct __pthread_mutex *mutex) +{ + return __pthread_mutex_timedlock_internal (mutex, 0); +} + +weak_alias (__pthread_mutex_lock, _pthread_mutex_lock); +weak_alias (__pthread_mutex_lock, pthread_mutex_lock); diff --git a/sysdeps/generic/pt-mutex-setprioceiling.c b/sysdeps/generic/pt-mutex-setprioceiling.c new file mode 100644 index 00000000..9fa8e50d --- /dev/null +++ b/sysdeps/generic/pt-mutex-setprioceiling.c @@ -0,0 +1,28 @@ +/* Set a mutex' priority ceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prio, + int *oldprio) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c new file mode 100644 index 00000000..e8c9b466 --- /dev/null +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -0,0 +1,148 @@ +/* Lock a mutex with a timeout. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +#define LOSE do { * (int *) 0 = 0; } while (1) + +int +pthread_mutex_timedlock (struct __pthread_mutex *mutex, + const struct timespec *abstime) +{ + return __pthread_mutex_timedlock_internal (mutex, abstime); +} + +/* Try to lock MUTEX, block until *ABSTIME if it is already held. As + a GNU extension, if TIMESPEC is NULL then wait forever. */ +int +__pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&mutex->__lock); + if (__pthread_spin_trylock (&mutex->__held) == 0) + /* Successfully acquired the lock. */ + { + if (mutex->attr) + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = _pthread_self (); + break; + + default: + LOSE; + } + + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + /* The lock is busy. */ + + self = _pthread_self (); + + if (mutex->attr) + { + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_ERRORCHECK: + if (mutex->owner == self) + { + __pthread_spin_unlock (&mutex->__lock); + return EDEADLK; + } + break; + + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner == self) + { + mutex->locks ++; + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + break; + + default: + LOSE; + } + } + + /* Add ourselves to the queue. */ + __pthread_enqueue (&mutex->__queue, self); + __pthread_spin_unlock (&mutex->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err = ETIMEDOUT); + + __pthread_spin_lock (&mutex->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&mutex->__lock); + + return err; + } + } + else + __pthread_block (self); + + if (mutex->attr) + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + assert (mutex->locks == 0); + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = self; + break; + + default: + LOSE; + } + + return 0; +} diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c new file mode 100644 index 00000000..b3c3fe3a --- /dev/null +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -0,0 +1,89 @@ +/* Try to Lock a mutex. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Lock MUTEX, block if we can't get it. */ +int +__pthread_mutex_trylock (struct __pthread_mutex *mutex) +{ + int err; + struct __pthread *self; + + __pthread_spin_lock (&mutex->__lock); + if (__pthread_spin_trylock (&mutex->__held) == 0) + /* Acquired the lock. */ + { + if (mutex->attr) + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = _pthread_self (); + break; + + default: + LOSE; + } + + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + err = EBUSY; + + if (mutex->attr) + { + self = _pthread_self (); + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_ERRORCHECK: + if (mutex->owner == self) + err = EDEADLK; + break; + + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner == self) + { + mutex->locks ++; + err = 0; + } + break; + + default: + LOSE; + } + } + + return err; +} + +weak_alias (__pthread_mutex_trylock, _pthread_mutex_trylock); +weak_alias (__pthread_mutex_trylock, pthread_mutex_trylock); diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c new file mode 100644 index 00000000..bbbe2b8f --- /dev/null +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -0,0 +1,82 @@ +/* Unlock a mutex. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Unlock MUTEX, rescheduling a waiting thread. */ +int +__pthread_mutex_unlock (pthread_mutex_t *mutex) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&mutex->__lock); + + if (mutex->attr) + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner != _pthread_self ()) + { + __pthread_spin_unlock (&mutex->__lock); + return EPERM; + } + + if (mutex->attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) + if (--mutex->locks > 0) + { + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + mutex->owner = 0; + break; + + default: + LOSE; + } + + if (mutex->__queue == NULL) + { + __pthread_spin_unlock (&mutex->__held); + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + wakeup = mutex->__queue; + __pthread_dequeue (wakeup); + + /* We do not unlock MUTEX->held: we are transferring the ownership + to the thread that we are waking up. */ + + __pthread_spin_unlock (&mutex->__lock); + __pthread_wakeup (wakeup); + + return 0; +} + +weak_alias (__pthread_mutex_unlock, _pthread_mutex_unlock); +weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock); diff --git a/sysdeps/generic/pt-mutexattr-destroy.c b/sysdeps/generic/pt-mutexattr-destroy.c new file mode 100644 index 00000000..fe7e95d2 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_mutexattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_destroy (pthread_mutexattr_t *attr) +{ + return 0; +} diff --git a/sysdeps/generic/pt-mutexattr-getprioceiling.c b/sysdeps/generic/pt-mutexattr-getprioceiling.c new file mode 100644 index 00000000..d03d7192 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-getprioceiling.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_getprioceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr, + int *prioceiling) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-mutexattr-getprotocol.c b/sysdeps/generic/pt-mutexattr-getprotocol.c new file mode 100644 index 00000000..d75021a3 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-getprotocol.c @@ -0,0 +1,29 @@ +/* pthread_mutexattr_getprotocol. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr, + int *protocol) +{ + *protocol = attr->protocol; + return 0; +} diff --git a/sysdeps/generic/pt-mutexattr-getpshared.c b/sysdeps/generic/pt-mutexattr-getpshared.c new file mode 100644 index 00000000..0dad13b8 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_mutexattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/sysdeps/generic/pt-mutexattr-gettype.c b/sysdeps/generic/pt-mutexattr-gettype.c new file mode 100644 index 00000000..ff2caea4 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-gettype.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_gettype. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type) +{ + *type = attr->mutex_type; + return 0; +} diff --git a/sysdeps/generic/pt-mutexattr-init.c b/sysdeps/generic/pt-mutexattr-init.c new file mode 100644 index 00000000..2f23673c --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-init.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_init (pthread_mutexattr_t *attr) +{ + *attr = __pthread_default_mutexattr; + return 0; +} diff --git a/sysdeps/generic/pt-mutexattr-setprioceiling.c b/sysdeps/generic/pt-mutexattr-setprioceiling.c new file mode 100644 index 00000000..a9bbd327 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-setprioceiling.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_setprioceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr, + int prioceiling) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-mutexattr-setprotocol.c b/sysdeps/generic/pt-mutexattr-setprotocol.c new file mode 100644 index 00000000..9a0d1b1f --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-setprotocol.c @@ -0,0 +1,42 @@ +/* pthread_mutexattr_setprotocol. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, + int protocol) +{ + if (protocol == __pthread_default_mutexattr.protocol) + { + attr->protocol = protocol; + return 0; + } + + switch (protocol) + { + case PTHREAD_PRIO_NONE: + case PTHREAD_PRIO_INHERIT: + case PTHREAD_PRIO_PROTECT: + return ENOTSUP; + default: + return EINVAL; + } +} diff --git a/sysdeps/generic/pt-mutexattr-setpshared.c b/sysdeps/generic/pt-mutexattr-setpshared.c new file mode 100644 index 00000000..bcbc4d91 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_mutexattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/sysdeps/generic/pt-mutexattr-settype.c b/sysdeps/generic/pt-mutexattr-settype.c new file mode 100644 index 00000000..e7ae213a --- /dev/null +++ b/sysdeps/generic/pt-mutexattr-settype.c @@ -0,0 +1,37 @@ +/* pthread_mutexattr_settype. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type) +{ + switch (type) + { + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_RECURSIVE: + attr->mutex_type = type; + return 0; + + default: + return EINVAL; + } +} diff --git a/sysdeps/generic/pt-mutexattr.c b/sysdeps/generic/pt-mutexattr.c new file mode 100644 index 00000000..647db241 --- /dev/null +++ b/sysdeps/generic/pt-mutexattr.c @@ -0,0 +1,29 @@ +/* Default mutex attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +const struct __pthread_mutexattr __pthread_default_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_DEFAULT +}; diff --git a/sysdeps/generic/pt-once.c b/sysdeps/generic/pt-once.c new file mode 100644 index 00000000..5be5e484 --- /dev/null +++ b/sysdeps/generic/pt-once.c @@ -0,0 +1,43 @@ +/* pthread_once. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + if (once_control->run == 0) + { + __pthread_spin_lock (&once_control->lock); + + if (once_control->run == 0) + { + init_routine (); + __memory_barrier (); + once_control->run = 1; + } + + __pthread_spin_unlock (&once_control->lock); + } + + return 0; +} diff --git a/sysdeps/generic/pt-rwlock-attr.c b/sysdeps/generic/pt-rwlock-attr.c new file mode 100644 index 00000000..1587feef --- /dev/null +++ b/sysdeps/generic/pt-rwlock-attr.c @@ -0,0 +1,26 @@ +/* Default rwlock attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +const struct __pthread_rwlockattr __pthread_default_rwlockattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE +}; diff --git a/sysdeps/generic/pt-rwlock-destroy.c b/sysdeps/generic/pt-rwlock-destroy.c new file mode 100644 index 00000000..f63c84d9 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-destroy.c @@ -0,0 +1,29 @@ +/* Destroy a rwlock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + return 0; +} + +weak_alias (_pthread_rwlock_destroy, pthread_rwlock_destroy); diff --git a/sysdeps/generic/pt-rwlock-init.c b/sysdeps/generic/pt-rwlock-init.c new file mode 100644 index 00000000..8fe87644 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-init.c @@ -0,0 +1,31 @@ +/* Initialize a rwlock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +_pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + *rwlock = __PTHREAD_RWLOCK_INITIALIZER; + return 0; +} + +weak_alias (_pthread_rwlock_init, pthread_rwlock_init); diff --git a/sysdeps/generic/pt-rwlock-rdlock.c b/sysdeps/generic/pt-rwlock-rdlock.c new file mode 100644 index 00000000..22c11204 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-rdlock.c @@ -0,0 +1,32 @@ +/* Acquire a rwlock for reading. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* Implemented in pt-rwlock-timedrdlock.c. */ +extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_mutex *mutex, + const struct timespec *abstime); + +/* Acquire RWLOCK for reading, block if we can't get it. */ +int +pthread_rwlock_rdlock (struct __pthread_rwlock *rwlock) +{ + return __pthread_rwlock_timedrdlock_internal (rwlock, 0); +} diff --git a/sysdeps/generic/pt-rwlock-timedrdlock.c b/sysdeps/generic/pt-rwlock-timedrdlock.c new file mode 100644 index 00000000..3660339b --- /dev/null +++ b/sysdeps/generic/pt-rwlock-timedrdlock.c @@ -0,0 +1,110 @@ +/* Acquire a rwlock for reading. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_rwlock_timedrdlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedrdlock_internal (rwlock, abstime); +} + +/* Acquire the rwlock *RWLOCK for reading blocking until *ABSTIME if + it is already held. As a GNU extension, if TIMESPEC is NULL then + wait forever. */ +int +__pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + rwlock->readers = 1; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + else + /* Lock is held, but is held by a reader? */ + if (rwlock->readers > 0) + /* Just add ourself to number of readers. */ + { + assert (rwlock->readerqueue == 0); + rwlock->readers ++; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + /* Better be blocked by a writer. */ + assert (rwlock->readers == 0); + + self = _pthread_self (); + + /* Add ourself to the queue. */ + __pthread_enqueue (&rwlock->readerqueue, self); + __pthread_spin_unlock (&rwlock->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err = ETIMEDOUT); + + __pthread_spin_lock (&rwlock->__lock); + if (self->prevp) + /* Disconnect ourself. */ + __pthread_dequeue (self); + __pthread_spin_unlock (&rwlock->__lock); + + return err; + } + } + else + __pthread_block (self); + + + /* The reader count has already been increment by whoever woke us + up. */ + + assert (rwlock->readers > 0); + + return 0; +} diff --git a/sysdeps/generic/pt-rwlock-timedwrlock.c b/sysdeps/generic/pt-rwlock-timedwrlock.c new file mode 100644 index 00000000..2f732175 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-timedwrlock.c @@ -0,0 +1,92 @@ +/* Acquire a rwlock for writing. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_rwlock_timedwrlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedwrlock_internal (rwlock, abstime); +} + +/* Acquire RWLOCK for writing blocking until *ABSTIME if we cannot get + it. As a special GNU extension, if ABSTIME is NULL then the wait + shall not time out. */ +int +__pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + self = _pthread_self (); + + /* Add ourselves to the queue. */ + __pthread_enqueue (&rwlock->writerqueue, self); + __pthread_spin_unlock (&rwlock->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err = ETIMEDOUT); + + __pthread_spin_lock (&rwlock->__lock); + if (self->prevp) + /* Disconnect ourself. */ + __pthread_dequeue (self); + __pthread_spin_unlock (&rwlock->__lock); + + return err; + } + } + else + __pthread_block (self); + + assert (rwlock->readers == 0); + + return 0; +} diff --git a/sysdeps/generic/pt-rwlock-tryrdlock.c b/sysdeps/generic/pt-rwlock-tryrdlock.c new file mode 100644 index 00000000..2419efb1 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-tryrdlock.c @@ -0,0 +1,56 @@ +/* Try to acquire a rwlock for reading. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Try to acquire RWLOCK. */ +int +pthread_rwlock_tryrdlock (struct __pthread_rwlock *rwlock) +{ + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + rwlock->readers = 1; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + else + /* Lock is held, but is held by a reader? */ + if (rwlock->readers > 0) + { + assert (rwlock->readerqueue == 0); + rwlock->readers ++; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + __pthread_spin_unlock (&rwlock->__lock); + + return EBUSY; +} diff --git a/sysdeps/generic/pt-rwlock-trywrlock.c b/sysdeps/generic/pt-rwlock-trywrlock.c new file mode 100644 index 00000000..6b9c5b56 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-trywrlock.c @@ -0,0 +1,46 @@ +/* Try to acquire a rwlock for writing. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Try to acquire RWLOCK for writing. */ +int +pthread_rwlock_trywrlock (struct __pthread_rwlock *rwlock) +{ + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + __pthread_spin_unlock (&rwlock->__lock); + + return EBUSY; +} diff --git a/sysdeps/generic/pt-rwlock-unlock.c b/sysdeps/generic/pt-rwlock-unlock.c new file mode 100644 index 00000000..fb23a0b9 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-unlock.c @@ -0,0 +1,90 @@ +/* Unlock a rwlock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Unlock *RWLOCK, rescheduling a waiting writer thread or, if there + are no threads waiting for a write lock, rescheduling the reader + threads. */ +int +pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&rwlock->__lock); + + assert (__pthread_spin_trylock (&rwlock->__held) == EBUSY); + + if (rwlock->readers > 1) + /* There are other readers. */ + { + rwlock->readers --; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + if (rwlock->readers == 1) + /* Last reader. */ + rwlock->readers = 0; + + + /* Wake someone else up. Try the writer queue first, then the + reader queue if that is empty. */ + + if (rwlock->writerqueue) + { + wakeup = rwlock->writerqueue; + __pthread_dequeue (wakeup); + + /* We do not unlock RWLOCK->held: we are transferring the ownership + to the thread that we are waking up. */ + + __pthread_spin_unlock (&rwlock->__lock); + __pthread_wakeup (wakeup); + + return 0; + } + + if (rwlock->readerqueue) + { + __pthread_queue_iterate (rwlock->readerqueue, wakeup) + rwlock->readers ++; + + wakeup = rwlock->readerqueue; + rwlock->readerqueue = 0; + + __pthread_spin_unlock (&rwlock->__lock); + + /* We can safely walk the list of waiting threads without holding + the lock since it is now decoupled from the rwlock. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + + return 0; + } + + + /* Noone is waiting. Just unlock it. */ + + __pthread_spin_unlock (&rwlock->__held); + __pthread_spin_unlock (&rwlock->__lock); + return 0; +} diff --git a/sysdeps/generic/pt-rwlock-wrlock.c b/sysdeps/generic/pt-rwlock-wrlock.c new file mode 100644 index 00000000..be85b906 --- /dev/null +++ b/sysdeps/generic/pt-rwlock-wrlock.c @@ -0,0 +1,34 @@ +/* Acquire a rwlock for writing. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Implemented in pt-rwlock-timedwrlock.c. */ +extern int __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime); + +/* Acquire RWLOCK for writing. */ +int +pthread_rwlock_wrlock (struct __pthread_rwlock *rwlock) +{ + return __pthread_rwlock_timedwrlock_internal (rwlock, 0); +} diff --git a/sysdeps/generic/pt-rwlockattr-destroy.c b/sysdeps/generic/pt-rwlockattr-destroy.c new file mode 100644 index 00000000..eabfcbe8 --- /dev/null +++ b/sysdeps/generic/pt-rwlockattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_rwlockattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + return 0; +} diff --git a/sysdeps/generic/pt-rwlockattr-getpshared.c b/sysdeps/generic/pt-rwlockattr-getpshared.c new file mode 100644 index 00000000..e8752c0c --- /dev/null +++ b/sysdeps/generic/pt-rwlockattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_rwlockattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/sysdeps/generic/pt-rwlockattr-init.c b/sysdeps/generic/pt-rwlockattr-init.c new file mode 100644 index 00000000..34da6bf0 --- /dev/null +++ b/sysdeps/generic/pt-rwlockattr-init.c @@ -0,0 +1,28 @@ +/* pthread_rwlockattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + *attr = __pthread_default_rwlockattr; + return 0; +} diff --git a/sysdeps/generic/pt-rwlockattr-setpshared.c b/sysdeps/generic/pt-rwlockattr-setpshared.c new file mode 100644 index 00000000..a861d034 --- /dev/null +++ b/sysdeps/generic/pt-rwlockattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_rwlockattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/sysdeps/generic/pt-setconcurrency.c b/sysdeps/generic/pt-setconcurrency.c new file mode 100644 index 00000000..cd55b1ba --- /dev/null +++ b/sysdeps/generic/pt-setconcurrency.c @@ -0,0 +1,34 @@ +/* Set the desired level of concurrency. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int __pthread_concurrency; + +int +pthread_setconcurrency (int new_level) +{ + if (new_level < 0) + return EINVAL; + + __pthread_concurrency = new_level; + + return 0; +} diff --git a/sysdeps/generic/pt-setschedparam.c b/sysdeps/generic/pt-setschedparam.c new file mode 100644 index 00000000..6b624a31 --- /dev/null +++ b/sysdeps/generic/pt-setschedparam.c @@ -0,0 +1,28 @@ +/* Set the scheduling parameters for a thread. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_setschedparam (pthread_t thread, int *policy, + const struct sched_param *param) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-setschedprio.c b/sysdeps/generic/pt-setschedprio.c new file mode 100644 index 00000000..60668eb1 --- /dev/null +++ b/sysdeps/generic/pt-setschedprio.c @@ -0,0 +1,27 @@ +/* Set the scheduling priority of a thread. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_setschedprio (pthread_t thread, int prio) +{ + return ENOSYS; +} diff --git a/sysdeps/generic/pt-setspecific.c b/sysdeps/generic/pt-setspecific.c new file mode 100644 index 00000000..d520c5df --- /dev/null +++ b/sysdeps/generic/pt-setspecific.c @@ -0,0 +1,27 @@ +/* pthread_setspecific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_setspecific (pthread_key_t key, const void *value) +{ + return EINVAL; +} diff --git a/sysdeps/hurd/pt-destroy-specific.c b/sysdeps/hurd/pt-destroy-specific.c new file mode 100644 index 00000000..82382228 --- /dev/null +++ b/sysdeps/hurd/pt-destroy-specific.c @@ -0,0 +1,77 @@ +/* __pthread_destory_specific. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +void +__pthread_destroy_specific (struct __pthread *thread) +{ + error_t err; + int i; + int seen_one; + + /* Check if there is any thread specific data. */ + if (! thread->thread_specifics) + return; + + __pthread_key_lock_ready (); + + /* Iterate and call the destructors on any thread specific data. */ + for (;;) + { + seen_one = 0; + + __pthread_mutex_lock (&__pthread_key_lock); + + for (i = 0; i < __pthread_key_count; i ++) + { + void *value; + + if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID) + break; + + value = ihash_find (thread->thread_specifics, i); + if (value) + { + seen_one = 1; + + err = ihash_remove (thread->thread_specifics, i); + assert (err == 1); + + __pthread_key_destructors[i] (value); + } + } + + __pthread_mutex_unlock (&__pthread_key_lock); + + if (! seen_one) + break; + + /* This may take a very long time. Let those blocking on + pthread_key_create or pthread_key_delete make progress. */ + sched_yield (); + } + + ihash_free (thread->thread_specifics); + thread->thread_specifics = 0; +} diff --git a/sysdeps/hurd/pt-getspecific.c b/sysdeps/hurd/pt-getspecific.c new file mode 100644 index 00000000..b5b5f5e5 --- /dev/null +++ b/sysdeps/hurd/pt-getspecific.c @@ -0,0 +1,37 @@ +/* pthread_getspecific. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +void * +pthread_getspecific (pthread_key_t key) +{ + struct __pthread *self; + + assert (key < __pthread_key_count); + + self = _pthread_self (); + if (! self->thread_specifics) + return 0; + + return ihash_find (self->thread_specifics, key); +} diff --git a/sysdeps/hurd/pt-init-specific.c b/sysdeps/hurd/pt-init-specific.c new file mode 100644 index 00000000..c1bacbcb --- /dev/null +++ b/sysdeps/hurd/pt-init-specific.c @@ -0,0 +1,30 @@ +/* __pthread_init_specific. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +error_t +__pthread_init_specific (struct __pthread *thread) +{ + thread->thread_specifics = 0; + return 0; +} diff --git a/sysdeps/hurd/pt-key-create.c b/sysdeps/hurd/pt-key-create.c new file mode 100644 index 00000000..b3e01412 --- /dev/null +++ b/sysdeps/hurd/pt-key-create.c @@ -0,0 +1,109 @@ +/* pthread_key_create. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +pthread_mutex_t __pthread_key_lock; + +void (**__pthread_key_destructors) (void *arg); +int __pthread_key_size; +int __pthread_key_count; +int __pthread_key_invalid_count; + +int +pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) +{ + /* Where to look for the next key slot. */ + static int index; + + __pthread_key_lock_ready (); + + __pthread_mutex_lock (&__pthread_key_lock); + + do_search: + /* Use the search hint and try to find a free slot. */ + for (; index < __pthread_key_count + && __pthread_key_destructors[index] != PTHREAD_KEY_INVALID; + index ++) + ; + + /* See if we actually found a free element. */ + if (index < __pthread_key_count) + { + assert (__pthread_key_destructors[index] == PTHREAD_KEY_INVALID); + assert (__pthread_key_invalid_count > 0); + + __pthread_key_invalid_count --; + __pthread_key_destructors[index] = destructor; + *key = index ++; + + __pthread_mutex_unlock (&__pthread_key_lock); + return 0; + } + + assert (index == __pthread_key_count); + + /* No space at the end. */ + if (__pthread_key_size == __pthread_key_count) + { + /* See if it is worth looking for a free element. */ + if (__pthread_key_invalid_count > 4 + && __pthread_key_invalid_count > __pthread_key_size / 8) + { + index = 0; + goto do_search; + } + + + /* Resize the array. */ + { + void *t; + int newsize; + + if (__pthread_key_size == 0) + newsize = 8; + else + newsize = __pthread_key_size * 2; + + t = realloc (__pthread_key_destructors, + newsize * sizeof (*__pthread_key_destructors)); + if (! t) + { + __pthread_mutex_unlock (&__pthread_key_lock); + return ENOMEM; + } + + __pthread_key_size = newsize; + __pthread_key_destructors = t; + } + } + + __pthread_key_destructors[index] = destructor; + *key = index; + + index ++; + __pthread_key_count ++; + + __pthread_mutex_unlock (&__pthread_key_lock); + return 0; +} diff --git a/sysdeps/hurd/pt-key-delete.c b/sysdeps/hurd/pt-key-delete.c new file mode 100644 index 00000000..7c1af715 --- /dev/null +++ b/sysdeps/hurd/pt-key-delete.c @@ -0,0 +1,45 @@ +/* pthread_key_delete. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_key_destory (pthread_key_t key) +{ + error_t err = 0; + + __pthread_key_lock_ready (); + + __pthread_mutex_lock (&__pthread_key_lock); + + if (key < 0 || key >= __pthread_key_count + || __pthread_key_destructors[key] == PTHREAD_KEY_INVALID) + err = EINVAL; + else + { + __pthread_key_destructors[key] = PTHREAD_KEY_INVALID; + __pthread_key_invalid_count ++; + } + + __pthread_mutex_unlock (&__pthread_key_lock); + + return err; +} diff --git a/sysdeps/hurd/pt-key.h b/sysdeps/hurd/pt-key.h new file mode 100644 index 00000000..739fbbad --- /dev/null +++ b/sysdeps/hurd/pt-key.h @@ -0,0 +1,76 @@ +/* pthread_key internal declatations for the Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#define PTHREAD_KEY_MEMBERS \ + ihash_t thread_specifics; + +#define PTHREAD_KEY_INVALID (void *) (-1) + + +/* __PTHREAD_KEY_DESTRUCTORS is an array of destructors with + __PTHREAD_KEY_SIZE elements. If an element with index less than + __PTHREAD_KEY_COUNT is invalid, it shall contain the value + PTHREAD_KEY_INVALID which shall be distinct from NULL. + + Normally, we just add new keys to the end of the array and realloc + it as necessary. The pthread_key_create routine may decide to + rescan the array if __PTHREAD_KEY_FREE is large. */ +extern void (**__pthread_key_destructors) (void *arg); +extern int __pthread_key_size; +extern int __pthread_key_count; +/* Number of invalid elements in the array. Does not include elements + for which memory has been allocated but which have not yet been + used (i.e. those elements with indexes greater than + __PTHREAD_KEY_COUNT). */ +extern int __pthread_key_invalid_count; + +/* Protects the above variables. This must be a recursive lock: the + destructors may call pthread_key_delete. */ +extern pthread_mutex_t __pthread_key_lock; + +#include + +static inline void +__pthread_key_lock_ready (void) +{ + static pthread_once_t o = PTHREAD_ONCE_INIT; + + void do_init (void) + { + int err; + pthread_mutexattr_t attr; + + err = pthread_mutexattr_init (&attr); + assert_perror (err); + + err = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); + assert_perror (err); + + err = pthread_mutex_init (&__pthread_key_lock, &attr); + assert_perror (err); + + err = pthread_mutexattr_destroy (&attr); + assert_perror (err); + } + + pthread_once (&o, do_init); +} diff --git a/sysdeps/hurd/pt-kill.c b/sysdeps/hurd/pt-kill.c new file mode 100644 index 00000000..f970e065 --- /dev/null +++ b/sysdeps/hurd/pt-kill.c @@ -0,0 +1,49 @@ +/* pthread_kill. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +int +pthread_kill (pthread_t thread, int sig) +{ + struct __pthread *pthread; + struct hurd_signal_detail detail; + struct hurd_sigstate *ss; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + ss = _hurd_thread_sigstate (pthread->kernel_thread); + assert (ss); + + detail.exc = 0; + detail.code = sig; + detail.error = 0; + + _hurd_raise_signal (ss, sig, &detail); + + return 0; +} diff --git a/sysdeps/hurd/pt-setspecific.c b/sysdeps/hurd/pt-setspecific.c new file mode 100644 index 00000000..bd752250 --- /dev/null +++ b/sysdeps/hurd/pt-setspecific.c @@ -0,0 +1,43 @@ +/* pthread_setspecific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_setspecific (pthread_key_t key, const void *value) +{ + error_t err; + struct __pthread *self = _pthread_self (); + + if (! self->thread_specifics) + { + err = ihash_create (&self->thread_specifics); + if (err) + return ENOMEM; + } + + err = ihash_add (self->thread_specifics, key, (void *) value, 0); + if (err) + return ENOMEM; + + return 0; +} diff --git a/sysdeps/i386/bits/atomic.h b/sysdeps/i386/bits/atomic.h new file mode 100644 index 00000000..0dfc1f60 --- /dev/null +++ b/sysdeps/i386/bits/atomic.h @@ -0,0 +1,66 @@ +/* Atomic operations. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +typedef __volatile int __atomic_t; + +static inline void +__atomic_inc (__atomic_t *__var) +{ + __asm__ __volatile ("lock; incl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline void +__atomic_dec (__atomic_t *__var) +{ + __asm__ __volatile ("lock; decl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline int +__atomic_dec_and_test (__atomic_t *__var) +{ + unsigned char __ret; + + __asm__ __volatile ("lock; decl %0; sete %1" + : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); + return __ret != 0; +} + +/* We assume that an __atomicptr_t is only used for pointers to + word-aligned objects, and use the lowest bit for a simple lock. */ +typedef __volatile int * __atomicptr_t; + +/* Actually we don't implement that yet, and assume that we run on + something that has the i486 instruction set. */ +static inline int +__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, + void * __newval) +{ + char __ret; + int __dummy; + + __asm__ __volatile ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (__ret), "=m" (*__ptr), "=a" (__dummy) + : "r" (__newval), "m" (*__ptr), "a" (__oldval)); + return __ret; +} + +#endif diff --git a/sysdeps/i386/bits/memory.h b/sysdeps/i386/bits/memory.h new file mode 100644 index 00000000..201305b9 --- /dev/null +++ b/sysdeps/i386/bits/memory.h @@ -0,0 +1,40 @@ +/* Memory barrier operations. i386 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MEMORY_H +#define _BITS_MEMORY_H 1 + +/* Prevent read and write reordering across this function. */ +inline void +__memory_barrier (void) +{ + int i; + + /* Any lock'ed instruction will do. We just do a simple + increment. */ + __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i)); +} + +/* Prevent read reordering across this function. */ +#define __memory_read_barrier __memory_barrier + +/* Prevent write reordering across this function. */ +#define __memory_write_barrier __memory_barrier + +#endif diff --git a/sysdeps/i386/bits/spin-lock.h b/sysdeps/i386/bits/spin-lock.h new file mode 100644 index 00000000..175656ef --- /dev/null +++ b/sysdeps/i386/bits/spin-lock.h @@ -0,0 +1,103 @@ +/* Machine-specific definitions for spin locks. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __volatile int __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE extern __inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + int __locked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__locked), "=m" (*__lock) : "0" (1)); + return __locked ? __EBUSY : 0; +} + +extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +extern inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + int __unlocked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0)); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/sysdeps/i386/machine-sp.h b/sysdeps/i386/machine-sp.h new file mode 100644 index 00000000..536f6902 --- /dev/null +++ b/sysdeps/i386/machine-sp.h @@ -0,0 +1,31 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994,97,2001 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + void *__sp__; \ + __asm__ ("movl %%esp, %0" : "=r" (__sp__)); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/sysdeps/i386/pt-machdep.h b/sysdeps/i386/pt-machdep.h new file mode 100644 index 00000000..6d456367 --- /dev/null +++ b/sysdeps/i386/pt-machdep.h @@ -0,0 +1,29 @@ +/* Machine dependent pthreads internal defenitions. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */ diff --git a/sysdeps/l4/hurd/i386/pt-machdep.c b/sysdeps/l4/hurd/i386/pt-machdep.c new file mode 100644 index 00000000..dbf5cd7e --- /dev/null +++ b/sysdeps/l4/hurd/i386/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Nothing to do. */ diff --git a/sysdeps/l4/hurd/i386/pt-setup.c b/sysdeps/l4/hurd/i386/pt-setup.c new file mode 100644 index 00000000..fe77d533 --- /dev/null +++ b/sysdeps/l4/hurd/i386/pt-setup.c @@ -0,0 +1,72 @@ +/* Setup thread stack. Hurd/i386 version. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- */ + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg) +{ + L4_Word_t *top; + + /* Calculate top of the new stack. */ + top = (L4_Word_t *) ((L4_Word_t) thread->stackaddr + thread->stacksize); + + if (start_routine) + { + /* Set up call frame. */ + *--top = (L4_Word_t) arg; /* Argument to START_ROUTINE. */ + *--top = (L4_Word_t) start_routine; + *--top = 0; /* Fake return address. */ + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + if (L4_SameThreads (thread->threadid, L4_Myself ())) + L4_Set_MyUserDefinedHandle (thread); + else + L4_Set_UserDefinedHandle (thread->threadid, thread); + + return 0; +} diff --git a/sysdeps/l4/hurd/pt-sysdep.c b/sysdeps/l4/hurd/pt-sysdep.c new file mode 100644 index 00000000..265592ca --- /dev/null +++ b/sysdeps/l4/hurd/pt-sysdep.c @@ -0,0 +1,58 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Forward. */ +static void *init_routine (void); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +void *(*_pthread_init_routine)(void) = &init_routine; + +/* This function is called from the Hurd-specific startup code. It + should return a new stack pointer for the main thread. The caller + will switch to this new stack before doing anything serious. */ +static void * +init_routine (void) +{ + struct __pthread *thread; + int err; + + /* Initialize the library. */ + __pthread_initialize (); + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, 0, 0); + assert_perror (err); + + __pthread_initialize (); + + /* Decrease the number of threads, to take into account that the + signal thread (which will be created by the startup code when we + return from here) shouldn't be seen as a user thread. */ +#warning Need to implement the signal thread. + // __pthread_total--; + + return (void *) thread->mcontext.sp; +} diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h new file mode 100644 index 00000000..e37beefa --- /dev/null +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -0,0 +1,50 @@ +/* Internal defenitions for pthreads library. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include +#include +#include + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size. */ +#define PTHREAD_STACK_DEFAULT (PAGE_SIZE) + +#define PTHREAD_SYSDEP_MEMBERS \ + L4_ThreadId_t threadid; \ + L4_Word_t my_errno; + +extern inline struct __pthread * +_pthread_self (void) +{ + return (struct __pthread *) L4_MyUserDefinedHandle (); +} + +extern inline void +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + /* XXX: can only implement this once we have a working memory manager. */ + return; +} + +#endif /* pt-sysdep.h */ diff --git a/sysdeps/l4/pt-block.c b/sysdeps/l4/pt-block.c new file mode 100644 index 00000000..050c6947 --- /dev/null +++ b/sysdeps/l4/pt-block.c @@ -0,0 +1,29 @@ +/* Block a thread. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + L4_Receive (L4_anylocalthread); +} diff --git a/sysdeps/l4/pt-docancel.c b/sysdeps/l4/pt-docancel.c new file mode 100644 index 00000000..9a3bb26c --- /dev/null +++ b/sysdeps/l4/pt-docancel.c @@ -0,0 +1,51 @@ +/* Cancel a thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + assert (p->cancel_pending = 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + if (L4_SameThreads (L4_Myself (), p->threadid)) + call_exit (); + else + { + L4_Word_t dummy; + L4_ThreadId_t dummy_id; + + /* Change the ip of the target thread to make it exit. */ + L4_ExchangeRegisters (p->threadid, (1 << 4), 0, call_exit, + 0, 0, L4_nilthread, + &dummy, &dummy, &dummy, &dummy, &dummy, + &dummy_id); + } + + return 0; +} diff --git a/sysdeps/l4/pt-stack-alloc.c b/sysdeps/l4/pt-stack-alloc.c new file mode 100644 index 00000000..e28d5310 --- /dev/null +++ b/sysdeps/l4/pt-stack-alloc.c @@ -0,0 +1,70 @@ +/* Allocate a new stack. L4 Hurd version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +#define __pthread_stacksize __pthread_default_attr.stacksize + +#include +#include + +static void * +allocate_page (void) +{ + L4_Fpage_t p; + /* The Kernel Interface page. */ + static L4_KernelInterfacePage_t *kip; + + if (! kip) + kip = L4_GetKernelInterface (); + +#define sigma0_tid() (L4_GlobalId (kip->ThreadInfo.X.UserBase, 1)) + p = L4_Sigma0_GetPage (sigma0_tid (), + L4_Fpage_Set_Attrs (L4_FpageLog2 (-1UL << 10, + PAGE_SHIFT), + L4_FullyAccessible)); + p.raw &= ~0x3ff; + + printf ("%s: Allocated page %x\n", + __FUNCTION__, p.raw); + + return (void *) p.raw; +} + + +/* Allocate a new stack of size STACKSIZE. If successfull, store the + address of the newly allocated stack in *STACKADDR and return 0. + Otherwise return an error code (EINVAL for an invalid stack size, + EAGAIN if the system lacked the necessary resources to allocate a + new stack). */ +int +__pthread_stack_alloc (void **stackaddr, size_t stacksize) +{ + if (stacksize != __pthread_stacksize) + return EINVAL; + + *stackaddr = allocate_page (); + if (! *stackaddr) + return EAGAIN; + + return 0; +} diff --git a/sysdeps/l4/pt-start.c b/sysdeps/l4/pt-start.c new file mode 100644 index 00000000..5a506998 --- /dev/null +++ b/sysdeps/l4/pt-start.c @@ -0,0 +1,103 @@ +/* Start thread. L4 Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +#include "task_client.h" + +extern L4_ThreadId_t __system_pager; +extern L4_ThreadId_t __task_server; + +#ifndef WORKING_EXREGS +static void +send_startup_ipc (L4_ThreadId_t id, L4_Word_t ip, L4_Word_t sp) +{ + L4_Msg_t msg; + + printf ("%s: Sending startup message to %x, " + "(ip=%x, sp=%x)\n", + __FUNCTION__, * (L4_Word_t *) &id, ip, sp); + + L4_Clear (&msg); +#ifdef HAVE_PROPAGATION + L4_Set_VirtualSender (pager_tid); + L4_Set_Propagation (&msg.tag); +#endif + L4_Append_Word (&msg, ip); + L4_Append_Word (&msg, sp); +#ifndef HAVE_PROPAGATION + L4_Append_Word (&msg, *(L4_Word_t *) &id); + id = __system_pager; +#if 0 + DODEBUG (2, printf ("%s: Redirecting start request to pager (%x).\n", + __FUNCTION__, * (L4_Word_t *) &id)); +#endif +#endif + L4_LoadMsg (&msg); + L4_Send (id); +} +#endif + +/* Start THREAD. We allocate all system-specific resources, including + a kernel thread, set it up, and get it running. */ +int +__pthread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + /* The main thread is already running: do nothing. */ + { + assert (__pthread_total == 1); + thread->threadid = __mach_thread_self (); + } + else + { + CORBA_Environment env; + + env = idl4_default_environment; + err = thread_create (__task_server, + L4_Version (L4_Myself ()), + * (L4_Word_t *) &__system_pager, + (L4_Word_t *) &thread->threadid, &env); + if (err) + return EAGAIN; + + env = idl4_default_environment; + err = thread_resume (__task_server, + * (L4_Word_t *) &thread->threadid, + &env); + assert (! err); + +#ifndef WORKING_EXREGS + L4_AbortIpc_and_stop (thread->threadid); + L4_Start_SpIp (thread->threadid, (L4_Word_t) thread->mcontext.sp, + (L4_Word_t) thread->mcontext.pc); +#endif + send_startup_ipc (thread->threadid, (L4_Word_t) thread->mcontext.pc, + (L4_Word_t) thread->mcontext.sp); + + } + + return 0; +} diff --git a/sysdeps/l4/pt-thread-alloc.c b/sysdeps/l4/pt-thread-alloc.c new file mode 100644 index 00000000..a9d5e212 --- /dev/null +++ b/sysdeps/l4/pt-thread-alloc.c @@ -0,0 +1,52 @@ +/* Start thread. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 1); + thread->thread_id = L4_Myself (); + } + else + { + CORBA_Environment env; + + env = idl4_default_environment; + err = thread_create (__task_server, + L4_Version (L4_Myself ()), + * (L4_Word_t *) &__system_pager, + (L4_Word_t *) &thread->threadid, &env); + if (err) + return EAGAIN; + } + + return 0; +} diff --git a/sysdeps/l4/pt-thread-halt.c b/sysdeps/l4/pt-thread-halt.c new file mode 100644 index 00000000..04d622f4 --- /dev/null +++ b/sysdeps/l4/pt-thread-halt.c @@ -0,0 +1,38 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +extern L4_ThreadId_t __task_server; + +/* Deallocate the kernel thread resources associated with THREAD. */ +void +__pthread_thread_halt (struct __pthread *thread) +{ + CORBA_Environment env = idl4_default_environment; + L4_Word_t *t = (L4_Word_t *) &thread->threadid; + + assert (*t); + assert (thread_terminate (__task_server, *t, &env)); + *t = 0; +} diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c new file mode 100644 index 00000000..c428d290 --- /dev/null +++ b/sysdeps/l4/pt-thread-start.c @@ -0,0 +1,92 @@ +/* Start thread. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +#include "task_client.h" + +extern L4_ThreadId_t __system_pager; +extern L4_ThreadId_t __task_server; + +#ifndef WORKING_EXREGS +static void +send_startup_ipc (L4_ThreadId_t id, L4_Word_t ip, L4_Word_t sp) +{ + L4_Msg_t msg; + + printf ("%s: Sending startup message to %x, " + "(ip=%x, sp=%x)\n", + __FUNCTION__, * (L4_Word_t *) &id, ip, sp); + + L4_Clear (&msg); +#ifdef HAVE_PROPAGATION + L4_Set_VirtualSender (pager_tid); + L4_Set_Propagation (&msg.tag); +#endif + L4_Append_Word (&msg, ip); + L4_Append_Word (&msg, sp); +#ifndef HAVE_PROPAGATION + L4_Append_Word (&msg, *(L4_Word_t *) &id); + id = __system_pager; +#if 0 + DODEBUG (2, printf ("%s: Redirecting start request to pager (%x).\n", + __FUNCTION__, * (L4_Word_t *) &id)); +#endif +#endif + L4_LoadMsg (&msg); + L4_Send (id); +} +#endif + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 1); + assert (thread->thread_id == L4_Myself ()); + } + else + { + env = idl4_default_environment; + err = thread_resume (__task_server, + * (L4_Word_t *) &thread->threadid, + &env); + assert (! err); + +#ifndef WORKING_EXREGS + L4_AbortIpc_and_stop (thread->threadid); + L4_Start_SpIp (thread->threadid, (L4_Word_t) thread->mcontext.sp, + (L4_Word_t) thread->mcontext.pc); +#endif + send_startup_ipc (thread->threadid, (L4_Word_t) thread->mcontext.pc, + (L4_Word_t) thread->mcontext.sp); + + } + + return 0; +} diff --git a/sysdeps/l4/pt-wakeup.c b/sysdeps/l4/pt-wakeup.c new file mode 100644 index 00000000..7b00e4f6 --- /dev/null +++ b/sysdeps/l4/pt-wakeup.c @@ -0,0 +1,29 @@ +/* Wakeup a thread. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + L4_Send (thread->threadid); +} diff --git a/sysdeps/mach/bits/spin-lock.h b/sysdeps/mach/bits/spin-lock.h new file mode 100644 index 00000000..f295df7a --- /dev/null +++ b/sysdeps/mach/bits/spin-lock.h @@ -0,0 +1,97 @@ +/* Definitions of user-visible names for spin locks. + Copyright (C) 1994, 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. */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include +#include /* This does all the work. */ + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __spin_lock_t __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +#ifndef __SPIN_LOCK_INITIALIZER +#error __SPIN_LOCK_INITIALIZER undefined: should be defined by . +#endif + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE extern __inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + return __spin_try_lock (__lock) ? 0 : __EBUSY; +} + +extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +extern inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + __spin_unlock (__lock); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/sysdeps/mach/hurd/i386/pt-machdep.c b/sysdeps/mach/hurd/i386/pt-machdep.c new file mode 100644 index 00000000..face46c5 --- /dev/null +++ b/sysdeps/mach/hurd/i386/pt-machdep.c @@ -0,0 +1,54 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +int +__thread_set_pcsp (thread_t thread, + int set_ip, void *ip, + int set_sp, void *sp) +{ + error_t err; + struct i386_thread_state state; + mach_msg_type_number_t state_count; + + state_count = i386_THREAD_STATE_COUNT; + + err = __thread_get_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, &state_count); + if (err) + return err; + + if (set_sp) + state.uesp = (unsigned int) sp; + if (set_ip) + state.eip = (unsigned int) ip; + + err = __thread_set_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, + i386_THREAD_STATE_COUNT); + if (err) + return err; + + return 0; +} diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c new file mode 100644 index 00000000..a2495046 --- /dev/null +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -0,0 +1,99 @@ +/* Setup thread stack. Hurd/i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- + | | + | Fast TSD | + | | + ----------------- + + We need to reserve __hurd_threadvar_max `unsigned long int's' of + (fast) thread-specific data (TSD) for the Hurd. */ + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg) +{ + error_t err; + uintptr_t *bottom, *top; + + /* Calculate the top of the new stack. */ + bottom = thread->stackaddr; + top = (uintptr_t *) ((uintptr_t) bottom + thread->stacksize); + + /* Next, make room for the TSDs. */ + top -= __hurd_threadvar_max; + + /* Save the self pointer. */ + top[_HURD_THREADVAR_THREAD] = thread; + + if (start_routine) + { + /* And then the call frame. */ + *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + *--top = (uintptr_t) start_routine; + *--top = 0; /* Fake return address. */ + } + + if (thread->guardsize) + { + err = __vm_protect (__mach_task_self (), (vm_address_t) bottom, + thread->guardsize, 0, 0); + assert_perror (err); + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + error_t err; + + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + if (thread->kernel_thread != __mach_thread_self ()) + { + err = __thread_set_pcsp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/hurd/pt-attr-setstackaddr.c b/sysdeps/mach/hurd/pt-attr-setstackaddr.c new file mode 100644 index 00000000..1225ed5b --- /dev/null +++ b/sysdeps/mach/hurd/pt-attr-setstackaddr.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstackaddr. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr) +{ + if ((long) stackaddr & (__pthread_stacksize - 1)) + return EINVAL; + + attr->stackaddr = stackaddr; + return 0; +} diff --git a/sysdeps/mach/hurd/pt-attr-setstacksize.c b/sysdeps/mach/hurd/pt-attr-setstacksize.c new file mode 100644 index 00000000..6471c0a3 --- /dev/null +++ b/sysdeps/mach/hurd/pt-attr-setstacksize.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstacksize. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + if (stacksize != __pthread_stacksize) + return EINVAL; + + attr->stacksize = stacksize; + return 0; +} diff --git a/sysdeps/mach/hurd/pt-docancel.c b/sysdeps/mach/hurd/pt-docancel.c new file mode 100644 index 00000000..58524ff0 --- /dev/null +++ b/sysdeps/mach/hurd/pt-docancel.c @@ -0,0 +1,57 @@ +/* Cancel a thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + assert (p->cancel_pending = 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + if (__mach_thread_self () == p->kernel_thread) + call_exit (); + else + { + error_t err; + + err = __thread_suspend (p->kernel_thread); + assert_perror (err); + + err = __thread_abort (p->kernel_thread); + assert_perror (err); + + err = __thread_set_pcsp (p->kernel_thread, + 1, (void *) call_exit, 0, 0); + assert_perror (err); + + err = __thread_resume (p->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/hurd/pt-sigstate-destroy.c b/sysdeps/mach/hurd/pt-sigstate-destroy.c new file mode 100644 index 00000000..8e56c5cf --- /dev/null +++ b/sysdeps/mach/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ + /* Nothing to do. */ +} diff --git a/sysdeps/mach/hurd/pt-sigstate-init.c b/sysdeps/mach/hurd/pt-sigstate-init.c new file mode 100644 index 00000000..da5a9455 --- /dev/null +++ b/sysdeps/mach/hurd/pt-sigstate-init.c @@ -0,0 +1,37 @@ +/* Initialize the signal state. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + void **location = + (void *) __hurd_threadvar_location_from_sp (_HURD_THREADVAR_SIGSTATE, + thread->stackaddr); + + /* The real initialization happens internally in glibc the first + time that _hurd_thead_sigstate is called. */ + *location = 0; + + return 0; +} diff --git a/sysdeps/mach/hurd/pt-sigstate.c b/sysdeps/mach/hurd/pt-sigstate.c new file mode 100644 index 00000000..68c79c5b --- /dev/null +++ b/sysdeps/mach/hurd/pt-sigstate.c @@ -0,0 +1,69 @@ +/* Set a thread's signal state. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending) +{ + error_t err = 0; + struct hurd_sigstate *ss; + + ss = _hurd_thread_sigstate (thread->kernel_thread); + assert (ss); + + __pthread_spin_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + switch (how) + { + case SIG_BLOCK: + ss->blocked |= *set; + break; + + case SIG_SETMASK: + ss->blocked = *set; + break; + + case SIG_UNBLOCK: + ss->blocked &= ~*set; + break; + + default: + err = EINVAL; + break; + } + + if (! err && clear_pending) + __sigemptyset (&ss->pending); + + __pthread_spin_unlock (&ss->lock); + + return err; +} diff --git a/sysdeps/mach/hurd/pt-sysdep.c b/sysdeps/mach/hurd/pt-sysdep.c new file mode 100644 index 00000000..b42fe255 --- /dev/null +++ b/sysdeps/mach/hurd/pt-sysdep.c @@ -0,0 +1,72 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include +#include + +#include + +#include + +/* Forward. */ +static int init_routine (void); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +int (*_cthread_init_routine)(void) = &init_routine; + +/* This function is called from the Hurd-specific startup code. It + should return a new stack pointer for the main thread. The caller + will switch to this new stack before doing anything serious. */ +static int +init_routine (void) +{ + struct __pthread *thread; + int err; + + /* Initialize the library. */ + __pthread_initialize (); + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, 0, 0); + assert_perror (err); + + ((void **) (__hurd_threadvar_stack_offset))[_HURD_THREADVAR_THREAD] + = thread; + + /* Decrease the number of threads, to take into account that the + signal thread (which will be created by the glibc startup code + when we return from here) shouldn't be seen as a user thread. */ + __pthread_total--; + + /* Make MiG code thread aware. */ + __mig_init (thread->stackaddr); + + /* Make sure we can find the per-thread variables. */ + __hurd_threadvar_stack_mask = ~(__pthread_default_attr.stacksize - 1); + __hurd_threadvar_stack_offset + = (__pthread_default_attr.stacksize + - __hurd_threadvar_max * sizeof (uintptr_t)); + + return (int) thread->mcontext.sp; +} diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h new file mode 100644 index 00000000..3addef7c --- /dev/null +++ b/sysdeps/mach/hurd/pt-sysdep.h @@ -0,0 +1,65 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include + +#include + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) + +#define PTHREAD_SYSDEP_MEMBERS \ + thread_t kernel_thread; \ + mach_msg_header_t wakeupmsg; + +#define _HURD_THREADVAR_THREAD _HURD_THREADVAR_DYNAMIC_USER + +#define _pthread_self() \ + ({ \ + struct __pthread *thread; \ + \ + assert (__pthread_threads); \ + thread = *(struct __pthread **) \ + __hurd_threadvar_location (_HURD_THREADVAR_THREAD); \ + \ + assert (thread); \ + assert (thread->kernel_thread == __mach_thread_self ()); \ + thread; \ + }) + +extern inline void +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize); +} + +/* Change thread THREAD's program counter to PC if SET_PC is true and + its stack pointer to SP if SET_IP is true. */ +extern int __thread_set_pcsp (thread_t thread, + int set_pc, void *pc, + int set_sp, void *sp); + + +#endif /* pt-sysdep.h */ diff --git a/sysdeps/mach/pt-block.c b/sysdeps/mach/pt-block.c new file mode 100644 index 00000000..a947b27c --- /dev/null +++ b/sysdeps/mach/pt-block.c @@ -0,0 +1,39 @@ +/* Block a thread. Mach version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +#include + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + mach_msg_header_t msg; + error_t err; + + err = __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg, + thread->wakeupmsg.msgh_remote_port, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} diff --git a/sysdeps/mach/pt-spin.c b/sysdeps/mach/pt-spin.c new file mode 100644 index 00000000..010faca8 --- /dev/null +++ b/sysdeps/mach/pt-spin.c @@ -0,0 +1,35 @@ +/* Spin locks. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* In glibc. */ +extern void __spin_lock_solid (__pthread_spinlock_t *lock); + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + __spin_lock_solid (lock); + return 0; +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/sysdeps/mach/pt-stack-alloc.c b/sysdeps/mach/pt-stack-alloc.c new file mode 100644 index 00000000..0956fc7d --- /dev/null +++ b/sysdeps/mach/pt-stack-alloc.c @@ -0,0 +1,74 @@ +/* Allocate a new stack. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +#include + +#define __pthread_stacksize __pthread_default_attr.stacksize + +/* The next address to use for stack allocation. */ +static vm_address_t next_stack_base = VM_MIN_ADDRESS; + + +/* Allocate a new stack of size STACKSIZE. If successful, store the + address of the newly allocated stack in *STACKADDR and return 0. + Otherwise return an error code (EINVAL for an invalid stack size, + EAGAIN if the system lacked the necessary resources to allocate a + new stack). */ +int +__pthread_stack_alloc (void **stackaddr, size_t stacksize) +{ + vm_offset_t base; + int i = 0; + + if (stacksize != __pthread_stacksize) + return EINVAL; + + get_stack: + i ++; + for (base = next_stack_base; + base < VM_MAX_ADDRESS + && __vm_allocate (__mach_task_self (), &base, + __pthread_stacksize, FALSE) != KERN_SUCCESS; + base += __pthread_stacksize) + ; + + if (base >= VM_MAX_ADDRESS) + { + if (i == 1) + { + next_stack_base = VM_MIN_ADDRESS; + goto get_stack; + } + else + return EAGAIN; + } + + if (base >= VM_MAX_ADDRESS) + return EAGAIN; + + next_stack_base = base + __pthread_stacksize; + + (*stackaddr) = (void *) base; + return 0; +} diff --git a/sysdeps/mach/pt-start.c b/sysdeps/mach/pt-start.c new file mode 100644 index 00000000..5e8cd5aa --- /dev/null +++ b/sysdeps/mach/pt-start.c @@ -0,0 +1,106 @@ +/* Start thread. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +#include + +/* Prepare a wakeup message. */ +static error_t +create_wakeupmsg (struct __pthread *thread) +{ + kern_return_t err; + + /* Build wakeup message. */ + thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); + thread->wakeupmsg.msgh_size = 0; + + err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &thread->wakeupmsg.msgh_remote_port); + if (err) + return EAGAIN; + + thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL; + thread->wakeupmsg.msgh_seqno = 0; + thread->wakeupmsg.msgh_id = 0; + + err = __mach_port_insert_right (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port, + thread->wakeupmsg.msgh_remote_port, + MACH_MSG_TYPE_MAKE_SEND); + if (err) + { + __mach_port_deallocate (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + return EAGAIN; + } + + return 0; +} + +/* Start THREAD. We allocate all system-specific resources, including + a kernel thread, set it up, and get it running. */ +int +__pthread_start (struct __pthread *thread) +{ + error_t err; + + err = create_wakeupmsg (thread); + if (err) + return err; + + /* If there are no pthreads in the system then the pthread library + is bootstrapping and the main thread must create initialize + itself. The thread itself is already running, it just has no + pthread context. We want to reuse what it already has (including + the kernel thread), however, we must determine which thread is + the main thread. + + We cannot test if __pthread_total is one as we later decrement it + before creating the signal thread. Currently, we check if + __pthread_num_threads--the number of allocated thread + structures--is one. __pthread_alloc has already been called in + __pthread_create_internal for us. This predicate could be + improved, however, it is sufficient for now. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 1); + thread->kernel_thread = __mach_thread_self (); + } + else + { + err = __thread_create (__mach_task_self (), &thread->kernel_thread); + if (err) + return EAGAIN; + + err = __thread_set_pcsp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp); + assert_perror (err); + + err = __thread_resume (thread->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c new file mode 100644 index 00000000..af929533 --- /dev/null +++ b/sysdeps/mach/pt-thread-alloc.c @@ -0,0 +1,98 @@ +/* Start thread. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +#include + +/* Prepare a wakeup message. */ +static error_t +create_wakeupmsg (struct __pthread *thread) +{ + kern_return_t err; + + /* Build wakeup message. */ + thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); + thread->wakeupmsg.msgh_size = 0; + + err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &thread->wakeupmsg.msgh_remote_port); + if (err) + return EAGAIN; + + thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL; + thread->wakeupmsg.msgh_seqno = 0; + thread->wakeupmsg.msgh_id = 0; + + err = __mach_port_insert_right (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port, + thread->wakeupmsg.msgh_remote_port, + MACH_MSG_TYPE_MAKE_SEND); + if (err) + { + __mach_port_deallocate (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + return EAGAIN; + } + + return 0; +} + +/* Allocate any resouces for THREAD. The new kernel thread should not + be eligible to be scheduled. */ +int +__pthread_thread_alloc (struct __pthread *thread) +{ + error_t err; + + err = create_wakeupmsg (thread); + if (err) + return err; + + /* If there are no pthreads in the system then the pthread library + is bootstrapping and the main thread must create initialize + itself. The thread itself is already running, it just has not + pthread context. We want to reuse what it already has (including + the kernel thread), however, we must determine which thread is + the main thread. + + We cannot test if __pthread_total is one as we later decrement + before creating the signal thread. Currently, we check if + __pthread_num_threads--the number of allocated thread + structures--is one. __pthread_alloc has already been called in + __pthread_create_internal for us. This predicate could be improved, + however, it is sufficient for now. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 0); + thread->kernel_thread = __mach_thread_self (); + } + else + { + err = __thread_create (__mach_task_self (), &thread->kernel_thread); + if (err) + return EAGAIN; + } + + return 0; +} diff --git a/sysdeps/mach/pt-thread-halt.c b/sysdeps/mach/pt-thread-halt.c new file mode 100644 index 00000000..84e6ac8e --- /dev/null +++ b/sysdeps/mach/pt-thread-halt.c @@ -0,0 +1,39 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + + +/* Deallocate the kernel thread resources associated with THREAD. */ +void +__pthread_thread_halt (struct __pthread *thread) +{ + error_t err; + + err = __mach_port_deallocate (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + assert_perror (err); + + err = __thread_terminate (thread->kernel_thread); + assert_perror (err); +} diff --git a/sysdeps/mach/pt-thread-start.c b/sysdeps/mach/pt-thread-start.c new file mode 100644 index 00000000..eade5098 --- /dev/null +++ b/sysdeps/mach/pt-thread-start.c @@ -0,0 +1,45 @@ +/* Start thread. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + { + /* The main thread is already running: do nothing. */ + assert (__pthread_total == 1); + assert (thread->kernel_thread == __mach_thread_self ()); + } + else + { + err = __thread_resume (thread->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/pt-timedblock.c b/sysdeps/mach/pt-timedblock.c new file mode 100644 index 00000000..6324ae76 --- /dev/null +++ b/sysdeps/mach/pt-timedblock.c @@ -0,0 +1,60 @@ +/* Block a thread with a timeout. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include +#include + +#include + +/* Block THREAD. */ +error_t +__pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime) +{ + error_t err; + mach_msg_header_t msg; + mach_msg_timeout_t ms; + struct timeval now; + + /* We have an absolute time and now we have to convert it to a + relative time. Arg. */ + + err = gettimeofday(&now, NULL); + assert (! err); + + ms = abstime->tv_sec * 1000 + (abstime->tv_nsec + 999999) / 1000000 + - now.tv_sec * 1000 - (now.tv_usec + 999) / 1000; + + if (ms <= 0) + return ETIMEDOUT; + + err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, + sizeof msg, thread->wakeupmsg.msgh_remote_port, + ms, MACH_PORT_NULL); + if (err == EMACH_RCV_TIMED_OUT) + return ETIMEDOUT; + + assert_perror (err); + return 0; +} diff --git a/sysdeps/mach/pt-wakeup.c b/sysdeps/mach/pt-wakeup.c new file mode 100644 index 00000000..8ab10fb8 --- /dev/null +++ b/sysdeps/mach/pt-wakeup.c @@ -0,0 +1,38 @@ +/* Wakeup a thread. Mach version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +#include + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + error_t err; + + err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG, + sizeof (mach_msg_header_t), 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} diff --git a/sysdeps/posix/pt-spin.c b/sysdeps/posix/pt-spin.c new file mode 100644 index 00000000..cdc482c1 --- /dev/null +++ b/sysdeps/posix/pt-spin.c @@ -0,0 +1,53 @@ +/* Spin locks. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* The default for single processor machines; don't spin, it's + pointless. */ +#ifndef __PTHREAD_SPIN_COUNT +# define __PTHREAD_SPIN_COUNT 1 +#endif + +/* The number of times to spin while trying to lock a spin lock object + before yielding the processor. */ +int __pthread_spin_count = __PTHREAD_SPIN_COUNT; + + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + int i; + + while (1) + { + for (i = 0; i < __pthread_spin_count; i++) + { + if (__pthread_spin_trylock (lock) == 0) + return 0; + } + + __sched_yield (); + } +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/tests/.cvsignore b/tests/.cvsignore new file mode 100644 index 00000000..70845e08 --- /dev/null +++ b/tests/.cvsignore @@ -0,0 +1 @@ +Makefile.in diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 00000000..9509c957 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,29 @@ +CFLAGS=-Wall -g + +LDLIBS = -lpthread + +CHECK_SRC := test-1.c test-2.c test-3.c test-6.c test-7.c test-8.c \ + test-9.c test-10.c test-11.c test-12.c test-13.c test-14.c \ + test-15.c test-16.c + +CHECK_OBJS := $(addsuffix .o,$(basename $(notdir $(CHECK_SRC)))) +CHECK_PROGS := $(basename $(notdir $(CHECK_SRC))) \ + $(addsuffix -static, $(basename $(CHECK_SRC))) + +%-static: %.o + $(CC) -static $(CFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS) + +check: $(CHECK_OBJS) $(CHECK_PROGS) + for i in $(CHECK_PROGS); do \ + echo -n Running $$i...\ ; \ + if ./$$i 2>&1 > $$i.out; \ + then \ + echo Success.; \ + else \ + echo Failure.; \ + fi \ + done + +clean: + rm -f $(CHECK_OBJS) $(CHECK_PROGS) \ + $(addsuffix .out,$(basename $(notdir $(CHECK_PROGS)))) \ No newline at end of file diff --git a/tests/test-1.c b/tests/test-1.c new file mode 100644 index 00000000..86c7c97e --- /dev/null +++ b/tests/test-1.c @@ -0,0 +1,49 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#define THREADS 500 + +void * +foo (void *arg) +{ + pthread_mutex_t *mutex = arg; + pthread_mutex_lock (mutex); + pthread_mutex_unlock (mutex); + return mutex; +} + +int +main (int argc, char **argv) +{ + int i; + error_t err; + pthread_t tid[THREADS]; + pthread_mutex_t mutex[THREADS]; + + for (i = 0; i < THREADS; i ++) + { + mutex[i] = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock (&mutex[i]); + err = pthread_create (&tid[i], 0, foo, &mutex[i]); + if (err) + error (1, err, "pthread_create"); + sched_yield (); + } + + for (i = THREADS - 1; i >= 0; i --) + { + void *ret; + pthread_mutex_unlock (&mutex[i]); + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + assert (ret == &mutex[i]); + } + + return 0; +} diff --git a/tests/test-10.c b/tests/test-10.c new file mode 100644 index 00000000..bec05c14 --- /dev/null +++ b/tests/test-10.c @@ -0,0 +1,46 @@ +/* Test error checking mutexes. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + error_t err; + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + + err = pthread_mutexattr_init (&mattr); + if (err) + error (1, err, "pthread_mutexattr_init"); + + err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_ERRORCHECK); + if (err) + error (1, err, "pthread_mutexattr_settype"); + + err = pthread_mutex_init (&mutex, &mattr); + if (err) + error (1, err, "pthread_mutex_init"); + + err = pthread_mutexattr_destroy (&mattr); + if (err) + error (1, err, "pthread_mutexattr_destroy"); + + err = pthread_mutex_lock (&mutex); + assert (err == 0); + + err = pthread_mutex_lock (&mutex); + assert (err == EDEADLK); + + err = pthread_mutex_unlock (&mutex); + assert (err == 0); + + err = pthread_mutex_unlock (&mutex); + assert (err == EPERM); + + return 0; +} diff --git a/tests/test-11.c b/tests/test-11.c new file mode 100644 index 00000000..de779a40 --- /dev/null +++ b/tests/test-11.c @@ -0,0 +1,143 @@ +/* Test rwlocks. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 1 + +int a; +int b; + +/* Get a read lock and assert that a == b. */ +void * +test1 (void *arg) +{ + error_t err; + pthread_rwlock_t *lock = arg; + int i; + + for (i = 0; i < 200; i ++) + { + err = pthread_rwlock_rdlock (lock); + assert (err == 0); + + assert (a == b); + + sched_yield (); + + assert (a == b); + + err = pthread_rwlock_unlock (lock); + assert (err == 0); + } + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + pthread_rwlockattr_t attr; + pthread_rwlock_t lock; + int pshared; + + int i; + pthread_t tid[THREADS]; + void *ret; + + err = pthread_rwlockattr_init (&attr); + if (err) + error (1, err, "pthread_rwlockattr_init"); + + err = pthread_rwlockattr_getpshared (&attr, &pshared); + if (err) + error (1, err, "pthread_rwlockattr_getpshared"); + + /* Assert the default state as mandated by POSIX. */ + assert (pshared == PTHREAD_PROCESS_PRIVATE); + + err = pthread_rwlockattr_setpshared (&attr, pshared); + if (err) + error (1, err, "pthread_rwlockattr_setpshared"); + + err = pthread_rwlock_init (&lock, &attr); + if (err) + error (1, err, "pthread_rwlock_init"); + + err = pthread_rwlockattr_destroy (&attr); + if (err) + error (1, err, "pthread_rwlockattr_destroy"); + + /* Now test the lock. */ + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, test1, &lock); + if (err) + error (1, err, "pthread_create"); + } + + for (i = 0; i < 10; i ++) + { + sched_yield (); + + /* Get a write lock. */ + pthread_rwlock_wrlock (&lock); + /* Increment a and b giving other threads a chance to run in + between. */ + sched_yield (); + a ++; + sched_yield (); + b ++; + sched_yield (); + /* Unlock. */ + pthread_rwlock_unlock (&lock); + } + + for (i = 0; i < THREADS; i ++) + { + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + } + + /* Read lock it. */ + err = pthread_rwlock_tryrdlock (&lock); + assert (err == 0); + + /* Try to write lock it. It should fail with EBUSY. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == EBUSY); + + /* Drop the read lock. */ + err = pthread_rwlock_unlock (&lock); + assert (err == 0); + + /* Get a write lock. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == 0); + + /* Fail trying to acquire another write lock. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == EBUSY); + + /* Try to get a read lock which should also fail. */ + err = pthread_rwlock_tryrdlock (&lock); + assert (err == EBUSY); + + /* Unlock it. */ + err = pthread_rwlock_unlock (&lock); + assert (err == 0); + + + err = pthread_rwlock_destroy (&lock); + if (err) + error (1, err, "pthread_rwlock_destroy"); + + return 0; +} diff --git a/tests/test-12.c b/tests/test-12.c new file mode 100644 index 00000000..2b784908 --- /dev/null +++ b/tests/test-12.c @@ -0,0 +1,29 @@ +/* Test concurrency level. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + int i; + int err; + + i = pthread_getconcurrency (); + assert (i == 0); + + err = pthread_setconcurrency (-1); + assert (err == EINVAL); + + err = pthread_setconcurrency (4); + assert (err == 0); + + i = pthread_getconcurrency (); + assert (i == 4); + + return 0; +} diff --git a/tests/test-13.c b/tests/test-13.c new file mode 100644 index 00000000..13b09051 --- /dev/null +++ b/tests/test-13.c @@ -0,0 +1,66 @@ +/* Test condition attributes and pthread_cond_timedwait. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_condattr_t attr; + pthread_cond_t cond; + struct timespec ts; + pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + struct timeval before, after; + int diff; + + err = pthread_condattr_init (&attr); + if (err) + error (1, err, "pthread_condattr_init"); + + err = pthread_condattr_getpshared (&attr, &i); + if (err) + error (1, err, "pthread_condattr_getpshared"); + assert (i == PTHREAD_PROCESS_PRIVATE); + + err = pthread_condattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); + assert (err == 0); + + err = pthread_cond_init (&cond, &attr); + if (err) + error (1, err, "pthread_cond_init"); + + err = pthread_condattr_destroy (&attr); + if (err) + error (1, err, "pthread_condattr_destroy"); + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Starting wait @ %d\n", (int) before.tv_sec); + + pthread_mutex_lock (&m); + err = pthread_cond_timedwait (&cond, &m, &ts); + + gettimeofday (&after, 0); + + printf ("End wait @ %d (err = %d)\n", (int) after.tv_sec, err); + + assert (err == ETIMEDOUT); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_cond_timedwait waited %d us", diff); + + return 0; +} diff --git a/tests/test-14.c b/tests/test-14.c new file mode 100644 index 00000000..b1dbfa66 --- /dev/null +++ b/tests/test-14.c @@ -0,0 +1,44 @@ +/* Test pthread_mutex_timedlock. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + error_t err; + struct timespec ts; + pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + struct timeval before, after; + int diff; + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Starting wait @ %d\n", (int) before.tv_sec); + + pthread_mutex_lock (&m); + /* A default mutex shall dead lock if locked twice. As such we do + not need spawn a second thread. */ + err = pthread_mutex_timedlock (&m, &ts); + assert (err == ETIMEDOUT); + + gettimeofday (&after, 0); + + printf ("End wait @ %d\n", (int) after.tv_sec); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); + + return 0; +} diff --git a/tests/test-15.c b/tests/test-15.c new file mode 100644 index 00000000..173f8b6b --- /dev/null +++ b/tests/test-15.c @@ -0,0 +1,87 @@ +/* Test pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#define THREADS 10 + +pthread_rwlock_t rwlock; + +void * +test (void *arg) +{ + error_t err; + int foo = (int) arg; + struct timespec ts; + struct timeval before, after; + int diff; + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Thread %d starting wait @ %d\n", pthread_self (), + (int) before.tv_sec); + + if (foo % 2 == 0) + err = pthread_rwlock_timedrdlock (&rwlock, &ts); + else + err = pthread_rwlock_timedwrlock (&rwlock, &ts); + + assert (err == ETIMEDOUT); + + gettimeofday (&after, 0); + + printf ("Thread %d ending wait @ %d\n", pthread_self (), + (int) after.tv_sec); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + err = pthread_rwlock_init (&rwlock, 0); + if (err) + error (1, err, "pthread_rwlock_init"); + + /* Lock it so all the threads will block. */ + err = pthread_rwlock_wrlock (&rwlock); + assert (err == 0); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, test, (void *) i); + if (err) + error (1, err, "pthread_create"); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + return 0; +} diff --git a/tests/test-16.c b/tests/test-16.c new file mode 100644 index 00000000..b6a52d01 --- /dev/null +++ b/tests/test-16.c @@ -0,0 +1,71 @@ +/* Test pthread_kill.c. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +pthread_t testthread; + +int i; + +void * +test (void *arg) +{ + error_t err; + + printf ("test: %d\n", pthread_self ()); + + err = pthread_kill (pthread_self (), SIGINFO); + if (err) + error (1, err, "pthread_kill"); + + /* To avoid using condition variables in a signal handler. */ + while (i == 0) + sched_yield (); + + return 0; +} + +static void +handler (int sig, siginfo_t *info, void *context) +{ + assert (pthread_equal (pthread_self (), testthread)); + printf ("handler: %d\n", pthread_self ()); + i = 1; +} + +int +main (int argc, char **argv) +{ + error_t err; + struct sigaction sa; + void *ret; + + printf ("main: %d\n", pthread_self ()); + + sa.sa_handler = handler; + sa.sa_mask = 0; + sa.sa_flags = 0; + + err = sigaction (SIGINFO, &sa, 0); + if (err) + error (1, err, "sigaction"); + + err = pthread_create (&testthread, 0, test, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_join (testthread, &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + + return 0; +} diff --git a/tests/test-2.c b/tests/test-2.c new file mode 100644 index 00000000..701462e8 --- /dev/null +++ b/tests/test-2.c @@ -0,0 +1,39 @@ +/* Test detachability. */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +void * +thread (void *arg) +{ + while (1) + sched_yield (); +} + +int +main (int argc, char **argv) +{ + int err; + pthread_t tid; + void *ret; + + err = pthread_create (&tid, 0, thread, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_detach (tid); + if (err) + error (1, err, "pthread_detach"); + + err = pthread_detach (tid); + assert (err == EINVAL); + + err = pthread_join (tid, &ret); + assert (err == EINVAL); + + return 0; +} diff --git a/tests/test-3.c b/tests/test-3.c new file mode 100644 index 00000000..7db2e43f --- /dev/null +++ b/tests/test-3.c @@ -0,0 +1,55 @@ +/* Test the thread attribute get and set methods. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + error_t err; + pthread_attr_t attr; + + int i; + struct sched_param sp; + void *p; + size_t sz; + + err = pthread_attr_init (&attr); + assert_perror (err); + + err = pthread_attr_destroy (&attr); + assert_perror (err); + + err = pthread_attr_init (&attr); + assert_perror (err); + +#define TEST1(foo, rv, v) \ + err = pthread_attr_get##foo (&attr, rv); \ + assert_perror (err); \ + \ + err = pthread_attr_set##foo (&attr, v); \ + assert_perror (err); + +#define TEST(foo, rv, v) TEST1(foo, rv, v) + + TEST(inheritsched, &i, i); + TEST(schedparam, &sp, &sp); + TEST(schedpolicy, &i, i); + TEST(scope, &i, i); + TEST(stackaddr, &p, p); + TEST(detachstate, &i, i); + TEST(guardsize, &sz, sz); + TEST(stacksize, &sz, sz); + + err = pthread_attr_getstack (&attr, &p, &sz); + assert_perror (err); + + err = pthread_attr_setstack (&attr, p, sz); + assert_perror (err); + + return 0; +} diff --git a/tests/test-4.c b/tests/test-4.c new file mode 100644 index 00000000..de9c8fe4 --- /dev/null +++ b/tests/test-4.c @@ -0,0 +1,86 @@ +/* Test the stack guard. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +size_t stacksize; + +void * +thr (void *arg) +{ + int i; + char *foo; + + foo = alloca (3 * stacksize / 4); + for (i = 0; i < sizeof foo; i ++) + foo[i] = -1; + + return (void *) 1; +} + +int +main (int argc, char *argv[]) +{ + error_t err; + pid_t child; + + child = fork (); + switch (child) + { + case -1: + error (1, errno, "fork"); + break; + + case 0: + { + pthread_attr_t attr; + pthread_t tid; + void *ret; + + err = pthread_attr_init (&attr); + assert_perror (err); + + err = pthread_attr_getstacksize (&attr, &stacksize); + assert_perror (err); + + err = pthread_attr_setguardsize (&attr, stacksize / 2); + if (err == ENOTSUP) + { + printf ("Stack guard attribute not supported.\n"); + return 1; + } + assert_perror (err); + + err = pthread_create (&tid, &attr, thr, 0); + assert_perror (err); + + err = pthread_attr_destroy (&attr); + assert_perror (err); + + err = pthread_join (tid, &ret); + /* Should never be successful. */ + printf ("Thread did not segfault!?!\n"); + assert_perror (err); + return 0; + } + + default: + { + pid_t pid; + int status; + + pid = waitpid (child, &status, 0); + printf ("pid = %d; child = %d; status = %d\n", pid, child, status); + assert (pid == child); + assert (status != 0); + } + } + + return 0; +} diff --git a/tests/test-5.c b/tests/test-5.c new file mode 100644 index 00000000..0f5000b2 --- /dev/null +++ b/tests/test-5.c @@ -0,0 +1,75 @@ +/* Test signals. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +void * +thr (void *arg) +{ + * (int *)0 = 0; + return 0; +} + +int foobar; + +int +main (int argc, char *argv[]) +{ + error_t err; + pid_t child; + + struct rlimit limit; + + limit.rlim_cur = 0; + limit.rlim_max = 0; + + err = setrlimit (RLIMIT_CORE, &limit); + if (err) + error (1, err, "setrlimit"); + + child = fork (); + switch (child) + { + case -1: + error (1, errno, "fork"); + break; + + case 0: + { + pthread_t tid; + void *ret; + + err = pthread_create (&tid, 0, thr, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_join (tid, &ret); + assert_perror (err); + + /* Should have never returned. Our parent expects us to fail + thus we succeed and indicate the error. */ + return 0; + } + + default: + { + pid_t pid; + int status; + + pid = waitpid (child, &status, 0); + printf ("pid = %d; child = %d; status = %d\n", pid, child, status); + assert (pid == child); + assert (status != 0); + } + } + + return 0; +} diff --git a/tests/test-6.c b/tests/test-6.c new file mode 100644 index 00000000..98aa8ba7 --- /dev/null +++ b/tests/test-6.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 500 +#define WAITS 3 + +void * +dowait (void *arg) +{ + pthread_barrier_t *barrier = arg; + int ret; + + ret = pthread_barrier_wait (barrier); + printf ("%d ", pthread_self ()); + return (void *) ret; +} + +int +main (int argc, char **argv) +{ + pthread_barrierattr_t attr; + pthread_barrier_t barrier; + + int i, j; + error_t err; + pthread_t tid[THREADS]; + + int havesyncs; + + err = pthread_barrierattr_init (&attr); + if (err) + error (1, err, "pthread_barrierattr_init"); + + err = pthread_barrierattr_getpshared (&attr, &i); + if (err) + error (1, err, "pthread_barrierattr_getpshared"); + assert (i == PTHREAD_PROCESS_PRIVATE || i == PTHREAD_PROCESS_SHARED); + + err = pthread_barrierattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); + if (err) + error (1, err, "pthread_barrierattr_setpshared"); + + err = pthread_barrier_init (&barrier, &attr, THREADS + 1); + if (err) + error (1, err, "pthread_barrier_init"); + + for (j = 0; j < WAITS; j ++) + { + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, dowait, &barrier); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + printf ("Manager will now call pthread_barrier_wait.\n"); + + havesyncs + = pthread_barrier_wait (&barrier) == PTHREAD_BARRIER_SERIAL_THREAD + ? 1 : 0; + + for (i = THREADS - 1; i >= 0; i --) + { + void *ret; + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + switch ((int) ret) + { + case 0: + break; + + case PTHREAD_BARRIER_SERIAL_THREAD: + havesyncs ++; + break; + + default: + assert (! "Unknown value returned from pthread_barrier_wait."); + break; + } + } + + printf ("\n"); + + assert (havesyncs == 1); + } + + return 0; +} diff --git a/tests/test-7.c b/tests/test-7.c new file mode 100644 index 00000000..bd97acfa --- /dev/null +++ b/tests/test-7.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 10 +#define KEYS 400 + +pthread_key_t key[KEYS]; + +void * +thr (void *arg) +{ + error_t err; + int i; + + for (i = 0; i < KEYS; i ++) + { + printf ("pthread_getspecific(%d).\n", key[i]); + assert (pthread_getspecific (key[i]) == NULL); + printf ("pthread_setspecific(%d, %d).\n", key[i], pthread_self ()); + err = pthread_setspecific (key[i], (void *) pthread_self ()); + printf ("pthread_setspecific(%d, %d) => %d.\n", key[i], pthread_self (), err); + assert_perror (err); + } + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + void des (void *val) + { + assert ((pthread_t) val == pthread_self ()); + } + + for (i = 0; i < KEYS; i ++) + err = pthread_key_create (&key[i], des); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, 0); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + return 0; +} diff --git a/tests/test-8.c b/tests/test-8.c new file mode 100644 index 00000000..85a7f8f6 --- /dev/null +++ b/tests/test-8.c @@ -0,0 +1,60 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 10 + +pthread_once_t inc_var_once = PTHREAD_ONCE_INIT; +int var; + +void +inc_var (void) +{ + var ++; +} + +void * +thr (void *arg) +{ + int i; + + for (i = 0; i < 500; i ++) + pthread_once (&inc_var_once, inc_var); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, 0); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + assert (thr (0) == 0); + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + assert (var == 1); + + return 0; +} diff --git a/tests/test-9.c b/tests/test-9.c new file mode 100644 index 00000000..82051570 --- /dev/null +++ b/tests/test-9.c @@ -0,0 +1,88 @@ +/* Test recursive mutexes. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 10 + +int foo; + +void * +thr (void *arg) +{ + int i; + + pthread_mutex_lock (arg); + + foo = pthread_self (); + + for (i = 0; i < 500; i ++) + pthread_mutex_lock (arg); + for (i = 0; i < 500; i ++) + pthread_mutex_unlock (arg); + + assert (foo == pthread_self ()); + + pthread_mutex_unlock (arg); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + + err = pthread_mutexattr_init (&mattr); + if (err) + error (1, err, "pthread_mutexattr_init"); + + err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_RECURSIVE); + if (err) + error (1, err, "pthread_mutexattr_settype"); + + err = pthread_mutex_init (&mutex, &mattr); + if (err) + error (1, err, "pthread_mutex_init"); + + err = pthread_mutexattr_destroy (&mattr); + if (err) + error (1, err, "pthread_mutexattr_destroy"); + + pthread_mutex_lock (&mutex); + pthread_mutex_lock (&mutex); + pthread_mutex_unlock (&mutex); + pthread_mutex_unlock (&mutex); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, &mutex); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + err = pthread_mutex_destroy (&mutex); + if (err) + error (1, err, "pthread_mutex_destroy"); + + return 0; +} -- cgit v1.2.3 From 1f98f3e86e46d339425b50a8e10fdb62b2278ca3 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Fri, 11 Oct 2002 23:57:47 +0000 Subject: Finish import. --- libpthread.a | 20 ++++++++++++++++++++ libpthread_pic.a | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 libpthread.a create mode 100644 libpthread_pic.a diff --git a/libpthread.a b/libpthread.a new file mode 100644 index 00000000..d0e689e9 --- /dev/null +++ b/libpthread.a @@ -0,0 +1,20 @@ +/* pthread initializer is weak in glibc. It must be included if glibc + is to start threading. */ +EXTERN(_cthread_init_routine) + +/* Weak references in glibc that must be filled if glibc is to be + thread safe. */ +EXTERN(cthread_detach) +EXTERN(cthread_fork) +EXTERN(cthread_keycreate) +EXTERN(cthread_getspecific) +EXTERN(__libc_getspecific) +EXTERN(cthread_setspecific) +EXTERN(__mutex_lock_solid) +EXTERN(__mutex_unlock_solid) +/* For libio stream locking. */ +EXTERN(_cthreads_flockfile) +EXTERN(_cthreads_funlockfile) +EXTERN(_cthreads_ftrylockfile) + +GROUP(-lpthread2 -lihash) diff --git a/libpthread_pic.a b/libpthread_pic.a new file mode 100644 index 00000000..5673b4e7 --- /dev/null +++ b/libpthread_pic.a @@ -0,0 +1,20 @@ +/* pthread initializer is weak in glibc. It must be included if glibc + is to start threading. */ +EXTERN(_cthread_init_routine) + +/* Weak references in glibc that must be filled if glibc is to be + thread safe. */ +EXTERN(cthread_detach) +EXTERN(cthread_fork) +EXTERN(cthread_keycreate) +EXTERN(cthread_getspecific) +EXTERN(__libc_getspecific) +EXTERN(cthread_setspecific) +EXTERN(__mutex_lock_solid) +EXTERN(__mutex_unlock_solid) +/* For libio stream locking. */ +EXTERN(_cthreads_flockfile) +EXTERN(_cthreads_funlockfile) +EXTERN(_cthreads_ftrylockfile) + +GROUP(-lpthread2_pic -lihash_pic) -- cgit v1.2.3 From d11acf233709ad78bcd49474cc940471382a318b Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sun, 13 Oct 2002 00:58:03 +0000 Subject: 2002-10-12 Neal H. Walfield * sysdeps/hurd/pt-destroy-specific.c (__pthread_destroy_specific): Only call the destructor if there is one set. --- sysdeps/hurd/pt-destroy-specific.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sysdeps/hurd/pt-destroy-specific.c b/sysdeps/hurd/pt-destroy-specific.c index 82382228..dbd3314b 100644 --- a/sysdeps/hurd/pt-destroy-specific.c +++ b/sysdeps/hurd/pt-destroy-specific.c @@ -53,12 +53,14 @@ __pthread_destroy_specific (struct __pthread *thread) value = ihash_find (thread->thread_specifics, i); if (value) { - seen_one = 1; - err = ihash_remove (thread->thread_specifics, i); assert (err == 1); - __pthread_key_destructors[i] (value); + if (__pthread_key_destructors[i]) + { + seen_one = 1; + __pthread_key_destructors[i] (value); + } } } -- cgit v1.2.3 From 9370b15b3013cea65c19ba4afd5b4c4375035774 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sat, 2 Nov 2002 23:41:51 +0000 Subject: 2002-11-02 Alfred M. Szmidt * sysdeps/generic/pt-key-delete.c, sysdeps/hurd/pt-key-delete.c (pthread_key_delete): Renamed from pthread_key_destroy. Reported by Michael Koch --- sysdeps/generic/pt-key-delete.c | 2 +- sysdeps/hurd/pt-key-delete.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sysdeps/generic/pt-key-delete.c b/sysdeps/generic/pt-key-delete.c index 2e36f044..6c86f8e2 100644 --- a/sysdeps/generic/pt-key-delete.c +++ b/sysdeps/generic/pt-key-delete.c @@ -21,7 +21,7 @@ #include int -pthread_key_destory (pthread_key_t key) +pthread_key_delete (pthread_key_t key) { return ENOSYS; } diff --git a/sysdeps/hurd/pt-key-delete.c b/sysdeps/hurd/pt-key-delete.c index 7c1af715..2426bb11 100644 --- a/sysdeps/hurd/pt-key-delete.c +++ b/sysdeps/hurd/pt-key-delete.c @@ -22,7 +22,7 @@ #include int -pthread_key_destory (pthread_key_t key) +pthread_key_delete (pthread_key_t key) { error_t err = 0; -- cgit v1.2.3 From fea6e6874929ef1b9005adbcdefa38f17287c06d Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 18 Nov 2002 22:20:58 +0000 Subject: 2002-11-18 Neal H. Walfield * sysdeps/mach/pt-wakeup.c (__pthread_wakeup): Use the size of THREAD->wakeupmsg which may not be a mach_msg_header_t. * sysdeps/generic/pt-mutex-timedlock.c (__pthread_mutex_timedlock_internal): Really test for equality. * sysdeps/generic/pt-rwlock-timedrdlock.c (__pthread_rwlock_timedrdlock_internal): Likewise. * sysdeps/generic/pt-rwlock-timedwrlock.c (__pthread_rwlock_timedwrlock_internal): Likewise. * sysdeps/generic/pt-cond-timedwait.c (__pthread_cond_timedwait_internal): On timeout, remove our thread structure from the wait queue if necessary. * sysdeps/l4/pt-start.c (__pthread_start): Call L4_Myself, not __mach_thread_self. * sysdeps/mach/hurd/i386/pt-setup.c: Include . (__pthread_setup): Do not leak references from __mach_thread_self. * sysdeps/mach/hurd/pt-docancel.c (__pthread_do_cancel): Likewise. * sysdeps/mach/hurd/pt-sysdep.h (_pthread_self): Likewise. * sysdeps/mach/pt-thread-alloc.c (__pthread_thread_alloc): Likewise. * sysdeps/mach/pt-thread-start.c (__pthread_thread_start): Likewise. * sysdeps/mach/pt-start.c: Remove dead file. --- sysdeps/generic/pt-cond-timedwait.c | 23 ++++++- sysdeps/generic/pt-mutex-timedlock.c | 2 +- sysdeps/generic/pt-rwlock-timedrdlock.c | 2 +- sysdeps/generic/pt-rwlock-timedwrlock.c | 2 +- sysdeps/l4/pt-start.c | 2 +- sysdeps/mach/hurd/i386/pt-setup.c | 8 ++- sysdeps/mach/hurd/pt-docancel.c | 9 ++- sysdeps/mach/hurd/pt-sysdep.h | 7 ++- sysdeps/mach/pt-start.c | 106 -------------------------------- sysdeps/mach/pt-thread-alloc.c | 2 + sysdeps/mach/pt-thread-start.c | 6 +- sysdeps/mach/pt-wakeup.c | 4 +- 12 files changed, 54 insertions(+), 119 deletions(-) delete mode 100644 sysdeps/mach/pt-start.c diff --git a/sysdeps/generic/pt-cond-timedwait.c b/sysdeps/generic/pt-cond-timedwait.c index 99761f3a..4abeb71c 100644 --- a/sysdeps/generic/pt-cond-timedwait.c +++ b/sysdeps/generic/pt-cond-timedwait.c @@ -73,7 +73,28 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond, pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &canceltype); if (abstime) - err = __pthread_timedblock (self, abstime); + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&mutex->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&mutex->__lock); + + return err; + } + } else { err = 0; diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index e8c9b466..3603986c 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -114,7 +114,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, disconnect ourself? It may remain until the next time we block. */ { - assert (err = ETIMEDOUT); + assert (err == ETIMEDOUT); __pthread_spin_lock (&mutex->__lock); if (self->prevp) diff --git a/sysdeps/generic/pt-rwlock-timedrdlock.c b/sysdeps/generic/pt-rwlock-timedrdlock.c index 3660339b..85cb9468 100644 --- a/sysdeps/generic/pt-rwlock-timedrdlock.c +++ b/sysdeps/generic/pt-rwlock-timedrdlock.c @@ -86,7 +86,7 @@ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, disconnect ourself? It may remain until the next time we block. */ { - assert (err = ETIMEDOUT); + assert (err == ETIMEDOUT); __pthread_spin_lock (&rwlock->__lock); if (self->prevp) diff --git a/sysdeps/generic/pt-rwlock-timedwrlock.c b/sysdeps/generic/pt-rwlock-timedwrlock.c index 2f732175..edf6413f 100644 --- a/sysdeps/generic/pt-rwlock-timedwrlock.c +++ b/sysdeps/generic/pt-rwlock-timedwrlock.c @@ -72,7 +72,7 @@ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, disconnect ourself? It may remain until the next time we block. */ { - assert (err = ETIMEDOUT); + assert (err == ETIMEDOUT); __pthread_spin_lock (&rwlock->__lock); if (self->prevp) diff --git a/sysdeps/l4/pt-start.c b/sysdeps/l4/pt-start.c index 5a506998..fb4e27be 100644 --- a/sysdeps/l4/pt-start.c +++ b/sysdeps/l4/pt-start.c @@ -69,7 +69,7 @@ __pthread_start (struct __pthread *thread) /* The main thread is already running: do nothing. */ { assert (__pthread_total == 1); - thread->threadid = __mach_thread_self (); + thread->threadid = L4_Myself (); } else { diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c index a2495046..369a28e1 100644 --- a/sysdeps/mach/hurd/i386/pt-setup.c +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -1,5 +1,5 @@ /* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000 Free Software Foundation, Inc. + 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 @@ -19,6 +19,7 @@ #include #include +#include #include @@ -83,17 +84,20 @@ __pthread_setup (struct __pthread *thread, void *(*start_routine)(void *), void *arg) { error_t err; + mach_port_t ktid; thread->mcontext.pc = entry_point; thread->mcontext.sp = stack_setup (thread, start_routine, arg); - if (thread->kernel_thread != __mach_thread_self ()) + ktid = __mach_port_self (); + if (thread->kernel_thread != ktid) { err = __thread_set_pcsp (thread->kernel_thread, 1, thread->mcontext.pc, 1, thread->mcontext.sp); assert_perror (err); } + __mach_port_deallocate (__mach_task_self (), ktid); return 0; } diff --git a/sysdeps/mach/hurd/pt-docancel.c b/sysdeps/mach/hurd/pt-docancel.c index 58524ff0..bac62a71 100644 --- a/sysdeps/mach/hurd/pt-docancel.c +++ b/sysdeps/mach/hurd/pt-docancel.c @@ -30,10 +30,17 @@ call_exit (void) int __pthread_do_cancel (struct __pthread *p) { + mach_port_t ktid; + int me; + assert (p->cancel_pending = 1); assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); - if (__mach_thread_self () == p->kernel_thread) + ktid = __mach_thread_self (); + me = p->kernel_thread == ktid; + __mach_port_deallocate (__mach_task_self (), ktid); + + if (me) call_exit (); else { diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h index 3addef7c..18de9c55 100644 --- a/sysdeps/mach/hurd/pt-sysdep.h +++ b/sysdeps/mach/hurd/pt-sysdep.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000 Free Software Foundation, Inc. + 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 @@ -45,7 +45,10 @@ __hurd_threadvar_location (_HURD_THREADVAR_THREAD); \ \ assert (thread); \ - assert (thread->kernel_thread == __mach_thread_self ()); \ + assert (({ mach_port_t ktid = __mach_thread_self (); \ + int ok = thread->kernel_thread == ktid; \ + __mach_port_deallocate (__mach_task_self (), ktid);\ + ok; })); \ thread; \ }) diff --git a/sysdeps/mach/pt-start.c b/sysdeps/mach/pt-start.c deleted file mode 100644 index 5e8cd5aa..00000000 --- a/sysdeps/mach/pt-start.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Start thread. Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -#include - -/* Prepare a wakeup message. */ -static error_t -create_wakeupmsg (struct __pthread *thread) -{ - kern_return_t err; - - /* Build wakeup message. */ - thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); - thread->wakeupmsg.msgh_size = 0; - - err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE, - &thread->wakeupmsg.msgh_remote_port); - if (err) - return EAGAIN; - - thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL; - thread->wakeupmsg.msgh_seqno = 0; - thread->wakeupmsg.msgh_id = 0; - - err = __mach_port_insert_right (__mach_task_self (), - thread->wakeupmsg.msgh_remote_port, - thread->wakeupmsg.msgh_remote_port, - MACH_MSG_TYPE_MAKE_SEND); - if (err) - { - __mach_port_deallocate (__mach_task_self (), - thread->wakeupmsg.msgh_remote_port); - return EAGAIN; - } - - return 0; -} - -/* Start THREAD. We allocate all system-specific resources, including - a kernel thread, set it up, and get it running. */ -int -__pthread_start (struct __pthread *thread) -{ - error_t err; - - err = create_wakeupmsg (thread); - if (err) - return err; - - /* If there are no pthreads in the system then the pthread library - is bootstrapping and the main thread must create initialize - itself. The thread itself is already running, it just has no - pthread context. We want to reuse what it already has (including - the kernel thread), however, we must determine which thread is - the main thread. - - We cannot test if __pthread_total is one as we later decrement it - before creating the signal thread. Currently, we check if - __pthread_num_threads--the number of allocated thread - structures--is one. __pthread_alloc has already been called in - __pthread_create_internal for us. This predicate could be - improved, however, it is sufficient for now. */ - if (__pthread_num_threads == 1) - { - assert (__pthread_total == 1); - thread->kernel_thread = __mach_thread_self (); - } - else - { - err = __thread_create (__mach_task_self (), &thread->kernel_thread); - if (err) - return EAGAIN; - - err = __thread_set_pcsp (thread->kernel_thread, - 1, thread->mcontext.pc, - 1, thread->mcontext.sp); - assert_perror (err); - - err = __thread_resume (thread->kernel_thread); - assert_perror (err); - } - - return 0; -} diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c index af929533..a191c712 100644 --- a/sysdeps/mach/pt-thread-alloc.c +++ b/sysdeps/mach/pt-thread-alloc.c @@ -86,6 +86,8 @@ __pthread_thread_alloc (struct __pthread *thread) { assert (__pthread_total == 0); thread->kernel_thread = __mach_thread_self (); + /* We implicitly hold a reference. */ + __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); } else { diff --git a/sysdeps/mach/pt-thread-start.c b/sysdeps/mach/pt-thread-start.c index eade5098..11b017ff 100644 --- a/sysdeps/mach/pt-thread-start.c +++ b/sysdeps/mach/pt-thread-start.c @@ -33,7 +33,11 @@ __pthread_thread_start (struct __pthread *thread) { /* The main thread is already running: do nothing. */ assert (__pthread_total == 1); - assert (thread->kernel_thread == __mach_thread_self ()); + assert (({ mach_port_t ktid = __mach_thread_self (); + int ok = thread->kernel_thread == ktid; + __mach_port_deallocate (__mach_task_self (), + thread->kernel_thread); + ok; })); } else { diff --git a/sysdeps/mach/pt-wakeup.c b/sysdeps/mach/pt-wakeup.c index 8ab10fb8..4920d102 100644 --- a/sysdeps/mach/pt-wakeup.c +++ b/sysdeps/mach/pt-wakeup.c @@ -1,5 +1,5 @@ /* Wakeup a thread. Mach version. - Copyright (C) 2000 Free Software Foundation, Inc. + 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 @@ -32,7 +32,7 @@ __pthread_wakeup (struct __pthread *thread) error_t err; err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG, - sizeof (mach_msg_header_t), 0, MACH_PORT_NULL, + sizeof (thread->wakeupmsg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); assert_perror (err); } -- cgit v1.2.3 From 765d563a530862765d8b7fea86082b5aa910b9a2 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 25 Nov 2002 21:07:35 +0000 Subject: 2002-11-25 Neal H. Walfield * sysdeps/mach/hurd/i386/pt-setup.c (__pthread_setup): Fix last change. --- sysdeps/mach/hurd/i386/pt-setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c index 369a28e1..9a855847 100644 --- a/sysdeps/mach/hurd/i386/pt-setup.c +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -89,7 +89,7 @@ __pthread_setup (struct __pthread *thread, thread->mcontext.pc = entry_point; thread->mcontext.sp = stack_setup (thread, start_routine, arg); - ktid = __mach_port_self (); + ktid = __mach_thread_self (); if (thread->kernel_thread != ktid) { err = __thread_set_pcsp (thread->kernel_thread, -- cgit v1.2.3 From 01d0d4c7d07b28326d2de95dd9000f876f661707 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 26 Nov 2002 17:50:48 +0000 Subject: 2002-11-26 Neal H. Walfield * pthread/pt-create.c [HAVE_USELOCAL]: Include . (entry_point) [HAVE_USELOCALE]: Initialize the thread to the global locale. --- pthread/pt-create.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pthread/pt-create.c b/pthread/pt-create.c index bbfc6606..0295a0af 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -26,6 +26,10 @@ #include +#ifdef HAVE_USELOCALE +# include +#endif + /* The total number of pthreads currently active. This is defined here since it would be really stupid to have a threads-using program that doesn't call `pthread_create'. */ @@ -36,6 +40,11 @@ __atomic_t __pthread_total; static void entry_point (void *(*start_routine)(void *), void *arg) { +#ifdef HAVE_USELOCALE + /* A fresh thread needs to be bound to the global locale. */ + uselocale (LC_GLOBAL_LOCALE); +#endif + pthread_exit (start_routine (arg)); } -- cgit v1.2.3 From 7d0bdd972bff821d9424c24f0046b7b5cdb2ac5d Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Mon, 1 Mar 2004 09:58:44 +0000 Subject: auth/ 2003-08-17 Marcus Brinkmann * auth.c: Include . (pending_users, pending_server): Change type to struct hurd_ihash, initialize with HURD_IHASH_INITIALIZER. (struct pending): Change type of member LOCP to hurd_ihash_locp_t. (S_auth_user_authenticate): Use hurd_ihash_* functions instead ihash_*. (S_auth_server_authenticate): Likewise. (main): Do not allocate the hash tables. console-client/ 2003-08-17 Marcus Brinkmann * vga-dynafont.c: Include . (struct mapped_character): Change type of LOCP to hurd_ihash_locp_t. (struct dynafont): Change type of CHARMAP to struct hurd_ihash. (dynafont_new): Use hurd_ihash_init instead of ihash_create. Remove variable ERR. Call hurd_ihash_add instead of ihash_add. (dynafont_free): Call hurd_ihash_destroy, no ihash_free. (dynafont_lookup_internal): Use hurd_ihash_find, not ihash_find. (dynafont_lookup_internal): Call hurd_ihash_locp_remove instead ihash_locp_remove, and hurd_ihash_add instead ihash_add. (dynafont_change_font): Likewise. Clean out LOCP if character is unmapped. ftpfs/ 2003-08-17 Marcus Brinkmann * ftpfs.h: Include . (struct ftpfs): Change type of INODE_MAPPINGS to struct hurd_ihash. (struct ftpfs_dir_entry): Change type of INODE_LOCP to hurd_ihash_locp_t. * node.c (ftpfs_create_node): Call hurd_ihash_add, not ihash_add. (netfs_node_norefs): Call hurd_ihash_locp_remove, not ihash_locp_remove. * fs.c: Include . (ftpfs_create): Call hurd_ihash_init, not hurd_ihash_create. Call hurd_ihash_destroy on error. libihash/ 2003-08-17 Marcus Brinkmann * ihash.c: Rewritten. * ihash.h: Rewritten. * Makefile (SRCS): Remove sizes.c. (LCLHDRS): Remove priv.h. * primes.c, sizes.c, priv.h: Files removed. 2003-08-17 Marcus Brinkmann * ports.h (struct port_bucket): Change type of HTABLE to struct hurd_ihash. (struct port_info): Change type of HENTRY to hurd_ihash_locp_t. * lookup-port.c (ports_lookup_port): Use hurd_ihash_find instead ihash_find. * bucket-iterate.c (_ports_bucket_class_iterate): Use HURD_IHASH_ITERATE instead ihash_iterate. * inhibit-all-rpcs.c (ports_inhibit_all_rpcs): Likewise. * inhibit-bucket-rpcs.c (ports_inhibit_bucket_rpcs): Likewise. * create-internal.c (_ports_create_port_internal): Use hurd_ihash_add instead ihash_add. * import-port.c (ports_import_port): Likewise. * reallocate-from-external.c (ports_reallocate_from_external): Likewise. * reallocate-port.c (ports_reallocate_port): Likewise. * transfer-right.c (ports_transfer_right): Likewise. * create-bucket.c: Include . (ports_create_bucket): Use hurd_ihash_init instead hurd_ihash_create. * class-iterate.c: Do not include . * claim-right.c (ports_claim_right): Call hurd_ihash_locp_remove instead ihash_locp_remove. * complete-deallocate.c (_ports_complete_deallocate): Likewise. * destroy-right.c (ports_destroy_right): Likewise. * reallocate-from-external.c (ports_reallocate_from_external): Likewise. * reallocate-port.c (ports_reallocate_port): Likewise. * transfer-right.c (ports_transfer_right): Likewise. libps/ 2003-08-17 Marcus Brinkmann * ps.h (struct ps_context): Change type of members procs, ttys, ttys_by_cttyid and users to struct hurd_ihash. * context.c (ps_context_create): Remove variables err_procs, err_ttys, err_ttys_by_cttyid and err_users. Use hurd_ihash_init instead of ihash_create. Call hurd_ihash_set_cleanup and the hurd_ihash_cleanup_t type instead of ihash_set_cleanup. (ps_context_free): Call hurd_ihash_destroy instead of ihash_free. (lookup): Call hurd_ihash_find instead ihash_find, hurd_ihash_add instead ihash_add. (ps_context_find_proc_stat): Take pointer of hash object. (ps_context_find_tty): Likewise. (ps_context_find_tty_by_cttyid): Likewise. (ps_context_find_user): Likewise. libpthread/ 2003-08-17 Marcus Brinkmann * sysdeps/hurd/pt-key.h (PTHREAD_KEY_MEMBERS): Change type of THREAD_SPECIFICS to hurd_ihash_t. * sysdeps/hurd/pt-setspecific.c (pthread_setspecific): Call hurd_ihash_create instead ihash_create, and hurd_ihash_add instead ihash_add. * sysdeps/hurd/pt-getspecific.c (pthread_getspecific): Call hurd_ihash_find instead of ihash_find. * sysdeps/hurd/pt-destroy-specific.c (__pthread_destroy_specific): Call hurd_ihash_find instead of ihash_find, hurd_ihash_remove instead of ihash_remove, and hurd_ihash_free instead of ihash_free. proc/ 2003-08-17 Marcus Brinkmann * proc.h: Include . (struct proc): Change type of members p_pidhashloc and p_taskhashloc to hurd_ihash_locp_t. (struct pgrp): Likewise for pg_hashloc. (struct session): Likewise for s_hashloc. * hash.c: Change type of pghash, pidhash, taskhash and sidhash to struct hurd_ihash and initialize them with HURD_IHASH_INITIALIZER. Include stddef.h. (pid_find): Call hurd_ihash_find instead ihash_find. (pid_find_allow_zombie): Likewise. (task_find): Likewise. (task_find_nocreate): Likewise. (pgrp_find): Likewise. (session_find): Likewise. (add_proc_to_hash): Call hurd_ihash_add instead ihash_add. (add_pgrp_to_hash): Likewise. (add_session_to_hash): Likewise. (remove_pgrp_from_hash): Call hurd_ihash_locp_remove instead ihash_locp_remove, and provide hash table pointer. (remove_proc_from_hash): Likewise. (remove_session_from_hash): Likewise. (prociterate): Use HURD_IHASH_ITERATE instead ihash_iterate. trans/ 2003-08-17 Marcus Brinkmann * fakeroot.c: Include . (struct netnode): Change type of member idport_locp to hurd_ihash_locp_t. (idport_ihash): Change type to struct hurd_ihash and initialize with HURD_IHASH_INITIALIZER. (new_node): Call hurd_ihash_add instead of ihash_add. (netfs_node_norefs): Call hrd_ihash_locp_remove instead ihash_locp_remove. (netfs_S_dir_lookup): Call hurd_ihash_find instead ihash_find. utils/ 2003-08-17 Marcus Brinkmann * rpctrace.c: Include . (struct traced_info): Change type of LOCP to hurd_ihash_locp_t. (msgid_ihash): Change type to struct hurd_ihash, and initialize with HURD_IHASH_INITIALIZER, don't set cleanup here. (traced_names): Likewise. (main): Call hurd_ihash_set_cleanup for msgid_ihash. Don't create traced_names. (parse_msgid_list): Call hurd_ihash_add instead ihash_add. (new_send_wrapper): Likewise. (msgid_info): Likewise. Call hurd_ihash_find instead ihash_find. (rewrite_right): Likewise. (traced_dropweak): Call hurd_ihash_locp_remove instead ihash_locp_remove. --- sysdeps/hurd/pt-destroy-specific.c | 6 +++--- sysdeps/hurd/pt-getspecific.c | 2 +- sysdeps/hurd/pt-key.h | 2 +- sysdeps/hurd/pt-setspecific.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sysdeps/hurd/pt-destroy-specific.c b/sysdeps/hurd/pt-destroy-specific.c index dbd3314b..23c7fbc0 100644 --- a/sysdeps/hurd/pt-destroy-specific.c +++ b/sysdeps/hurd/pt-destroy-specific.c @@ -50,10 +50,10 @@ __pthread_destroy_specific (struct __pthread *thread) if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID) break; - value = ihash_find (thread->thread_specifics, i); + value = hurd_ihash_find (thread->thread_specifics, i); if (value) { - err = ihash_remove (thread->thread_specifics, i); + err = hurd_ihash_remove (thread->thread_specifics, i); assert (err == 1); if (__pthread_key_destructors[i]) @@ -74,6 +74,6 @@ __pthread_destroy_specific (struct __pthread *thread) sched_yield (); } - ihash_free (thread->thread_specifics); + hurd_ihash_free (thread->thread_specifics); thread->thread_specifics = 0; } diff --git a/sysdeps/hurd/pt-getspecific.c b/sysdeps/hurd/pt-getspecific.c index b5b5f5e5..30605984 100644 --- a/sysdeps/hurd/pt-getspecific.c +++ b/sysdeps/hurd/pt-getspecific.c @@ -33,5 +33,5 @@ pthread_getspecific (pthread_key_t key) if (! self->thread_specifics) return 0; - return ihash_find (self->thread_specifics, key); + return hurd_ihash_find (self->thread_specifics, key); } diff --git a/sysdeps/hurd/pt-key.h b/sysdeps/hurd/pt-key.h index 739fbbad..494e01d7 100644 --- a/sysdeps/hurd/pt-key.h +++ b/sysdeps/hurd/pt-key.h @@ -21,7 +21,7 @@ #include #define PTHREAD_KEY_MEMBERS \ - ihash_t thread_specifics; + hurd_ihash_t thread_specifics; #define PTHREAD_KEY_INVALID (void *) (-1) diff --git a/sysdeps/hurd/pt-setspecific.c b/sysdeps/hurd/pt-setspecific.c index bd752250..89ca4d7f 100644 --- a/sysdeps/hurd/pt-setspecific.c +++ b/sysdeps/hurd/pt-setspecific.c @@ -30,12 +30,12 @@ pthread_setspecific (pthread_key_t key, const void *value) if (! self->thread_specifics) { - err = ihash_create (&self->thread_specifics); + err = hurd_ihash_create (&self->thread_specifics, HURD_IHASH_NO_LOCP); if (err) return ENOMEM; } - err = ihash_add (self->thread_specifics, key, (void *) value, 0); + err = hurd_ihash_add (self->thread_specifics, key, (void *) value); if (err) return ENOMEM; -- cgit v1.2.3 From f2b09556f28624f7428cbf6184f4836dad4009bf Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 18 Jan 2005 09:57:35 +0000 Subject: libpthread/ 2005-01-12 Pietro Ferrari * include/pthread/pthread.h (pthread_spin_destroy): Replace extern inline with extern __inline. (pthread_spin_init): Likewise. (pthread_spin_lock): Likewise. (pthread_spin_trylock): Likewise. (pthread_spin_unlock): Likewise. * sysdeps/mach/bits/spin-lock.h (__pthread_spin_lock): Likewise. * sysdeps/i386/bits/spin-lock.h (__pthread_spin_lock): Likewise. * sysdeps/generic/bits/mutex.h (__pthread_mutex_trylock): Likewise. (pthread_mutex_lock): Likewise. (pthread_mutex_trylock): Likewise. * sysdeps/generic/bits/pthread.h (pthread_equal): Likewise. --- sysdeps/generic/bits/mutex.h | 6 +++--- sysdeps/generic/bits/pthread.h | 2 +- sysdeps/i386/bits/spin-lock.h | 4 ++-- sysdeps/mach/bits/spin-lock.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 2baf0408..9958b8d1 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -108,7 +108,7 @@ __pthread_mutex_lock (struct __pthread_mutex *__mutex) return _pthread_mutex_lock (__mutex); } -extern inline int +extern __inline int __pthread_mutex_trylock (struct __pthread_mutex *__mutex) { extern int _pthread_mutex_trylock (struct __pthread_mutex *); @@ -120,13 +120,13 @@ __pthread_mutex_trylock (struct __pthread_mutex *__mutex) return _pthread_mutex_trylock (__mutex); } -extern inline int +extern __inline int pthread_mutex_lock (struct __pthread_mutex *__mutex) { return __pthread_mutex_lock (__mutex); } -extern inline int +extern __inline int pthread_mutex_trylock (struct __pthread_mutex *__mutex) { return __pthread_mutex_trylock (__mutex); diff --git a/sysdeps/generic/bits/pthread.h b/sysdeps/generic/bits/pthread.h index 740325d0..3f9df13d 100644 --- a/sysdeps/generic/bits/pthread.h +++ b/sysdeps/generic/bits/pthread.h @@ -24,7 +24,7 @@ typedef int pthread_t; /* Return true if __T1 and __T2 both name the same thread. Otherwise, false. */ -extern inline int +extern __inline int pthread_equal (pthread_t __t1, pthread_t __t2) { return __t1 == __t2; diff --git a/sysdeps/i386/bits/spin-lock.h b/sysdeps/i386/bits/spin-lock.h index 175656ef..3176a15f 100644 --- a/sysdeps/i386/bits/spin-lock.h +++ b/sysdeps/i386/bits/spin-lock.h @@ -74,10 +74,10 @@ __pthread_spin_trylock (__pthread_spinlock_t *__lock) return __locked ? __EBUSY : 0; } -extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern __inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); -extern inline int +extern __inline int __pthread_spin_lock (__pthread_spinlock_t *__lock) { if (__pthread_spin_trylock (__lock)) diff --git a/sysdeps/mach/bits/spin-lock.h b/sysdeps/mach/bits/spin-lock.h index f295df7a..e137c244 100644 --- a/sysdeps/mach/bits/spin-lock.h +++ b/sysdeps/mach/bits/spin-lock.h @@ -70,10 +70,10 @@ __pthread_spin_trylock (__pthread_spinlock_t *__lock) return __spin_try_lock (__lock) ? 0 : __EBUSY; } -extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern __inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); -extern inline int +extern __inline int __pthread_spin_lock (__pthread_spinlock_t *__lock) { if (__pthread_spin_trylock (__lock)) -- cgit v1.2.3 From d5bd96ef227dbb794326a8d707d04c9ffcdb3969 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 18 Jan 2005 10:08:52 +0000 Subject: libpthread/ 2005-01-18 Neal H. Walfield * sysdeps/mach/hurd/pt-sysdep.h (__pthread_stack_dealloc): Add __always_inline__ attribute. * sysdeps/l4/hurd/pt-sysdep.h (_pthread_self): Likewise. (__attribute__): Likewise. --- sysdeps/l4/hurd/pt-sysdep.h | 2 ++ sysdeps/mach/hurd/pt-sysdep.h | 1 + 2 files changed, 3 insertions(+) diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h index e37beefa..87175330 100644 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -35,6 +35,7 @@ L4_Word_t my_errno; extern inline struct __pthread * +__attribute__((__always_inline__)) _pthread_self (void) { return (struct __pthread *) L4_MyUserDefinedHandle (); @@ -42,6 +43,7 @@ _pthread_self (void) extern inline void __pthread_stack_dealloc (void *stackaddr, size_t stacksize) +__attribute__((__always_inline__)) { /* XXX: can only implement this once we have a working memory manager. */ return; diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h index 18de9c55..83bad963 100644 --- a/sysdeps/mach/hurd/pt-sysdep.h +++ b/sysdeps/mach/hurd/pt-sysdep.h @@ -53,6 +53,7 @@ }) extern inline void +__attribute__((__always_inline__)) __pthread_stack_dealloc (void *stackaddr, size_t stacksize) { __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize); -- cgit v1.2.3 From 925d7efa3ce2bae7a2e889a57e7337de4877ff75 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 8 Feb 2005 14:42:03 +0000 Subject: libpthread/ 2005-02-08 Neal H. Walfield * sysdeps/mach/pt-spin.c (__pthread_spin_lock): Make a weak alias to _pthread_spin_lock. * sysdeps/posix/pt-spin.c (__pthread_spin_lock): Likewise. --- sysdeps/mach/pt-spin.c | 3 ++- sysdeps/posix/pt-spin.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sysdeps/mach/pt-spin.c b/sysdeps/mach/pt-spin.c index 010faca8..d9a2a32a 100644 --- a/sysdeps/mach/pt-spin.c +++ b/sysdeps/mach/pt-spin.c @@ -1,5 +1,5 @@ /* Spin locks. Mach version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2004 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 @@ -33,3 +33,4 @@ _pthread_spin_lock (__pthread_spinlock_t *lock) } weak_alias (_pthread_spin_lock, pthread_spin_lock); +weak_alias (_pthread_spin_lock, __pthread_spin_lock); diff --git a/sysdeps/posix/pt-spin.c b/sysdeps/posix/pt-spin.c index cdc482c1..486030de 100644 --- a/sysdeps/posix/pt-spin.c +++ b/sysdeps/posix/pt-spin.c @@ -1,5 +1,5 @@ /* Spin locks. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2004 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 @@ -51,3 +51,4 @@ _pthread_spin_lock (__pthread_spinlock_t *lock) } weak_alias (_pthread_spin_lock, pthread_spin_lock); +weak_alias (_pthread_spin_lock, __pthread_spin_lock); -- cgit v1.2.3 From 3f126cc9b3b8fb6f98dd4bdbe4f69f89ec7ab1a4 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 20 Apr 2005 15:26:52 +0000 Subject: libpthread/ 2005-04-20 Neal H. Walfield * sysdeps/generic/pt-setschedparam.c: policy's type is int, not int *. * include/pthread/pthread.h: Likewise. Reported by Christopher `Physicman' Bodenstein . --- sysdeps/generic/pt-setschedparam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sysdeps/generic/pt-setschedparam.c b/sysdeps/generic/pt-setschedparam.c index 6b624a31..a70b0796 100644 --- a/sysdeps/generic/pt-setschedparam.c +++ b/sysdeps/generic/pt-setschedparam.c @@ -1,5 +1,5 @@ /* Set the scheduling parameters for a thread. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -21,7 +21,7 @@ #include int -pthread_setschedparam (pthread_t thread, int *policy, +pthread_setschedparam (pthread_t thread, int policy, const struct sched_param *param) { return ENOSYS; -- cgit v1.2.3 From 6c7755ebb4718153b144b59f9becbf1b5e785f02 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 2 May 2005 22:00:34 +0000 Subject: libpthread/ 2005-05-02 Neal H. Walfield * pthread/pt-alloc.c (__pthread_alloc): Set the thread id to the table index plus one. * pthread/pt-internal.h (__pthread_getid): Index __pthread_threads using THREAD - 1, not THREAD. (__pthread_setid): Likewise. * pthread/pt-create.c (__pthread_create_internal): Likewise. * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock): When returning EBUSY, don't forget to first unlock MUTEX->__HELD. --- pthread/pt-alloc.c | 14 +++++++------- pthread/pt-create.c | 4 ++-- pthread/pt-internal.h | 11 +++++++---- sysdeps/generic/pt-mutex-trylock.c | 6 ++++-- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index 5cdc85df..e8d3c033 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -1,5 +1,5 @@ /* Allocate a new thread structure. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -139,10 +139,10 @@ __pthread_alloc (struct __pthread **pthread) if (__pthread_num_threads < __pthread_max_threads) { - /* We have a free slot. Use the slot number as - the thread ID for the new thread. */ - new->thread = __pthread_num_threads++; - __pthread_threads[new->thread] = NULL; + /* We have a free slot. Use the slot number plus one as the + thread ID for the new thread. */ + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; pthread_rwlock_unlock (&__pthread_threads_lock); @@ -203,8 +203,8 @@ __pthread_alloc (struct __pthread **pthread) __pthread_threads = threads; /* And allocate ourselves one of the newly created slots. */ - new->thread = __pthread_num_threads++; - __pthread_threads[new->thread] = NULL; + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; pthread_rwlock_unlock (&__pthread_threads_lock); diff --git a/pthread/pt-create.c b/pthread/pt-create.c index 0295a0af..cf5b32d8 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -1,5 +1,5 @@ /* Thread creation. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -168,7 +168,7 @@ __pthread_create_internal (struct __pthread **thread, other thread should be using this entry (we also assume that the store is atomic). */ pthread_rwlock_rdlock (&__pthread_threads_lock); - __pthread_threads[pthread->thread] = pthread; + __pthread_threads[pthread->thread - 1] = pthread; pthread_rwlock_unlock (&__pthread_threads_lock); /* At this point it is possible to guess our pthread ID. We have to diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index a32345c4..75631db0 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2005 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 @@ -134,20 +134,23 @@ extern int __pthread_num_threads; /* Concurrency hint. */ extern int __pthread_concurrency; -/* Array of __pthread structures and its lock. */ +/* Array of __pthread structures and its lock. Indexed by the pthread + id minus one. (Why not just use the pthread id? Because some + brain-dead users of the pthread interface incorrectly assume that 0 + is an invalid pthread id.) */ extern struct __pthread **__pthread_threads; extern pthread_rwlock_t __pthread_threads_lock; #define __pthread_getid(thread) \ ({ struct __pthread *__t; \ pthread_rwlock_rdlock (&__pthread_threads_lock); \ - __t = __pthread_threads[thread]; \ + __t = __pthread_threads[thread - 1]; \ pthread_rwlock_unlock (&__pthread_threads_lock); \ __t; }) #define __pthread_setid(thread, pthread) \ pthread_rwlock_wrlock (&__pthread_threads_lock); \ - __pthread_threads[thread] = pthread; \ + __pthread_threads[thread - 1] = pthread; \ pthread_rwlock_unlock (&__pthread_threads_lock); /* Similar to pthread_self, but returns the thread descriptor instead diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index b3c3fe3a..9457ddac 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -1,5 +1,5 @@ /* Try to Lock a mutex. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -23,7 +23,7 @@ #define LOSE do { * (int *) 0 = 0; } while (1) -/* Lock MUTEX, block if we can't get it. */ +/* Lock MUTEX, return EBUSY if we can't get it. */ int __pthread_mutex_trylock (struct __pthread_mutex *mutex) { @@ -82,6 +82,8 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) } } + __pthread_spin_unlock (&mutex->__lock); + return err; } -- cgit v1.2.3 From 317c73af1d3142947ba5f5d2f5251c4a34abda52 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 4 May 2005 16:04:06 +0000 Subject: libpthread/ 2005-05-04 Neal H. Walfield * Makefile (SRCS): Add pt-thread_dealloc.c. * sysdeps/mach/pt-thread-dealloc.c: New file. * pthread/pt-internal.h (__pthread_thread_dealloc): New declaration. (__pthread_thread_halt): Add parameter NEED_DEALLOC. Update callers. * sysdeps/mach/pt-thread-halt.c (__pthread_thread_halt): Respect new NEED_DEALLOC parameter. Move code which deallocates kernel resources from here ... * sysdeps/mach/pt-thread-dealloc.c (__pthread_thread_dealloc): ...to here. * pthread/pt-create.c (__pthread_create_internal): Call __pthread_thread_dealloc on failure. * pthread/pt-exit.c (pthread_exit): Call __pthread_thread_dealloc. * sysdeps/mach/pt-thread-alloc.c (create_wakeupmsg): Call __mach_port_destroy to deallocate the receive right. __mach_port_deallocate won't do it. * pthread/pt-detach.c (pthread_detach): Don't call __pthread_thread_halt a second time. * sysdeps/mach/hurd/pt-sysdep.c (_cthread_init_routine): Fix declaration. (init_routine): Update declaration and remove gratuitous cast. --- pthread/pt-create.c | 3 ++- pthread/pt-detach.c | 4 +--- pthread/pt-exit.c | 13 +++++++++---- pthread/pt-internal.h | 20 +++++++++++++++----- sysdeps/mach/hurd/pt-sysdep.c | 10 +++++----- sysdeps/mach/pt-thread-alloc.c | 9 +++++---- sysdeps/mach/pt-thread-dealloc.c | 41 ++++++++++++++++++++++++++++++++++++++++ sysdeps/mach/pt-thread-halt.c | 18 +++++++++++------- 8 files changed, 89 insertions(+), 29 deletions(-) create mode 100644 sysdeps/mach/pt-thread-dealloc.c diff --git a/pthread/pt-create.c b/pthread/pt-create.c index cf5b32d8..bad5d83f 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -192,7 +192,8 @@ __pthread_create_internal (struct __pthread **thread, failed_sigstate: __pthread_sigstate_destroy (pthread); failed_setup: - __pthread_thread_halt (pthread); + __pthread_thread_dealloc (pthread); + __pthread_thread_halt (pthread, 0); failed_thread_alloc: __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); pthread->stack = 0; diff --git a/pthread/pt-detach.c b/pthread/pt-detach.c index c22f6a03..42a84080 100644 --- a/pthread/pt-detach.c +++ b/pthread/pt-detach.c @@ -1,5 +1,5 @@ /* Detach a thread. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2005 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 @@ -58,8 +58,6 @@ pthread_detach (pthread_t thread) __pthread_mutex_unlock (&pthread->state_lock); - __pthread_thread_halt (pthread); - assert (pthread->stack); __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); pthread->stack = 0; diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c index fb9e97c0..7484ffd1 100644 --- a/pthread/pt-exit.c +++ b/pthread/pt-exit.c @@ -1,5 +1,5 @@ /* Thread termination. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -35,6 +35,7 @@ pthread_exit (void *status) struct __pthread *self = _pthread_self (); struct __pthread_cancelation_handler **handlers; int oldstate; + int need_dealloc; /* Run any cancelation handlers. According to POSIX, the cancellation cleanup handlers should be called with cancellation @@ -69,10 +70,13 @@ pthread_exit (void *status) if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) status = PTHREAD_CANCELED; + __pthread_thread_dealloc (self); + switch (self->state) { default: - assert (! "This cannot happen!"); + assert (! "Consistency error: unexpected self->state"); + abort (); break; case PTHREAD_DETACHED: @@ -82,7 +86,7 @@ pthread_exit (void *status) deallocate our own stack. However, it will eventually be reused when this thread structure is recycled. */ __pthread_mutex_unlock (&self->state_lock); - __pthread_dealloc (self); + need_dealloc = 1; break; @@ -99,6 +103,7 @@ pthread_exit (void *status) waiting to join us. */ pthread_cond_broadcast (&self->state_cond); __pthread_mutex_unlock (&self->state_lock); + need_dealloc = 0; break; } @@ -108,7 +113,7 @@ pthread_exit (void *status) This means that before freeing any resources, such a thread should make sure that this thread is really halted. */ - __pthread_thread_halt (self); + __pthread_thread_halt (self, need_dealloc); /* NOTREACHED */ abort (); diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 75631db0..e9086956 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -195,16 +195,26 @@ extern int __pthread_setup (struct __pthread *thread, void *(*start_routine)(void *), void *arg); -/* Allocate a kernel thread for THREAD; it must not be placed on the - run queue. */ +/* Allocate a kernel thread (and any miscellaneous system dependent + resources) for THREAD; it must not be placed on the run queue. */ extern int __pthread_thread_alloc (struct __pthread *thread); +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +extern void __pthread_thread_dealloc (struct __pthread *thread); + /* Start THREAD making it eligible to run. */ extern int __pthread_thread_start (struct __pthread *thread); -/* Stop thread thread and deallocate any kernel resources associated - with THREAD. */ -extern void __pthread_thread_halt (struct __pthread *thread); +/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is + true, the function must call __pthread_dealloc on THREAD. + + NB: The thread executing this function may be the thread which is + being halted, thus the last action should be halting the thread + itself. */ +extern void __pthread_thread_halt (struct __pthread *thread, + int need_dealloc); /* Block THREAD. */ diff --git a/sysdeps/mach/hurd/pt-sysdep.c b/sysdeps/mach/hurd/pt-sysdep.c index b42fe255..5e070067 100644 --- a/sysdeps/mach/hurd/pt-sysdep.c +++ b/sysdeps/mach/hurd/pt-sysdep.c @@ -1,5 +1,5 @@ /* System dependent pthreads code. Hurd version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -29,16 +29,16 @@ #include /* Forward. */ -static int init_routine (void); +static void *init_routine (void); /* OK, the name of this variable isn't really appropriate, but I don't want to change it yet. */ -int (*_cthread_init_routine)(void) = &init_routine; +void *(*_cthread_init_routine)(void) = &init_routine; /* This function is called from the Hurd-specific startup code. It should return a new stack pointer for the main thread. The caller will switch to this new stack before doing anything serious. */ -static int +static void * init_routine (void) { struct __pthread *thread; @@ -68,5 +68,5 @@ init_routine (void) = (__pthread_default_attr.stacksize - __hurd_threadvar_max * sizeof (uintptr_t)); - return (int) thread->mcontext.sp; + return thread->mcontext.sp; } diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c index a191c712..1acba98a 100644 --- a/sysdeps/mach/pt-thread-alloc.c +++ b/sysdeps/mach/pt-thread-alloc.c @@ -1,5 +1,5 @@ /* Start thread. Mach version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -50,8 +50,8 @@ create_wakeupmsg (struct __pthread *thread) MACH_MSG_TYPE_MAKE_SEND); if (err) { - __mach_port_deallocate (__mach_task_self (), - thread->wakeupmsg.msgh_remote_port); + __mach_port_destroy (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); return EAGAIN; } @@ -86,7 +86,8 @@ __pthread_thread_alloc (struct __pthread *thread) { assert (__pthread_total == 0); thread->kernel_thread = __mach_thread_self (); - /* We implicitly hold a reference. */ + /* We implicitly hold a reference drop the one that we just + acquired. */ __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); } else diff --git a/sysdeps/mach/pt-thread-dealloc.c b/sysdeps/mach/pt-thread-dealloc.c new file mode 100644 index 00000000..55d8c4d5 --- /dev/null +++ b/sysdeps/mach/pt-thread-dealloc.c @@ -0,0 +1,41 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +void +__pthread_thread_dealloc (struct __pthread *thread) +{ + /* Why no assert? Easy. When Mach kills a task, it starts by + invalidating the task port and then terminating the threads one + by one. But while it is terminating them, they are still + eligible to be scheduled. Imagine we have two threads, one calls + exit, one calls pthread_exit. The second one may run this after + the mask port can been destroyed thus gratuitously triggering the + assert. */ + __mach_port_destroy (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); +} diff --git a/sysdeps/mach/pt-thread-halt.c b/sysdeps/mach/pt-thread-halt.c index 84e6ac8e..9f860247 100644 --- a/sysdeps/mach/pt-thread-halt.c +++ b/sysdeps/mach/pt-thread-halt.c @@ -1,5 +1,5 @@ /* Deallocate the kernel thread resources. Mach version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -23,17 +23,21 @@ #include +/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is + true, the function must call __pthread_dealloc on THREAD. -/* Deallocate the kernel thread resources associated with THREAD. */ + NB: The thread executing this function may be the thread which is + being halted, thus the last action should be halting the thread + itself. */ void -__pthread_thread_halt (struct __pthread *thread) +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) { error_t err; + thread_t tid = thread->kernel_thread; - err = __mach_port_deallocate (__mach_task_self (), - thread->wakeupmsg.msgh_remote_port); - assert_perror (err); + if (need_dealloc) + __pthread_dealloc (thread); - err = __thread_terminate (thread->kernel_thread); + err = __thread_terminate (tid); assert_perror (err); } -- cgit v1.2.3 From 4878d30d853a947ea22de2ac8aa2dca6c1035821 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 12 May 2005 11:50:42 +0000 Subject: libpthread/ 2005-05-12 Neal H. Walfield * Makefile (SRCS): Add sem-close.c sem-destroy.c sem-getvalue.c sem-init.c sem-open.c sem-post.c sem-timedwait.c sem-trywait.c sem-unlink.c and sem-wait.c. (sysdeps_headers): Add semaphore.h bits/semaphore.h. * include/semaphore.h: New file. * sysdeps/generic/sem-close.c: New file. * sysdeps/generic/sem-destroy.c: New file. * sysdeps/generic/sem-getvalue.c: New file. * sysdeps/generic/sem-init.c: New file. * sysdeps/generic/sem-open.c: New file. * sysdeps/generic/sem-post.c: New file. * sysdeps/generic/sem-timedwait.c: New file. * sysdeps/generic/sem-trywait.c: New file. * sysdeps/generic/sem-unlink.c: New file. * sysdeps/generic/sem-wait.c: New file. * sysdeps/generic/bits/semaphore.h: New file. --- sysdeps/generic/bits/semaphore.h | 43 +++++++++++++++++++ sysdeps/generic/sem-close.c | 32 ++++++++++++++ sysdeps/generic/sem-destroy.c | 38 +++++++++++++++++ sysdeps/generic/sem-getvalue.c | 33 ++++++++++++++ sysdeps/generic/sem-init.c | 46 ++++++++++++++++++++ sysdeps/generic/sem-open.c | 32 ++++++++++++++ sysdeps/generic/sem-post.c | 62 +++++++++++++++++++++++++++ sysdeps/generic/sem-timedwait.c | 92 ++++++++++++++++++++++++++++++++++++++++ sysdeps/generic/sem-trywait.c | 42 ++++++++++++++++++ sysdeps/generic/sem-unlink.c | 32 ++++++++++++++ sysdeps/generic/sem-wait.c | 32 ++++++++++++++ 11 files changed, 484 insertions(+) create mode 100644 sysdeps/generic/bits/semaphore.h create mode 100644 sysdeps/generic/sem-close.c create mode 100644 sysdeps/generic/sem-destroy.c create mode 100644 sysdeps/generic/sem-getvalue.c create mode 100644 sysdeps/generic/sem-init.c create mode 100644 sysdeps/generic/sem-open.c create mode 100644 sysdeps/generic/sem-post.c create mode 100644 sysdeps/generic/sem-timedwait.c create mode 100644 sysdeps/generic/sem-trywait.c create mode 100644 sysdeps/generic/sem-unlink.c create mode 100644 sysdeps/generic/sem-wait.c diff --git a/sysdeps/generic/bits/semaphore.h b/sysdeps/generic/bits/semaphore.h new file mode 100644 index 00000000..b53f47e3 --- /dev/null +++ b/sysdeps/generic/bits/semaphore.h @@ -0,0 +1,43 @@ +/* Semaphore type. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_SEMAPHORE_H +#define _BITS_SEMAPHORE_H 1 + +#ifndef _SEMAPHORE_H +#error Never include directly. +#endif + +#include + +/* User visible part of a semaphore. */ +struct __semaphore + { + __pthread_spinlock_t __lock; + struct __pthread *__queue; + int __pshared; + int __value; + void *__data; + }; + +/* Initializer for a semaphore. */ +#define __SEMAPHORE_INITIALIZER(pshared, value) \ + { __SPIN_LOCK_INITIALIZER, NULL, (pshared), (value), NULL } + +#endif /* bits/mutex.h */ diff --git a/sysdeps/generic/sem-close.c b/sysdeps/generic/sem-close.c new file mode 100644 index 00000000..b82946bf --- /dev/null +++ b/sysdeps/generic/sem-close.c @@ -0,0 +1,32 @@ +/* Close a named semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_close (sem_t *sem) +{ + errno = EOPNOTSUPP; + return -1; +} + +weak_alias (__sem_close, sem_close); diff --git a/sysdeps/generic/sem-destroy.c b/sysdeps/generic/sem-destroy.c new file mode 100644 index 00000000..693b06dd --- /dev/null +++ b/sysdeps/generic/sem-destroy.c @@ -0,0 +1,38 @@ +/* Destroy a semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_destroy (sem_t *sem) +{ + if (sem->__queue) + /* There are threads waiting on *SEM. */ + { + errno = EBUSY; + return -1; + } + + return 0; +} + +weak_alias (__sem_destroy, sem_destroy); diff --git a/sysdeps/generic/sem-getvalue.c b/sysdeps/generic/sem-getvalue.c new file mode 100644 index 00000000..cb0439c4 --- /dev/null +++ b/sysdeps/generic/sem-getvalue.c @@ -0,0 +1,33 @@ +/* Get the value of a semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +__sem_getvalue (sem_t *restrict sem, int *restrict value) +{ + __pthread_spin_lock (&sem->__lock); + *value = sem->__value; + __pthread_spin_unlock (&sem->__lock); + + return 0; +} + +weak_alias (__sem_getvalue, sem_getvalue); diff --git a/sysdeps/generic/sem-init.c b/sysdeps/generic/sem-init.c new file mode 100644 index 00000000..f516ec98 --- /dev/null +++ b/sysdeps/generic/sem-init.c @@ -0,0 +1,46 @@ +/* Initialize a semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_init (sem_t *sem, int pshared, unsigned value) +{ + if (pshared != 0) + { + errno = EOPNOTSUPP; + return -1; + } + +#ifdef SEM_VALUE_MAX + if (value > SEM_VALUE_MAX) + { + errno = EINVAL; + return -1; + } +#endif + + *sem = (sem_t) __SEMAPHORE_INITIALIZER (pshared, value); + return 0; +} + +weak_alias (__sem_init, sem_init); diff --git a/sysdeps/generic/sem-open.c b/sysdeps/generic/sem-open.c new file mode 100644 index 00000000..426cbdb8 --- /dev/null +++ b/sysdeps/generic/sem-open.c @@ -0,0 +1,32 @@ +/* Open a named semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +sem_t * +__sem_open (const char *name, int open_flags, ...) +{ + errno = EOPNOTSUPP; + return SEM_FAILED; +} + +weak_alias (__sem_open, sem_open); diff --git a/sysdeps/generic/sem-post.c b/sysdeps/generic/sem-post.c new file mode 100644 index 00000000..c283784e --- /dev/null +++ b/sysdeps/generic/sem-post.c @@ -0,0 +1,62 @@ +/* Post a semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_post (sem_t *sem) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Do a quick up. */ + { + assert (! sem->__queue); + sem->__value ++; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + if (! sem->__queue) + /* No one waiting. */ + { + sem->__value = 1; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + /* Wake someone up. */ + + /* First dequeue someone. */ + wakeup = sem->__queue; + __pthread_dequeue (wakeup); + + /* Then drop the lock and transfer control. */ + __pthread_spin_unlock (&sem->__lock); + + __pthread_wakeup (wakeup); + + return 0; +} + +weak_alias (__sem_post, sem_post); diff --git a/sysdeps/generic/sem-timedwait.c b/sysdeps/generic/sem-timedwait.c new file mode 100644 index 00000000..f3d280b7 --- /dev/null +++ b/sysdeps/generic/sem-timedwait.c @@ -0,0 +1,92 @@ +/* Wait on a semaphore with a timeout. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +int +__sem_timedwait_internal (sem_t *restrict sem, + const struct timespec *restrict timeout) +{ + struct __pthread *self; + + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Successful down. */ + { + sem->__value --; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + /* Add ourselves to the queue. */ + self = _pthread_self (); + + __pthread_enqueue (&sem->__queue, self); + __pthread_spin_unlock (&sem->__lock); + + /* Block the thread. */ + if (timeout) + { + error_t err; + + if (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000) + { + errno = EINVAL; + return -1; + } + + err = __pthread_timedblock (self, timeout); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&sem->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&sem->__lock); + + errno = err; + return -1; + } + } + else + __pthread_block (self); + + return 0; +} + +int +__sem_timedwait (sem_t *restrict sem, + const struct timespec *restrict timeout) +{ + return __sem_timedwait_internal (sem, timeout); +} + +weak_alias (__sem_timedwait, sem_timedwait); diff --git a/sysdeps/generic/sem-trywait.c b/sysdeps/generic/sem-trywait.c new file mode 100644 index 00000000..e47d5595 --- /dev/null +++ b/sysdeps/generic/sem-trywait.c @@ -0,0 +1,42 @@ +/* Lock a semaphore if it does not require blocking. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_trywait (sem_t *sem) +{ + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Successful down. */ + { + sem->__value --; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + __pthread_spin_unlock (&sem->__lock); + + errno = EAGAIN; + return -1; +} + +weak_alias (__sem_trywait, sem_trywait); diff --git a/sysdeps/generic/sem-unlink.c b/sysdeps/generic/sem-unlink.c new file mode 100644 index 00000000..95b63ed8 --- /dev/null +++ b/sysdeps/generic/sem-unlink.c @@ -0,0 +1,32 @@ +/* Unlink a named semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_unlink (const char *name) +{ + errno = EOPNOTSUPP; + return -1; +} + +weak_alias (__sem_unlink, sem_unlink); diff --git a/sysdeps/generic/sem-wait.c b/sysdeps/generic/sem-wait.c new file mode 100644 index 00000000..46c7baf4 --- /dev/null +++ b/sysdeps/generic/sem-wait.c @@ -0,0 +1,32 @@ +/* Wait on a semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +extern int __sem_timedwait_internal (sem_t *restrict sem, + const struct timespec *restrict timeout); + +int +__sem_wait (sem_t *sem) +{ + return __sem_timedwait_internal (sem, 0); +} + +weak_alias (__sem_wait, sem_wait); -- cgit v1.2.3 From 1c31ded80a4e76294ba08b2da2117b0af8c5cdaa Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 12 May 2005 20:55:38 +0000 Subject: libpthread/ 2005-05-12 Neal H. Walfield * include/pthread/pthread.h (pthread_exit): Add noreturn attribute. * sysdeps/generic/bits/condition.h (__PTHREAD_COND_INITIALIZER): Don't create a compound literal. * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_INITIALIZER): Don't create a compound literal. (pthread_mutex_init): Don't assign to *__MUTEX directly. Initialize an intermediate local variable and then copy the result. * sysdeps/generic/bits/rwlock.h (__PTHREAD_RWLOCK_INITIALIZER): Don't create a compound literal. (pthread_rwlock_init): Don't assign to *__RWLOCK directly. Initialize an intermediate local variable and then copy the result. * sysdeps/i386/bits/spin-lock.h (__SPIN_LOCK_INITIALIZER): Don't create a compound literal. * pthread/pt-alloc.c (initialize_pthread): Cast PTHREAD_MUTEX_INITIALIZER and PTHREAD_COND_INITIALIZER to create a compound literal. * tests/test-1.c (main): Use pthread_mutex_init, not PTHREAD_MUTEX_INIT for mutex initialization * sysdeps/generic/pt-barrier-init.c (pthread_barrier_init): Remove assert. Copy ATTR if non-defaults are used. * sysdeps/generic/pt-cond-init.c (pthread_cond_init): Include . Remove assert. Copy ATTR if non-defaults are used. * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): Cast PTHREAD_MUTEX_INITIALIZER to create a compound literal. * sysdeps/generic/pt-rwlock-init.c: Include . (_pthread_rwlock_init): Cast __PTHREAD_RWLOCK_INITIALIZER to create a compound literal. Copy ATTR if non-defaults are used. * sysdeps/generic/pt-cond-timedwait.c (__pthread_cond_timedwait_internal): Check that ABSTIME->TV_NSEC is valid. Don't shadow ERR. Don't return before cleaning up. * sysdeps/generic/pt-mutex-timedlock.c (pthread_mutex_timedlock): Move after __pthread_mutex_timedlock_internal. Check that ABSTIME->TV_NSEC is valid. * sysdeps/generic/pt-rwlock-timedrdlock.c (pthread_rwlock_timedrdlock): Move after. __pthread_rwlock_timedrdlock_internal. (__pthread_rwlock_timedrdlock_internal): Check that ABSTIME->TV_NSEC is valid. * sysdeps/generic/pt-rwlock-timedwrlock.c (pthread_rwlock_timedwrlock): Move after __pthread_rwlock_timedwrlock_internal. (__pthread_rwlock_timedwrlock_internal): Check that ABSTIME->TV_NSEC is valid. * sysdeps/generic/sem-timedwait.c (__sem_timedwait_internal): Check that TIMEOUT->TV_NSEC is valid before enqueuing the thread. * sysdeps/generic/pt-rwlock-rdlock.c (__pthread_rwlock_timedrdlock_internal): Fix declaration. * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock): Don't return EDEADLK. POSIX does not allow it. * sysdeps/mach/pt-timedblock.c (__pthread_timedblock): Calculate the relative timeout without overflowing. * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Cast THREAD. --- pthread/pt-alloc.c | 4 ++-- sysdeps/generic/bits/condition.h | 5 ++--- sysdeps/generic/bits/mutex.h | 10 +++++----- sysdeps/generic/bits/rwlock.h | 8 ++++---- sysdeps/generic/pt-barrier-init.c | 16 +++++++++++++--- sysdeps/generic/pt-cond-init.c | 17 ++++++++++++++--- sysdeps/generic/pt-cond-timedwait.c | 9 ++++----- sysdeps/generic/pt-mutex-init.c | 4 ++-- sysdeps/generic/pt-mutex-timedlock.c | 19 +++++++++++-------- sysdeps/generic/pt-mutex-trylock.c | 5 +++-- sysdeps/generic/pt-rwlock-init.c | 18 ++++++++++++++++-- sysdeps/generic/pt-rwlock-rdlock.c | 4 ++-- sysdeps/generic/pt-rwlock-timedrdlock.c | 19 +++++++++++-------- sysdeps/generic/pt-rwlock-timedwrlock.c | 19 +++++++++++-------- sysdeps/generic/sem-timedwait.c | 12 ++++++------ sysdeps/i386/bits/spin-lock.h | 4 ++-- sysdeps/mach/hurd/i386/pt-setup.c | 4 ++-- sysdeps/mach/pt-timedblock.c | 22 +++++++++++++++------- tests/test-1.c | 2 +- 19 files changed, 126 insertions(+), 75 deletions(-) diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index e8d3c033..30dcede0 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -69,8 +69,8 @@ initialize_pthread (struct __pthread *new, int recycling) new->stack = 0; - new->state_lock = PTHREAD_MUTEX_INITIALIZER; - new->state_cond = PTHREAD_COND_INITIALIZER; + new->state_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + new->state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER; new->cancelation_handlers = 0; diff --git a/sysdeps/generic/bits/condition.h b/sysdeps/generic/bits/condition.h index cb7e935c..f3b09be4 100644 --- a/sysdeps/generic/bits/condition.h +++ b/sysdeps/generic/bits/condition.h @@ -1,5 +1,5 @@ /* Condition type. Generic version. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2005 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 @@ -34,7 +34,6 @@ struct __pthread_cond /* Initializer for a condition variable. */ #define __PTHREAD_COND_INITIALIZER \ - ((struct __pthread_cond) \ - { __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL }) + { __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL } #endif /* bits/condition.h */ diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 9958b8d1..2e32d783 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -1,5 +1,5 @@ /* Mutex type. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -52,9 +52,7 @@ struct __pthread_mutex /* Initializer for a mutex. N.B. this also happens to be compatible with the cthread mutex initializer. */ # define __PTHREAD_MUTEX_INITIALIZER \ - ((struct __pthread_mutex) \ - { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, \ - NULL, 0, 0 }) + { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } # endif #endif /* Not __pthread_mutex_defined. */ @@ -74,13 +72,15 @@ _EXTERN_INLINE int pthread_mutex_init (struct __pthread_mutex *__mutex, const pthread_mutexattr_t *attr) { + struct __pthread_mutex initialized_mutex = __PTHREAD_MUTEX_INITIALIZER; + extern int _pthread_mutex_init (struct __pthread_mutex *, const pthread_mutexattr_t *); if (attr) return _pthread_mutex_init (__mutex, attr); - *__mutex = __PTHREAD_MUTEX_INITIALIZER; + *__mutex = initialized_mutex; return 0; } diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h index d089b0c6..5793f65d 100644 --- a/sysdeps/generic/bits/rwlock.h +++ b/sysdeps/generic/bits/rwlock.h @@ -1,5 +1,5 @@ /* rwlock type. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -40,21 +40,21 @@ struct __pthread_rwlock /* Initializer for a rwlock. */ #define __PTHREAD_RWLOCK_INITIALIZER \ - ((struct __pthread_rwlock) \ - { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 }) + { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } _EXTERN_INLINE int pthread_rwlock_init (struct __pthread_rwlock *__rwlock, const struct __pthread_rwlockattr *__attr) { + struct __pthread_rwlock initialized_rwlock = __PTHREAD_RWLOCK_INITIALIZER; extern int _pthread_rwlock_init (struct __pthread_rwlock *, const struct __pthread_rwlockattr *); if (__attr) return _pthread_rwlock_init (__rwlock, __attr); - *__rwlock = __PTHREAD_RWLOCK_INITIALIZER; + *__rwlock = initialized_rwlock; return 0; } diff --git a/sysdeps/generic/pt-barrier-init.c b/sysdeps/generic/pt-barrier-init.c index 57911d51..c42b3bb6 100644 --- a/sysdeps/generic/pt-barrier-init.c +++ b/sysdeps/generic/pt-barrier-init.c @@ -1,5 +1,5 @@ /* pthread_barrier_init. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -28,8 +28,6 @@ pthread_barrier_init (pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned count) { - assert (attr->pshared == PTHREAD_PROCESS_PRIVATE); - if (count == 0) return EINVAL; @@ -39,5 +37,17 @@ pthread_barrier_init (pthread_barrier_t *barrier, barrier->pending = count; barrier->count = count; + if (! attr + || memcmp (attr, &__pthread_default_barrierattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + barrier->attr = malloc (sizeof *attr); + if (! barrier->attr) + return ENOMEM; + + *barrier->attr = *attr; return 0; } diff --git a/sysdeps/generic/pt-cond-init.c b/sysdeps/generic/pt-cond-init.c index 4afcc94e..b9e9fb7a 100644 --- a/sysdeps/generic/pt-cond-init.c +++ b/sysdeps/generic/pt-cond-init.c @@ -19,6 +19,7 @@ #include #include +#include #include @@ -26,9 +27,19 @@ int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr) { - if (attr) - assert (attr->pshared == PTHREAD_PROCESS_PRIVATE); + *cond = (pthread_cond_t) __PTHREAD_COND_INITIALIZER; - *cond = __PTHREAD_COND_INITIALIZER; + if (! attr + || memcmp (attr, &__pthread_default_condattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + cond->__attr = malloc (sizeof *attr); + if (! cond->__attr) + return ENOMEM; + + *cond->__attr = *attr; return 0; } diff --git a/sysdeps/generic/pt-cond-timedwait.c b/sysdeps/generic/pt-cond-timedwait.c index 4abeb71c..c10bdb30 100644 --- a/sysdeps/generic/pt-cond-timedwait.c +++ b/sysdeps/generic/pt-cond-timedwait.c @@ -1,5 +1,5 @@ /* Wait on a condition. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -58,6 +58,9 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond, __pthread_mutex_lock (mutex); } + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + struct __pthread *self = _pthread_self (); /* Add ourselves to the list of waiters. */ @@ -74,8 +77,6 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond, if (abstime) { - error_t err; - err = __pthread_timedblock (self, abstime); if (err) /* We timed out. We may need to disconnect ourself from the @@ -91,8 +92,6 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond, if (self->prevp) __pthread_dequeue (self); __pthread_spin_unlock (&mutex->__lock); - - return err; } } else diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c index 2902f6e4..23c9f0d9 100644 --- a/sysdeps/generic/pt-mutex-init.c +++ b/sysdeps/generic/pt-mutex-init.c @@ -1,5 +1,5 @@ /* Initialize a mutex. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -28,7 +28,7 @@ int _pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { - *mutex = __PTHREAD_MUTEX_INITIALIZER; + *mutex = (pthread_mutex_t) __PTHREAD_MUTEX_INITIALIZER; if (! attr || memcmp (attr, &__pthread_default_mutexattr, sizeof (*attr) == 0)) diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index 3603986c..5e222bd3 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -1,5 +1,5 @@ /* Lock a mutex with a timeout. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -24,13 +24,6 @@ #define LOSE do { * (int *) 0 = 0; } while (1) -int -pthread_mutex_timedlock (struct __pthread_mutex *mutex, - const struct timespec *abstime) -{ - return __pthread_mutex_timedlock_internal (mutex, abstime); -} - /* Try to lock MUTEX, block until *ABSTIME if it is already held. As a GNU extension, if TIMESPEC is NULL then wait forever. */ int @@ -96,6 +89,9 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, } } + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + /* Add ourselves to the queue. */ __pthread_enqueue (&mutex->__queue, self); __pthread_spin_unlock (&mutex->__lock); @@ -146,3 +142,10 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, return 0; } + +int +pthread_mutex_timedlock (struct __pthread_mutex *mutex, + const struct timespec *abstime) +{ + return __pthread_mutex_timedlock_internal (mutex, abstime); +} diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index 9457ddac..6fdea1ae 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -65,8 +65,9 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) break; case PTHREAD_MUTEX_ERRORCHECK: - if (mutex->owner == self) - err = EDEADLK; + /* We could check if MUTEX->OWNER is SELF, however, POSIX + does not permit pthread_mutex_trylock to return EDEADLK + instead of EBUSY, only pthread_mutex_lock. */ break; case PTHREAD_MUTEX_RECURSIVE: diff --git a/sysdeps/generic/pt-rwlock-init.c b/sysdeps/generic/pt-rwlock-init.c index 8fe87644..d6c8c1ae 100644 --- a/sysdeps/generic/pt-rwlock-init.c +++ b/sysdeps/generic/pt-rwlock-init.c @@ -1,5 +1,5 @@ /* Initialize a rwlock. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -18,13 +18,27 @@ Boston, MA 02111-1307, USA. */ #include +#include #include int _pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { - *rwlock = __PTHREAD_RWLOCK_INITIALIZER; + *rwlock = (pthread_rwlock_t) __PTHREAD_RWLOCK_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_rwlockattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + rwlock->__attr = malloc (sizeof *attr); + if (! rwlock->__attr) + return ENOMEM; + + *rwlock->__attr = *attr; return 0; } diff --git a/sysdeps/generic/pt-rwlock-rdlock.c b/sysdeps/generic/pt-rwlock-rdlock.c index 22c11204..480cf489 100644 --- a/sysdeps/generic/pt-rwlock-rdlock.c +++ b/sysdeps/generic/pt-rwlock-rdlock.c @@ -1,5 +1,5 @@ /* Acquire a rwlock for reading. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -21,7 +21,7 @@ #include /* Implemented in pt-rwlock-timedrdlock.c. */ -extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_mutex *mutex, +extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, const struct timespec *abstime); /* Acquire RWLOCK for reading, block if we can't get it. */ diff --git a/sysdeps/generic/pt-rwlock-timedrdlock.c b/sysdeps/generic/pt-rwlock-timedrdlock.c index 85cb9468..ba610fa5 100644 --- a/sysdeps/generic/pt-rwlock-timedrdlock.c +++ b/sysdeps/generic/pt-rwlock-timedrdlock.c @@ -1,5 +1,5 @@ /* Acquire a rwlock for reading. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -22,13 +22,6 @@ #include -int -pthread_rwlock_timedrdlock (struct __pthread_rwlock *rwlock, - const struct timespec *abstime) -{ - return __pthread_rwlock_timedrdlock_internal (rwlock, abstime); -} - /* Acquire the rwlock *RWLOCK for reading blocking until *ABSTIME if it is already held. As a GNU extension, if TIMESPEC is NULL then wait forever. */ @@ -66,6 +59,9 @@ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, /* Better be blocked by a writer. */ assert (rwlock->readers == 0); + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + self = _pthread_self (); /* Add ourself to the queue. */ @@ -108,3 +104,10 @@ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, return 0; } + +int +pthread_rwlock_timedrdlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedrdlock_internal (rwlock, abstime); +} diff --git a/sysdeps/generic/pt-rwlock-timedwrlock.c b/sysdeps/generic/pt-rwlock-timedwrlock.c index edf6413f..04eab51f 100644 --- a/sysdeps/generic/pt-rwlock-timedwrlock.c +++ b/sysdeps/generic/pt-rwlock-timedwrlock.c @@ -1,5 +1,5 @@ /* Acquire a rwlock for writing. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -22,13 +22,6 @@ #include -int -pthread_rwlock_timedwrlock (struct __pthread_rwlock *rwlock, - const struct timespec *abstime) -{ - return __pthread_rwlock_timedwrlock_internal (rwlock, abstime); -} - /* Acquire RWLOCK for writing blocking until *ABSTIME if we cannot get it. As a special GNU extension, if ABSTIME is NULL then the wait shall not time out. */ @@ -52,6 +45,9 @@ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, /* The lock is busy. */ + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + self = _pthread_self (); /* Add ourselves to the queue. */ @@ -90,3 +86,10 @@ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, return 0; } + +int +pthread_rwlock_timedwrlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedwrlock_internal (rwlock, abstime); +} diff --git a/sysdeps/generic/sem-timedwait.c b/sysdeps/generic/sem-timedwait.c index f3d280b7..0c521117 100644 --- a/sysdeps/generic/sem-timedwait.c +++ b/sysdeps/generic/sem-timedwait.c @@ -39,6 +39,12 @@ __sem_timedwait_internal (sem_t *restrict sem, return 0; } + if (timeout && (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000)) + { + errno = EINVAL; + return -1; + } + /* Add ourselves to the queue. */ self = _pthread_self (); @@ -50,12 +56,6 @@ __sem_timedwait_internal (sem_t *restrict sem, { error_t err; - if (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000) - { - errno = EINVAL; - return -1; - } - err = __pthread_timedblock (self, timeout); if (err) /* We timed out. We may need to disconnect ourself from the diff --git a/sysdeps/i386/bits/spin-lock.h b/sysdeps/i386/bits/spin-lock.h index 3176a15f..e86bc13e 100644 --- a/sysdeps/i386/bits/spin-lock.h +++ b/sysdeps/i386/bits/spin-lock.h @@ -1,5 +1,5 @@ /* Machine-specific definitions for spin locks. i386 version. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2005 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 @@ -32,7 +32,7 @@ __BEGIN_DECLS typedef __volatile int __pthread_spinlock_t; /* Initializer for a spin lock object. */ -# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) +# define __SPIN_LOCK_INITIALIZER (0) #if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c index 9a855847..32ace6ad 100644 --- a/sysdeps/mach/hurd/i386/pt-setup.c +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -1,5 +1,5 @@ /* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -58,7 +58,7 @@ stack_setup (struct __pthread *thread, top -= __hurd_threadvar_max; /* Save the self pointer. */ - top[_HURD_THREADVAR_THREAD] = thread; + top[_HURD_THREADVAR_THREAD] = (void *) thread; if (start_routine) { diff --git a/sysdeps/mach/pt-timedblock.c b/sysdeps/mach/pt-timedblock.c index 6324ae76..ddb8baec 100644 --- a/sysdeps/mach/pt-timedblock.c +++ b/sysdeps/mach/pt-timedblock.c @@ -1,5 +1,5 @@ /* Block a thread with a timeout. Mach version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -34,7 +34,7 @@ __pthread_timedblock (struct __pthread *thread, { error_t err; mach_msg_header_t msg; - mach_msg_timeout_t ms; + mach_msg_timeout_t timeout; struct timeval now; /* We have an absolute time and now we have to convert it to a @@ -43,15 +43,23 @@ __pthread_timedblock (struct __pthread *thread, err = gettimeofday(&now, NULL); assert (! err); - ms = abstime->tv_sec * 1000 + (abstime->tv_nsec + 999999) / 1000000 - - now.tv_sec * 1000 - (now.tv_usec + 999) / 1000; - - if (ms <= 0) + if (now.tv_sec > abstime->tv_sec + || (now.tv_sec == abstime->tv_sec + && now.tv_usec > ((abstime->tv_nsec + 999) / 1000))) return ETIMEDOUT; + timeout = (abstime->tv_sec - now.tv_sec) * 1000; + + if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec) + timeout -= (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000; + else + /* Need to do a carry. */ + timeout -= 1000 + ((abstime->tv_nsec + 999999) / 1000000) + - (now.tv_usec + 999) / 1000; + err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, sizeof msg, thread->wakeupmsg.msgh_remote_port, - ms, MACH_PORT_NULL); + timeout, MACH_PORT_NULL); if (err == EMACH_RCV_TIMED_OUT) return ETIMEDOUT; diff --git a/tests/test-1.c b/tests/test-1.c index 86c7c97e..318fd6e9 100644 --- a/tests/test-1.c +++ b/tests/test-1.c @@ -27,7 +27,7 @@ main (int argc, char **argv) for (i = 0; i < THREADS; i ++) { - mutex[i] = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_init (&mutex[i], 0); pthread_mutex_lock (&mutex[i]); err = pthread_create (&tid[i], 0, foo, &mutex[i]); if (err) -- cgit v1.2.3 From b84dccc8e92cf6de249bcc5ae1c40af82ad233ec Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 20 Jan 2007 13:07:06 +0000 Subject: 2006-01-20 Samuel Thibault Do not let other libraries (like libX11) override libpthread's pthread_mutex_*, pthread_rwlock_* and sem_* dynamic symbols. * libpthread/sysdeps/generic/pt-mutex-destroy.c (pthread_mutex_destroy): Make the alias strong. * libpthread/sysdeps/generic/pt-mutex-init.c (pthread_mutex_init): Likewise. * libpthread/sysdeps/generic/pt-mutex-lock.c (_pthread_mutex_lock, pthread_mutex_lock): Likewise. * libpthread/sysdeps/generic/pt-mutex-trylock.c (_pthread_mutex_trylock, pthread_mutex_trylock): Likewise. * libpthread/sysdeps/generic/pt-mutex-unlock.c (_pthread_mutex_lock, pthread_mutex_unlock): Likewise. * libpthread/sysdeps/generic/pt-rwlock-destroy.c (pthread_rwlock_destroy): Likewise. * libpthread/sysdeps/generic/pt-rwlock-init.c (pthread_rwlock_init): Likewise. * libpthread/sysdeps/generic/sem-destroy.c (sem_destroy): Likewise. * libpthread/sysdeps/generic/sem-getvalue.c (sem_getvalue): Likewise. * libpthread/sysdeps/generic/sem-init.c (sem_init): Likewise. * libpthread/sysdeps/generic/sem-open.c (sem_open): Likewise. * libpthread/sysdeps/generic/sem-post.c (sem_post): Likewise. * libpthread/sysdeps/generic/sem-timedwait.c (sem_timedwait): Likewise. * libpthread/sysdeps/generic/sem-trywait.c (sem_trywait): Likewise. * libpthread/sysdeps/generic/sem-unlink.c (sem_unlink): Likewise. * libpthread/sysdeps/generic/sem-wait.c (sem_wait): Likewise. --- sysdeps/generic/pt-mutex-destroy.c | 2 +- sysdeps/generic/pt-mutex-init.c | 2 +- sysdeps/generic/pt-mutex-lock.c | 4 ++-- sysdeps/generic/pt-mutex-trylock.c | 4 ++-- sysdeps/generic/pt-mutex-unlock.c | 4 ++-- sysdeps/generic/pt-rwlock-destroy.c | 2 +- sysdeps/generic/pt-rwlock-init.c | 2 +- sysdeps/generic/sem-close.c | 2 +- sysdeps/generic/sem-destroy.c | 2 +- sysdeps/generic/sem-getvalue.c | 2 +- sysdeps/generic/sem-init.c | 2 +- sysdeps/generic/sem-open.c | 2 +- sysdeps/generic/sem-post.c | 2 +- sysdeps/generic/sem-timedwait.c | 2 +- sysdeps/generic/sem-trywait.c | 2 +- sysdeps/generic/sem-unlink.c | 2 +- sysdeps/generic/sem-wait.c | 2 +- 17 files changed, 20 insertions(+), 20 deletions(-) diff --git a/sysdeps/generic/pt-mutex-destroy.c b/sysdeps/generic/pt-mutex-destroy.c index d9fb59ce..72faefe6 100644 --- a/sysdeps/generic/pt-mutex-destroy.c +++ b/sysdeps/generic/pt-mutex-destroy.c @@ -32,4 +32,4 @@ _pthread_mutex_destroy (pthread_mutex_t *mutex) return 0; } -weak_alias (_pthread_mutex_destroy, pthread_mutex_destroy); +strong_alias (_pthread_mutex_destroy, pthread_mutex_destroy); diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c index 23c9f0d9..da1781bf 100644 --- a/sysdeps/generic/pt-mutex-init.c +++ b/sysdeps/generic/pt-mutex-init.c @@ -45,4 +45,4 @@ _pthread_mutex_init (pthread_mutex_t *mutex, return 0; } -weak_alias (_pthread_mutex_init, pthread_mutex_init); +strong_alias (_pthread_mutex_init, pthread_mutex_init); diff --git a/sysdeps/generic/pt-mutex-lock.c b/sysdeps/generic/pt-mutex-lock.c index 58d3827c..60fc55ab 100644 --- a/sysdeps/generic/pt-mutex-lock.c +++ b/sysdeps/generic/pt-mutex-lock.c @@ -33,5 +33,5 @@ __pthread_mutex_lock (struct __pthread_mutex *mutex) return __pthread_mutex_timedlock_internal (mutex, 0); } -weak_alias (__pthread_mutex_lock, _pthread_mutex_lock); -weak_alias (__pthread_mutex_lock, pthread_mutex_lock); +strong_alias (__pthread_mutex_lock, _pthread_mutex_lock); +strong_alias (__pthread_mutex_lock, pthread_mutex_lock); diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index 6fdea1ae..d56f6e1c 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -88,5 +88,5 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) return err; } -weak_alias (__pthread_mutex_trylock, _pthread_mutex_trylock); -weak_alias (__pthread_mutex_trylock, pthread_mutex_trylock); +strong_alias (__pthread_mutex_trylock, _pthread_mutex_trylock); +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock); diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index bbbe2b8f..2f719d3e 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -78,5 +78,5 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) return 0; } -weak_alias (__pthread_mutex_unlock, _pthread_mutex_unlock); -weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock); +strong_alias (__pthread_mutex_unlock, _pthread_mutex_unlock); +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock); diff --git a/sysdeps/generic/pt-rwlock-destroy.c b/sysdeps/generic/pt-rwlock-destroy.c index f63c84d9..034d9300 100644 --- a/sysdeps/generic/pt-rwlock-destroy.c +++ b/sysdeps/generic/pt-rwlock-destroy.c @@ -26,4 +26,4 @@ _pthread_rwlock_destroy (pthread_rwlock_t *rwlock) return 0; } -weak_alias (_pthread_rwlock_destroy, pthread_rwlock_destroy); +strong_alias (_pthread_rwlock_destroy, pthread_rwlock_destroy); diff --git a/sysdeps/generic/pt-rwlock-init.c b/sysdeps/generic/pt-rwlock-init.c index d6c8c1ae..8aa495ec 100644 --- a/sysdeps/generic/pt-rwlock-init.c +++ b/sysdeps/generic/pt-rwlock-init.c @@ -42,4 +42,4 @@ _pthread_rwlock_init (pthread_rwlock_t *rwlock, return 0; } -weak_alias (_pthread_rwlock_init, pthread_rwlock_init); +strong_alias (_pthread_rwlock_init, pthread_rwlock_init); diff --git a/sysdeps/generic/sem-close.c b/sysdeps/generic/sem-close.c index b82946bf..9f48032f 100644 --- a/sysdeps/generic/sem-close.c +++ b/sysdeps/generic/sem-close.c @@ -29,4 +29,4 @@ __sem_close (sem_t *sem) return -1; } -weak_alias (__sem_close, sem_close); +strong_alias (__sem_close, sem_close); diff --git a/sysdeps/generic/sem-destroy.c b/sysdeps/generic/sem-destroy.c index 693b06dd..985f4ad3 100644 --- a/sysdeps/generic/sem-destroy.c +++ b/sysdeps/generic/sem-destroy.c @@ -35,4 +35,4 @@ __sem_destroy (sem_t *sem) return 0; } -weak_alias (__sem_destroy, sem_destroy); +strong_alias (__sem_destroy, sem_destroy); diff --git a/sysdeps/generic/sem-getvalue.c b/sysdeps/generic/sem-getvalue.c index cb0439c4..8e418e38 100644 --- a/sysdeps/generic/sem-getvalue.c +++ b/sysdeps/generic/sem-getvalue.c @@ -30,4 +30,4 @@ __sem_getvalue (sem_t *restrict sem, int *restrict value) return 0; } -weak_alias (__sem_getvalue, sem_getvalue); +strong_alias (__sem_getvalue, sem_getvalue); diff --git a/sysdeps/generic/sem-init.c b/sysdeps/generic/sem-init.c index f516ec98..6c6d79e7 100644 --- a/sysdeps/generic/sem-init.c +++ b/sysdeps/generic/sem-init.c @@ -43,4 +43,4 @@ __sem_init (sem_t *sem, int pshared, unsigned value) return 0; } -weak_alias (__sem_init, sem_init); +strong_alias (__sem_init, sem_init); diff --git a/sysdeps/generic/sem-open.c b/sysdeps/generic/sem-open.c index 426cbdb8..9eb13aae 100644 --- a/sysdeps/generic/sem-open.c +++ b/sysdeps/generic/sem-open.c @@ -29,4 +29,4 @@ __sem_open (const char *name, int open_flags, ...) return SEM_FAILED; } -weak_alias (__sem_open, sem_open); +strong_alias (__sem_open, sem_open); diff --git a/sysdeps/generic/sem-post.c b/sysdeps/generic/sem-post.c index c283784e..0e20ea7a 100644 --- a/sysdeps/generic/sem-post.c +++ b/sysdeps/generic/sem-post.c @@ -59,4 +59,4 @@ __sem_post (sem_t *sem) return 0; } -weak_alias (__sem_post, sem_post); +strong_alias (__sem_post, sem_post); diff --git a/sysdeps/generic/sem-timedwait.c b/sysdeps/generic/sem-timedwait.c index 0c521117..d01bfdb0 100644 --- a/sysdeps/generic/sem-timedwait.c +++ b/sysdeps/generic/sem-timedwait.c @@ -89,4 +89,4 @@ __sem_timedwait (sem_t *restrict sem, return __sem_timedwait_internal (sem, timeout); } -weak_alias (__sem_timedwait, sem_timedwait); +strong_alias (__sem_timedwait, sem_timedwait); diff --git a/sysdeps/generic/sem-trywait.c b/sysdeps/generic/sem-trywait.c index e47d5595..199f317b 100644 --- a/sysdeps/generic/sem-trywait.c +++ b/sysdeps/generic/sem-trywait.c @@ -39,4 +39,4 @@ __sem_trywait (sem_t *sem) return -1; } -weak_alias (__sem_trywait, sem_trywait); +strong_alias (__sem_trywait, sem_trywait); diff --git a/sysdeps/generic/sem-unlink.c b/sysdeps/generic/sem-unlink.c index 95b63ed8..519f4f7b 100644 --- a/sysdeps/generic/sem-unlink.c +++ b/sysdeps/generic/sem-unlink.c @@ -29,4 +29,4 @@ __sem_unlink (const char *name) return -1; } -weak_alias (__sem_unlink, sem_unlink); +strong_alias (__sem_unlink, sem_unlink); diff --git a/sysdeps/generic/sem-wait.c b/sysdeps/generic/sem-wait.c index 46c7baf4..50752f32 100644 --- a/sysdeps/generic/sem-wait.c +++ b/sysdeps/generic/sem-wait.c @@ -29,4 +29,4 @@ __sem_wait (sem_t *sem) return __sem_timedwait_internal (sem, 0); } -weak_alias (__sem_wait, sem_wait); +strong_alias (__sem_wait, sem_wait); -- cgit v1.2.3 From 3b7f26ed578b0550accc53658bff7f7e6b8bd35d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 3 Mar 2007 23:57:37 +0000 Subject: 2006-03-04 Samuel Thibault * libpthread/sysdeps/i386/machine-sp.h (thread_stack_pointer): Optimize esp read. * libpthread/i386/cthreads.h (cthread_sp): Likewise. --- sysdeps/i386/machine-sp.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sysdeps/i386/machine-sp.h b/sysdeps/i386/machine-sp.h index 536f6902..945a36b8 100644 --- a/sysdeps/i386/machine-sp.h +++ b/sysdeps/i386/machine-sp.h @@ -23,8 +23,7 @@ /* Return the current stack pointer. */ #define __thread_stack_pointer() ({ \ - void *__sp__; \ - __asm__ ("movl %%esp, %0" : "=r" (__sp__)); \ + register void *__sp__ asm("esp"); \ __sp__; \ }) -- cgit v1.2.3 From 2e10e74697a257cd032d586c0ec7413874758c82 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 4 Mar 2007 00:05:21 +0000 Subject: 2006-03-04 Samuel Thibault * libpthread/include/pthread/pthread.h: Add the restrict keyword where appropriate for full compliance. * libpthread/pthread/pt-internal.h: Likewise. * libpthread/sysdeps/generic/bits/mutex.h: Likewise. * libpthread/sysdeps/generic/bits/rwlock.h: Likewise. * libpthread/TODO: Drop that TODO item. --- pthread/pt-internal.h | 20 +++++++++++--------- sysdeps/generic/bits/mutex.h | 4 ++-- sysdeps/generic/bits/rwlock.h | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index e9086956..efd4ffb9 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -165,10 +165,10 @@ extern void __pthread_initialize (void); /* Internal version of pthread_create. Rather than return the new tid, we return the whole __pthread structure in *PTHREAD. */ -extern int __pthread_create_internal (struct __pthread **pthread, - const pthread_attr_t *attr, +extern int __pthread_create_internal (struct __pthread **__restrict pthread, + const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), - void *arg); + void *__restrict arg); /* Allocate a new thread structure and a pthread thread ID (but not a kernel thread or a stack). */ @@ -189,10 +189,11 @@ extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize); /* Setup thread THREAD's context. */ -extern int __pthread_setup (struct __pthread *thread, +extern int __pthread_setup (struct __pthread *__restrict thread, void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg); + void *(*start_routine)(void *), + void *__restrict arg); /* Allocate a kernel thread (and any miscellaneous system dependent @@ -221,8 +222,8 @@ extern void __pthread_thread_halt (struct __pthread *thread, extern void __pthread_block (struct __pthread *thread); /* Block THREAD until *ABSTIME is reached. */ -extern error_t __pthread_timedblock (struct __pthread *thread, - const struct timespec *abstime); +extern error_t __pthread_timedblock (struct __pthread *__restrict thread, + const struct timespec *__restrict abstime); /* Wakeup THREAD. */ extern void __pthread_wakeup (struct __pthread *thread); @@ -250,8 +251,9 @@ extern error_t __pthread_sigstate_init (struct __pthread *thread); extern void __pthread_sigstate_destroy (struct __pthread *thread); /* Modify thread *THREAD's signal state. */ -extern error_t __pthread_sigstate (struct __pthread *thread, int how, - const sigset_t *set, sigset_t *oset, +extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how, + const sigset_t *__restrict set, + sigset_t *__restrict oset, int clear_pending); diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 2e32d783..feb6d075 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -69,8 +69,8 @@ struct __pthread_mutex # endif _EXTERN_INLINE int -pthread_mutex_init (struct __pthread_mutex *__mutex, - const pthread_mutexattr_t *attr) +pthread_mutex_init (struct __pthread_mutex *__restrict __mutex, + const pthread_mutexattr_t *__restrict attr) { struct __pthread_mutex initialized_mutex = __PTHREAD_MUTEX_INITIALIZER; diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h index 5793f65d..fc429b45 100644 --- a/sysdeps/generic/bits/rwlock.h +++ b/sysdeps/generic/bits/rwlock.h @@ -44,8 +44,8 @@ struct __pthread_rwlock _EXTERN_INLINE int -pthread_rwlock_init (struct __pthread_rwlock *__rwlock, - const struct __pthread_rwlockattr *__attr) +pthread_rwlock_init (struct __pthread_rwlock *__restrict __rwlock, + const struct __pthread_rwlockattr *__restrict __attr) { struct __pthread_rwlock initialized_rwlock = __PTHREAD_RWLOCK_INITIALIZER; extern int _pthread_rwlock_init (struct __pthread_rwlock *, -- cgit v1.2.3 From 9b015d3e10df9242b0a0aa7ad8a0bd65746384b6 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 24 Jun 2007 15:11:52 +0000 Subject: 2007-06-24 Samuel Thibault * include/semaphore.h (sem_timedwait): Declare only if __USE_XOPEN2K is defined. * include/pthread/pthread.h (pthread_attr_getstack) (pthread_attr_setstack, pthread_mutex_timedlock) (pthread_condattr_getclock, pthread_condattr_setclock) (pthread_rwlock_timedrdlock, pthread_rwlock_timedwrlock) (pthread_barrierattr_t, pthread_barrierattr_init) (pthread_barrierattr_destroy, pthread_barrierattr_getpshared) (pthread_barrierattr_setpshared, pthread_barrier_t) (PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_init) (pthread_barrier_destroy, pthread_barrier_wait) (pthread_getcpuclockid): Declare only if __USE_XOPEN2K is defined. (pthread_mutexattr_getprioceiling, pthread_mutexattr_setprioceiling) (pthread_mutexattr_getprotocol, pthread_mutexattr_setprotocol) (pthread_mutexattr_gettype, pthread_mutexattr_settype) (pthread_mutex_getprioceiling, pthread_mutex_setprioceiling) (pthread_setconcurrency, pthread_getconcurrency): Declare only if __USE_UNIX98 is defined. (pthread_rwlockattr_t, pthread_rwlockattr_init) (pthread_rwlockattr_destroy, pthread_rwlockattr_getpshared) (pthread_rwlockattr_setpshared, pthread_rwlock_t, pthread_rwlock_init) (pthread_rwlock_destroy, pthread_rwlock_rdlock) (pthread_rwlock_tryrdlock, pthread_rwlock_wrlock) (pthread_rwlock_trywrlock, pthread_rwlock_unlock): Declare only if __USE_UNIX98 or __USE_XOPEN2K are defined. (PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, PTHREAD_PRIO_PROTECT) (PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_ERRORCHECK) (PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_DEFAULT): Define only if __USE_UNIX98 is defined. (PTHREAD_MUTEX_FAST_NP): Define for compatibility when __USE_GNU is defined. * sysdeps/generic/bits/rwlock.h (pthread_rwlock_init) (pthread_rwlock_destroy): Declare only if __USE_UNIX98 or __USE_XOPEN2K are defined. * TODO: Drop that TODO item. --- sysdeps/generic/bits/rwlock.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h index fc429b45..5afc4a37 100644 --- a/sysdeps/generic/bits/rwlock.h +++ b/sysdeps/generic/bits/rwlock.h @@ -43,6 +43,7 @@ struct __pthread_rwlock { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } +#if defined __USE_UNIX98 || defined __USE_XOPEN2K _EXTERN_INLINE int pthread_rwlock_init (struct __pthread_rwlock *__restrict __rwlock, const struct __pthread_rwlockattr *__restrict __attr) @@ -69,5 +70,6 @@ pthread_rwlock_destroy (struct __pthread_rwlock *__rwlock) return 0; } +#endif #endif /* bits/rwlock.h */ -- cgit v1.2.3 From 8caaa8379e5a1500863792514189d6e8f414dcaf Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 2 Aug 2007 22:51:14 +0000 Subject: 2007-08-02 Samuel Thibault * sysdeps/generic/bits/mutex.h (pthread_mutex_init) (pthread_mutex_destroy, __pthread_mutex_lock, __pthread_mutex_trylock) (pthread_mutex_lock, pthread_mutex_trylock): Remove inline definitions. * sysdeps/generic/bits/rwlock.h (pthread_rwlock_init) (pthread_rwlock_destroy): Likewise. --- sysdeps/generic/bits/mutex.h | 72 ------------------------------------------- sysdeps/generic/bits/rwlock.h | 29 ----------------- 2 files changed, 101 deletions(-) diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index feb6d075..1aaf80ed 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -62,78 +62,6 @@ struct __pthread_mutex #include #include -#ifdef __USE_EXTERN_INLINES - -# ifndef _EXTERN_INLINE -# define _EXTERN_INLINE extern __inline -# endif - -_EXTERN_INLINE int -pthread_mutex_init (struct __pthread_mutex *__restrict __mutex, - const pthread_mutexattr_t *__restrict attr) -{ - struct __pthread_mutex initialized_mutex = __PTHREAD_MUTEX_INITIALIZER; - - extern int _pthread_mutex_init (struct __pthread_mutex *, - const pthread_mutexattr_t *); - - if (attr) - return _pthread_mutex_init (__mutex, attr); - - *__mutex = initialized_mutex; - return 0; -} - -_EXTERN_INLINE int -pthread_mutex_destroy (struct __pthread_mutex *__mutex) -{ - extern int _pthread_mutex_destroy (struct __pthread_mutex *); - - if (__mutex->attr || __mutex->data) - return _pthread_mutex_destroy (__mutex); - - return 0; -} - -_EXTERN_INLINE int -__pthread_mutex_lock (struct __pthread_mutex *__mutex) -{ - extern int _pthread_mutex_lock (struct __pthread_mutex *); - - if (__mutex->attr == NULL - && __mutex->data == NULL - && __pthread_spin_trylock (&__mutex->__held) == 0) - return 0; - - return _pthread_mutex_lock (__mutex); -} - -extern __inline int -__pthread_mutex_trylock (struct __pthread_mutex *__mutex) -{ - extern int _pthread_mutex_trylock (struct __pthread_mutex *); - - if (__mutex->attr == NULL - && __mutex->data == NULL) - return __pthread_spin_trylock (&__mutex->__held); - - return _pthread_mutex_trylock (__mutex); -} - -extern __inline int -pthread_mutex_lock (struct __pthread_mutex *__mutex) -{ - return __pthread_mutex_lock (__mutex); -} - -extern __inline int -pthread_mutex_trylock (struct __pthread_mutex *__mutex) -{ - return __pthread_mutex_trylock (__mutex); -} - -#endif /* Use extern inlines. */ - #endif #endif /* bits/mutex.h */ diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h index 5afc4a37..696f9c25 100644 --- a/sysdeps/generic/bits/rwlock.h +++ b/sysdeps/generic/bits/rwlock.h @@ -43,33 +43,4 @@ struct __pthread_rwlock { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } -#if defined __USE_UNIX98 || defined __USE_XOPEN2K -_EXTERN_INLINE int -pthread_rwlock_init (struct __pthread_rwlock *__restrict __rwlock, - const struct __pthread_rwlockattr *__restrict __attr) -{ - struct __pthread_rwlock initialized_rwlock = __PTHREAD_RWLOCK_INITIALIZER; - extern int _pthread_rwlock_init (struct __pthread_rwlock *, - const struct __pthread_rwlockattr *); - - if (__attr) - return _pthread_rwlock_init (__rwlock, __attr); - - *__rwlock = initialized_rwlock; - return 0; -} - -_EXTERN_INLINE int -pthread_rwlock_destroy (struct __pthread_rwlock *__rwlock) -{ - extern int _pthread_rwlock_destroy (struct __pthread_rwlock *); - - if (__rwlock->__attr - || __rwlock->__data) - return _pthread_rwlock_destroy (__rwlock); - - return 0; -} -#endif - #endif /* bits/rwlock.h */ -- cgit v1.2.3 From 5f60c7ab2316b9b4c61294b754a08e4cb1a9c4e6 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 1 Jan 2008 04:07:14 +0000 Subject: 2008-01-01 Samuel Thibault Date: Fri, 29 Feb 2008 09:53:35 +0000 Subject: 2008-02-29 Samuel Thibault Date: Sat, 17 May 2008 20:07:56 +0000 Subject: 2008-05-17 Samuel Thibault * include/pthread/pthread.h (pthread_getattr_np): New declaration. * pthread/pt-getattr.c: New file. * Makefile (SRCS): Add pt-getattr.c. --- pthread/pt-getattr.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pthread/pt-getattr.c diff --git a/pthread/pt-getattr.c b/pthread/pt-getattr.c new file mode 100644 index 00000000..24599c6e --- /dev/null +++ b/pthread/pt-getattr.c @@ -0,0 +1,49 @@ +/* Thread attributes retrieval. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread THREAD. It shall be called on an uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +int +pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) +{ + struct __pthread *pthread; + + pthread = __pthread_getid(thread); + if (pthread == NULL) + return ESRCH; + + /* Some attributes (schedparam, inheritsched, contentionscope and schedpolicy) + are not supported yet, so fill them with our default values. */ + *attr = __pthread_default_attr; + + attr->stackaddr = pthread->stackaddr; + attr->stacksize = pthread->stacksize; + attr->guardsize = pthread->guardsize; + attr->detachstate = (pthread->state == PTHREAD_DETACHED + ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + + return 0; +} -- cgit v1.2.3 From b2a1b2813ee59a9a1a789e49146ffb6fb1001eb7 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 27 May 2008 18:37:29 +0000 Subject: 2008-05-27 Neal H. Walfield * sysdeps/mach/hurd/pt-docancel.c (__pthread_do_cancel): Fix assert. --- sysdeps/mach/hurd/pt-docancel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sysdeps/mach/hurd/pt-docancel.c b/sysdeps/mach/hurd/pt-docancel.c index bac62a71..b81a5c70 100644 --- a/sysdeps/mach/hurd/pt-docancel.c +++ b/sysdeps/mach/hurd/pt-docancel.c @@ -1,5 +1,5 @@ /* Cancel a thread. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 @@ -33,7 +33,7 @@ __pthread_do_cancel (struct __pthread *p) mach_port_t ktid; int me; - assert (p->cancel_pending = 1); + assert (p->cancel_pending == 1); assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); ktid = __mach_thread_self (); -- cgit v1.2.3 From c7e4a8e5fa992c489aa7bc7153fb8208b7270cb0 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 27 May 2008 18:37:56 +0000 Subject: 2008-05-27 Neal H. Walfield * pthread/pt-internal.h (__pthread_queue_iterate): Before returning the current element, save its next pointer. (__pthread_dequeuing_iterate): Likewise. --- pthread/pt-internal.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index efd4ffb9..5583dfc3 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -114,15 +114,22 @@ __pthread_dequeue (struct __pthread *thread) } /* Iterate over QUEUE storing each element in ELEMENT. */ -#define __pthread_queue_iterate(queue, element) \ - for (element = queue; element; element = element->next) +#define __pthread_queue_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + true); \ + ) /* Iterate over QUEUE dequeuing each element, storing it in ELEMENT. */ -#define __pthread_dequeuing_iterate(queue, element) \ - for (element = queue; \ - element && ((element->prevp = 0), 1); \ - element = element->next) +#define __pthread_dequeuing_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + ((element)->prevp = 0), \ + true); \ + ) /* The total number of threads currently active. */ extern __atomic_t __pthread_total; -- cgit v1.2.3 From e59767048830a9a4c8f541aa86c925f767c04bfb Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sat, 7 Jun 2008 15:23:00 +0000 Subject: 2008-06-07 Neal H. Walfield * pthread/pt-internal.h (__pthread_queue_iterate): Use 1, not true. (__pthread_dequeuing_iterate): Likewise. --- pthread/pt-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 5583dfc3..d9bf7bc1 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -118,7 +118,7 @@ __pthread_dequeue (struct __pthread *thread) for (struct __pthread *__pdi_next = (queue); \ ((element) = __pdi_next) \ && ((__pdi_next = __pdi_next->next), \ - true); \ + 1); \ ) /* Iterate over QUEUE dequeuing each element, storing it in @@ -128,7 +128,7 @@ __pthread_dequeue (struct __pthread *thread) ((element) = __pdi_next) \ && ((__pdi_next = __pdi_next->next), \ ((element)->prevp = 0), \ - true); \ + 1); \ ) /* The total number of threads currently active. */ -- cgit v1.2.3 From 05ec15bddd06d4790adb7dd27df03b5cf226d386 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sun, 22 Jun 2008 09:05:31 +0000 Subject: 2008-06-22 Neal H. Walfield * sysdeps/generic/pt-mutex-timedlock.c (__pthread_mutex_timedlock_internal) [! NDEBUG]: Set MUTEX->OWNER appropriately and assert that it is consistent. * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock) [! NDEBUG]: Set MUTEX->OWNER appropriately and assert that it is consistent. * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock) [! NDEBUG]: Set MUTEX->OWNER. --- sysdeps/generic/pt-mutex-timedlock.c | 24 +++++++++++++++++++++++- sysdeps/generic/pt-mutex-trylock.c | 14 +++++++++++++- sysdeps/generic/pt-mutex-unlock.c | 28 +++++++++++++++++++++++----- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index 5e222bd3..265a4530 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -1,5 +1,5 @@ /* Lock a mutex with a timeout. Generic version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2008 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 @@ -36,6 +36,18 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, if (__pthread_spin_trylock (&mutex->__held) == 0) /* Successfully acquired the lock. */ { +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif + if (mutex->attr) switch (mutex->attr->mutex_type) { @@ -59,12 +71,14 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, /* The lock is busy. */ self = _pthread_self (); + assert (self); if (mutex->attr) { switch (mutex->attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: + assert (mutex->owner != self); break; case PTHREAD_MUTEX_ERRORCHECK: @@ -88,6 +102,10 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, LOSE; } } + else + assert (mutex->owner != self); + + assert (mutex->owner); if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) return EINVAL; @@ -123,6 +141,10 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, else __pthread_block (self); +#ifndef NDEBUG + assert (mutex->owner == self); +#endif + if (mutex->attr) switch (mutex->attr->mutex_type) { diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index d56f6e1c..5264dc7b 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -1,5 +1,5 @@ /* Try to Lock a mutex. Generic version. - Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2008 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 @@ -34,6 +34,18 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) if (__pthread_spin_trylock (&mutex->__held) == 0) /* Acquired the lock. */ { +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif + if (mutex->attr) switch (mutex->attr->mutex_type) { diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index 2f719d3e..d2a42570 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -1,5 +1,5 @@ /* Unlock a mutex. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 @@ -31,12 +31,25 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) __pthread_spin_lock (&mutex->__lock); - if (mutex->attr) + if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#ifndef NDEBUG + if (_pthread_self ()) + { + assert (mutex->owner); + assertx (mutex->owner == _pthread_self (), + "%p(%x) != %p(%x)", + mutex->owner, + ((struct __pthread *) mutex->owner)->threadid, + _pthread_self (), + _pthread_self ()->threadid); + mutex->owner = NULL; + } +#endif + } + else switch (mutex->attr->mutex_type) { - case PTHREAD_MUTEX_NORMAL: - break; - case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_RECURSIVE: if (mutex->owner != _pthread_self ()) @@ -59,6 +72,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) LOSE; } + if (mutex->__queue == NULL) { __pthread_spin_unlock (&mutex->__held); @@ -69,6 +83,10 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) wakeup = mutex->__queue; __pthread_dequeue (wakeup); +#ifndef NDEBUG + mutex->owner = wakeup; +#endif + /* We do not unlock MUTEX->held: we are transferring the ownership to the thread that we are waking up. */ -- cgit v1.2.3 From c50decbb1e33f0b16cce1fa53e8c72c88315289e Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 27 Jun 2008 22:35:16 +0000 Subject: 2008-06-27 Samuel Thibault * sysdeps/generic/bits/thread-barrier.h: Remove unused file. --- sysdeps/generic/bits/thread-barrier.h | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 sysdeps/generic/bits/thread-barrier.h diff --git a/sysdeps/generic/bits/thread-barrier.h b/sysdeps/generic/bits/thread-barrier.h deleted file mode 100644 index 23d51ae5..00000000 --- a/sysdeps/generic/bits/thread-barrier.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Thread barrier attribute type. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_THREAD_BARRIER_H -#define _BITS_THREAD_BARRIER_H 1 - -/* This structure describes the attributes of a POSIX thread barrier. - Note that not all of them are supported on all systems. */ -struct __pthread_attr -{ - enum __ -}; - -#endif /* bits/thread-barrier.h */ -- cgit v1.2.3 From 0acb426838244a35d632eb5030b3ffcc293414e2 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 28 Jun 2008 00:06:52 +0000 Subject: 2008-06-27 Samuel Thibault * include/pthread/pthread.h: Do not define __need_clockid_t, include , and define clockid_t if __clockid_defined is not defined. Include (pthread_equal): New extern inline. (pthread_cleanup_push, pthread_cleanup_pop): New macros. (__pthread_process_shared, __pthread_inheritsched, __pthread_contentionscope, __pthread_detachstate, __pthread_mutex_protocol, __pthread_mutex_type, pthread_attr_t, pthread_mutex_attr_t, pthread_mutex_t, pthread_condattr_t, pthread_cond_t, pthread_spinlock_t, pthread_rwlockattr_t, pthread_rwlock_t, pthread_barrierattr_t, pthread_barrier_t, pthread_key_t, pthread_once_t): Move enums and typedefs to... * include/pthread/pthreadtypes.h: ... new file. * sysdeps/generic/bits/cancelation.h (pthread_cleanup_push): Rename macro to __pthread_cleanup_push. (pthread_cleanup_pop): Rename macro to __pthread_cleanup_pop. * sysdeps/generic/bits/barrier-attr.h (__pthread_process_shared): Forward-declare enum. * sysdeps/generic/bits/condition-attr.h (__pthread_process_shared): Likewise. * sysdeps/generic/bits/mutex-attr.h (__pthread_mutex_protocol, __pthread_process_shared, __pthread_mutex_type): Likewise. * sysdeps/generic/bits/rwlock-attr.h (__pthread_process_shared): Likewise. * sysdeps/generic/bits/thread-attr.h (__pthread_detachstate, __pthread_inheritsched, __pthread_contentionscope): Likewise. * sysdeps/generic/bits/pthread.h (pthread_t): Rename type to __pthread_t. (pthread_equal): Rename to __pthread_equal. --- sysdeps/generic/bits/barrier-attr.h | 2 ++ sysdeps/generic/bits/cancelation.h | 4 ++-- sysdeps/generic/bits/condition-attr.h | 2 ++ sysdeps/generic/bits/mutex-attr.h | 4 ++++ sysdeps/generic/bits/pthread.h | 6 +++--- sysdeps/generic/bits/rwlock-attr.h | 2 ++ sysdeps/generic/bits/thread-attr.h | 4 ++++ 7 files changed, 19 insertions(+), 5 deletions(-) diff --git a/sysdeps/generic/bits/barrier-attr.h b/sysdeps/generic/bits/barrier-attr.h index 86f3cb02..d8d09db9 100644 --- a/sysdeps/generic/bits/barrier-attr.h +++ b/sysdeps/generic/bits/barrier-attr.h @@ -20,6 +20,8 @@ #ifndef _BITS_BARRIER_ATTR_H #define _BITS_BARRIER_ATTR_H 1 +enum __pthread_process_shared; + /* This structure describes the attributes of a POSIX thread barrier. Note that not all of them are supported on all systems. */ struct __pthread_barrierattr diff --git a/sysdeps/generic/bits/cancelation.h b/sysdeps/generic/bits/cancelation.h index bb6b58a1..f94b6e34 100644 --- a/sysdeps/generic/bits/cancelation.h +++ b/sysdeps/generic/bits/cancelation.h @@ -32,7 +32,7 @@ struct __pthread_cancelation_handler /* Returns the thread local location of the cleanup handler stack. */ struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); -#define pthread_cleanup_push(rt, rtarg) \ +#define __pthread_cleanup_push(rt, rtarg) \ { \ struct __pthread_cancelation_handler **__handlers \ = __pthread_get_cleanup_stack (); \ @@ -44,7 +44,7 @@ struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); }; \ *__handlers = &__handler; -#define pthread_cleanup_pop(execute) \ +#define __pthread_cleanup_pop(execute) \ if (execute) \ __handler.handler (__handler.arg); \ assert (*__handlers == &__handler); \ diff --git a/sysdeps/generic/bits/condition-attr.h b/sysdeps/generic/bits/condition-attr.h index 2d48dfb6..49bbf7f1 100644 --- a/sysdeps/generic/bits/condition-attr.h +++ b/sysdeps/generic/bits/condition-attr.h @@ -22,6 +22,8 @@ #include +enum __pthread_process_shared; + /* User visible part of a condition attribute variable. */ struct __pthread_condattr { diff --git a/sysdeps/generic/bits/mutex-attr.h b/sysdeps/generic/bits/mutex-attr.h index 883b0746..5d3d611a 100644 --- a/sysdeps/generic/bits/mutex-attr.h +++ b/sysdeps/generic/bits/mutex-attr.h @@ -20,6 +20,10 @@ #ifndef _BITS_MUTEX_ATTR_H #define _BITS_MUTEX_ATTR_H 1 +enum __pthread_mutex_protocol; +enum __pthread_process_shared; +enum __pthread_mutex_type; + /* This structure describes the attributes of a POSIX mutex attribute. */ struct __pthread_mutexattr diff --git a/sysdeps/generic/bits/pthread.h b/sysdeps/generic/bits/pthread.h index 5e239d67..0e8ad9e9 100644 --- a/sysdeps/generic/bits/pthread.h +++ b/sysdeps/generic/bits/pthread.h @@ -20,16 +20,16 @@ #ifndef _BITS_PTHREAD_H #define _BITS_PTHREAD_H 1 -typedef int pthread_t; +typedef int __pthread_t; /* Return true if __T1 and __T2 both name the same thread. Otherwise, false. */ extern int -pthread_equal (pthread_t __t1, pthread_t __t2); +__pthread_equal (__pthread_t __t1, __pthread_t __t2); #ifdef __USE_EXTERN_INLINES __extern_inline int -pthread_equal (pthread_t __t1, pthread_t __t2) +__pthread_equal (__pthread_t __t1, __pthread_t __t2) { return __t1 == __t2; } diff --git a/sysdeps/generic/bits/rwlock-attr.h b/sysdeps/generic/bits/rwlock-attr.h index 44765bd6..b4f26c46 100644 --- a/sysdeps/generic/bits/rwlock-attr.h +++ b/sysdeps/generic/bits/rwlock-attr.h @@ -20,6 +20,8 @@ #ifndef _BITS_RWLOCK_ATTR_H #define _BITS_RWLOCK_ATTR_H 1 +enum __pthread_process_shared; + /* This structure describes the attributes of a POSIX thread rwlock. Note that not all of them are supported on all systems. */ struct __pthread_rwlockattr diff --git a/sysdeps/generic/bits/thread-attr.h b/sysdeps/generic/bits/thread-attr.h index 31630221..3250f515 100644 --- a/sysdeps/generic/bits/thread-attr.h +++ b/sysdeps/generic/bits/thread-attr.h @@ -22,6 +22,10 @@ #include +enum __pthread_detachstate; +enum __pthread_inheritsched; +enum __pthread_contentionscope; + /* This structure describes the attributes of a POSIX thread. Note that not all of them are supported on all systems. */ struct __pthread_attr -- cgit v1.2.3 From 531acb4bc4f8c16a5e202a9ce702b012f923ac7b Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 29 Jun 2008 02:43:00 +0000 Subject: 2008-06-29 Samuel Thibault * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): Do not use assertx and threadid. --- sysdeps/generic/pt-mutex-unlock.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index d2a42570..bfb9803e 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -37,12 +37,16 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) if (_pthread_self ()) { assert (mutex->owner); +#if 0 assertx (mutex->owner == _pthread_self (), "%p(%x) != %p(%x)", mutex->owner, ((struct __pthread *) mutex->owner)->threadid, _pthread_self (), _pthread_self ()->threadid); +#else + assert (mutex->owner == _pthread_self ()); +#endif mutex->owner = NULL; } #endif -- cgit v1.2.3 From ee8a3f2e096d10bca782d78be24b12562e73d935 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Tue, 1 Jul 2008 11:43:18 +0000 Subject: Update copyright years. --- pthread/pt-internal.h | 2 +- sysdeps/generic/bits/barrier-attr.h | 2 +- sysdeps/generic/bits/cancelation.h | 2 +- sysdeps/generic/bits/condition-attr.h | 2 +- sysdeps/generic/bits/mutex-attr.h | 2 +- sysdeps/generic/bits/mutex.h | 2 +- sysdeps/generic/bits/pthread.h | 2 +- sysdeps/generic/bits/rwlock-attr.h | 2 +- sysdeps/generic/bits/rwlock.h | 2 +- sysdeps/generic/bits/thread-attr.h | 2 +- sysdeps/generic/pt-mutex-destroy.c | 2 +- sysdeps/generic/pt-mutex-init.c | 2 +- sysdeps/generic/pt-mutex-lock.c | 2 +- sysdeps/generic/pt-mutex-trylock.c | 2 +- sysdeps/generic/pt-mutex-unlock.c | 2 +- sysdeps/generic/pt-rwlock-destroy.c | 2 +- sysdeps/generic/pt-rwlock-init.c | 2 +- sysdeps/generic/sem-destroy.c | 2 +- sysdeps/generic/sem-getvalue.c | 2 +- sysdeps/generic/sem-init.c | 2 +- sysdeps/generic/sem-open.c | 2 +- sysdeps/generic/sem-post.c | 2 +- sysdeps/generic/sem-timedwait.c | 2 +- sysdeps/generic/sem-trywait.c | 2 +- sysdeps/generic/sem-unlink.c | 2 +- sysdeps/generic/sem-wait.c | 2 +- sysdeps/i386/bits/memory.h | 2 +- sysdeps/i386/bits/spin-lock.h | 2 +- sysdeps/i386/machine-sp.h | 2 +- sysdeps/l4/hurd/i386/pt-setup.c | 2 +- sysdeps/mach/bits/spin-lock.h | 2 +- sysdeps/mach/hurd/i386/pt-setup.c | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index d9bf7bc1..e7c85fda 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2005, 2006, 2008 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 diff --git a/sysdeps/generic/bits/barrier-attr.h b/sysdeps/generic/bits/barrier-attr.h index d8d09db9..a9900b71 100644 --- a/sysdeps/generic/bits/barrier-attr.h +++ b/sysdeps/generic/bits/barrier-attr.h @@ -1,5 +1,5 @@ /* Thread barrier attribute type. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 diff --git a/sysdeps/generic/bits/cancelation.h b/sysdeps/generic/bits/cancelation.h index f94b6e34..f446d595 100644 --- a/sysdeps/generic/bits/cancelation.h +++ b/sysdeps/generic/bits/cancelation.h @@ -1,5 +1,5 @@ /* Cancelation. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 diff --git a/sysdeps/generic/bits/condition-attr.h b/sysdeps/generic/bits/condition-attr.h index 49bbf7f1..a1311286 100644 --- a/sysdeps/generic/bits/condition-attr.h +++ b/sysdeps/generic/bits/condition-attr.h @@ -1,5 +1,5 @@ /* Condition attribute type. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 diff --git a/sysdeps/generic/bits/mutex-attr.h b/sysdeps/generic/bits/mutex-attr.h index 5d3d611a..7a5c45c2 100644 --- a/sysdeps/generic/bits/mutex-attr.h +++ b/sysdeps/generic/bits/mutex-attr.h @@ -1,5 +1,5 @@ /* Mutex attribute type. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 1aaf80ed..b44fa6df 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -1,5 +1,5 @@ /* Mutex type. Generic version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2006, 2007 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 diff --git a/sysdeps/generic/bits/pthread.h b/sysdeps/generic/bits/pthread.h index 0e8ad9e9..80e6b096 100644 --- a/sysdeps/generic/bits/pthread.h +++ b/sysdeps/generic/bits/pthread.h @@ -1,5 +1,5 @@ /* Pthread data structures. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 diff --git a/sysdeps/generic/bits/rwlock-attr.h b/sysdeps/generic/bits/rwlock-attr.h index b4f26c46..dba99f1d 100644 --- a/sysdeps/generic/bits/rwlock-attr.h +++ b/sysdeps/generic/bits/rwlock-attr.h @@ -1,5 +1,5 @@ /* Thread rwlock attribute type. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h index 696f9c25..3d600ec3 100644 --- a/sysdeps/generic/bits/rwlock.h +++ b/sysdeps/generic/bits/rwlock.h @@ -1,5 +1,5 @@ /* rwlock type. Generic version. - Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2006, 2007 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 diff --git a/sysdeps/generic/bits/thread-attr.h b/sysdeps/generic/bits/thread-attr.h index 3250f515..c3a93fde 100644 --- a/sysdeps/generic/bits/thread-attr.h +++ b/sysdeps/generic/bits/thread-attr.h @@ -1,5 +1,5 @@ /* Thread attribute type. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 diff --git a/sysdeps/generic/pt-mutex-destroy.c b/sysdeps/generic/pt-mutex-destroy.c index 72faefe6..71fc692f 100644 --- a/sysdeps/generic/pt-mutex-destroy.c +++ b/sysdeps/generic/pt-mutex-destroy.c @@ -1,5 +1,5 @@ /* Destroy a mutex. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2006 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 diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c index da1781bf..94076730 100644 --- a/sysdeps/generic/pt-mutex-init.c +++ b/sysdeps/generic/pt-mutex-init.c @@ -1,5 +1,5 @@ /* Initialize a mutex. Generic version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2006 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 diff --git a/sysdeps/generic/pt-mutex-lock.c b/sysdeps/generic/pt-mutex-lock.c index 60fc55ab..528e593f 100644 --- a/sysdeps/generic/pt-mutex-lock.c +++ b/sysdeps/generic/pt-mutex-lock.c @@ -1,5 +1,5 @@ /* Lock a mutex. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2006 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 diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index 5264dc7b..d523205e 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -1,5 +1,5 @@ /* Try to Lock a mutex. Generic version. - Copyright (C) 2002, 2005, 2008 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2006, 2008 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 diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index bfb9803e..4352042e 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -1,5 +1,5 @@ /* Unlock a mutex. Generic version. - Copyright (C) 2000, 2002, 2008 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2006, 2008 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 diff --git a/sysdeps/generic/pt-rwlock-destroy.c b/sysdeps/generic/pt-rwlock-destroy.c index 034d9300..045eebd8 100644 --- a/sysdeps/generic/pt-rwlock-destroy.c +++ b/sysdeps/generic/pt-rwlock-destroy.c @@ -1,5 +1,5 @@ /* Destroy a rwlock. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006 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 diff --git a/sysdeps/generic/pt-rwlock-init.c b/sysdeps/generic/pt-rwlock-init.c index 8aa495ec..c9ff9b28 100644 --- a/sysdeps/generic/pt-rwlock-init.c +++ b/sysdeps/generic/pt-rwlock-init.c @@ -1,5 +1,5 @@ /* Initialize a rwlock. Generic version. - Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2006 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 diff --git a/sysdeps/generic/sem-destroy.c b/sysdeps/generic/sem-destroy.c index 985f4ad3..6486599c 100644 --- a/sysdeps/generic/sem-destroy.c +++ b/sysdeps/generic/sem-destroy.c @@ -1,5 +1,5 @@ /* Destroy a semaphore. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-getvalue.c b/sysdeps/generic/sem-getvalue.c index 8e418e38..7762089b 100644 --- a/sysdeps/generic/sem-getvalue.c +++ b/sysdeps/generic/sem-getvalue.c @@ -1,5 +1,5 @@ /* Get the value of a semaphore. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-init.c b/sysdeps/generic/sem-init.c index 6c6d79e7..d2414f5d 100644 --- a/sysdeps/generic/sem-init.c +++ b/sysdeps/generic/sem-init.c @@ -1,5 +1,5 @@ /* Initialize a semaphore. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-open.c b/sysdeps/generic/sem-open.c index 9eb13aae..bae87ed0 100644 --- a/sysdeps/generic/sem-open.c +++ b/sysdeps/generic/sem-open.c @@ -1,5 +1,5 @@ /* Open a named semaphore. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-post.c b/sysdeps/generic/sem-post.c index 0e20ea7a..6d438bf2 100644 --- a/sysdeps/generic/sem-post.c +++ b/sysdeps/generic/sem-post.c @@ -1,5 +1,5 @@ /* Post a semaphore. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-timedwait.c b/sysdeps/generic/sem-timedwait.c index d01bfdb0..f9040009 100644 --- a/sysdeps/generic/sem-timedwait.c +++ b/sysdeps/generic/sem-timedwait.c @@ -1,5 +1,5 @@ /* Wait on a semaphore with a timeout. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-trywait.c b/sysdeps/generic/sem-trywait.c index 199f317b..437e2822 100644 --- a/sysdeps/generic/sem-trywait.c +++ b/sysdeps/generic/sem-trywait.c @@ -1,5 +1,5 @@ /* Lock a semaphore if it does not require blocking. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-unlink.c b/sysdeps/generic/sem-unlink.c index 519f4f7b..570ed614 100644 --- a/sysdeps/generic/sem-unlink.c +++ b/sysdeps/generic/sem-unlink.c @@ -1,5 +1,5 @@ /* Unlink a named semaphore. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/generic/sem-wait.c b/sysdeps/generic/sem-wait.c index 50752f32..8347480c 100644 --- a/sysdeps/generic/sem-wait.c +++ b/sysdeps/generic/sem-wait.c @@ -1,5 +1,5 @@ /* Wait on a semaphore. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 diff --git a/sysdeps/i386/bits/memory.h b/sysdeps/i386/bits/memory.h index 57c1463c..e47a8e2d 100644 --- a/sysdeps/i386/bits/memory.h +++ b/sysdeps/i386/bits/memory.h @@ -1,5 +1,5 @@ /* Memory barrier operations. i386 version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 diff --git a/sysdeps/i386/bits/spin-lock.h b/sysdeps/i386/bits/spin-lock.h index d893654d..30b0c64b 100644 --- a/sysdeps/i386/bits/spin-lock.h +++ b/sysdeps/i386/bits/spin-lock.h @@ -1,5 +1,5 @@ /* Machine-specific definitions for spin locks. i386 version. - Copyright (C) 2000, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2005, 2008 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 diff --git a/sysdeps/i386/machine-sp.h b/sysdeps/i386/machine-sp.h index 945a36b8..cef6ab72 100644 --- a/sysdeps/i386/machine-sp.h +++ b/sysdeps/i386/machine-sp.h @@ -1,5 +1,5 @@ /* Machine-specific function to return the stack pointer. i386 version. - Copyright (C) 1994,97,2001 Free Software Foundation, Inc. + Copyright (C) 1994, 1997, 2001, 2006 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 diff --git a/sysdeps/l4/hurd/i386/pt-setup.c b/sysdeps/l4/hurd/i386/pt-setup.c index 6afcd141..6540ee5b 100644 --- a/sysdeps/l4/hurd/i386/pt-setup.c +++ b/sysdeps/l4/hurd/i386/pt-setup.c @@ -1,5 +1,5 @@ /* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 diff --git a/sysdeps/mach/bits/spin-lock.h b/sysdeps/mach/bits/spin-lock.h index 031e9cec..0cbf11ed 100644 --- a/sysdeps/mach/bits/spin-lock.h +++ b/sysdeps/mach/bits/spin-lock.h @@ -1,5 +1,5 @@ /* Definitions of user-visible names for spin locks. - Copyright (C) 1994, 1997, 2002 Free Software Foundation, Inc. + Copyright (C) 1994, 1997, 2002, 2008 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 diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c index 71f60e23..5abbcfcd 100644 --- a/sysdeps/mach/hurd/i386/pt-setup.c +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -1,5 +1,5 @@ /* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2008 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 -- cgit v1.2.3 From 9a5c2e448de0531aa59f909667b9b55cc9d66c4c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 2 Aug 2008 20:21:20 +0000 Subject: 2008-08-02 Samuel Thibault * sysdeps/generic/bits/mutex.h: Do not include and --- sysdeps/generic/bits/mutex.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index b44fa6df..5c7fedec 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -57,11 +57,4 @@ struct __pthread_mutex # endif #endif /* Not __pthread_mutex_defined. */ -#ifdef _BITS_MUTEX_H - -#include -#include - -#endif - #endif /* bits/mutex.h */ -- cgit v1.2.3 From 65384669214e2025f8d6aa99f5dad71a96f08ac0 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 2 Aug 2008 20:40:14 +0000 Subject: 2008-08-02 Samuel Thibault [libpthread] * sysdeps/i386/bits/memory.h (__memory_barrier): Add memory clobber. * sysdeps/i386/bits/spin-lock.h (__pthread_spin_trylock, __pthread_spin_unlock): Add memory clobbers. [libthreads] * i386/cthreads.h (spin_unlock, spin_try_lock): Add memory clobbers. --- sysdeps/i386/bits/memory.h | 2 +- sysdeps/i386/bits/spin-lock.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sysdeps/i386/bits/memory.h b/sysdeps/i386/bits/memory.h index e47a8e2d..932c4086 100644 --- a/sysdeps/i386/bits/memory.h +++ b/sysdeps/i386/bits/memory.h @@ -28,7 +28,7 @@ __memory_barrier (void) /* Any lock'ed instruction will do. We just do a simple increment. */ - __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i)); + __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i) : "memory"); } /* Prevent read reordering across this function. */ diff --git a/sysdeps/i386/bits/spin-lock.h b/sysdeps/i386/bits/spin-lock.h index 30b0c64b..a3066979 100644 --- a/sysdeps/i386/bits/spin-lock.h +++ b/sysdeps/i386/bits/spin-lock.h @@ -70,7 +70,7 @@ __pthread_spin_trylock (__pthread_spinlock_t *__lock) { int __locked; __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__locked), "=m" (*__lock) : "0" (1)); + : "=&r" (__locked), "=m" (*__lock) : "0" (1) : "memory"); return __locked ? __EBUSY : 0; } @@ -92,7 +92,7 @@ __pthread_spin_unlock (__pthread_spinlock_t *__lock) { int __unlocked; __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__unlocked), "=m" (*__lock) : "0" (0)); + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0) : "memory"); return 0; } -- cgit v1.2.3 From 996cf59d4a6846650b1778f658f60eef3ac41dcf Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 3 Aug 2008 00:13:13 +0000 Subject: * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Fix cast from thread to integer. Fix reservation of stack room for initial frame. * sysdeps/l4/hurd/i386/pt-setup.c (stack_setup): Fix reservation of stack room for initial frame. --- sysdeps/l4/hurd/i386/pt-setup.c | 2 +- sysdeps/mach/hurd/i386/pt-setup.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sysdeps/l4/hurd/i386/pt-setup.c b/sysdeps/l4/hurd/i386/pt-setup.c index 6540ee5b..2b7a3e23 100644 --- a/sysdeps/l4/hurd/i386/pt-setup.c +++ b/sysdeps/l4/hurd/i386/pt-setup.c @@ -47,7 +47,7 @@ stack_setup (struct __pthread *thread, if (start_routine) { /* Set up call frame. */ - top -= 2*sizeof(L4_Word_t); + top -= 2; top = (unsigned long) top & ~0xf; top[1] = (L4_Word_t) arg; /* Argument to START_ROUTINE. */ top[0] = (L4_Word_t) start_routine; diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c index 5abbcfcd..ba438d6a 100644 --- a/sysdeps/mach/hurd/i386/pt-setup.c +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -58,12 +58,12 @@ stack_setup (struct __pthread *thread, top -= __hurd_threadvar_max; /* Save the self pointer. */ - top[_HURD_THREADVAR_THREAD] = (void *) thread; + top[_HURD_THREADVAR_THREAD] = (uintptr_t) thread; if (start_routine) { /* And then the call frame. */ - top -= 2*sizeof(uintptr_t); + top -= 2; top = (uintptr_t) top & ~0xf; top[1] = (uintptr_t) arg; /* Argument to START_ROUTINE. */ top[0] = (uintptr_t) start_routine; -- cgit v1.2.3 From ae95cbb0720fa57dfca6113ee940e2d8ff2af074 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Sun, 3 Aug 2008 07:02:36 +0000 Subject: Update copyright year. --- sysdeps/generic/bits/mutex.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 5c7fedec..7c77a8d2 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -1,5 +1,8 @@ /* Mutex type. Generic version. - Copyright (C) 2000, 2002, 2005, 2006, 2007 Free Software Foundation, Inc. + + Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008 + 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 -- cgit v1.2.3 From 9ad7bd71fb25affd53a0ace2d7f922ffc8c570d1 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 3 Aug 2008 18:56:49 +0000 Subject: * Makefile (sysdeps_headers): Add spin-lock-inline.h. (SYSDEP_PATH): Move sysdeps/i386 right after sysdeps/$(MICROKERNEL)/i386. * include/pthread/pthread.h: Include . * sysdeps/i386/bits/spin-lock.h: Move inlines to... * sysdeps/i386/bits/spin-lock-inline.h: ... new file. * sysdeps/mach/bits/spin-lock.h: Move inlines to... * sysdeps/mach/bits/spin-lock-inline.h: ... new file. --- sysdeps/i386/bits/spin-lock-inline.h | 98 ++++++++++++++++++++++++++++++++++++ sysdeps/i386/bits/spin-lock.h | 64 ----------------------- sysdeps/mach/bits/spin-lock-inline.h | 90 +++++++++++++++++++++++++++++++++ sysdeps/mach/bits/spin-lock.h | 59 ---------------------- 4 files changed, 188 insertions(+), 123 deletions(-) create mode 100644 sysdeps/i386/bits/spin-lock-inline.h create mode 100644 sysdeps/mach/bits/spin-lock-inline.h diff --git a/sysdeps/i386/bits/spin-lock-inline.h b/sysdeps/i386/bits/spin-lock-inline.h new file mode 100644 index 00000000..0f3ca581 --- /dev/null +++ b/sysdeps/i386/bits/spin-lock-inline.h @@ -0,0 +1,98 @@ +/* Machine-specific definitions for spin locks. i386 version. + Copyright (C) 2000, 2005, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_SPIN_LOCK_INLINE_H +#define _BITS_SPIN_LOCK_INLINE_H 1 + +#include +#include + +__BEGIN_DECLS + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE __extern_inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + int __locked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__locked), "=m" (*__lock) : "0" (1) : "memory"); + return __locked ? __EBUSY : 0; +} + +__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +__extern_inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + int __unlocked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0) : "memory"); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/sysdeps/i386/bits/spin-lock.h b/sysdeps/i386/bits/spin-lock.h index a3066979..2662b6fb 100644 --- a/sysdeps/i386/bits/spin-lock.h +++ b/sysdeps/i386/bits/spin-lock.h @@ -34,70 +34,6 @@ typedef __volatile int __pthread_spinlock_t; /* Initializer for a spin lock object. */ # define __SPIN_LOCK_INITIALIZER (0) -#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES - -# ifndef __EBUSY -# include -# define __EBUSY EBUSY -# endif - -# ifndef __PT_SPIN_INLINE -# define __PT_SPIN_INLINE __extern_inline -# endif - -__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_destroy (__pthread_spinlock_t *__lock) -{ - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, - int __pshared); - -__PT_SPIN_INLINE int -__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) -{ - *__lock = __SPIN_LOCK_INITIALIZER; - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_trylock (__pthread_spinlock_t *__lock) -{ - int __locked; - __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__locked), "=m" (*__lock) : "0" (1) : "memory"); - return __locked ? __EBUSY : 0; -} - -__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); -extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); - -__extern_inline int -__pthread_spin_lock (__pthread_spinlock_t *__lock) -{ - if (__pthread_spin_trylock (__lock)) - return _pthread_spin_lock (__lock); - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_unlock (__pthread_spinlock_t *__lock) -{ - int __unlocked; - __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__unlocked), "=m" (*__lock) : "0" (0) : "memory"); - return 0; -} - -#endif /* Use extern inlines or force inlines. */ - __END_DECLS #endif /* bits/spin-lock.h */ diff --git a/sysdeps/mach/bits/spin-lock-inline.h b/sysdeps/mach/bits/spin-lock-inline.h new file mode 100644 index 00000000..bb066d0b --- /dev/null +++ b/sysdeps/mach/bits/spin-lock-inline.h @@ -0,0 +1,90 @@ +/* Definitions of user-visible names for spin locks. + Copyright (C) 1994, 1997, 2002, 2008 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. */ + +#ifndef _BITS_SPIN_LOCK_INLINE_H +#define _BITS_SPIN_LOCK_INLINE_H 1 + +#include +#include +#include /* This does all the work. */ + +__BEGIN_DECLS + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE __extern_inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + return __spin_try_lock (__lock) ? 0 : __EBUSY; +} + +__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +__extern_inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + __spin_unlock (__lock); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/sysdeps/mach/bits/spin-lock.h b/sysdeps/mach/bits/spin-lock.h index 0cbf11ed..54425cc6 100644 --- a/sysdeps/mach/bits/spin-lock.h +++ b/sysdeps/mach/bits/spin-lock.h @@ -33,65 +33,6 @@ typedef __spin_lock_t __pthread_spinlock_t; #error __SPIN_LOCK_INITIALIZER undefined: should be defined by . #endif -#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES - -# ifndef __EBUSY -# include -# define __EBUSY EBUSY -# endif - -# ifndef __PT_SPIN_INLINE -# define __PT_SPIN_INLINE __extern_inline -# endif - -__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_destroy (__pthread_spinlock_t *__lock) -{ - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, - int __pshared); - -__PT_SPIN_INLINE int -__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) -{ - *__lock = __SPIN_LOCK_INITIALIZER; - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_trylock (__pthread_spinlock_t *__lock) -{ - return __spin_try_lock (__lock) ? 0 : __EBUSY; -} - -__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); -extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); - -__extern_inline int -__pthread_spin_lock (__pthread_spinlock_t *__lock) -{ - if (__pthread_spin_trylock (__lock)) - return _pthread_spin_lock (__lock); - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_unlock (__pthread_spinlock_t *__lock) -{ - __spin_unlock (__lock); - return 0; -} - -#endif /* Use extern inlines or force inlines. */ - __END_DECLS #endif /* bits/spin-lock.h */ -- cgit v1.2.3 From 528735cb06bb4383977e0748b19458d1859648b9 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 11 Aug 2008 19:30:30 +0000 Subject: 2008-08-11 Neal H. Walfield * sysdeps/l4/pt-docancel.c: Remove file. * sysdeps/l4/pt-thread-alloc.c: Likewise. * sysdeps/l4/pt-wakeup.c: Likewise. * sysdeps/l4/pt-thread-halt.c: Likewise. * sysdeps/l4/pt-start.c: Likewise. * sysdeps/l4/pt-stack-alloc.c: Likewise. * sysdeps/l4/pt-thread-start.c: Likewise. * sysdeps/l4/pt-block.c: Likewise. * sysdeps/l4/hurd/pt-sysdep.h: Likewise. * sysdeps/l4/hurd/pt-sysdep.c: Likewise. * sysdeps/l4/hurd/i386/pt-setup.c: Likewise. * sysdeps/l4/hurd/i386/pt-machdep.c: Likewise. --- sysdeps/l4/hurd/i386/pt-machdep.c | 20 -------- sysdeps/l4/hurd/i386/pt-setup.c | 74 --------------------------- sysdeps/l4/hurd/pt-sysdep.c | 58 --------------------- sysdeps/l4/hurd/pt-sysdep.h | 52 ------------------- sysdeps/l4/pt-block.c | 29 ----------- sysdeps/l4/pt-docancel.c | 51 ------------------- sysdeps/l4/pt-stack-alloc.c | 70 -------------------------- sysdeps/l4/pt-start.c | 103 -------------------------------------- sysdeps/l4/pt-thread-alloc.c | 52 ------------------- sysdeps/l4/pt-thread-halt.c | 38 -------------- sysdeps/l4/pt-thread-start.c | 92 ---------------------------------- sysdeps/l4/pt-wakeup.c | 29 ----------- 12 files changed, 668 deletions(-) delete mode 100644 sysdeps/l4/hurd/i386/pt-machdep.c delete mode 100644 sysdeps/l4/hurd/i386/pt-setup.c delete mode 100644 sysdeps/l4/hurd/pt-sysdep.c delete mode 100644 sysdeps/l4/hurd/pt-sysdep.h delete mode 100644 sysdeps/l4/pt-block.c delete mode 100644 sysdeps/l4/pt-docancel.c delete mode 100644 sysdeps/l4/pt-stack-alloc.c delete mode 100644 sysdeps/l4/pt-start.c delete mode 100644 sysdeps/l4/pt-thread-alloc.c delete mode 100644 sysdeps/l4/pt-thread-halt.c delete mode 100644 sysdeps/l4/pt-thread-start.c delete mode 100644 sysdeps/l4/pt-wakeup.c diff --git a/sysdeps/l4/hurd/i386/pt-machdep.c b/sysdeps/l4/hurd/i386/pt-machdep.c deleted file mode 100644 index dbf5cd7e..00000000 --- a/sysdeps/l4/hurd/i386/pt-machdep.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Machine dependent pthreads code. Hurd/i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* Nothing to do. */ diff --git a/sysdeps/l4/hurd/i386/pt-setup.c b/sysdeps/l4/hurd/i386/pt-setup.c deleted file mode 100644 index 2b7a3e23..00000000 --- a/sysdeps/l4/hurd/i386/pt-setup.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000, 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* The stack layout used on the i386 is: - - ----------------- - | ARG | - ----------------- - | START_ROUTINE | - ----------------- - | 0 | - ----------------- */ - -/* Set up the stack for THREAD, such that it appears as if - START_ROUTINE and ARG were passed to the new thread's entry-point. - Return the stack pointer for the new thread. We also take the - opportunity to install THREAD in our utcb. */ -static void * -stack_setup (struct __pthread *thread, - void *(*start_routine)(void *), void *arg) -{ - L4_Word_t *top; - - /* Calculate top of the new stack. */ - top = (L4_Word_t *) ((L4_Word_t) thread->stackaddr + thread->stacksize); - - if (start_routine) - { - /* Set up call frame. */ - top -= 2; - top = (unsigned long) top & ~0xf; - top[1] = (L4_Word_t) arg; /* Argument to START_ROUTINE. */ - top[0] = (L4_Word_t) start_routine; - *--top = 0; /* Fake return address. */ - } - - return top; -} - -int -__pthread_setup (struct __pthread *thread, - void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg) -{ - thread->mcontext.pc = entry_point; - thread->mcontext.sp = stack_setup (thread, start_routine, arg); - - if (L4_SameThreads (thread->threadid, L4_Myself ())) - L4_Set_MyUserDefinedHandle (thread); - else - L4_Set_UserDefinedHandle (thread->threadid, thread); - - return 0; -} diff --git a/sysdeps/l4/hurd/pt-sysdep.c b/sysdeps/l4/hurd/pt-sysdep.c deleted file mode 100644 index 265592ca..00000000 --- a/sysdeps/l4/hurd/pt-sysdep.c +++ /dev/null @@ -1,58 +0,0 @@ -/* System dependent pthreads code. Hurd version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Forward. */ -static void *init_routine (void); - -/* OK, the name of this variable isn't really appropriate, but I don't - want to change it yet. */ -void *(*_pthread_init_routine)(void) = &init_routine; - -/* This function is called from the Hurd-specific startup code. It - should return a new stack pointer for the main thread. The caller - will switch to this new stack before doing anything serious. */ -static void * -init_routine (void) -{ - struct __pthread *thread; - int err; - - /* Initialize the library. */ - __pthread_initialize (); - - /* Create the pthread structure for the main thread (i.e. us). */ - err = __pthread_create_internal (&thread, 0, 0, 0); - assert_perror (err); - - __pthread_initialize (); - - /* Decrease the number of threads, to take into account that the - signal thread (which will be created by the startup code when we - return from here) shouldn't be seen as a user thread. */ -#warning Need to implement the signal thread. - // __pthread_total--; - - return (void *) thread->mcontext.sp; -} diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h deleted file mode 100644 index 87175330..00000000 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Internal defenitions for pthreads library. - 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _PT_SYSDEP_H -#define _PT_SYSDEP_H 1 - -#include -#include -#include - -/* XXX */ -#define _POSIX_THREAD_THREADS_MAX 64 - -/* The default stack size. */ -#define PTHREAD_STACK_DEFAULT (PAGE_SIZE) - -#define PTHREAD_SYSDEP_MEMBERS \ - L4_ThreadId_t threadid; \ - L4_Word_t my_errno; - -extern inline struct __pthread * -__attribute__((__always_inline__)) -_pthread_self (void) -{ - return (struct __pthread *) L4_MyUserDefinedHandle (); -} - -extern inline void -__pthread_stack_dealloc (void *stackaddr, size_t stacksize) -__attribute__((__always_inline__)) -{ - /* XXX: can only implement this once we have a working memory manager. */ - return; -} - -#endif /* pt-sysdep.h */ diff --git a/sysdeps/l4/pt-block.c b/sysdeps/l4/pt-block.c deleted file mode 100644 index 050c6947..00000000 --- a/sysdeps/l4/pt-block.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Block a thread. L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* Block THREAD. */ -void -__pthread_block (struct __pthread *thread) -{ - L4_Receive (L4_anylocalthread); -} diff --git a/sysdeps/l4/pt-docancel.c b/sysdeps/l4/pt-docancel.c deleted file mode 100644 index 9a3bb26c..00000000 --- a/sysdeps/l4/pt-docancel.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Cancel a thread. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -static void -call_exit (void) -{ - pthread_exit (0); -} - -int -__pthread_do_cancel (struct __pthread *p) -{ - assert (p->cancel_pending = 1); - assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); - - if (L4_SameThreads (L4_Myself (), p->threadid)) - call_exit (); - else - { - L4_Word_t dummy; - L4_ThreadId_t dummy_id; - - /* Change the ip of the target thread to make it exit. */ - L4_ExchangeRegisters (p->threadid, (1 << 4), 0, call_exit, - 0, 0, L4_nilthread, - &dummy, &dummy, &dummy, &dummy, &dummy, - &dummy_id); - } - - return 0; -} diff --git a/sysdeps/l4/pt-stack-alloc.c b/sysdeps/l4/pt-stack-alloc.c deleted file mode 100644 index e28d5310..00000000 --- a/sysdeps/l4/pt-stack-alloc.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Allocate a new stack. L4 Hurd version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -#define __pthread_stacksize __pthread_default_attr.stacksize - -#include -#include - -static void * -allocate_page (void) -{ - L4_Fpage_t p; - /* The Kernel Interface page. */ - static L4_KernelInterfacePage_t *kip; - - if (! kip) - kip = L4_GetKernelInterface (); - -#define sigma0_tid() (L4_GlobalId (kip->ThreadInfo.X.UserBase, 1)) - p = L4_Sigma0_GetPage (sigma0_tid (), - L4_Fpage_Set_Attrs (L4_FpageLog2 (-1UL << 10, - PAGE_SHIFT), - L4_FullyAccessible)); - p.raw &= ~0x3ff; - - printf ("%s: Allocated page %x\n", - __FUNCTION__, p.raw); - - return (void *) p.raw; -} - - -/* Allocate a new stack of size STACKSIZE. If successfull, store the - address of the newly allocated stack in *STACKADDR and return 0. - Otherwise return an error code (EINVAL for an invalid stack size, - EAGAIN if the system lacked the necessary resources to allocate a - new stack). */ -int -__pthread_stack_alloc (void **stackaddr, size_t stacksize) -{ - if (stacksize != __pthread_stacksize) - return EINVAL; - - *stackaddr = allocate_page (); - if (! *stackaddr) - return EAGAIN; - - return 0; -} diff --git a/sysdeps/l4/pt-start.c b/sysdeps/l4/pt-start.c deleted file mode 100644 index fb4e27be..00000000 --- a/sysdeps/l4/pt-start.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Start thread. L4 Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -#include "task_client.h" - -extern L4_ThreadId_t __system_pager; -extern L4_ThreadId_t __task_server; - -#ifndef WORKING_EXREGS -static void -send_startup_ipc (L4_ThreadId_t id, L4_Word_t ip, L4_Word_t sp) -{ - L4_Msg_t msg; - - printf ("%s: Sending startup message to %x, " - "(ip=%x, sp=%x)\n", - __FUNCTION__, * (L4_Word_t *) &id, ip, sp); - - L4_Clear (&msg); -#ifdef HAVE_PROPAGATION - L4_Set_VirtualSender (pager_tid); - L4_Set_Propagation (&msg.tag); -#endif - L4_Append_Word (&msg, ip); - L4_Append_Word (&msg, sp); -#ifndef HAVE_PROPAGATION - L4_Append_Word (&msg, *(L4_Word_t *) &id); - id = __system_pager; -#if 0 - DODEBUG (2, printf ("%s: Redirecting start request to pager (%x).\n", - __FUNCTION__, * (L4_Word_t *) &id)); -#endif -#endif - L4_LoadMsg (&msg); - L4_Send (id); -} -#endif - -/* Start THREAD. We allocate all system-specific resources, including - a kernel thread, set it up, and get it running. */ -int -__pthread_start (struct __pthread *thread) -{ - error_t err; - - if (__pthread_num_threads == 1) - /* The main thread is already running: do nothing. */ - { - assert (__pthread_total == 1); - thread->threadid = L4_Myself (); - } - else - { - CORBA_Environment env; - - env = idl4_default_environment; - err = thread_create (__task_server, - L4_Version (L4_Myself ()), - * (L4_Word_t *) &__system_pager, - (L4_Word_t *) &thread->threadid, &env); - if (err) - return EAGAIN; - - env = idl4_default_environment; - err = thread_resume (__task_server, - * (L4_Word_t *) &thread->threadid, - &env); - assert (! err); - -#ifndef WORKING_EXREGS - L4_AbortIpc_and_stop (thread->threadid); - L4_Start_SpIp (thread->threadid, (L4_Word_t) thread->mcontext.sp, - (L4_Word_t) thread->mcontext.pc); -#endif - send_startup_ipc (thread->threadid, (L4_Word_t) thread->mcontext.pc, - (L4_Word_t) thread->mcontext.sp); - - } - - return 0; -} diff --git a/sysdeps/l4/pt-thread-alloc.c b/sysdeps/l4/pt-thread-alloc.c deleted file mode 100644 index a9d5e212..00000000 --- a/sysdeps/l4/pt-thread-alloc.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Start thread. L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Start THREAD. Get the kernel thread scheduled and running. */ -int -__pthread_thread_start (struct __pthread *thread) -{ - error_t err; - - /* The main thread is already running of course. */ - if (__pthread_num_threads == 1) - { - assert (__pthread_total == 1); - thread->thread_id = L4_Myself (); - } - else - { - CORBA_Environment env; - - env = idl4_default_environment; - err = thread_create (__task_server, - L4_Version (L4_Myself ()), - * (L4_Word_t *) &__system_pager, - (L4_Word_t *) &thread->threadid, &env); - if (err) - return EAGAIN; - } - - return 0; -} diff --git a/sysdeps/l4/pt-thread-halt.c b/sysdeps/l4/pt-thread-halt.c deleted file mode 100644 index 04d622f4..00000000 --- a/sysdeps/l4/pt-thread-halt.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Deallocate the kernel thread resources. Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -extern L4_ThreadId_t __task_server; - -/* Deallocate the kernel thread resources associated with THREAD. */ -void -__pthread_thread_halt (struct __pthread *thread) -{ - CORBA_Environment env = idl4_default_environment; - L4_Word_t *t = (L4_Word_t *) &thread->threadid; - - assert (*t); - assert (thread_terminate (__task_server, *t, &env)); - *t = 0; -} diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c deleted file mode 100644 index c428d290..00000000 --- a/sysdeps/l4/pt-thread-start.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Start thread. L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -#include "task_client.h" - -extern L4_ThreadId_t __system_pager; -extern L4_ThreadId_t __task_server; - -#ifndef WORKING_EXREGS -static void -send_startup_ipc (L4_ThreadId_t id, L4_Word_t ip, L4_Word_t sp) -{ - L4_Msg_t msg; - - printf ("%s: Sending startup message to %x, " - "(ip=%x, sp=%x)\n", - __FUNCTION__, * (L4_Word_t *) &id, ip, sp); - - L4_Clear (&msg); -#ifdef HAVE_PROPAGATION - L4_Set_VirtualSender (pager_tid); - L4_Set_Propagation (&msg.tag); -#endif - L4_Append_Word (&msg, ip); - L4_Append_Word (&msg, sp); -#ifndef HAVE_PROPAGATION - L4_Append_Word (&msg, *(L4_Word_t *) &id); - id = __system_pager; -#if 0 - DODEBUG (2, printf ("%s: Redirecting start request to pager (%x).\n", - __FUNCTION__, * (L4_Word_t *) &id)); -#endif -#endif - L4_LoadMsg (&msg); - L4_Send (id); -} -#endif - -/* Start THREAD. Get the kernel thread scheduled and running. */ -int -__pthread_thread_start (struct __pthread *thread) -{ - error_t err; - - /* The main thread is already running of course. */ - if (__pthread_num_threads == 1) - { - assert (__pthread_total == 1); - assert (thread->thread_id == L4_Myself ()); - } - else - { - env = idl4_default_environment; - err = thread_resume (__task_server, - * (L4_Word_t *) &thread->threadid, - &env); - assert (! err); - -#ifndef WORKING_EXREGS - L4_AbortIpc_and_stop (thread->threadid); - L4_Start_SpIp (thread->threadid, (L4_Word_t) thread->mcontext.sp, - (L4_Word_t) thread->mcontext.pc); -#endif - send_startup_ipc (thread->threadid, (L4_Word_t) thread->mcontext.pc, - (L4_Word_t) thread->mcontext.sp); - - } - - return 0; -} diff --git a/sysdeps/l4/pt-wakeup.c b/sysdeps/l4/pt-wakeup.c deleted file mode 100644 index 7b00e4f6..00000000 --- a/sysdeps/l4/pt-wakeup.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Wakeup a thread. L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* Wakeup THREAD. */ -void -__pthread_wakeup (struct __pthread *thread) -{ - L4_Send (thread->threadid); -} -- cgit v1.2.3 From 1b52c5eb6e185eeef966f67a96a2c44146abfbd7 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 12 Aug 2008 07:10:31 +0000 Subject: 2008-08-12 Neal H. Walfield * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): Remove dead code. --- sysdeps/generic/pt-mutex-unlock.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index 4352042e..d1ef23a3 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -37,16 +37,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) if (_pthread_self ()) { assert (mutex->owner); -#if 0 - assertx (mutex->owner == _pthread_self (), - "%p(%x) != %p(%x)", - mutex->owner, - ((struct __pthread *) mutex->owner)->threadid, - _pthread_self (), - _pthread_self ()->threadid); -#else assert (mutex->owner == _pthread_self ()); -#endif mutex->owner = NULL; } #endif -- cgit v1.2.3 From 87bbfdf3b5718544942498f0d980e13a0f4110da Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Thu, 18 Mar 2004 02:44:20 +0000 Subject: 2004-03-17 Marcus Brinkmann * libpthread: New directory, populated with Neal H. Walfields pthread implementation. --- Makefile.am | 129 ++++++ Makefile.in | 809 ++++++++++++++++++++++++++++++++++ headers.m4 | 35 ++ pthread/pt-create.c | 24 +- pthread/pt-internal.h | 7 +- sysdeps/generic/bits/pthreadtypes.h | 29 ++ sysdeps/generic/pt-rwlock-rdlock.c | 2 +- sysdeps/hurd/pt-destroy-specific.c | 11 +- sysdeps/hurd/pt-getspecific.c | 2 +- sysdeps/hurd/pt-key.h | 2 +- sysdeps/i386/bits/atomic.h | 66 --- sysdeps/i386/bits/memory.h | 40 -- sysdeps/i386/bits/spin-lock.h | 103 ----- sysdeps/i386/machine-sp.h | 31 -- sysdeps/i386/pt-machdep.h | 29 -- sysdeps/ia32/bits/atomic.h | 66 +++ sysdeps/ia32/bits/memory.h | 40 ++ sysdeps/ia32/bits/spin-lock.h | 103 +++++ sysdeps/ia32/machine-sp.h | 31 ++ sysdeps/ia32/pt-machdep.h | 29 ++ sysdeps/l4/bits/pthread-np.h | 38 ++ sysdeps/l4/hurd/i386/pt-machdep.c | 20 - sysdeps/l4/hurd/i386/pt-setup.c | 72 --- sysdeps/l4/hurd/ia32/pt-machdep.c | 20 + sysdeps/l4/hurd/ia32/pt-setup.c | 72 +++ sysdeps/l4/hurd/powerpc/pt-machdep.c | 20 + sysdeps/l4/hurd/powerpc/pt-setup.c | 93 ++++ sysdeps/l4/hurd/pt-kill.c | 30 ++ sysdeps/l4/hurd/pt-sigstate-destroy.c | 28 ++ sysdeps/l4/hurd/pt-sigstate-init.c | 28 ++ sysdeps/l4/hurd/pt-sigstate.c | 32 ++ sysdeps/l4/hurd/pt-sysdep.c | 2 +- sysdeps/l4/hurd/pt-sysdep.h | 12 +- sysdeps/l4/pt-block.c | 4 +- sysdeps/l4/pt-create-np.c | 47 ++ sysdeps/l4/pt-docancel.c | 3 +- sysdeps/l4/pt-spin.c | 60 +++ sysdeps/l4/pt-stack-alloc.c | 25 +- sysdeps/l4/pt-thread-alloc.c | 12 +- sysdeps/l4/pt-thread-halt.c | 11 +- sysdeps/l4/pt-thread-init.c | 34 ++ sysdeps/l4/pt-thread-start.c | 68 +-- sysdeps/l4/pt-timedblock.c | 34 ++ sysdeps/l4/pt-wakeup.c | 4 +- sysdeps/mach/hurd/i386/pt-machdep.c | 54 --- sysdeps/mach/hurd/i386/pt-setup.c | 103 ----- sysdeps/mach/hurd/ia32/pt-machdep.c | 54 +++ sysdeps/mach/hurd/ia32/pt-setup.c | 103 +++++ sysdeps/powerpc/bits/atomic.h | 84 ++++ sysdeps/powerpc/bits/machine-lock.h | 78 ++++ sysdeps/powerpc/bits/memory.h | 36 ++ sysdeps/powerpc/bits/spin-lock.h | 108 +++++ sysdeps/powerpc/machine-sp.h | 31 ++ sysdeps/powerpc/pt-machdep.h | 29 ++ 54 files changed, 2398 insertions(+), 639 deletions(-) create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 headers.m4 create mode 100644 sysdeps/generic/bits/pthreadtypes.h delete mode 100644 sysdeps/i386/bits/atomic.h delete mode 100644 sysdeps/i386/bits/memory.h delete mode 100644 sysdeps/i386/bits/spin-lock.h delete mode 100644 sysdeps/i386/machine-sp.h delete mode 100644 sysdeps/i386/pt-machdep.h create mode 100644 sysdeps/ia32/bits/atomic.h create mode 100644 sysdeps/ia32/bits/memory.h create mode 100644 sysdeps/ia32/bits/spin-lock.h create mode 100644 sysdeps/ia32/machine-sp.h create mode 100644 sysdeps/ia32/pt-machdep.h create mode 100644 sysdeps/l4/bits/pthread-np.h delete mode 100644 sysdeps/l4/hurd/i386/pt-machdep.c delete mode 100644 sysdeps/l4/hurd/i386/pt-setup.c create mode 100644 sysdeps/l4/hurd/ia32/pt-machdep.c create mode 100644 sysdeps/l4/hurd/ia32/pt-setup.c create mode 100644 sysdeps/l4/hurd/powerpc/pt-machdep.c create mode 100644 sysdeps/l4/hurd/powerpc/pt-setup.c create mode 100644 sysdeps/l4/hurd/pt-kill.c create mode 100644 sysdeps/l4/hurd/pt-sigstate-destroy.c create mode 100644 sysdeps/l4/hurd/pt-sigstate-init.c create mode 100644 sysdeps/l4/hurd/pt-sigstate.c create mode 100644 sysdeps/l4/pt-create-np.c create mode 100644 sysdeps/l4/pt-spin.c create mode 100644 sysdeps/l4/pt-thread-init.c create mode 100644 sysdeps/l4/pt-timedblock.c delete mode 100644 sysdeps/mach/hurd/i386/pt-machdep.c delete mode 100644 sysdeps/mach/hurd/i386/pt-setup.c create mode 100644 sysdeps/mach/hurd/ia32/pt-machdep.c create mode 100644 sysdeps/mach/hurd/ia32/pt-setup.c create mode 100644 sysdeps/powerpc/bits/atomic.h create mode 100644 sysdeps/powerpc/bits/machine-lock.h create mode 100644 sysdeps/powerpc/bits/memory.h create mode 100644 sysdeps/powerpc/bits/spin-lock.h create mode 100644 sysdeps/powerpc/machine-sp.h create mode 100644 sysdeps/powerpc/pt-machdep.h diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..24896080 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,129 @@ +# Makefile.am - Makefile template for libpthread. +# Copyright (C) 2003 Free Software Foundation, Inc. +# +# This file is part of the GNU Hurd. +# +# The GNU Hurd is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU Hurd 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 General Public License for more details. +# +# You should have received a copy of the GNU 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 + +if ARCH_IA32 + arch=ia32 +endif +if ARCH_POWERPC + arch=powerpc +endif + +# The source files is scattered over several directories. Add +# all these directories to the vpath. +SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ + $(srcdir)/sysdeps/l4/${arch} \ + $(srcdir)/sysdeps/l4/hurd \ + $(srcdir)/sysdeps/l4 \ + $(srcdir)/sysdeps/hurd \ + $(srcdir)/sysdeps/${arch} \ + $(srcdir)/sysdeps/generic \ + $(srcdir)/sysdeps/posix \ + $(srcdir)/pthread \ + $(srcdir)/include +vpath %.c $(SYSDEP_PATH) + +AM_CPPFLAGS = -I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ + -I$(top_srcdir)/libc-parts $(addprefix -I, $(SYSDEP_PATH)) \ + -imacros $(srcdir)/include/libc-symbols.h + +# Sources. +SYSDEPS := lockfile.c + +noinst_LIBRARIES = libpthread.a +libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ + pt-attr-getguardsize.c pt-attr-getinheritsched.c \ + pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ + pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ + pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ + pt-attr-setinheritsched.c pt-attr-setschedparam.c \ + pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ + pt-attr-setstackaddr.c pt-attr-setstacksize.c pt-attr.c \ + pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ + pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ + pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ + pt-destroy-specific.c pt-init-specific.c \ + pt-key-create.c pt-key-delete.c \ + pt-getspecific.c pt-setspecific.c \ + pt-once.c \ + pt-alloc.c \ + pt-create.c \ + pt-create-np.c \ + pt-equal.c \ + pt-dealloc.c \ + pt-detach.c \ + pt-exit.c \ + pt-initialize.c \ + pt-join.c \ + pt-self.c \ + pt-sigmask.c \ + pt-spin-inlines.c \ + pt-cleanup.c \ + pt-setcancelstate.c \ + pt-setcanceltype.c \ + pt-testcancel.c \ + pt-cancel.c \ + pt-mutexattr.c \ + pt-mutexattr-destroy.c pt-mutexattr-init.c \ + pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ + pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ + pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ + pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ + pt-mutex-init.c pt-mutex-destroy.c \ + pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ + pt-mutex-unlock.c \ + pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ + pt-rwlock-attr.c \ + pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ + pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ + pt-rwlock-init.c pt-rwlock-destroy.c \ + pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ + pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ + pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ + pt-rwlock-unlock.c \ + pt-cond.c \ + pt-condattr-init.c pt-condattr-destroy.c \ + pt-condattr-getclock.c pt-condattr-getpshared.c \ + pt-condattr-setclock.c pt-condattr-setpshared.c \ + pt-cond-destroy.c pt-cond-init.c \ + pt-cond-brdcast.c \ + pt-cond-signal.c \ + pt-cond-wait.c \ + pt-cond-timedwait.c \ + pt-stack-alloc.c \ + pt-thread-alloc.c \ + pt-thread-start.c \ + pt-thread-halt.c \ + pt-thread-init.c \ + pt-getconcurrency.c pt-setconcurrency.c \ + pt-block.c \ + pt-timedblock.c \ + pt-wakeup.c \ + pt-docancel.c \ + pt-sysdep.c \ + pt-setup.c \ + pt-machdep.c \ + pt-spin.c \ + pt-sigstate-init.c \ + pt-sigstate-destroy.c \ + pt-sigstate.c \ + pt-atfork.c \ + pt-kill.c \ + pt-getcpuclockid.c \ + pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..26e32873 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,809 @@ +# Makefile.in generated by automake 1.7.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am - Makefile template for libpthread. +# Copyright (C) 2003 Free Software Foundation, Inc. +# +# This file is part of the GNU Hurd. +# +# The GNU Hurd is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU Hurd 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 General Public License for more details. +# +# You should have received a copy of the GNU 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 + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +ARCH_IA32_FALSE = @ARCH_IA32_FALSE@ +ARCH_IA32_TRUE = @ARCH_IA32_TRUE@ +ARCH_POWERPC_FALSE = @ARCH_POWERPC_FALSE@ +ARCH_POWERPC_TRUE = @ARCH_POWERPC_TRUE@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DVIPS = @DVIPS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EXEEXT = @EXEEXT@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LATEX = @LATEX@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +NM = @NM@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PS2PDF = @PS2PDF@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SORT = @SORT@ +STATIC_GLIBC = @STATIC_GLIBC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_NM = @ac_ct_NM@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ + +@ARCH_IA32_TRUE@arch = ia32 +@ARCH_POWERPC_TRUE@arch = powerpc + +# The source files is scattered over several directories. Add +# all these directories to the vpath. +SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ + $(srcdir)/sysdeps/l4/${arch} \ + $(srcdir)/sysdeps/l4/hurd \ + $(srcdir)/sysdeps/l4 \ + $(srcdir)/sysdeps/hurd \ + $(srcdir)/sysdeps/${arch} \ + $(srcdir)/sysdeps/generic \ + $(srcdir)/sysdeps/posix \ + $(srcdir)/pthread \ + $(srcdir)/include + + +AM_CPPFLAGS = -I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ + -I$(top_srcdir)/libc-parts $(addprefix -I, $(SYSDEP_PATH)) \ + -imacros $(srcdir)/include/libc-symbols.h + + +# Sources. +SYSDEPS := lockfile.c + +noinst_LIBRARIES = libpthread.a +libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ + pt-attr-getguardsize.c pt-attr-getinheritsched.c \ + pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ + pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ + pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ + pt-attr-setinheritsched.c pt-attr-setschedparam.c \ + pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ + pt-attr-setstackaddr.c pt-attr-setstacksize.c pt-attr.c \ + pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ + pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ + pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ + pt-destroy-specific.c pt-init-specific.c \ + pt-key-create.c pt-key-delete.c \ + pt-getspecific.c pt-setspecific.c \ + pt-once.c \ + pt-alloc.c \ + pt-create.c \ + pt-create-np.c \ + pt-equal.c \ + pt-dealloc.c \ + pt-detach.c \ + pt-exit.c \ + pt-initialize.c \ + pt-join.c \ + pt-self.c \ + pt-sigmask.c \ + pt-spin-inlines.c \ + pt-cleanup.c \ + pt-setcancelstate.c \ + pt-setcanceltype.c \ + pt-testcancel.c \ + pt-cancel.c \ + pt-mutexattr.c \ + pt-mutexattr-destroy.c pt-mutexattr-init.c \ + pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ + pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ + pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ + pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ + pt-mutex-init.c pt-mutex-destroy.c \ + pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ + pt-mutex-unlock.c \ + pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ + pt-rwlock-attr.c \ + pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ + pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ + pt-rwlock-init.c pt-rwlock-destroy.c \ + pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ + pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ + pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ + pt-rwlock-unlock.c \ + pt-cond.c \ + pt-condattr-init.c pt-condattr-destroy.c \ + pt-condattr-getclock.c pt-condattr-getpshared.c \ + pt-condattr-setclock.c pt-condattr-setpshared.c \ + pt-cond-destroy.c pt-cond-init.c \ + pt-cond-brdcast.c \ + pt-cond-signal.c \ + pt-cond-wait.c \ + pt-cond-timedwait.c \ + pt-stack-alloc.c \ + pt-thread-alloc.c \ + pt-thread-start.c \ + pt-thread-halt.c \ + pt-thread-init.c \ + pt-getconcurrency.c pt-setconcurrency.c \ + pt-block.c \ + pt-timedblock.c \ + pt-wakeup.c \ + pt-docancel.c \ + pt-sysdep.c \ + pt-setup.c \ + pt-machdep.c \ + pt-spin.c \ + pt-sigstate-init.c \ + pt-sigstate-destroy.c \ + pt-sigstate.c \ + pt-atfork.c \ + pt-kill.c \ + pt-getcpuclockid.c \ + pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c + +subdir = libpthread +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libpthread_a_AR = $(AR) cru +libpthread_a_LIBADD = +am_libpthread_a_OBJECTS = pt-attr.$(OBJEXT) pt-attr-destroy.$(OBJEXT) \ + pt-attr-getdetachstate.$(OBJEXT) pt-attr-getguardsize.$(OBJEXT) \ + pt-attr-getinheritsched.$(OBJEXT) \ + pt-attr-getschedparam.$(OBJEXT) \ + pt-attr-getschedpolicy.$(OBJEXT) pt-attr-getscope.$(OBJEXT) \ + pt-attr-getstack.$(OBJEXT) pt-attr-getstackaddr.$(OBJEXT) \ + pt-attr-getstacksize.$(OBJEXT) pt-attr-init.$(OBJEXT) \ + pt-attr-setdetachstate.$(OBJEXT) pt-attr-setguardsize.$(OBJEXT) \ + pt-attr-setinheritsched.$(OBJEXT) \ + pt-attr-setschedparam.$(OBJEXT) \ + pt-attr-setschedpolicy.$(OBJEXT) pt-attr-setscope.$(OBJEXT) \ + pt-attr-setstack.$(OBJEXT) pt-attr-setstackaddr.$(OBJEXT) \ + pt-attr-setstacksize.$(OBJEXT) pt-attr.$(OBJEXT) \ + pt-barrier-destroy.$(OBJEXT) pt-barrier-init.$(OBJEXT) \ + pt-barrier-wait.$(OBJEXT) pt-barrier.$(OBJEXT) \ + pt-barrierattr-destroy.$(OBJEXT) pt-barrierattr-init.$(OBJEXT) \ + pt-barrierattr-getpshared.$(OBJEXT) \ + pt-barrierattr-setpshared.$(OBJEXT) \ + pt-destroy-specific.$(OBJEXT) pt-init-specific.$(OBJEXT) \ + pt-key-create.$(OBJEXT) pt-key-delete.$(OBJEXT) \ + pt-getspecific.$(OBJEXT) pt-setspecific.$(OBJEXT) \ + pt-once.$(OBJEXT) pt-alloc.$(OBJEXT) pt-create.$(OBJEXT) \ + pt-create-np.$(OBJEXT) pt-equal.$(OBJEXT) pt-dealloc.$(OBJEXT) \ + pt-detach.$(OBJEXT) pt-exit.$(OBJEXT) pt-initialize.$(OBJEXT) \ + pt-join.$(OBJEXT) pt-self.$(OBJEXT) pt-sigmask.$(OBJEXT) \ + pt-spin-inlines.$(OBJEXT) pt-cleanup.$(OBJEXT) \ + pt-setcancelstate.$(OBJEXT) pt-setcanceltype.$(OBJEXT) \ + pt-testcancel.$(OBJEXT) pt-cancel.$(OBJEXT) \ + pt-mutexattr.$(OBJEXT) pt-mutexattr-destroy.$(OBJEXT) \ + pt-mutexattr-init.$(OBJEXT) \ + pt-mutexattr-getprioceiling.$(OBJEXT) \ + pt-mutexattr-getprotocol.$(OBJEXT) \ + pt-mutexattr-getpshared.$(OBJEXT) \ + pt-mutexattr-gettype.$(OBJEXT) \ + pt-mutexattr-setprioceiling.$(OBJEXT) \ + pt-mutexattr-setprotocol.$(OBJEXT) \ + pt-mutexattr-setpshared.$(OBJEXT) \ + pt-mutexattr-settype.$(OBJEXT) pt-mutex-init.$(OBJEXT) \ + pt-mutex-destroy.$(OBJEXT) pt-mutex-lock.$(OBJEXT) \ + pt-mutex-trylock.$(OBJEXT) pt-mutex-timedlock.$(OBJEXT) \ + pt-mutex-unlock.$(OBJEXT) pt-mutex-getprioceiling.$(OBJEXT) \ + pt-mutex-setprioceiling.$(OBJEXT) pt-rwlock-attr.$(OBJEXT) \ + pt-rwlockattr-init.$(OBJEXT) pt-rwlockattr-destroy.$(OBJEXT) \ + pt-rwlockattr-getpshared.$(OBJEXT) \ + pt-rwlockattr-setpshared.$(OBJEXT) pt-rwlock-init.$(OBJEXT) \ + pt-rwlock-destroy.$(OBJEXT) pt-rwlock-rdlock.$(OBJEXT) \ + pt-rwlock-tryrdlock.$(OBJEXT) pt-rwlock-trywrlock.$(OBJEXT) \ + pt-rwlock-wrlock.$(OBJEXT) pt-rwlock-timedrdlock.$(OBJEXT) \ + pt-rwlock-timedwrlock.$(OBJEXT) pt-rwlock-unlock.$(OBJEXT) \ + pt-cond.$(OBJEXT) pt-condattr-init.$(OBJEXT) \ + pt-condattr-destroy.$(OBJEXT) pt-condattr-getclock.$(OBJEXT) \ + pt-condattr-getpshared.$(OBJEXT) pt-condattr-setclock.$(OBJEXT) \ + pt-condattr-setpshared.$(OBJEXT) pt-cond-destroy.$(OBJEXT) \ + pt-cond-init.$(OBJEXT) pt-cond-brdcast.$(OBJEXT) \ + pt-cond-signal.$(OBJEXT) pt-cond-wait.$(OBJEXT) \ + pt-cond-timedwait.$(OBJEXT) pt-stack-alloc.$(OBJEXT) \ + pt-thread-alloc.$(OBJEXT) pt-thread-start.$(OBJEXT) \ + pt-thread-halt.$(OBJEXT) pt-thread-init.$(OBJEXT) \ + pt-getconcurrency.$(OBJEXT) pt-setconcurrency.$(OBJEXT) \ + pt-block.$(OBJEXT) pt-timedblock.$(OBJEXT) pt-wakeup.$(OBJEXT) \ + pt-docancel.$(OBJEXT) pt-sysdep.$(OBJEXT) pt-setup.$(OBJEXT) \ + pt-machdep.$(OBJEXT) pt-spin.$(OBJEXT) \ + pt-sigstate-init.$(OBJEXT) pt-sigstate-destroy.$(OBJEXT) \ + pt-sigstate.$(OBJEXT) pt-atfork.$(OBJEXT) pt-kill.$(OBJEXT) \ + pt-getcpuclockid.$(OBJEXT) pt-getschedparam.$(OBJEXT) \ + pt-setschedparam.$(OBJEXT) pt-setschedprio.$(OBJEXT) +libpthread_a_OBJECTS = $(am_libpthread_a_OBJECTS) + +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/pt-alloc.Po ./$(DEPDIR)/pt-atfork.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getdetachstate.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getguardsize.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getinheritsched.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getschedparam.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getschedpolicy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getscope.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getstack.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getstackaddr.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getstacksize.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setdetachstate.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setguardsize.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setinheritsched.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setschedparam.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setschedpolicy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setscope.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setstack.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setstackaddr.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setstacksize.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier-wait.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-getpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-setpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-block.Po ./$(DEPDIR)/pt-cancel.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-cleanup.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-brdcast.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-signal.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-timedwait.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-wait.Po ./$(DEPDIR)/pt-cond.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-getclock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-getpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-setclock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-setpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-create-np.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-create.Po ./$(DEPDIR)/pt-dealloc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-destroy-specific.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-detach.Po ./$(DEPDIR)/pt-docancel.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-equal.Po ./$(DEPDIR)/pt-exit.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-getconcurrency.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-getcpuclockid.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-getschedparam.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-getspecific.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-init-specific.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-initialize.Po ./$(DEPDIR)/pt-join.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-key-create.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-key-delete.Po ./$(DEPDIR)/pt-kill.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-machdep.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-getprioceiling.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-lock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-setprioceiling.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-timedlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-trylock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-unlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-getprioceiling.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-getprotocol.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-getpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-gettype.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-setprioceiling.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-setprotocol.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-setpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-settype.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr.Po ./$(DEPDIR)/pt-once.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-attr.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-rdlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-timedrdlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-timedwrlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-tryrdlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-trywrlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-unlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-wrlock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-getpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-setpshared.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-self.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-setcancelstate.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-setcanceltype.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-setconcurrency.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-setschedparam.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-setschedprio.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-setspecific.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-setup.Po ./$(DEPDIR)/pt-sigmask.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-sigstate-destroy.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-sigstate-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-sigstate.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-spin-inlines.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-spin.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-stack-alloc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-sysdep.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-testcancel.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-alloc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-halt.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-init.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-start.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-timedblock.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-wakeup.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libpthread_a_SOURCES) +DIST_COMMON = ChangeLog Makefile.am Makefile.in TODO +SOURCES = $(libpthread_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu libpthread/Makefile +Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libpthread.a: $(libpthread_a_OBJECTS) $(libpthread_a_DEPENDENCIES) + -rm -f libpthread.a + $(libpthread_a_AR) libpthread.a $(libpthread_a_OBJECTS) $(libpthread_a_LIBADD) + $(RANLIB) libpthread.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-alloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-atfork.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getdetachstate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getguardsize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getinheritsched.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getschedparam.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getschedpolicy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getscope.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getstack.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getstackaddr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getstacksize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setdetachstate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setguardsize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setinheritsched.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setschedparam.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setschedpolicy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setscope.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setstack.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setstackaddr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setstacksize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier-wait.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-getpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-setpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-block.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cancel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cleanup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-brdcast.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-signal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-timedwait.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-wait.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-getclock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-getpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-setclock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-setpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-create-np.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-create.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-dealloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-destroy-specific.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-detach.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-docancel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-equal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-exit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getconcurrency.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getcpuclockid.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getschedparam.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getspecific.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-init-specific.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-initialize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-join.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-key-create.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-key-delete.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-kill.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-machdep.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-getprioceiling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-lock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-setprioceiling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-timedlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-trylock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-unlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-getprioceiling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-getprotocol.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-getpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-gettype.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-setprioceiling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-setprotocol.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-setpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-settype.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-once.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-attr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-rdlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-timedrdlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-timedwrlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-tryrdlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-trywrlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-unlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-wrlock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-getpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-setpshared.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-self.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setcancelstate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setcanceltype.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setconcurrency.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setschedparam.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setschedprio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setspecific.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigmask.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigstate-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigstate-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigstate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-spin-inlines.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-spin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-stack-alloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sysdep.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-testcancel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-alloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-halt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-init.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-start.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-timedblock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-wakeup.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am + +vpath %.c $(SYSDEP_PATH) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/headers.m4 b/headers.m4 new file mode 100644 index 00000000..4fceecbf --- /dev/null +++ b/headers.m4 @@ -0,0 +1,35 @@ +# headers.m4 - Autoconf snippets to install links for header files. +# Copyright 2003 Free Software Foundation, Inc. +# Written by Marcus Brinkmann . +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +AC_CONFIG_LINKS([ + include/pthread.h:libpthread/include/pthread.h + include/pthread/pthread.h:libpthread/include/pthread/pthread.h + include/bits/atomic.h:libpthread/sysdeps/${arch}/bits/atomic.h + include/bits/memory.h:libpthread/sysdeps/${arch}/bits/memory.h + include/bits/spin-lock.h:libpthread/sysdeps/${arch}/bits/spin-lock.h + include/bits/pthreadtypes.h:libpthread/sysdeps/generic/bits/pthreadtypes.h + include/bits/barrier-attr.h:libpthread/sysdeps/generic/bits/barrier-attr.h + include/bits/barrier.h:libpthread/sysdeps/generic/bits/barrier.h + include/bits/cancelation.h:libpthread/sysdeps/generic/bits/cancelation.h + include/bits/condition-attr.h:libpthread/sysdeps/generic/bits/condition-attr.h + include/bits/condition.h:libpthread/sysdeps/generic/bits/condition.h + include/bits/mutex-attr.h:libpthread/sysdeps/generic/bits/mutex-attr.h + include/bits/mutex.h:libpthread/sysdeps/generic/bits/mutex.h + include/bits/once.h:libpthread/sysdeps/generic/bits/once.h + include/bits/pthread.h:libpthread/sysdeps/generic/bits/pthread.h + include/bits/rwlock-attr.h:libpthread/sysdeps/generic/bits/rwlock-attr.h + include/bits/rwlock.h:libpthread/sysdeps/generic/bits/rwlock.h + include/bits/thread-attr.h:libpthread/sysdeps/generic/bits/thread-attr.h + include/bits/thread-barrier.h:libpthread/sysdeps/generic/bits/thread-barrier.h + include/bits/thread-specific.h:libpthread/sysdeps/generic/bits/thread-specific.h + include/bits/pthread-np.h:libpthread/sysdeps/l4/bits/pthread-np.h +]) diff --git a/pthread/pt-create.c b/pthread/pt-create.c index 0295a0af..727fbac1 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -57,7 +57,7 @@ pthread_create (pthread_t *thread, const pthread_attr_t *attr, int err; struct __pthread *pthread; - err = __pthread_create_internal (&pthread, attr, start_routine, arg); + err = __pthread_create_internal (&pthread, attr, 0, start_routine, arg); if (! err) *thread = pthread->thread; @@ -69,6 +69,7 @@ pthread_create (pthread_t *thread, const pthread_attr_t *attr, int __pthread_create_internal (struct __pthread **thread, const pthread_attr_t *attr, + void *provided_thread, void *(*start_routine)(void *), void *arg) { int err; @@ -122,10 +123,20 @@ __pthread_create_internal (struct __pthread **thread, pthread->stack = 1; } - /* Allocate the kernel thread and other required resources. */ - err = __pthread_thread_alloc (pthread); - if (err) - goto failed_thread_alloc; + /* Allocate the kernel thread and other required resources + if they were not provided with this call. */ + if (!provided_thread) + { + err = __pthread_thread_alloc (pthread); + if (err) + goto failed_thread_alloc; + } + else + { + err = __pthread_init_provided_thread (pthread, provided_thread); + if (err) + goto failed_thread_alloc; + } /* And initialize the rest of the machine context. This may include additional machine- and system-specific initializations that @@ -146,7 +157,8 @@ __pthread_create_internal (struct __pthread **thread, shall be empty." If the currnet thread is not a pthread then we just inherit the process' sigmask. */ if (__pthread_num_threads == 1) - err = sigprocmask (0, 0, &sigset); + /* FIXME no sigprocmask yet */ + err = 0; /* sigprocmask (0, 0, &sigset); */ else err = __pthread_sigstate (_pthread_self (), 0, 0, &sigset, 0); assert_perror (err); diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index a32345c4..79ce19c7 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -21,11 +21,12 @@ #define _PT_INTERNAL_H 1 #include +#if 0 #include #include #include #include - +#endif #include #include @@ -164,6 +165,7 @@ extern void __pthread_initialize (void); tid, we return the whole __pthread structure in *PTHREAD. */ extern int __pthread_create_internal (struct __pthread **pthread, const pthread_attr_t *attr, + void *provided_thread, void *(*start_routine)(void *), void *arg); @@ -203,6 +205,9 @@ extern int __pthread_thread_start (struct __pthread *thread); with THREAD. */ extern void __pthread_thread_halt (struct __pthread *thread); +/* Initialize provided kernel thread. */ +extern int __pthread_init_provided_thread (struct __pthread *thread, + void *p); /* Block THREAD. */ extern void __pthread_block (struct __pthread *thread); diff --git a/sysdeps/generic/bits/pthreadtypes.h b/sysdeps/generic/bits/pthreadtypes.h new file mode 100644 index 00000000..e5cbfd2a --- /dev/null +++ b/sysdeps/generic/bits/pthreadtypes.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#endif /* bits/pthreadtypes.h */ diff --git a/sysdeps/generic/pt-rwlock-rdlock.c b/sysdeps/generic/pt-rwlock-rdlock.c index 22c11204..d060c38f 100644 --- a/sysdeps/generic/pt-rwlock-rdlock.c +++ b/sysdeps/generic/pt-rwlock-rdlock.c @@ -21,7 +21,7 @@ #include /* Implemented in pt-rwlock-timedrdlock.c. */ -extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_mutex *mutex, +extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *mutex, const struct timespec *abstime); /* Acquire RWLOCK for reading, block if we can't get it. */ diff --git a/sysdeps/hurd/pt-destroy-specific.c b/sysdeps/hurd/pt-destroy-specific.c index dbd3314b..2006f2b8 100644 --- a/sysdeps/hurd/pt-destroy-specific.c +++ b/sysdeps/hurd/pt-destroy-specific.c @@ -50,10 +50,10 @@ __pthread_destroy_specific (struct __pthread *thread) if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID) break; - value = ihash_find (thread->thread_specifics, i); + value = hurd_ihash_find (thread->thread_specifics, i); if (value) { - err = ihash_remove (thread->thread_specifics, i); + err = hurd_ihash_remove (thread->thread_specifics, i); assert (err == 1); if (__pthread_key_destructors[i]) @@ -71,9 +71,10 @@ __pthread_destroy_specific (struct __pthread *thread) /* This may take a very long time. Let those blocking on pthread_key_create or pthread_key_delete make progress. */ - sched_yield (); + /* FIXME what should we do with this one? */ + /* sched_yield (); */ } - - ihash_free (thread->thread_specifics); + + hurd_ihash_free (thread->thread_specifics); thread->thread_specifics = 0; } diff --git a/sysdeps/hurd/pt-getspecific.c b/sysdeps/hurd/pt-getspecific.c index b5b5f5e5..30605984 100644 --- a/sysdeps/hurd/pt-getspecific.c +++ b/sysdeps/hurd/pt-getspecific.c @@ -33,5 +33,5 @@ pthread_getspecific (pthread_key_t key) if (! self->thread_specifics) return 0; - return ihash_find (self->thread_specifics, key); + return hurd_ihash_find (self->thread_specifics, key); } diff --git a/sysdeps/hurd/pt-key.h b/sysdeps/hurd/pt-key.h index 739fbbad..494e01d7 100644 --- a/sysdeps/hurd/pt-key.h +++ b/sysdeps/hurd/pt-key.h @@ -21,7 +21,7 @@ #include #define PTHREAD_KEY_MEMBERS \ - ihash_t thread_specifics; + hurd_ihash_t thread_specifics; #define PTHREAD_KEY_INVALID (void *) (-1) diff --git a/sysdeps/i386/bits/atomic.h b/sysdeps/i386/bits/atomic.h deleted file mode 100644 index 0dfc1f60..00000000 --- a/sysdeps/i386/bits/atomic.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Atomic operations. i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_ATOMIC_H -#define _BITS_ATOMIC_H 1 - -typedef __volatile int __atomic_t; - -static inline void -__atomic_inc (__atomic_t *__var) -{ - __asm__ __volatile ("lock; incl %0" : "=m" (*__var) : "m" (*__var)); -} - -static inline void -__atomic_dec (__atomic_t *__var) -{ - __asm__ __volatile ("lock; decl %0" : "=m" (*__var) : "m" (*__var)); -} - -static inline int -__atomic_dec_and_test (__atomic_t *__var) -{ - unsigned char __ret; - - __asm__ __volatile ("lock; decl %0; sete %1" - : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); - return __ret != 0; -} - -/* We assume that an __atomicptr_t is only used for pointers to - word-aligned objects, and use the lowest bit for a simple lock. */ -typedef __volatile int * __atomicptr_t; - -/* Actually we don't implement that yet, and assume that we run on - something that has the i486 instruction set. */ -static inline int -__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, - void * __newval) -{ - char __ret; - int __dummy; - - __asm__ __volatile ("lock; cmpxchgl %3, %1; sete %0" - : "=q" (__ret), "=m" (*__ptr), "=a" (__dummy) - : "r" (__newval), "m" (*__ptr), "a" (__oldval)); - return __ret; -} - -#endif diff --git a/sysdeps/i386/bits/memory.h b/sysdeps/i386/bits/memory.h deleted file mode 100644 index 201305b9..00000000 --- a/sysdeps/i386/bits/memory.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Memory barrier operations. i386 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_MEMORY_H -#define _BITS_MEMORY_H 1 - -/* Prevent read and write reordering across this function. */ -inline void -__memory_barrier (void) -{ - int i; - - /* Any lock'ed instruction will do. We just do a simple - increment. */ - __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i)); -} - -/* Prevent read reordering across this function. */ -#define __memory_read_barrier __memory_barrier - -/* Prevent write reordering across this function. */ -#define __memory_write_barrier __memory_barrier - -#endif diff --git a/sysdeps/i386/bits/spin-lock.h b/sysdeps/i386/bits/spin-lock.h deleted file mode 100644 index 175656ef..00000000 --- a/sysdeps/i386/bits/spin-lock.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Machine-specific definitions for spin locks. i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * Never include this file directly; use or instead. - */ - -#ifndef _BITS_SPIN_LOCK_H -#define _BITS_SPIN_LOCK_H 1 - -#include - -__BEGIN_DECLS - -/* The type of a spin lock object. */ -typedef __volatile int __pthread_spinlock_t; - -/* Initializer for a spin lock object. */ -# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) - -#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES - -# ifndef __EBUSY -# include -# define __EBUSY EBUSY -# endif - -# ifndef __PT_SPIN_INLINE -# define __PT_SPIN_INLINE extern __inline -# endif - -__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_destroy (__pthread_spinlock_t *__lock) -{ - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, - int __pshared); - -__PT_SPIN_INLINE int -__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) -{ - *__lock = __SPIN_LOCK_INITIALIZER; - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_trylock (__pthread_spinlock_t *__lock) -{ - int __locked; - __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__locked), "=m" (*__lock) : "0" (1)); - return __locked ? __EBUSY : 0; -} - -extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); -extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); - -extern inline int -__pthread_spin_lock (__pthread_spinlock_t *__lock) -{ - if (__pthread_spin_trylock (__lock)) - return _pthread_spin_lock (__lock); - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_unlock (__pthread_spinlock_t *__lock) -{ - int __unlocked; - __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__unlocked), "=m" (*__lock) : "0" (0)); - return 0; -} - -#endif /* Use extern inlines or force inlines. */ - -__END_DECLS - -#endif /* bits/spin-lock.h */ diff --git a/sysdeps/i386/machine-sp.h b/sysdeps/i386/machine-sp.h deleted file mode 100644 index 536f6902..00000000 --- a/sysdeps/i386/machine-sp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Machine-specific function to return the stack pointer. i386 version. - Copyright (C) 1994,97,2001 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. */ - -#ifndef _MACHINE_SP_H -#define _MACHINE_SP_H - -/* Return the current stack pointer. */ - -#define __thread_stack_pointer() ({ \ - void *__sp__; \ - __asm__ ("movl %%esp, %0" : "=r" (__sp__)); \ - __sp__; \ -}) - -#endif /* machine-sp.h */ diff --git a/sysdeps/i386/pt-machdep.h b/sysdeps/i386/pt-machdep.h deleted file mode 100644 index 6d456367..00000000 --- a/sysdeps/i386/pt-machdep.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Machine dependent pthreads internal defenitions. i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _PT_MACHDEP_H -#define _PT_MACHDEP_H 1 - -struct pthread_mcontext -{ - void *pc; - void *sp; -}; - -#endif /* pt-machdep.h */ diff --git a/sysdeps/ia32/bits/atomic.h b/sysdeps/ia32/bits/atomic.h new file mode 100644 index 00000000..0dfc1f60 --- /dev/null +++ b/sysdeps/ia32/bits/atomic.h @@ -0,0 +1,66 @@ +/* Atomic operations. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +typedef __volatile int __atomic_t; + +static inline void +__atomic_inc (__atomic_t *__var) +{ + __asm__ __volatile ("lock; incl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline void +__atomic_dec (__atomic_t *__var) +{ + __asm__ __volatile ("lock; decl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline int +__atomic_dec_and_test (__atomic_t *__var) +{ + unsigned char __ret; + + __asm__ __volatile ("lock; decl %0; sete %1" + : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); + return __ret != 0; +} + +/* We assume that an __atomicptr_t is only used for pointers to + word-aligned objects, and use the lowest bit for a simple lock. */ +typedef __volatile int * __atomicptr_t; + +/* Actually we don't implement that yet, and assume that we run on + something that has the i486 instruction set. */ +static inline int +__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, + void * __newval) +{ + char __ret; + int __dummy; + + __asm__ __volatile ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (__ret), "=m" (*__ptr), "=a" (__dummy) + : "r" (__newval), "m" (*__ptr), "a" (__oldval)); + return __ret; +} + +#endif diff --git a/sysdeps/ia32/bits/memory.h b/sysdeps/ia32/bits/memory.h new file mode 100644 index 00000000..201305b9 --- /dev/null +++ b/sysdeps/ia32/bits/memory.h @@ -0,0 +1,40 @@ +/* Memory barrier operations. i386 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MEMORY_H +#define _BITS_MEMORY_H 1 + +/* Prevent read and write reordering across this function. */ +inline void +__memory_barrier (void) +{ + int i; + + /* Any lock'ed instruction will do. We just do a simple + increment. */ + __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i)); +} + +/* Prevent read reordering across this function. */ +#define __memory_read_barrier __memory_barrier + +/* Prevent write reordering across this function. */ +#define __memory_write_barrier __memory_barrier + +#endif diff --git a/sysdeps/ia32/bits/spin-lock.h b/sysdeps/ia32/bits/spin-lock.h new file mode 100644 index 00000000..175656ef --- /dev/null +++ b/sysdeps/ia32/bits/spin-lock.h @@ -0,0 +1,103 @@ +/* Machine-specific definitions for spin locks. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __volatile int __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE extern __inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + int __locked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__locked), "=m" (*__lock) : "0" (1)); + return __locked ? __EBUSY : 0; +} + +extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +extern inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + int __unlocked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0)); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/sysdeps/ia32/machine-sp.h b/sysdeps/ia32/machine-sp.h new file mode 100644 index 00000000..536f6902 --- /dev/null +++ b/sysdeps/ia32/machine-sp.h @@ -0,0 +1,31 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994,97,2001 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + void *__sp__; \ + __asm__ ("movl %%esp, %0" : "=r" (__sp__)); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/sysdeps/ia32/pt-machdep.h b/sysdeps/ia32/pt-machdep.h new file mode 100644 index 00000000..6d456367 --- /dev/null +++ b/sysdeps/ia32/pt-machdep.h @@ -0,0 +1,29 @@ +/* Machine dependent pthreads internal defenitions. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */ diff --git a/sysdeps/l4/bits/pthread-np.h b/sysdeps/l4/bits/pthread-np.h new file mode 100644 index 00000000..b487e6dc --- /dev/null +++ b/sysdeps/l4/bits/pthread-np.h @@ -0,0 +1,38 @@ +/* Non-portable functions. L4 version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. TID is the provided L4 + kernel thread. */ +extern int pthread_create_from_l4_tid_np (pthread_t *thread, + const pthread_attr_t *attr, + l4_thread_id_t tid, + void *(*start_routine)(void *), + void *arg); + +#endif /* bits/pthread-np.h */ diff --git a/sysdeps/l4/hurd/i386/pt-machdep.c b/sysdeps/l4/hurd/i386/pt-machdep.c deleted file mode 100644 index dbf5cd7e..00000000 --- a/sysdeps/l4/hurd/i386/pt-machdep.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Machine dependent pthreads code. Hurd/i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* Nothing to do. */ diff --git a/sysdeps/l4/hurd/i386/pt-setup.c b/sysdeps/l4/hurd/i386/pt-setup.c deleted file mode 100644 index fe77d533..00000000 --- a/sysdeps/l4/hurd/i386/pt-setup.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Setup thread stack. Hurd/i386 version. - 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* The stack layout used on the i386 is: - - ----------------- - | ARG | - ----------------- - | START_ROUTINE | - ----------------- - | 0 | - ----------------- */ - -/* Set up the stack for THREAD, such that it appears as if - START_ROUTINE and ARG were passed to the new thread's entry-point. - Return the stack pointer for the new thread. We also take the - opportunity to install THREAD in our utcb. */ -static void * -stack_setup (struct __pthread *thread, - void *(*start_routine)(void *), void *arg) -{ - L4_Word_t *top; - - /* Calculate top of the new stack. */ - top = (L4_Word_t *) ((L4_Word_t) thread->stackaddr + thread->stacksize); - - if (start_routine) - { - /* Set up call frame. */ - *--top = (L4_Word_t) arg; /* Argument to START_ROUTINE. */ - *--top = (L4_Word_t) start_routine; - *--top = 0; /* Fake return address. */ - } - - return top; -} - -int -__pthread_setup (struct __pthread *thread, - void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg) -{ - thread->mcontext.pc = entry_point; - thread->mcontext.sp = stack_setup (thread, start_routine, arg); - - if (L4_SameThreads (thread->threadid, L4_Myself ())) - L4_Set_MyUserDefinedHandle (thread); - else - L4_Set_UserDefinedHandle (thread->threadid, thread); - - return 0; -} diff --git a/sysdeps/l4/hurd/ia32/pt-machdep.c b/sysdeps/l4/hurd/ia32/pt-machdep.c new file mode 100644 index 00000000..dbf5cd7e --- /dev/null +++ b/sysdeps/l4/hurd/ia32/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Nothing to do. */ diff --git a/sysdeps/l4/hurd/ia32/pt-setup.c b/sysdeps/l4/hurd/ia32/pt-setup.c new file mode 100644 index 00000000..e244dc16 --- /dev/null +++ b/sysdeps/l4/hurd/ia32/pt-setup.c @@ -0,0 +1,72 @@ +/* Setup thread stack. Hurd/i386 version. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- */ + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg) +{ + l4_word_t *top; + + /* Calculate top of the new stack. */ + top = (l4_word_t *) ((l4_word_t) thread->stackaddr + thread->stacksize); + + if (start_routine) + { + /* Set up call frame. */ + *--top = (l4_word_t) arg; /* Argument to START_ROUTINE. */ + *--top = (l4_word_t) start_routine; + *--top = 0; /* Fake return address. */ + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + if (l4_same_threads (thread->threadid, l4_myself ())) + l4_set_user_defined_handle ((l4_word_t) thread); + else + l4_set_user_defined_handle_of (thread->threadid, + (l4_word_t) thread); + return 0; +} diff --git a/sysdeps/l4/hurd/powerpc/pt-machdep.c b/sysdeps/l4/hurd/powerpc/pt-machdep.c new file mode 100644 index 00000000..754d203e --- /dev/null +++ b/sysdeps/l4/hurd/powerpc/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Nothing to do. */ diff --git a/sysdeps/l4/hurd/powerpc/pt-setup.c b/sysdeps/l4/hurd/powerpc/pt-setup.c new file mode 100644 index 00000000..d3cf4ec3 --- /dev/null +++ b/sysdeps/l4/hurd/powerpc/pt-setup.c @@ -0,0 +1,93 @@ +/* Setup thread stack. Hurd/PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Arguments is passed in registers on the PowerPC. But the + exchange registers syscall only allows us to set the PC and the + stack pointer so we put the entry point and start function on + the stack. */ +struct start_info +{ + void (*entry_point) (void *(*)(void *), void *); + void *(*start_routine) (void *); + void *arg; +}; + +void first_entry_1 (void); + +/* Stage 1 entry function. The start_info structure is inlined on the + stack. Put values into registers and call entry function. */ +asm (" ;\ +first_entry_1: ;\ + lwz 0, 0(1) ;\ + lwz 3, 4(1) ;\ + lwz 4, 8(1) ;\ + mtctr 0 ;\ + bctrl ;\ +"); + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + l4_word_t *top; + + /* Calculate top of the new stack. */ + top = (l4_word_t *) ((l4_word_t) thread->stackaddr + thread->stacksize); + + /* Initial stack frame. */ + top[-4] = 0; + top = top - 4; + + if (start_routine) + { + struct start_info *info = ((struct start_info *) top) - 1; + + info->entry_point = entry_point; + info->start_routine = start_routine; + info->arg = arg; + return (void *) info; + } + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = first_entry_1; + thread->mcontext.sp = stack_setup (thread, entry_point, + start_routine, arg); + + if (l4_same_threads (thread->threadid, l4_myself ())) + l4_set_user_defined_handle ((l4_word_t) thread); + else + l4_set_user_defined_handle_of (thread->threadid, + (l4_word_t) thread); + return 0; +} diff --git a/sysdeps/l4/hurd/pt-kill.c b/sysdeps/l4/hurd/pt-kill.c new file mode 100644 index 00000000..1e64af49 --- /dev/null +++ b/sysdeps/l4/hurd/pt-kill.c @@ -0,0 +1,30 @@ +/* pthread_kill. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +pthread_kill (pthread_t thread, int sig) +{ + return ESRCH; +} diff --git a/sysdeps/l4/hurd/pt-sigstate-destroy.c b/sysdeps/l4/hurd/pt-sigstate-destroy.c new file mode 100644 index 00000000..997a0369 --- /dev/null +++ b/sysdeps/l4/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ + /* Nothing to do. */ +} diff --git a/sysdeps/l4/hurd/pt-sigstate-init.c b/sysdeps/l4/hurd/pt-sigstate-init.c new file mode 100644 index 00000000..25a3920c --- /dev/null +++ b/sysdeps/l4/hurd/pt-sigstate-init.c @@ -0,0 +1,28 @@ +/* Initialize the signal state. Hurd on L4 version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + return 0; +} diff --git a/sysdeps/l4/hurd/pt-sigstate.c b/sysdeps/l4/hurd/pt-sigstate.c new file mode 100644 index 00000000..490c95fe --- /dev/null +++ b/sysdeps/l4/hurd/pt-sigstate.c @@ -0,0 +1,32 @@ +/* Set a thread's signal state. Hurd on L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending) +{ + return EINVAL; +} diff --git a/sysdeps/l4/hurd/pt-sysdep.c b/sysdeps/l4/hurd/pt-sysdep.c index 265592ca..f23a137a 100644 --- a/sysdeps/l4/hurd/pt-sysdep.c +++ b/sysdeps/l4/hurd/pt-sysdep.c @@ -43,7 +43,7 @@ init_routine (void) __pthread_initialize (); /* Create the pthread structure for the main thread (i.e. us). */ - err = __pthread_create_internal (&thread, 0, 0, 0); + err = __pthread_create_internal (&thread, 0, 0, 0, 0); assert_perror (err); __pthread_initialize (); diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h index e37beefa..7e69d709 100644 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -20,24 +20,22 @@ #ifndef _PT_SYSDEP_H #define _PT_SYSDEP_H 1 -#include -#include -#include +#include /* XXX */ #define _POSIX_THREAD_THREADS_MAX 64 /* The default stack size. */ -#define PTHREAD_STACK_DEFAULT (PAGE_SIZE) +#define PTHREAD_STACK_DEFAULT 4096 #define PTHREAD_SYSDEP_MEMBERS \ - L4_ThreadId_t threadid; \ - L4_Word_t my_errno; + l4_thread_id_t threadid; \ + l4_word_t my_errno; extern inline struct __pthread * _pthread_self (void) { - return (struct __pthread *) L4_MyUserDefinedHandle (); + return (struct __pthread *) l4_user_defined_handle (); } extern inline void diff --git a/sysdeps/l4/pt-block.c b/sysdeps/l4/pt-block.c index 050c6947..5992dc14 100644 --- a/sysdeps/l4/pt-block.c +++ b/sysdeps/l4/pt-block.c @@ -17,7 +17,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include #include @@ -25,5 +25,5 @@ void __pthread_block (struct __pthread *thread) { - L4_Receive (L4_anylocalthread); + l4_receive (l4_anylocalthread); } diff --git a/sysdeps/l4/pt-create-np.c b/sysdeps/l4/pt-create-np.c new file mode 100644 index 00000000..d5a23668 --- /dev/null +++ b/sysdeps/l4/pt-create-np.c @@ -0,0 +1,47 @@ +/* Thread creation from provided L4 thread. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +#include + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. TID is the provided L4 + kernel thread. */ +int +pthread_create_from_l4_tid_np (pthread_t *thread, + const pthread_attr_t *attr, + l4_thread_id_t tid, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + + err = __pthread_create_internal (&pthread, attr, (void *) &tid, + start_routine, arg); + if (! err) + *thread = pthread->thread; + + return err; +} diff --git a/sysdeps/l4/pt-docancel.c b/sysdeps/l4/pt-docancel.c index 9a3bb26c..e832e26e 100644 --- a/sysdeps/l4/pt-docancel.c +++ b/sysdeps/l4/pt-docancel.c @@ -30,6 +30,7 @@ call_exit (void) int __pthread_do_cancel (struct __pthread *p) { +#if 0 assert (p->cancel_pending = 1); assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); @@ -46,6 +47,6 @@ __pthread_do_cancel (struct __pthread *p) &dummy, &dummy, &dummy, &dummy, &dummy, &dummy_id); } - +#endif return 0; } diff --git a/sysdeps/l4/pt-spin.c b/sysdeps/l4/pt-spin.c new file mode 100644 index 00000000..355253ee --- /dev/null +++ b/sysdeps/l4/pt-spin.c @@ -0,0 +1,60 @@ +/* Spin locks. L4 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +/* The default for single processor machines; don't spin, it's + pointless. */ +#ifndef __PTHREAD_SPIN_COUNT +# define __PTHREAD_SPIN_COUNT 1 +#endif + +/* The number of times to spin while trying to lock a spin lock object + before yielding the processor. */ +int __pthread_spin_count = __PTHREAD_SPIN_COUNT; + + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + l4_time_t timeout; + int i; + + timeout.period.m = 1; + timeout.period.e = 1; + + while (1) + { + for (i = 0; i < __pthread_spin_count; i++) + { + if (__pthread_spin_trylock (lock) == 0) + return 0; + } + /* FIXME verify this */ + l4_receive_timeout (l4_nilthread, timeout); + timeout.period.e++; + } +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/sysdeps/l4/pt-stack-alloc.c b/sysdeps/l4/pt-stack-alloc.c index e28d5310..9a254141 100644 --- a/sysdeps/l4/pt-stack-alloc.c +++ b/sysdeps/l4/pt-stack-alloc.c @@ -17,37 +17,20 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include #include +#include #include #define __pthread_stacksize __pthread_default_attr.stacksize -#include -#include static void * allocate_page (void) { - L4_Fpage_t p; - /* The Kernel Interface page. */ - static L4_KernelInterfacePage_t *kip; - - if (! kip) - kip = L4_GetKernelInterface (); - -#define sigma0_tid() (L4_GlobalId (kip->ThreadInfo.X.UserBase, 1)) - p = L4_Sigma0_GetPage (sigma0_tid (), - L4_Fpage_Set_Attrs (L4_FpageLog2 (-1UL << 10, - PAGE_SHIFT), - L4_FullyAccessible)); - p.raw &= ~0x3ff; - - printf ("%s: Allocated page %x\n", - __FUNCTION__, p.raw); - - return (void *) p.raw; + return mmap + (NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); } diff --git a/sysdeps/l4/pt-thread-alloc.c b/sysdeps/l4/pt-thread-alloc.c index a9d5e212..00e99ff9 100644 --- a/sysdeps/l4/pt-thread-alloc.c +++ b/sysdeps/l4/pt-thread-alloc.c @@ -1,5 +1,5 @@ -/* Start thread. L4 version. - Copyright (C) 2002 Free Software Foundation, Inc. +/* Allocate kernel thread. L4 version. + Copyright (C) 2003 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 @@ -23,9 +23,8 @@ #include -/* Start THREAD. Get the kernel thread scheduled and running. */ int -__pthread_thread_start (struct __pthread *thread) +__pthread_thread_alloc (struct __pthread *thread) { error_t err; @@ -33,10 +32,11 @@ __pthread_thread_start (struct __pthread *thread) if (__pthread_num_threads == 1) { assert (__pthread_total == 1); - thread->thread_id = L4_Myself (); + thread->threadid = l4_myself (); } else { +#if 0 CORBA_Environment env; env = idl4_default_environment; @@ -45,8 +45,8 @@ __pthread_thread_start (struct __pthread *thread) * (L4_Word_t *) &__system_pager, (L4_Word_t *) &thread->threadid, &env); if (err) +#endif return EAGAIN; } - return 0; } diff --git a/sysdeps/l4/pt-thread-halt.c b/sysdeps/l4/pt-thread-halt.c index 04d622f4..ea97eea0 100644 --- a/sysdeps/l4/pt-thread-halt.c +++ b/sysdeps/l4/pt-thread-halt.c @@ -19,20 +19,13 @@ #include #include -#include #include -extern L4_ThreadId_t __task_server; - /* Deallocate the kernel thread resources associated with THREAD. */ void __pthread_thread_halt (struct __pthread *thread) { - CORBA_Environment env = idl4_default_environment; - L4_Word_t *t = (L4_Word_t *) &thread->threadid; - - assert (*t); - assert (thread_terminate (__task_server, *t, &env)); - *t = 0; + /* FIXME reuse thread somehow */ + l4_stop (thread->threadid); } diff --git a/sysdeps/l4/pt-thread-init.c b/sysdeps/l4/pt-thread-init.c new file mode 100644 index 00000000..ac50d58d --- /dev/null +++ b/sysdeps/l4/pt-thread-init.c @@ -0,0 +1,34 @@ +/* Start thread. L4 version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Initialize provided kernel thread. */ +int +__pthread_init_provided_thread (struct __pthread *thread, + void *p) +{ + l4_thread_id_t *tid = (l4_thread_id_t *) p; + thread->threadid = *tid; + return 0; +} diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c index c428d290..36770703 100644 --- a/sysdeps/l4/pt-thread-start.c +++ b/sysdeps/l4/pt-thread-start.c @@ -1,5 +1,5 @@ /* Start thread. L4 version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2003 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 @@ -23,70 +23,24 @@ #include -#include "task_client.h" - -extern L4_ThreadId_t __system_pager; -extern L4_ThreadId_t __task_server; - -#ifndef WORKING_EXREGS -static void -send_startup_ipc (L4_ThreadId_t id, L4_Word_t ip, L4_Word_t sp) -{ - L4_Msg_t msg; - - printf ("%s: Sending startup message to %x, " - "(ip=%x, sp=%x)\n", - __FUNCTION__, * (L4_Word_t *) &id, ip, sp); - - L4_Clear (&msg); -#ifdef HAVE_PROPAGATION - L4_Set_VirtualSender (pager_tid); - L4_Set_Propagation (&msg.tag); -#endif - L4_Append_Word (&msg, ip); - L4_Append_Word (&msg, sp); -#ifndef HAVE_PROPAGATION - L4_Append_Word (&msg, *(L4_Word_t *) &id); - id = __system_pager; -#if 0 - DODEBUG (2, printf ("%s: Redirecting start request to pager (%x).\n", - __FUNCTION__, * (L4_Word_t *) &id)); -#endif -#endif - L4_LoadMsg (&msg); - L4_Send (id); -} -#endif - /* Start THREAD. Get the kernel thread scheduled and running. */ int __pthread_thread_start (struct __pthread *thread) { - error_t err; - /* The main thread is already running of course. */ if (__pthread_num_threads == 1) - { - assert (__pthread_total == 1); - assert (thread->thread_id == L4_Myself ()); - } + assert (__pthread_total == 1); else { - env = idl4_default_environment; - err = thread_resume (__task_server, - * (L4_Word_t *) &thread->threadid, - &env); - assert (! err); - -#ifndef WORKING_EXREGS - L4_AbortIpc_and_stop (thread->threadid); - L4_Start_SpIp (thread->threadid, (L4_Word_t) thread->mcontext.sp, - (L4_Word_t) thread->mcontext.pc); -#endif - send_startup_ipc (thread->threadid, (L4_Word_t) thread->mcontext.pc, - (L4_Word_t) thread->mcontext.sp); - + l4_thread_id_t dest = thread->threadid; + l4_word_t control = (L4_XCHG_REGS_SET_HALT | L4_XCHG_REGS_SET_SP + | L4_XCHG_REGS_SET_IP | L4_XCHG_REGS_SET_PAGER); + l4_word_t sp = (l4_word_t) thread->mcontext.sp; + l4_word_t ip = (l4_word_t) thread->mcontext.pc; + l4_word_t dummy = 0; + l4_thread_id_t pager = l4_pager (); + + l4_exchange_registers (&dest, &control, &sp, &ip, &dummy, &dummy, &pager); } - return 0; } diff --git a/sysdeps/l4/pt-timedblock.c b/sysdeps/l4/pt-timedblock.c new file mode 100644 index 00000000..fda14401 --- /dev/null +++ b/sysdeps/l4/pt-timedblock.c @@ -0,0 +1,34 @@ +/* Block a thread with a timeout. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +/* Block THREAD. */ +error_t +__pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime) +{ + __pthread_block (thread); + return 0; +} diff --git a/sysdeps/l4/pt-wakeup.c b/sysdeps/l4/pt-wakeup.c index 7b00e4f6..342a2204 100644 --- a/sysdeps/l4/pt-wakeup.c +++ b/sysdeps/l4/pt-wakeup.c @@ -17,7 +17,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include #include @@ -25,5 +25,5 @@ void __pthread_wakeup (struct __pthread *thread) { - L4_Send (thread->threadid); + l4_send (thread->threadid); } diff --git a/sysdeps/mach/hurd/i386/pt-machdep.c b/sysdeps/mach/hurd/i386/pt-machdep.c deleted file mode 100644 index face46c5..00000000 --- a/sysdeps/mach/hurd/i386/pt-machdep.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Machine dependent pthreads code. Hurd/i386 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include -#include - -int -__thread_set_pcsp (thread_t thread, - int set_ip, void *ip, - int set_sp, void *sp) -{ - error_t err; - struct i386_thread_state state; - mach_msg_type_number_t state_count; - - state_count = i386_THREAD_STATE_COUNT; - - err = __thread_get_state (thread, i386_THREAD_STATE, - (thread_state_t) &state, &state_count); - if (err) - return err; - - if (set_sp) - state.uesp = (unsigned int) sp; - if (set_ip) - state.eip = (unsigned int) ip; - - err = __thread_set_state (thread, i386_THREAD_STATE, - (thread_state_t) &state, - i386_THREAD_STATE_COUNT); - if (err) - return err; - - return 0; -} diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c deleted file mode 100644 index 9a855847..00000000 --- a/sysdeps/mach/hurd/i386/pt-setup.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Setup thread stack. Hurd/i386 version. - 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* The stack layout used on the i386 is: - - ----------------- - | ARG | - ----------------- - | START_ROUTINE | - ----------------- - | 0 | - ----------------- - | | - | Fast TSD | - | | - ----------------- - - We need to reserve __hurd_threadvar_max `unsigned long int's' of - (fast) thread-specific data (TSD) for the Hurd. */ - -/* Set up the stack for THREAD, such that it appears as if - START_ROUTINE and ARG were passed to the new thread's entry-point. - Return the stack pointer for the new thread. */ -static void * -stack_setup (struct __pthread *thread, - void *(*start_routine)(void *), void *arg) -{ - error_t err; - uintptr_t *bottom, *top; - - /* Calculate the top of the new stack. */ - bottom = thread->stackaddr; - top = (uintptr_t *) ((uintptr_t) bottom + thread->stacksize); - - /* Next, make room for the TSDs. */ - top -= __hurd_threadvar_max; - - /* Save the self pointer. */ - top[_HURD_THREADVAR_THREAD] = thread; - - if (start_routine) - { - /* And then the call frame. */ - *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ - *--top = (uintptr_t) start_routine; - *--top = 0; /* Fake return address. */ - } - - if (thread->guardsize) - { - err = __vm_protect (__mach_task_self (), (vm_address_t) bottom, - thread->guardsize, 0, 0); - assert_perror (err); - } - - return top; -} - -int -__pthread_setup (struct __pthread *thread, - void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg) -{ - error_t err; - mach_port_t ktid; - - thread->mcontext.pc = entry_point; - thread->mcontext.sp = stack_setup (thread, start_routine, arg); - - ktid = __mach_thread_self (); - if (thread->kernel_thread != ktid) - { - err = __thread_set_pcsp (thread->kernel_thread, - 1, thread->mcontext.pc, - 1, thread->mcontext.sp); - assert_perror (err); - } - __mach_port_deallocate (__mach_task_self (), ktid); - - return 0; -} diff --git a/sysdeps/mach/hurd/ia32/pt-machdep.c b/sysdeps/mach/hurd/ia32/pt-machdep.c new file mode 100644 index 00000000..face46c5 --- /dev/null +++ b/sysdeps/mach/hurd/ia32/pt-machdep.c @@ -0,0 +1,54 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +int +__thread_set_pcsp (thread_t thread, + int set_ip, void *ip, + int set_sp, void *sp) +{ + error_t err; + struct i386_thread_state state; + mach_msg_type_number_t state_count; + + state_count = i386_THREAD_STATE_COUNT; + + err = __thread_get_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, &state_count); + if (err) + return err; + + if (set_sp) + state.uesp = (unsigned int) sp; + if (set_ip) + state.eip = (unsigned int) ip; + + err = __thread_set_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, + i386_THREAD_STATE_COUNT); + if (err) + return err; + + return 0; +} diff --git a/sysdeps/mach/hurd/ia32/pt-setup.c b/sysdeps/mach/hurd/ia32/pt-setup.c new file mode 100644 index 00000000..9a855847 --- /dev/null +++ b/sysdeps/mach/hurd/ia32/pt-setup.c @@ -0,0 +1,103 @@ +/* Setup thread stack. Hurd/i386 version. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- + | | + | Fast TSD | + | | + ----------------- + + We need to reserve __hurd_threadvar_max `unsigned long int's' of + (fast) thread-specific data (TSD) for the Hurd. */ + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg) +{ + error_t err; + uintptr_t *bottom, *top; + + /* Calculate the top of the new stack. */ + bottom = thread->stackaddr; + top = (uintptr_t *) ((uintptr_t) bottom + thread->stacksize); + + /* Next, make room for the TSDs. */ + top -= __hurd_threadvar_max; + + /* Save the self pointer. */ + top[_HURD_THREADVAR_THREAD] = thread; + + if (start_routine) + { + /* And then the call frame. */ + *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + *--top = (uintptr_t) start_routine; + *--top = 0; /* Fake return address. */ + } + + if (thread->guardsize) + { + err = __vm_protect (__mach_task_self (), (vm_address_t) bottom, + thread->guardsize, 0, 0); + assert_perror (err); + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + error_t err; + mach_port_t ktid; + + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + ktid = __mach_thread_self (); + if (thread->kernel_thread != ktid) + { + err = __thread_set_pcsp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp); + assert_perror (err); + } + __mach_port_deallocate (__mach_task_self (), ktid); + + return 0; +} diff --git a/sysdeps/powerpc/bits/atomic.h b/sysdeps/powerpc/bits/atomic.h new file mode 100644 index 00000000..5ba19cd0 --- /dev/null +++ b/sysdeps/powerpc/bits/atomic.h @@ -0,0 +1,84 @@ +/* Atomic operations. PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +typedef __volatile int __atomic_t; + +static inline void +__atomic_inc (__atomic_t *__var) +{ + int tmp; + __asm__ ("\n\ +0: lwarx %0,0,%1 \n\ + add%I2 %0,%0,%2 \n\ + stwcx. %0,0,%1 \n\ + bne- 0b \n\ +" : "=&b"(tmp) : "r" (__var), "Ir"(1) : "cr0", "memory"); +} + +static inline void +__atomic_dec (__atomic_t *__var) +{ + int tmp; + __asm__ ("\n\ +0: lwarx %0,0,%1 \n\ + add%I2 %0,%0,%2 \n\ + stwcx. %0,0,%1 \n\ + bne- 0b \n\ +" : "=&b"(tmp) : "r" (__var), "Ir"(-1) : "cr0", "memory"); +} + +static inline int +__atomic_dec_and_test (__atomic_t *__var) +{ + unsigned char __ret; + +#if 0 + __asm__ __volatile ("lock; decl %0; sete %1" + : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); +#endif + return __ret != 0; +} + +/* We assume that an __atomicptr_t is only used for pointers to + word-aligned objects, and use the lowest bit for a simple lock. */ +typedef __volatile int * __atomicptr_t; + +/* Actually we don't implement that yet, and assume that we run on + something that has the i486 instruction set. */ +static inline int +__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, + void * __newval) +{ + int __ret; + __asm__ ("\n\ +0: lwarx %0,0,%1 \n\ + sub%I2c. %0,%0,%2 \n\ + cntlzw %0,%0 \n\ + bne- 1f \n\ + stwcx. %3,0,%1 \n\ + bne- 0b \n\ +1: \n\ +" : "=&b"(__ret) : "r"(__ptr), "Ir"(__oldval), "r"(__newval) : "cr0", "memory"); + return __ret >> 5; +} + +#endif diff --git a/sysdeps/powerpc/bits/machine-lock.h b/sysdeps/powerpc/bits/machine-lock.h new file mode 100644 index 00000000..cba6b0a6 --- /dev/null +++ b/sysdeps/powerpc/bits/machine-lock.h @@ -0,0 +1,78 @@ +/* Machine-specific definition for spin locks. PowerPC version. + Copyright (C) 1994,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. */ + +#ifndef _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile long int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0L + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + long int __locked; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (register __spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); + return !__rtn; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %0,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock) : "cr0"); + return __rtn; +} + + +#endif /* machine-lock.h */ diff --git a/sysdeps/powerpc/bits/memory.h b/sysdeps/powerpc/bits/memory.h new file mode 100644 index 00000000..96624c3e --- /dev/null +++ b/sysdeps/powerpc/bits/memory.h @@ -0,0 +1,36 @@ +/* Memory barrier operations. PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MEMORY_H +#define _BITS_MEMORY_H 1 + +/* Prevent read and write reordering across this function. */ +inline void +__memory_barrier (void) +{ + asm ("sync" ::: "memory"); +} + +/* Prevent read reordering across this function. */ +#define __memory_read_barrier __memory_barrier + +/* Prevent write reordering across this function. */ +#define __memory_write_barrier __memory_barrier + +#endif diff --git a/sysdeps/powerpc/bits/spin-lock.h b/sysdeps/powerpc/bits/spin-lock.h new file mode 100644 index 00000000..1dc25710 --- /dev/null +++ b/sysdeps/powerpc/bits/spin-lock.h @@ -0,0 +1,108 @@ +/* Machine-specific definitions for spin locks. PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __volatile int __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE extern __inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); + return __rtn ? __EBUSY : 0; +} + +extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +extern inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + long int __locked; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/sysdeps/powerpc/machine-sp.h b/sysdeps/powerpc/machine-sp.h new file mode 100644 index 00000000..aa787c59 --- /dev/null +++ b/sysdeps/powerpc/machine-sp.h @@ -0,0 +1,31 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994,97,2001 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + void *__sp__; \ + __asm__ ("mr %0, 1" : "=r" (__sp__)); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/sysdeps/powerpc/pt-machdep.h b/sysdeps/powerpc/pt-machdep.h new file mode 100644 index 00000000..6d456367 --- /dev/null +++ b/sysdeps/powerpc/pt-machdep.h @@ -0,0 +1,29 @@ +/* Machine dependent pthreads internal defenitions. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */ -- cgit v1.2.3 From 3bbee34f0e375e9fd768cc0e59949b0c16849bd5 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Thu, 18 Mar 2004 02:53:15 +0000 Subject: 2004-03-17 Marcus Brinkmann * sysdeps/l4/pt-spin.c (_pthread_spin_lock): Implement using new time period interface. --- sysdeps/l4/pt-spin.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sysdeps/l4/pt-spin.c b/sysdeps/l4/pt-spin.c index 355253ee..d2917d61 100644 --- a/sysdeps/l4/pt-spin.c +++ b/sysdeps/l4/pt-spin.c @@ -40,9 +40,10 @@ _pthread_spin_lock (__pthread_spinlock_t *lock) { l4_time_t timeout; int i; - - timeout.period.m = 1; - timeout.period.e = 1; + + /* Start with a small timeout of 2 microseconds, then back off + exponentially. */ + timeout = l4_time_period (2); while (1) { @@ -51,9 +52,11 @@ _pthread_spin_lock (__pthread_spinlock_t *lock) if (__pthread_spin_trylock (lock) == 0) return 0; } - /* FIXME verify this */ - l4_receive_timeout (l4_nilthread, timeout); - timeout.period.e++; + l4_sleep (timeout); + + timeout = l4_time_mul2 (timeout); + if (timeout == L4_NEVER) + timeout = L4_TIME_PERIOD_MAX; } } -- cgit v1.2.3 From 0f67345c47f86459d5fd854d664797316824d250 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Thu, 18 Mar 2004 02:54:43 +0000 Subject: 2004-03-17 Marcus Brinkmann * sysdeps/l4/pt-thread-start.c (__pthread_thread_start): Use L4 convenience interface. --- sysdeps/l4/pt-thread-start.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c index 36770703..72c4d302 100644 --- a/sysdeps/l4/pt-thread-start.c +++ b/sysdeps/l4/pt-thread-start.c @@ -32,15 +32,9 @@ __pthread_thread_start (struct __pthread *thread) assert (__pthread_total == 1); else { - l4_thread_id_t dest = thread->threadid; - l4_word_t control = (L4_XCHG_REGS_SET_HALT | L4_XCHG_REGS_SET_SP - | L4_XCHG_REGS_SET_IP | L4_XCHG_REGS_SET_PAGER); - l4_word_t sp = (l4_word_t) thread->mcontext.sp; - l4_word_t ip = (l4_word_t) thread->mcontext.pc; - l4_word_t dummy = 0; - l4_thread_id_t pager = l4_pager (); - - l4_exchange_registers (&dest, &control, &sp, &ip, &dummy, &dummy, &pager); + l4_set_pager_of (thread->threadid, l4_pager ()); + l4_start_sp_ip (thread->threadid, (l4_word_t) thread->mcontext.sp, + (l4_word_t) thread->mcontext.pc); } return 0; } -- cgit v1.2.3 From 0ba014f072e0d19c16d0584672ec9f65cc451a54 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Thu, 18 Mar 2004 02:58:51 +0000 Subject: Fix copyright year. --- sysdeps/l4/pt-spin.c | 2 +- sysdeps/l4/pt-thread-start.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sysdeps/l4/pt-spin.c b/sysdeps/l4/pt-spin.c index d2917d61..b6978b0c 100644 --- a/sysdeps/l4/pt-spin.c +++ b/sysdeps/l4/pt-spin.c @@ -1,5 +1,5 @@ /* Spin locks. L4 version. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2004 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 diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c index 72c4d302..10996e1c 100644 --- a/sysdeps/l4/pt-thread-start.c +++ b/sysdeps/l4/pt-thread-start.c @@ -1,5 +1,5 @@ /* Start thread. L4 version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 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 -- cgit v1.2.3 From 0d723d7f3a762f106de2f95af2fdaaa650359d80 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 19 Mar 2004 04:18:42 +0000 Subject: 2004-03-19 Marcus Brinkmann * sysdeps/l4/bits/pthread-np.h (pthread_pool_add_np, pthread_pool_get_np): New prototypes. * sysdeps/l4/pt-pool-np.c: New file. * Makefile.am (libpthread_a_SOURCES): Add pt-pool-np.c. * sysdeps/l4/pt-thread-alloc.c (__pthread_thread_alloc): Try to allocate thread from pool. * sysdeps/l4/pt-thread-halt.c (__pthread_thread_halt): Add thread to pool after stopping it. --- Makefile.am | 1 + Makefile.in | 66 +++++++++++++++++++++++--------------------- sysdeps/l4/bits/pthread-np.h | 6 ++++ sysdeps/l4/pt-pool-np.c | 52 ++++++++++++++++++++++++++++++++++ sysdeps/l4/pt-thread-alloc.c | 4 +++ sysdeps/l4/pt-thread-halt.c | 6 ++-- 6 files changed, 101 insertions(+), 34 deletions(-) create mode 100644 sysdeps/l4/pt-pool-np.c diff --git a/Makefile.am b/Makefile.am index 24896080..e9cedcb3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,6 +64,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-alloc.c \ pt-create.c \ pt-create-np.c \ + pt-pool-np.c \ pt-equal.c \ pt-dealloc.c \ pt-detach.c \ diff --git a/Makefile.in b/Makefile.in index 26e32873..58d86455 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.3 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -82,12 +82,15 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EXEEXT = @EXEEXT@ +FIG2DEV = @FIG2DEV@ +HURD_LADEN_LOAD_ADDRESS = @HURD_LADEN_LOAD_ADDRESS@ +HURD_PHYSMEM_LOAD_ADDRESS = @HURD_PHYSMEM_LOAD_ADDRESS@ +HURD_WORTEL_LOAD_ADDRESS = @HURD_WORTEL_LOAD_ADDRESS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LATEX = @LATEX@ -LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ @@ -196,6 +199,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-alloc.c \ pt-create.c \ pt-create-np.c \ + pt-pool-np.c \ pt-equal.c \ pt-dealloc.c \ pt-detach.c \ @@ -260,6 +264,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c subdir = libpthread +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -289,14 +294,14 @@ am_libpthread_a_OBJECTS = pt-attr.$(OBJEXT) pt-attr-destroy.$(OBJEXT) \ pt-key-create.$(OBJEXT) pt-key-delete.$(OBJEXT) \ pt-getspecific.$(OBJEXT) pt-setspecific.$(OBJEXT) \ pt-once.$(OBJEXT) pt-alloc.$(OBJEXT) pt-create.$(OBJEXT) \ - pt-create-np.$(OBJEXT) pt-equal.$(OBJEXT) pt-dealloc.$(OBJEXT) \ - pt-detach.$(OBJEXT) pt-exit.$(OBJEXT) pt-initialize.$(OBJEXT) \ - pt-join.$(OBJEXT) pt-self.$(OBJEXT) pt-sigmask.$(OBJEXT) \ - pt-spin-inlines.$(OBJEXT) pt-cleanup.$(OBJEXT) \ - pt-setcancelstate.$(OBJEXT) pt-setcanceltype.$(OBJEXT) \ - pt-testcancel.$(OBJEXT) pt-cancel.$(OBJEXT) \ - pt-mutexattr.$(OBJEXT) pt-mutexattr-destroy.$(OBJEXT) \ - pt-mutexattr-init.$(OBJEXT) \ + pt-create-np.$(OBJEXT) pt-pool-np.$(OBJEXT) pt-equal.$(OBJEXT) \ + pt-dealloc.$(OBJEXT) pt-detach.$(OBJEXT) pt-exit.$(OBJEXT) \ + pt-initialize.$(OBJEXT) pt-join.$(OBJEXT) pt-self.$(OBJEXT) \ + pt-sigmask.$(OBJEXT) pt-spin-inlines.$(OBJEXT) \ + pt-cleanup.$(OBJEXT) pt-setcancelstate.$(OBJEXT) \ + pt-setcanceltype.$(OBJEXT) pt-testcancel.$(OBJEXT) \ + pt-cancel.$(OBJEXT) pt-mutexattr.$(OBJEXT) \ + pt-mutexattr-destroy.$(OBJEXT) pt-mutexattr-init.$(OBJEXT) \ pt-mutexattr-getprioceiling.$(OBJEXT) \ pt-mutexattr-getprotocol.$(OBJEXT) \ pt-mutexattr-getpshared.$(OBJEXT) \ @@ -415,6 +420,7 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-setpshared.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-settype.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr.Po ./$(DEPDIR)/pt-once.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pt-pool-np.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-attr.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-destroy.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-init.Po \ @@ -456,7 +462,7 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libpthread_a_SOURCES) -DIST_COMMON = ChangeLog Makefile.am Makefile.in TODO +DIST_COMMON = $(srcdir)/Makefile.in ChangeLog Makefile.am TODO SOURCES = $(libpthread_a_SOURCES) all: all-am @@ -568,6 +574,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-settype.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-once.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-pool-np.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-attr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-destroy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-init.Po@am__quote@ @@ -606,13 +613,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-timedblock.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-wakeup.Po@am__quote@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ -@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @@ -623,7 +627,7 @@ distclean-depend: .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ -@am__fastdepCC_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @@ -722,7 +726,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -734,7 +737,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -742,7 +745,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -752,9 +755,10 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am - -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -775,7 +779,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am - + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am @@ -794,14 +799,13 @@ uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-info-am + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am vpath %.c $(SYSDEP_PATH) # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/sysdeps/l4/bits/pthread-np.h b/sysdeps/l4/bits/pthread-np.h index b487e6dc..7e807107 100644 --- a/sysdeps/l4/bits/pthread-np.h +++ b/sysdeps/l4/bits/pthread-np.h @@ -35,4 +35,10 @@ extern int pthread_create_from_l4_tid_np (pthread_t *thread, void *(*start_routine)(void *), void *arg); +/* Add the thread TID to the internal kernel thread pool. */ +int pthread_pool_add_np (l4_thread_id_t tid); + +/* Get the first thread from the pool. */ +l4_thread_id_t pthread_pool_get_np (void); + #endif /* bits/pthread-np.h */ diff --git a/sysdeps/l4/pt-pool-np.c b/sysdeps/l4/pt-pool-np.c new file mode 100644 index 00000000..c59e15a9 --- /dev/null +++ b/sysdeps/l4/pt-pool-np.c @@ -0,0 +1,52 @@ +/* Thread pool for L4 threads. + Copyright (C) 2004 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; + +l4_thread_id_t pool_list = l4_nilthread; + +/* Add the thread TID to the pthread kernel thread pool. */ +int +pthread_pool_add_np (l4_thread_id_t tid) +{ + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + l4_set_user_defined_handle_of (tid, pool_list); + pool_list = tid; + __pthread_mutex_unlock (&pool_lock); + return 0; +} + + +/* Get the first thread from the pool. */ +l4_thread_id_t +pthread_pool_get_np (void) +{ + l4_thread_id_t tid; + + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + tid = pool_list; + pool_list = l4_user_defined_handle_of (tid); + __pthread_mutex_unlock (&pool_lock); + return tid; +} diff --git a/sysdeps/l4/pt-thread-alloc.c b/sysdeps/l4/pt-thread-alloc.c index 00e99ff9..07784f5f 100644 --- a/sysdeps/l4/pt-thread-alloc.c +++ b/sysdeps/l4/pt-thread-alloc.c @@ -36,6 +36,10 @@ __pthread_thread_alloc (struct __pthread *thread) } else { + thread->threadid = pthread_pool_get_np (); + if (thread->threadid != l4_nilthread) + return 0; + #if 0 CORBA_Environment env; diff --git a/sysdeps/l4/pt-thread-halt.c b/sysdeps/l4/pt-thread-halt.c index ea97eea0..991123c2 100644 --- a/sysdeps/l4/pt-thread-halt.c +++ b/sysdeps/l4/pt-thread-halt.c @@ -1,5 +1,5 @@ -/* Deallocate the kernel thread resources. Mach version. - Copyright (C) 2000,02 Free Software Foundation, Inc. +/* Deallocate the kernel thread resources. L4version. + Copyright (C) 2000, 2002, 2004 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 @@ -26,6 +26,6 @@ void __pthread_thread_halt (struct __pthread *thread) { - /* FIXME reuse thread somehow */ l4_stop (thread->threadid); + pthread_pool_add_np (thread->threadid); } -- cgit v1.2.3 From 165fba0793d197c83d3c30efbf75105460af2b5f Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 19 Mar 2004 04:26:42 +0000 Subject: Fix last change. --- sysdeps/l4/pt-pool-np.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sysdeps/l4/pt-pool-np.c b/sysdeps/l4/pt-pool-np.c index c59e15a9..d006b4f3 100644 --- a/sysdeps/l4/pt-pool-np.c +++ b/sysdeps/l4/pt-pool-np.c @@ -46,7 +46,8 @@ pthread_pool_get_np (void) __pthread_mutex_lock (&pool_lock); /* FIXME: Do error checking. */ tid = pool_list; - pool_list = l4_user_defined_handle_of (tid); + if (tid != l4_nilthread) + pool_list = l4_user_defined_handle_of (tid); __pthread_mutex_unlock (&pool_lock); return tid; } -- cgit v1.2.3 From 3869934a2d3c37046bf771816fc2a9275853f87c Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Tue, 23 Mar 2004 03:43:49 +0000 Subject: 2004-03-23 Marcus Brinkmann * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_INITIALIZER): Remove compound statement. (pthread_mutex_init): Use compound statement with initializer. * pthread/pt-alloc.c (initialize_pthread): Likewise. * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): Likewise. --- pthread/pt-alloc.c | 2 +- sysdeps/generic/bits/mutex.h | 5 ++--- sysdeps/generic/pt-mutex-init.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index 5cdc85df..7c15fe15 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -69,7 +69,7 @@ initialize_pthread (struct __pthread *new, int recycling) new->stack = 0; - new->state_lock = PTHREAD_MUTEX_INITIALIZER; + new->state_lock = (struct __pthread_mutex) PTHREAD_MUTEX_INITIALIZER; new->state_cond = PTHREAD_COND_INITIALIZER; new->cancelation_handlers = 0; diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 2baf0408..ecbcff8b 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -52,9 +52,8 @@ struct __pthread_mutex /* Initializer for a mutex. N.B. this also happens to be compatible with the cthread mutex initializer. */ # define __PTHREAD_MUTEX_INITIALIZER \ - ((struct __pthread_mutex) \ { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, \ - NULL, 0, 0 }) + NULL, 0, 0 } # endif #endif /* Not __pthread_mutex_defined. */ @@ -80,7 +79,7 @@ pthread_mutex_init (struct __pthread_mutex *__mutex, if (attr) return _pthread_mutex_init (__mutex, attr); - *__mutex = __PTHREAD_MUTEX_INITIALIZER; + *__mutex = (struct __pthread_mutex) __PTHREAD_MUTEX_INITIALIZER; return 0; } diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c index 2902f6e4..100f485f 100644 --- a/sysdeps/generic/pt-mutex-init.c +++ b/sysdeps/generic/pt-mutex-init.c @@ -28,7 +28,7 @@ int _pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { - *mutex = __PTHREAD_MUTEX_INITIALIZER; + *mutex = (struct __pthread_mutex) __PTHREAD_MUTEX_INITIALIZER; if (! attr || memcmp (attr, &__pthread_default_mutexattr, sizeof (*attr) == 0)) -- cgit v1.2.3 From 92b03cf0bef2df9496852342bb15de9252a2c630 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 29 Oct 2004 01:00:59 +0000 Subject: 2004-10-29 Marcus Brinkmann * platform: New directory. * configure.ac (AC_CONFIG_FILES): Add platform/alpha/Makefile, platform/amd64/Makefile, platform/ia32/Makefile, platform/ia64/Makefile, platform/powerpc/Makefile, platform/powerpc64/Makefile and platform/Makefile. * Makefile.am (SUBDIRS): Add platform. libpthread/ 2004-10-29 Marcus Brinkmann * headers.am (AC_CONFIG_LINKS): Remove include/bits/atomic.h. platform/ 2004-10-29 Marcus Brinkmann * Initial commit. --- headers.m4 | 1 - 1 file changed, 1 deletion(-) diff --git a/headers.m4 b/headers.m4 index 4fceecbf..df49c84e 100644 --- a/headers.m4 +++ b/headers.m4 @@ -13,7 +13,6 @@ AC_CONFIG_LINKS([ include/pthread.h:libpthread/include/pthread.h include/pthread/pthread.h:libpthread/include/pthread/pthread.h - include/bits/atomic.h:libpthread/sysdeps/${arch}/bits/atomic.h include/bits/memory.h:libpthread/sysdeps/${arch}/bits/memory.h include/bits/spin-lock.h:libpthread/sysdeps/${arch}/bits/spin-lock.h include/bits/pthreadtypes.h:libpthread/sysdeps/generic/bits/pthreadtypes.h -- cgit v1.2.3 From 19981a7f1fbe8ef0fcc7a018d467060c7acaaa1b Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Mon, 1 Nov 2004 15:49:58 +0000 Subject: Remove spurious file. --- Makefile.in | 813 ------------------------------------------------------------ 1 file changed, 813 deletions(-) delete mode 100644 Makefile.in diff --git a/Makefile.in b/Makefile.in deleted file mode 100644 index 58d86455..00000000 --- a/Makefile.in +++ /dev/null @@ -1,813 +0,0 @@ -# Makefile.in generated by automake 1.7.9 from Makefile.am. -# @configure_input@ - -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 -# Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# Makefile.am - Makefile template for libpthread. -# Copyright (C) 2003 Free Software Foundation, Inc. -# -# This file is part of the GNU Hurd. -# -# The GNU Hurd is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# The GNU Hurd 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 General Public License for more details. -# -# You should have received a copy of the GNU 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 - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. - -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_triplet = @host@ -ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ -AMTAR = @AMTAR@ -AR = @AR@ -ARCH_IA32_FALSE = @ARCH_IA32_FALSE@ -ARCH_IA32_TRUE = @ARCH_IA32_TRUE@ -ARCH_POWERPC_FALSE = @ARCH_POWERPC_FALSE@ -ARCH_POWERPC_TRUE = @ARCH_POWERPC_TRUE@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCAS = @CCAS@ -CCASFLAGS = @CCASFLAGS@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DVIPS = @DVIPS@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EXEEXT = @EXEEXT@ -FIG2DEV = @FIG2DEV@ -HURD_LADEN_LOAD_ADDRESS = @HURD_LADEN_LOAD_ADDRESS@ -HURD_PHYSMEM_LOAD_ADDRESS = @HURD_PHYSMEM_LOAD_ADDRESS@ -HURD_WORTEL_LOAD_ADDRESS = @HURD_WORTEL_LOAD_ADDRESS@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LATEX = @LATEX@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ -MAKEINFO = @MAKEINFO@ -NM = @NM@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PS2PDF = @PS2PDF@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SORT = @SORT@ -STATIC_GLIBC = @STATIC_GLIBC@ -STRIP = @STRIP@ -VERSION = @VERSION@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_NM = @ac_ct_NM@ -ac_ct_RANLIB = @ac_ct_RANLIB@ -ac_ct_STRIP = @ac_ct_STRIP@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -datadir = @datadir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -oldincludedir = @oldincludedir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ - -@ARCH_IA32_TRUE@arch = ia32 -@ARCH_POWERPC_TRUE@arch = powerpc - -# The source files is scattered over several directories. Add -# all these directories to the vpath. -SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ - $(srcdir)/sysdeps/l4/${arch} \ - $(srcdir)/sysdeps/l4/hurd \ - $(srcdir)/sysdeps/l4 \ - $(srcdir)/sysdeps/hurd \ - $(srcdir)/sysdeps/${arch} \ - $(srcdir)/sysdeps/generic \ - $(srcdir)/sysdeps/posix \ - $(srcdir)/pthread \ - $(srcdir)/include - - -AM_CPPFLAGS = -I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ - -I$(top_srcdir)/libc-parts $(addprefix -I, $(SYSDEP_PATH)) \ - -imacros $(srcdir)/include/libc-symbols.h - - -# Sources. -SYSDEPS := lockfile.c - -noinst_LIBRARIES = libpthread.a -libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ - pt-attr-getguardsize.c pt-attr-getinheritsched.c \ - pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ - pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ - pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ - pt-attr-setinheritsched.c pt-attr-setschedparam.c \ - pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ - pt-attr-setstackaddr.c pt-attr-setstacksize.c pt-attr.c \ - pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ - pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ - pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ - pt-destroy-specific.c pt-init-specific.c \ - pt-key-create.c pt-key-delete.c \ - pt-getspecific.c pt-setspecific.c \ - pt-once.c \ - pt-alloc.c \ - pt-create.c \ - pt-create-np.c \ - pt-pool-np.c \ - pt-equal.c \ - pt-dealloc.c \ - pt-detach.c \ - pt-exit.c \ - pt-initialize.c \ - pt-join.c \ - pt-self.c \ - pt-sigmask.c \ - pt-spin-inlines.c \ - pt-cleanup.c \ - pt-setcancelstate.c \ - pt-setcanceltype.c \ - pt-testcancel.c \ - pt-cancel.c \ - pt-mutexattr.c \ - pt-mutexattr-destroy.c pt-mutexattr-init.c \ - pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ - pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ - pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ - pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ - pt-mutex-init.c pt-mutex-destroy.c \ - pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ - pt-mutex-unlock.c \ - pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ - pt-rwlock-attr.c \ - pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ - pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ - pt-rwlock-init.c pt-rwlock-destroy.c \ - pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ - pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ - pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ - pt-rwlock-unlock.c \ - pt-cond.c \ - pt-condattr-init.c pt-condattr-destroy.c \ - pt-condattr-getclock.c pt-condattr-getpshared.c \ - pt-condattr-setclock.c pt-condattr-setpshared.c \ - pt-cond-destroy.c pt-cond-init.c \ - pt-cond-brdcast.c \ - pt-cond-signal.c \ - pt-cond-wait.c \ - pt-cond-timedwait.c \ - pt-stack-alloc.c \ - pt-thread-alloc.c \ - pt-thread-start.c \ - pt-thread-halt.c \ - pt-thread-init.c \ - pt-getconcurrency.c pt-setconcurrency.c \ - pt-block.c \ - pt-timedblock.c \ - pt-wakeup.c \ - pt-docancel.c \ - pt-sysdep.c \ - pt-setup.c \ - pt-machdep.c \ - pt-spin.c \ - pt-sigstate-init.c \ - pt-sigstate-destroy.c \ - pt-sigstate.c \ - pt-atfork.c \ - pt-kill.c \ - pt-getcpuclockid.c \ - pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c - -subdir = libpthread -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -LIBRARIES = $(noinst_LIBRARIES) - -libpthread_a_AR = $(AR) cru -libpthread_a_LIBADD = -am_libpthread_a_OBJECTS = pt-attr.$(OBJEXT) pt-attr-destroy.$(OBJEXT) \ - pt-attr-getdetachstate.$(OBJEXT) pt-attr-getguardsize.$(OBJEXT) \ - pt-attr-getinheritsched.$(OBJEXT) \ - pt-attr-getschedparam.$(OBJEXT) \ - pt-attr-getschedpolicy.$(OBJEXT) pt-attr-getscope.$(OBJEXT) \ - pt-attr-getstack.$(OBJEXT) pt-attr-getstackaddr.$(OBJEXT) \ - pt-attr-getstacksize.$(OBJEXT) pt-attr-init.$(OBJEXT) \ - pt-attr-setdetachstate.$(OBJEXT) pt-attr-setguardsize.$(OBJEXT) \ - pt-attr-setinheritsched.$(OBJEXT) \ - pt-attr-setschedparam.$(OBJEXT) \ - pt-attr-setschedpolicy.$(OBJEXT) pt-attr-setscope.$(OBJEXT) \ - pt-attr-setstack.$(OBJEXT) pt-attr-setstackaddr.$(OBJEXT) \ - pt-attr-setstacksize.$(OBJEXT) pt-attr.$(OBJEXT) \ - pt-barrier-destroy.$(OBJEXT) pt-barrier-init.$(OBJEXT) \ - pt-barrier-wait.$(OBJEXT) pt-barrier.$(OBJEXT) \ - pt-barrierattr-destroy.$(OBJEXT) pt-barrierattr-init.$(OBJEXT) \ - pt-barrierattr-getpshared.$(OBJEXT) \ - pt-barrierattr-setpshared.$(OBJEXT) \ - pt-destroy-specific.$(OBJEXT) pt-init-specific.$(OBJEXT) \ - pt-key-create.$(OBJEXT) pt-key-delete.$(OBJEXT) \ - pt-getspecific.$(OBJEXT) pt-setspecific.$(OBJEXT) \ - pt-once.$(OBJEXT) pt-alloc.$(OBJEXT) pt-create.$(OBJEXT) \ - pt-create-np.$(OBJEXT) pt-pool-np.$(OBJEXT) pt-equal.$(OBJEXT) \ - pt-dealloc.$(OBJEXT) pt-detach.$(OBJEXT) pt-exit.$(OBJEXT) \ - pt-initialize.$(OBJEXT) pt-join.$(OBJEXT) pt-self.$(OBJEXT) \ - pt-sigmask.$(OBJEXT) pt-spin-inlines.$(OBJEXT) \ - pt-cleanup.$(OBJEXT) pt-setcancelstate.$(OBJEXT) \ - pt-setcanceltype.$(OBJEXT) pt-testcancel.$(OBJEXT) \ - pt-cancel.$(OBJEXT) pt-mutexattr.$(OBJEXT) \ - pt-mutexattr-destroy.$(OBJEXT) pt-mutexattr-init.$(OBJEXT) \ - pt-mutexattr-getprioceiling.$(OBJEXT) \ - pt-mutexattr-getprotocol.$(OBJEXT) \ - pt-mutexattr-getpshared.$(OBJEXT) \ - pt-mutexattr-gettype.$(OBJEXT) \ - pt-mutexattr-setprioceiling.$(OBJEXT) \ - pt-mutexattr-setprotocol.$(OBJEXT) \ - pt-mutexattr-setpshared.$(OBJEXT) \ - pt-mutexattr-settype.$(OBJEXT) pt-mutex-init.$(OBJEXT) \ - pt-mutex-destroy.$(OBJEXT) pt-mutex-lock.$(OBJEXT) \ - pt-mutex-trylock.$(OBJEXT) pt-mutex-timedlock.$(OBJEXT) \ - pt-mutex-unlock.$(OBJEXT) pt-mutex-getprioceiling.$(OBJEXT) \ - pt-mutex-setprioceiling.$(OBJEXT) pt-rwlock-attr.$(OBJEXT) \ - pt-rwlockattr-init.$(OBJEXT) pt-rwlockattr-destroy.$(OBJEXT) \ - pt-rwlockattr-getpshared.$(OBJEXT) \ - pt-rwlockattr-setpshared.$(OBJEXT) pt-rwlock-init.$(OBJEXT) \ - pt-rwlock-destroy.$(OBJEXT) pt-rwlock-rdlock.$(OBJEXT) \ - pt-rwlock-tryrdlock.$(OBJEXT) pt-rwlock-trywrlock.$(OBJEXT) \ - pt-rwlock-wrlock.$(OBJEXT) pt-rwlock-timedrdlock.$(OBJEXT) \ - pt-rwlock-timedwrlock.$(OBJEXT) pt-rwlock-unlock.$(OBJEXT) \ - pt-cond.$(OBJEXT) pt-condattr-init.$(OBJEXT) \ - pt-condattr-destroy.$(OBJEXT) pt-condattr-getclock.$(OBJEXT) \ - pt-condattr-getpshared.$(OBJEXT) pt-condattr-setclock.$(OBJEXT) \ - pt-condattr-setpshared.$(OBJEXT) pt-cond-destroy.$(OBJEXT) \ - pt-cond-init.$(OBJEXT) pt-cond-brdcast.$(OBJEXT) \ - pt-cond-signal.$(OBJEXT) pt-cond-wait.$(OBJEXT) \ - pt-cond-timedwait.$(OBJEXT) pt-stack-alloc.$(OBJEXT) \ - pt-thread-alloc.$(OBJEXT) pt-thread-start.$(OBJEXT) \ - pt-thread-halt.$(OBJEXT) pt-thread-init.$(OBJEXT) \ - pt-getconcurrency.$(OBJEXT) pt-setconcurrency.$(OBJEXT) \ - pt-block.$(OBJEXT) pt-timedblock.$(OBJEXT) pt-wakeup.$(OBJEXT) \ - pt-docancel.$(OBJEXT) pt-sysdep.$(OBJEXT) pt-setup.$(OBJEXT) \ - pt-machdep.$(OBJEXT) pt-spin.$(OBJEXT) \ - pt-sigstate-init.$(OBJEXT) pt-sigstate-destroy.$(OBJEXT) \ - pt-sigstate.$(OBJEXT) pt-atfork.$(OBJEXT) pt-kill.$(OBJEXT) \ - pt-getcpuclockid.$(OBJEXT) pt-getschedparam.$(OBJEXT) \ - pt-setschedparam.$(OBJEXT) pt-setschedprio.$(OBJEXT) -libpthread_a_OBJECTS = $(am_libpthread_a_OBJECTS) - -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/pt-alloc.Po ./$(DEPDIR)/pt-atfork.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getdetachstate.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getguardsize.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getinheritsched.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getschedparam.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getschedpolicy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getscope.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getstack.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getstackaddr.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-getstacksize.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setdetachstate.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setguardsize.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setinheritsched.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setschedparam.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setschedpolicy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setscope.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setstack.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setstackaddr.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr-setstacksize.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-attr.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier-wait.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrier.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-getpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-barrierattr-setpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-block.Po ./$(DEPDIR)/pt-cancel.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-cleanup.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-brdcast.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-signal.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-timedwait.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-cond-wait.Po ./$(DEPDIR)/pt-cond.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-getclock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-getpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-setclock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-condattr-setpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-create-np.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-create.Po ./$(DEPDIR)/pt-dealloc.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-destroy-specific.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-detach.Po ./$(DEPDIR)/pt-docancel.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-equal.Po ./$(DEPDIR)/pt-exit.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-getconcurrency.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-getcpuclockid.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-getschedparam.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-getspecific.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-init-specific.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-initialize.Po ./$(DEPDIR)/pt-join.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-key-create.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-key-delete.Po ./$(DEPDIR)/pt-kill.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-machdep.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-getprioceiling.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-lock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-setprioceiling.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-timedlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-trylock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutex-unlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-getprioceiling.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-getprotocol.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-getpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-gettype.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-setprioceiling.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-setprotocol.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-setpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr-settype.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-mutexattr.Po ./$(DEPDIR)/pt-once.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-pool-np.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-attr.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-rdlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-timedrdlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-timedwrlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-tryrdlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-trywrlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-unlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlock-wrlock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-getpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-rwlockattr-setpshared.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-self.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-setcancelstate.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-setcanceltype.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-setconcurrency.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-setschedparam.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-setschedprio.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-setspecific.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-setup.Po ./$(DEPDIR)/pt-sigmask.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-sigstate-destroy.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-sigstate-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-sigstate.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-spin-inlines.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-spin.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-stack-alloc.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-sysdep.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-testcancel.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-alloc.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-halt.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-init.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-thread-start.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-timedblock.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pt-wakeup.Po -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -DIST_SOURCES = $(libpthread_a_SOURCES) -DIST_COMMON = $(srcdir)/Makefile.in ChangeLog Makefile.am TODO -SOURCES = $(libpthread_a_SOURCES) - -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu libpthread/Makefile -Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -libpthread.a: $(libpthread_a_OBJECTS) $(libpthread_a_DEPENDENCIES) - -rm -f libpthread.a - $(libpthread_a_AR) libpthread.a $(libpthread_a_OBJECTS) $(libpthread_a_LIBADD) - $(RANLIB) libpthread.a - -mostlyclean-compile: - -rm -f *.$(OBJEXT) core *.core - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-alloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-atfork.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getdetachstate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getguardsize.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getinheritsched.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getschedparam.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getschedpolicy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getscope.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getstack.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getstackaddr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-getstacksize.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setdetachstate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setguardsize.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setinheritsched.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setschedparam.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setschedpolicy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setscope.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setstack.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setstackaddr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr-setstacksize.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-attr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier-wait.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrier.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-getpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-barrierattr-setpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-block.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cancel.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cleanup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-brdcast.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-signal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-timedwait.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond-wait.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-cond.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-getclock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-getpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-setclock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-condattr-setpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-create-np.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-create.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-dealloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-destroy-specific.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-detach.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-docancel.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-equal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-exit.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getconcurrency.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getcpuclockid.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getschedparam.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-getspecific.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-init-specific.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-initialize.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-join.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-key-create.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-key-delete.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-kill.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-machdep.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-getprioceiling.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-lock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-setprioceiling.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-timedlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-trylock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutex-unlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-getprioceiling.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-getprotocol.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-getpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-gettype.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-setprioceiling.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-setprotocol.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-setpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr-settype.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-mutexattr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-once.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-pool-np.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-attr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-rdlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-timedrdlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-timedwrlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-tryrdlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-trywrlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-unlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlock-wrlock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-getpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-rwlockattr-setpshared.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-self.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setcancelstate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setcanceltype.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setconcurrency.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setschedparam.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setschedprio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setspecific.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-setup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigmask.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigstate-destroy.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigstate-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sigstate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-spin-inlines.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-spin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-stack-alloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-sysdep.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-testcancel.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-alloc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-halt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-init.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-thread-start.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-timedblock.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pt-wakeup.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ -@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ -@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ -@am__fastdepCC_TRUE@ fi -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< - -.c.obj: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ -@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ -@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ -@am__fastdepCC_TRUE@ fi -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` -uninstall-info-am: - -ETAGS = etags -ETAGSFLAGS = - -CTAGS = ctags -CTAGSFLAGS = - -tags: TAGS - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(ETAGS_ARGS)$$tags$$unique" \ - || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique - -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) - -top_distdir = .. -distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkinstalldirs) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LIBRARIES) - -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -info: info-am - -info-am: - -install-data-am: - -install-exec-am: - -install-info: install-info-am - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-info-am - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES ctags distclean distclean-compile \ - distclean-generic distclean-tags distdir dvi dvi-am info \ - info-am install install-am install-data install-data-am \ - install-exec install-exec-am install-info install-info-am \ - install-man install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ - ps ps-am tags uninstall uninstall-am uninstall-info-am - -vpath %.c $(SYSDEP_PATH) -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: -- cgit v1.2.3 From 7c600777057893b7e48b10963dca2444f25f9217 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Mon, 1 Nov 2004 17:04:00 +0000 Subject: 2004-11-01 Marcus Brinkmann * pthread/pt-internal.h: Include , not . (__pthread_total): Change type of declaration to uatomic_max_t. * pthread/pt-alloc.c: Include , not . (__pthread_free_threads): Change type to uatomicptr_t. (__pthread_alloc): Call atomic_compare_and_exchange_val_acq instead of __atomicptr_compare_and_swap. * pthread/pt-create.c: Include , not . (__pthread_total): Change type to uatomic_max_t. (__pthread_create_internal): Call atomic_increment, not __atomic_inc and atomic_decrement, not __atomic_dec. * pthread/pt-dealloc.c: Include , not . (__pthread_free_threads): Declare as uatomicptr_t. (__pthread_dealloc): Call atomic_compare_and_exchange_val_acq instead of __atomicptr_compare_and_swap. * pthread/pt-exit.c: Include , not . (pthread_exit): Call atomic_decrement_and_test instead of __atomic_dec_and_test. * sysdeps/l4/pt-create-np.c: Do not include . --- pthread/pt-alloc.c | 12 ++++++------ pthread/pt-create.c | 10 +++++----- pthread/pt-dealloc.c | 8 ++++---- pthread/pt-exit.c | 6 +++--- pthread/pt-internal.h | 6 +++--- sysdeps/l4/pt-create-np.c | 2 -- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index 7c15fe15..dd9760d6 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -25,7 +25,7 @@ #include -#include +#include /* This braindamage is necessary because the standard says that some of the threads functions "shall fail" if "No thread could be found @@ -46,7 +46,7 @@ pthread_rwlock_t __pthread_threads_lock; /* List of thread structures corresponding to free thread IDs. */ -__atomicptr_t __pthread_free_threads; +uatomicptr_t __pthread_free_threads; static inline error_t initialize_pthread (struct __pthread *new, int recycling) @@ -97,8 +97,8 @@ __pthread_alloc (struct __pthread **pthread) /* Try to re-use a thread structure before creating a new one. */ while ((new = (struct __pthread *)__pthread_free_threads)) { - if (__atomicptr_compare_and_swap (&__pthread_free_threads, - new, new->next)) + if (atomic_compare_and_exchange_val_acq (&__pthread_free_threads, + new, new->next)) { /* Yes, we managed to get one. The thread number in the thread structure still refers to the correct slot. */ @@ -110,8 +110,8 @@ __pthread_alloc (struct __pthread **pthread) while (1) { new->next = (struct __pthread *)__pthread_free_threads; - if (__atomicptr_compare_and_swap (&__pthread_free_threads, - new->next, new)) + if (atomic_compare_and_exchange_val_acq + (&__pthread_free_threads, new->next, new)) break; } diff --git a/pthread/pt-create.c b/pthread/pt-create.c index 727fbac1..95df677e 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -1,5 +1,5 @@ /* Thread creation. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2004 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 @@ -22,7 +22,7 @@ #include #include -#include +#include #include @@ -33,7 +33,7 @@ /* The total number of pthreads currently active. This is defined here since it would be really stupid to have a threads-using program that doesn't call `pthread_create'. */ -__atomic_t __pthread_total; +uatomic_max_t __pthread_total; /* The entry-point for new threads. */ @@ -173,7 +173,7 @@ __pthread_create_internal (struct __pthread **thread, the number of threads from within the new thread isn't an option since this thread might return and call `pthread_exit' before the new thread runs. */ - __atomic_inc (&__pthread_total); + atomic_increment (&__pthread_total); /* Store a pointer to this thread in the thread ID lookup table. We could use __thread_setid, however, we only lock for reading as no @@ -200,7 +200,7 @@ __pthread_create_internal (struct __pthread **thread, failed_starting: __pthread_setid (pthread->thread, NULL); - __atomic_dec (&__pthread_total); + atomic_decrement (&__pthread_total); failed_sigstate: __pthread_sigstate_destroy (pthread); failed_setup: diff --git a/pthread/pt-dealloc.c b/pthread/pt-dealloc.c index 1fc7a7b3..f89f3545 100644 --- a/pthread/pt-dealloc.c +++ b/pthread/pt-dealloc.c @@ -23,10 +23,10 @@ #include -#include +#include /* List of thread structures corresponding to free thread IDs. */ -extern __atomicptr_t __pthread_free_threads; +extern uatomicptr_t __pthread_free_threads; /* Deallocate the thread structure for PTHREAD and the resources associated with it. */ @@ -54,8 +54,8 @@ __pthread_dealloc (struct __pthread *pthread) while (1) { pthread->next = (struct __pthread *)__pthread_free_threads; - if (__atomicptr_compare_and_swap (&__pthread_free_threads, - pthread->next, pthread)) + if (atomic_compare_and_exchange_val_acq (&__pthread_free_threads, + pthread->next, pthread)) return; } diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c index fb9e97c0..68f596dc 100644 --- a/pthread/pt-exit.c +++ b/pthread/pt-exit.c @@ -1,5 +1,5 @@ /* Thread termination. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2004 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 @@ -24,7 +24,7 @@ #include -#include +#include /* Terminate the current thread and make STATUS available to any @@ -56,7 +56,7 @@ pthread_exit (void *status) /* Decrease the number of threads. We use an atomic operation to make sure that only the last thread calls `exit'. */ - if (__atomic_dec_and_test (&__pthread_total)) + if (atomic_decrement_and_test (&__pthread_total)) /* We are the last thread. */ exit (0); diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 79ce19c7..af3dd875 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2004 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 @@ -27,7 +27,7 @@ #include #include #endif -#include +#include #include @@ -126,7 +126,7 @@ __pthread_dequeue (struct __pthread *thread) element = element->next) /* The total number of threads currently active. */ -extern __atomic_t __pthread_total; +extern uatomic_max_t __pthread_total; /* The total number of thread IDs currently in use, or on the list of available thread IDs. */ diff --git a/sysdeps/l4/pt-create-np.c b/sysdeps/l4/pt-create-np.c index d5a23668..627d6d04 100644 --- a/sysdeps/l4/pt-create-np.c +++ b/sysdeps/l4/pt-create-np.c @@ -22,8 +22,6 @@ #include #include -#include - #include /* Create a thread with attributes given by ATTR, executing -- cgit v1.2.3 From 905902fe736354fa553aea0e38e52bc294f84e92 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Mon, 1 Nov 2004 17:28:43 +0000 Subject: 2004-11-01 Marcus Brinkmann * pthread/pt-create.c (__pthread_total): Change type to uatomic32_t. * pthread/pt-internal.h (__pthread_total): Likewise in declaration. --- pthread/pt-create.c | 2 +- pthread/pt-internal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pthread/pt-create.c b/pthread/pt-create.c index 95df677e..8d348fb9 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -33,7 +33,7 @@ /* The total number of pthreads currently active. This is defined here since it would be really stupid to have a threads-using program that doesn't call `pthread_create'. */ -uatomic_max_t __pthread_total; +uatomic32_t __pthread_total; /* The entry-point for new threads. */ diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index af3dd875..436f8703 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -126,7 +126,7 @@ __pthread_dequeue (struct __pthread *thread) element = element->next) /* The total number of threads currently active. */ -extern uatomic_max_t __pthread_total; +extern uatomic32_t __pthread_total; /* The total number of thread IDs currently in use, or on the list of available thread IDs. */ -- cgit v1.2.3 From a77e8d9fb87aa1d7ab97839877ad9da9f57e36e3 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Tue, 2 Nov 2004 03:52:19 +0000 Subject: 2004-11-02 Marcus Brinkmann * sysdeps/generic/bits/condition.h (__PTHREAD_COND_INITIALIZER): Remove compound statement. * pthread/pt-alloc.c (initialize_pthread): Use compound statement. * sysdeps/generic/pt-cond-init.c (pthread_cond_init): Likewise. --- pthread/pt-alloc.c | 2 +- sysdeps/generic/bits/condition.h | 3 +-- sysdeps/generic/pt-cond-init.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index dd9760d6..615b7289 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -70,7 +70,7 @@ initialize_pthread (struct __pthread *new, int recycling) new->stack = 0; new->state_lock = (struct __pthread_mutex) PTHREAD_MUTEX_INITIALIZER; - new->state_cond = PTHREAD_COND_INITIALIZER; + new->state_cond = (struct __pthread_cond) PTHREAD_COND_INITIALIZER; new->cancelation_handlers = 0; diff --git a/sysdeps/generic/bits/condition.h b/sysdeps/generic/bits/condition.h index cb7e935c..a194b05d 100644 --- a/sysdeps/generic/bits/condition.h +++ b/sysdeps/generic/bits/condition.h @@ -34,7 +34,6 @@ struct __pthread_cond /* Initializer for a condition variable. */ #define __PTHREAD_COND_INITIALIZER \ - ((struct __pthread_cond) \ - { __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL }) + { __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL } #endif /* bits/condition.h */ diff --git a/sysdeps/generic/pt-cond-init.c b/sysdeps/generic/pt-cond-init.c index 4afcc94e..a01a94ba 100644 --- a/sysdeps/generic/pt-cond-init.c +++ b/sysdeps/generic/pt-cond-init.c @@ -29,6 +29,6 @@ pthread_cond_init (pthread_cond_t *cond, if (attr) assert (attr->pshared == PTHREAD_PROCESS_PRIVATE); - *cond = __PTHREAD_COND_INITIALIZER; + *cond = (struct __pthread_cond) __PTHREAD_COND_INITIALIZER; return 0; } -- cgit v1.2.3 From 3d47808ce03e2e96f39c4d051e0d7f83bbd49180 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 12 Jan 2005 10:33:39 +0000 Subject: libc-parts/ 2005-01-12 Neal H. Walfield * assert.h: Include prototype for printf. (assert) [!NDEBUG]: Rewrite to do something useful. libhurd-cap-server/ 2005-01-12 Neal H. Walfield * class-init.c (hurd_cap_class_init_untyped): Fix assert. * bucket-manage-mt.c (manage_mt_worker): Likewise. libpthread/ 2005-01-12 Neal H. Walfield * sysdeps/l4/pt-thread-alloc.c: Replace assert with a compile time warning. * sysdeps/l4/hurd/pt-sigstate.c (__pthread_sigstate): Don't return EINVAL. Pretend to work so the generic code is happy. --- sysdeps/l4/hurd/pt-sigstate.c | 5 +++-- sysdeps/l4/pt-thread-alloc.c | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sysdeps/l4/hurd/pt-sigstate.c b/sysdeps/l4/hurd/pt-sigstate.c index 490c95fe..8ab80347 100644 --- a/sysdeps/l4/hurd/pt-sigstate.c +++ b/sysdeps/l4/hurd/pt-sigstate.c @@ -1,5 +1,5 @@ /* Set a thread's signal state. Hurd on L4 version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 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 @@ -28,5 +28,6 @@ __pthread_sigstate (struct __pthread *thread, int how, const sigset_t *set, sigset_t *oset, int clear_pending) { - return EINVAL; + /* FIXME: Do the right thing here. */ + return 0; } diff --git a/sysdeps/l4/pt-thread-alloc.c b/sysdeps/l4/pt-thread-alloc.c index 07784f5f..fc2f43b4 100644 --- a/sysdeps/l4/pt-thread-alloc.c +++ b/sysdeps/l4/pt-thread-alloc.c @@ -1,5 +1,5 @@ /* Allocate kernel thread. L4 version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2005 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 @@ -31,7 +31,13 @@ __pthread_thread_alloc (struct __pthread *thread) /* The main thread is already running of course. */ if (__pthread_num_threads == 1) { + /* XXX: The initialization code needs to make this consistent. + Right now, we have none and this whole library is a hack + anyways. */ +#warning __pthread_total is inconsistent. +#if 0 assert (__pthread_total == 1); +#endif thread->threadid = l4_myself (); } else -- cgit v1.2.3 From 8b5dd2555959dd72143fa43382dc15532a0b420a Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 8 Feb 2005 16:17:13 +0000 Subject: libpthread/ 2005-02-08 Neal H. Walfield * sysdeps/posix/pt-spin.c (__pthread_spin_lock): Make a weak alias to _pthread_spin_lock. * sysdeps/l4/hurd/pt-sysdep.h (_pthread_self): Add __always_inline__ attribute. (__pthread_stack_dealloc): Likewise. --- sysdeps/l4/hurd/pt-sysdep.h | 4 +++- sysdeps/posix/pt-spin.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h index 7e69d709..0b5abb74 100644 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -33,12 +33,14 @@ l4_word_t my_errno; extern inline struct __pthread * +__attribute__((__always_inline__)) _pthread_self (void) { return (struct __pthread *) l4_user_defined_handle (); } extern inline void +__attribute__((__always_inline__)) __pthread_stack_dealloc (void *stackaddr, size_t stacksize) { /* XXX: can only implement this once we have a working memory manager. */ diff --git a/sysdeps/posix/pt-spin.c b/sysdeps/posix/pt-spin.c index cdc482c1..26793b08 100644 --- a/sysdeps/posix/pt-spin.c +++ b/sysdeps/posix/pt-spin.c @@ -1,5 +1,5 @@ /* Spin locks. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2005 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 @@ -51,3 +51,4 @@ _pthread_spin_lock (__pthread_spinlock_t *lock) } weak_alias (_pthread_spin_lock, pthread_spin_lock); +weak_alias (_pthread_spin_lock, __pthread_spin_lock); -- cgit v1.2.3 From 7373049ff9aac3dbfe088da7d30b2724d15fa67a Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 6 Aug 2007 16:32:43 +0000 Subject: 2007-08-06 Neal H. Walfield * sysdeps/l4/bits/pthread-np.h (pthread_create_from_l4_tid_np): Don't require the GNU interface: use _L4_thread_id_t, not l4_thread_id_t. (pthread_pool_add_np): Likewise. (pthread_pool_get_np): Likewise. * sysdeps/l4/pt-create-np.c (pthread_create_from_l4_tid_np): Likewise. * sysdeps/l4/pt-pool-np.c (pool_list): Likewise. (pthread_pool_add_np): Likewise. (pthread_pool_get_np): Likewise. --- sysdeps/l4/bits/pthread-np.h | 8 ++++---- sysdeps/l4/pt-create-np.c | 4 ++-- sysdeps/l4/pt-pool-np.c | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sysdeps/l4/bits/pthread-np.h b/sysdeps/l4/bits/pthread-np.h index 7e807107..3a98cd3f 100644 --- a/sysdeps/l4/bits/pthread-np.h +++ b/sysdeps/l4/bits/pthread-np.h @@ -1,5 +1,5 @@ /* Non-portable functions. L4 version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2007 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 @@ -31,14 +31,14 @@ kernel thread. */ extern int pthread_create_from_l4_tid_np (pthread_t *thread, const pthread_attr_t *attr, - l4_thread_id_t tid, + _L4_thread_id_t tid, void *(*start_routine)(void *), void *arg); /* Add the thread TID to the internal kernel thread pool. */ -int pthread_pool_add_np (l4_thread_id_t tid); +extern int pthread_pool_add_np (_L4_thread_id_t tid); /* Get the first thread from the pool. */ -l4_thread_id_t pthread_pool_get_np (void); +extern _L4_thread_id_t pthread_pool_get_np (void); #endif /* bits/pthread-np.h */ diff --git a/sysdeps/l4/pt-create-np.c b/sysdeps/l4/pt-create-np.c index 627d6d04..57c782cc 100644 --- a/sysdeps/l4/pt-create-np.c +++ b/sysdeps/l4/pt-create-np.c @@ -1,5 +1,5 @@ /* Thread creation from provided L4 thread. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2007 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 @@ -30,7 +30,7 @@ int pthread_create_from_l4_tid_np (pthread_t *thread, const pthread_attr_t *attr, - l4_thread_id_t tid, + _L4_thread_id_t tid, void *(*start_routine)(void *), void *arg) { int err; diff --git a/sysdeps/l4/pt-pool-np.c b/sysdeps/l4/pt-pool-np.c index d006b4f3..c72f2eb2 100644 --- a/sysdeps/l4/pt-pool-np.c +++ b/sysdeps/l4/pt-pool-np.c @@ -1,5 +1,5 @@ /* Thread pool for L4 threads. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2007 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 @@ -22,11 +22,11 @@ static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; -l4_thread_id_t pool_list = l4_nilthread; +_L4_thread_id_t pool_list = l4_nilthread; /* Add the thread TID to the pthread kernel thread pool. */ int -pthread_pool_add_np (l4_thread_id_t tid) +pthread_pool_add_np (_L4_thread_id_t tid) { __pthread_mutex_lock (&pool_lock); /* FIXME: Do error checking. */ @@ -38,10 +38,10 @@ pthread_pool_add_np (l4_thread_id_t tid) /* Get the first thread from the pool. */ -l4_thread_id_t +_L4_thread_id_t pthread_pool_get_np (void) { - l4_thread_id_t tid; + _L4_thread_id_t tid; __pthread_mutex_lock (&pool_lock); /* FIXME: Do error checking. */ -- cgit v1.2.3 From 961d71afd49f55395e6dbfe203d6b968e4105ee0 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 20 Nov 2007 17:39:57 +0000 Subject: 2007-11-20 Neal H. Walfield * Makefile.am (libpthread_a_SOURCES): Remove pt-create-np.c. * sysdeps/l4/pt-create-np.c: Remove file. * sysdeps/l4/pt-pool-np.c (pthread_pool_add_np): Change tid from an _L4_thread_id_t to an l4_thread_id_t. (pthread_pool_get_np): Return an l4_thread_id_t, not a _L4_thread_id_t. * sysdeps/l4/bits/pthread-np.h (pthread_create_from_l4_tid_np): Remove declaration. (pthread_pool_add_np): Change tid from an _L4_thread_id_t to an l4_thread_id_t. (pthread_pool_get_np): Return an l4_thread_id_t, not a _L4_thread_id_t. * sysdeps/l4/pt-docancel.c (__pthread_do_cancel): Implement for the case that the target thread is not the executing thread. * sysdeps/l4/pt-thread-alloc.c (__pthread_thread_alloc): Return EAGAIN if pthread_pool_get_np does not return a thread. Update comments. * sysdeps/l4/pt-thread-start.c (__pthread_thread_start): Don't set the thread's pager. Assert that if this is the first thread, then THREAD->THREADID is designates the running thread. * sysdeps/l4/pt-timedblock.c (__pthread_timedblock): Add warning about incomplete implementation. * Makefile.am (libpthread_a_SOURCES): Remove pt-thread-init.c. * sysdeps/l4/pt-thread-init.c: Remove dead file. * sysdeps/l4/pt-start.c: Remove dead file. --- Makefile.am | 2 - sysdeps/l4/bits/pthread-np.h | 13 +----- sysdeps/l4/pt-create-np.c | 46 ------------------- sysdeps/l4/pt-docancel.c | 20 +++------ sysdeps/l4/pt-pool-np.c | 4 +- sysdeps/l4/pt-start.c | 103 ------------------------------------------- sysdeps/l4/pt-thread-alloc.c | 23 +--------- sysdeps/l4/pt-thread-init.c | 34 -------------- sysdeps/l4/pt-thread-start.c | 12 ++--- sysdeps/l4/pt-timedblock.c | 1 + 10 files changed, 18 insertions(+), 240 deletions(-) delete mode 100644 sysdeps/l4/pt-create-np.c delete mode 100644 sysdeps/l4/pt-start.c delete mode 100644 sysdeps/l4/pt-thread-init.c diff --git a/Makefile.am b/Makefile.am index bef3f17a..a1db8f42 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,6 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-once.c \ pt-alloc.c \ pt-create.c \ - pt-create-np.c \ pt-pool-np.c \ pt-equal.c \ pt-dealloc.c \ @@ -110,7 +109,6 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-thread-alloc.c \ pt-thread-start.c \ pt-thread-halt.c \ - pt-thread-init.c \ pt-getconcurrency.c pt-setconcurrency.c \ pt-block.c \ pt-timedblock.c \ diff --git a/sysdeps/l4/bits/pthread-np.h b/sysdeps/l4/bits/pthread-np.h index 3a98cd3f..6a02bdc0 100644 --- a/sysdeps/l4/bits/pthread-np.h +++ b/sysdeps/l4/bits/pthread-np.h @@ -26,19 +26,10 @@ #include -/* Create a thread with attributes given by ATTR, executing - START_ROUTINE with argument ARG. TID is the provided L4 - kernel thread. */ -extern int pthread_create_from_l4_tid_np (pthread_t *thread, - const pthread_attr_t *attr, - _L4_thread_id_t tid, - void *(*start_routine)(void *), - void *arg); - /* Add the thread TID to the internal kernel thread pool. */ -extern int pthread_pool_add_np (_L4_thread_id_t tid); +extern int pthread_pool_add_np (l4_thread_id_t tid); /* Get the first thread from the pool. */ -extern _L4_thread_id_t pthread_pool_get_np (void); +extern l4_thread_id_t pthread_pool_get_np (void); #endif /* bits/pthread-np.h */ diff --git a/sysdeps/l4/pt-create-np.c b/sysdeps/l4/pt-create-np.c deleted file mode 100644 index 68b8b004..00000000 --- a/sysdeps/l4/pt-create-np.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Thread creation from provided L4 thread. - Copyright (C) 2003, 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -/* Create a thread with attributes given by ATTR, executing - START_ROUTINE with argument ARG. TID is the provided L4 - kernel thread. */ -int -pthread_create_from_l4_tid_np (pthread_t *thread, - const pthread_attr_t *attr, - _L4_thread_id_t tid, - void *(*start_routine)(void *), void *arg) -{ - int err; - struct __pthread *pthread; - -#warning Does not use TID. - err = __pthread_create_internal (&pthread, attr, - start_routine, arg); - if (! err) - *thread = pthread->thread; - - return err; -} diff --git a/sysdeps/l4/pt-docancel.c b/sysdeps/l4/pt-docancel.c index e832e26e..a3965d0d 100644 --- a/sysdeps/l4/pt-docancel.c +++ b/sysdeps/l4/pt-docancel.c @@ -1,5 +1,5 @@ /* Cancel a thread. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2007 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 @@ -30,23 +30,13 @@ call_exit (void) int __pthread_do_cancel (struct __pthread *p) { -#if 0 - assert (p->cancel_pending = 1); + assert (p->cancel_pending == 1); assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); - if (L4_SameThreads (L4_Myself (), p->threadid)) + if (l4_is_thread_equal (l4_myself (), p->threadid)) call_exit (); else - { - L4_Word_t dummy; - L4_ThreadId_t dummy_id; - - /* Change the ip of the target thread to make it exit. */ - L4_ExchangeRegisters (p->threadid, (1 << 4), 0, call_exit, - 0, 0, L4_nilthread, - &dummy, &dummy, &dummy, &dummy, &dummy, - &dummy_id); - } -#endif + l4_start_sp_ip (p->threadid, (l4_word_t) p->mcontext.sp, + (l4_word_t) call_exit); return 0; } diff --git a/sysdeps/l4/pt-pool-np.c b/sysdeps/l4/pt-pool-np.c index f59a3e2b..e83022ba 100644 --- a/sysdeps/l4/pt-pool-np.c +++ b/sysdeps/l4/pt-pool-np.c @@ -26,7 +26,7 @@ _L4_thread_id_t pool_list = l4_nilthread; /* Add the thread TID to the pthread kernel thread pool. */ int -pthread_pool_add_np (_L4_thread_id_t tid, bool stop) +pthread_pool_add_np (l4_thread_id_t tid) { __pthread_mutex_lock (&pool_lock); /* FIXME: Do error checking. */ @@ -39,7 +39,7 @@ pthread_pool_add_np (_L4_thread_id_t tid, bool stop) /* Get the first thread from the pool. */ -_L4_thread_id_t +l4_thread_id_t pthread_pool_get_np (void) { _L4_thread_id_t tid; diff --git a/sysdeps/l4/pt-start.c b/sysdeps/l4/pt-start.c deleted file mode 100644 index fb4e27be..00000000 --- a/sysdeps/l4/pt-start.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Start thread. L4 Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -#include "task_client.h" - -extern L4_ThreadId_t __system_pager; -extern L4_ThreadId_t __task_server; - -#ifndef WORKING_EXREGS -static void -send_startup_ipc (L4_ThreadId_t id, L4_Word_t ip, L4_Word_t sp) -{ - L4_Msg_t msg; - - printf ("%s: Sending startup message to %x, " - "(ip=%x, sp=%x)\n", - __FUNCTION__, * (L4_Word_t *) &id, ip, sp); - - L4_Clear (&msg); -#ifdef HAVE_PROPAGATION - L4_Set_VirtualSender (pager_tid); - L4_Set_Propagation (&msg.tag); -#endif - L4_Append_Word (&msg, ip); - L4_Append_Word (&msg, sp); -#ifndef HAVE_PROPAGATION - L4_Append_Word (&msg, *(L4_Word_t *) &id); - id = __system_pager; -#if 0 - DODEBUG (2, printf ("%s: Redirecting start request to pager (%x).\n", - __FUNCTION__, * (L4_Word_t *) &id)); -#endif -#endif - L4_LoadMsg (&msg); - L4_Send (id); -} -#endif - -/* Start THREAD. We allocate all system-specific resources, including - a kernel thread, set it up, and get it running. */ -int -__pthread_start (struct __pthread *thread) -{ - error_t err; - - if (__pthread_num_threads == 1) - /* The main thread is already running: do nothing. */ - { - assert (__pthread_total == 1); - thread->threadid = L4_Myself (); - } - else - { - CORBA_Environment env; - - env = idl4_default_environment; - err = thread_create (__task_server, - L4_Version (L4_Myself ()), - * (L4_Word_t *) &__system_pager, - (L4_Word_t *) &thread->threadid, &env); - if (err) - return EAGAIN; - - env = idl4_default_environment; - err = thread_resume (__task_server, - * (L4_Word_t *) &thread->threadid, - &env); - assert (! err); - -#ifndef WORKING_EXREGS - L4_AbortIpc_and_stop (thread->threadid); - L4_Start_SpIp (thread->threadid, (L4_Word_t) thread->mcontext.sp, - (L4_Word_t) thread->mcontext.pc); -#endif - send_startup_ipc (thread->threadid, (L4_Word_t) thread->mcontext.pc, - (L4_Word_t) thread->mcontext.sp); - - } - - return 0; -} diff --git a/sysdeps/l4/pt-thread-alloc.c b/sysdeps/l4/pt-thread-alloc.c index fc2f43b4..ec69afb5 100644 --- a/sysdeps/l4/pt-thread-alloc.c +++ b/sysdeps/l4/pt-thread-alloc.c @@ -30,33 +30,14 @@ __pthread_thread_alloc (struct __pthread *thread) /* The main thread is already running of course. */ if (__pthread_num_threads == 1) - { - /* XXX: The initialization code needs to make this consistent. - Right now, we have none and this whole library is a hack - anyways. */ -#warning __pthread_total is inconsistent. -#if 0 - assert (__pthread_total == 1); -#endif - thread->threadid = l4_myself (); - } + thread->threadid = l4_myself (); else { thread->threadid = pthread_pool_get_np (); if (thread->threadid != l4_nilthread) return 0; -#if 0 - CORBA_Environment env; - - env = idl4_default_environment; - err = thread_create (__task_server, - L4_Version (L4_Myself ()), - * (L4_Word_t *) &__system_pager, - (L4_Word_t *) &thread->threadid, &env); - if (err) -#endif - return EAGAIN; + return EAGAIN; } return 0; } diff --git a/sysdeps/l4/pt-thread-init.c b/sysdeps/l4/pt-thread-init.c deleted file mode 100644 index ac50d58d..00000000 --- a/sysdeps/l4/pt-thread-init.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Start thread. L4 version. - Copyright (C) 2003 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Initialize provided kernel thread. */ -int -__pthread_init_provided_thread (struct __pthread *thread, - void *p) -{ - l4_thread_id_t *tid = (l4_thread_id_t *) p; - thread->threadid = *tid; - return 0; -} diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c index 10996e1c..538d0444 100644 --- a/sysdeps/l4/pt-thread-start.c +++ b/sysdeps/l4/pt-thread-start.c @@ -1,5 +1,5 @@ /* Start thread. L4 version. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2007 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 @@ -29,12 +29,12 @@ __pthread_thread_start (struct __pthread *thread) { /* The main thread is already running of course. */ if (__pthread_num_threads == 1) - assert (__pthread_total == 1); - else { - l4_set_pager_of (thread->threadid, l4_pager ()); - l4_start_sp_ip (thread->threadid, (l4_word_t) thread->mcontext.sp, - (l4_word_t) thread->mcontext.pc); + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); } + else + l4_start_sp_ip (thread->threadid, (l4_word_t) thread->mcontext.sp, + (l4_word_t) thread->mcontext.pc); return 0; } diff --git a/sysdeps/l4/pt-timedblock.c b/sysdeps/l4/pt-timedblock.c index fda14401..ce7972bd 100644 --- a/sysdeps/l4/pt-timedblock.c +++ b/sysdeps/l4/pt-timedblock.c @@ -29,6 +29,7 @@ error_t __pthread_timedblock (struct __pthread *thread, const struct timespec *abstime) { +#warning Need gettimeofday to implement properly. __pthread_block (thread); return 0; } -- cgit v1.2.3 From 96d719679962ea3f765b3e3f23672af130de9c1d Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 20 Nov 2007 18:38:00 +0000 Subject: 2007-11-20 Neal H. Walfield * sysdeps/l4/pt-thread-dealloc.c: New file. * Makefile.am (libpthread_a_SOURCES): Add pt-thread-dealloc.c. * sysdeps/l4/hurd/pt-sysdep.h (PTHREAD_STACK_DEFAULT): Change to 2MB. * sysdeps/l4/hurd/pt-sysdep.c (sched_yield): New function. (sigprocmask): Likewise. (init_routine): Only call __pthread_initialize once. Update comments. --- Makefile.am | 1 + sysdeps/l4/hurd/pt-sysdep.c | 28 +++++++++++++++++----------- sysdeps/l4/hurd/pt-sysdep.h | 4 ++-- sysdeps/l4/pt-thread-dealloc.c | 32 ++++++++++++++++++++++++++++++++ sysdeps/l4/pt-thread-start.c | 2 +- 5 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 sysdeps/l4/pt-thread-dealloc.c diff --git a/Makefile.am b/Makefile.am index a1db8f42..9249d937 100644 --- a/Makefile.am +++ b/Makefile.am @@ -107,6 +107,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-cond-timedwait.c \ pt-stack-alloc.c \ pt-thread-alloc.c \ + pt-thread-dealloc.c \ pt-thread-start.c \ pt-thread-halt.c \ pt-getconcurrency.c pt-setconcurrency.c \ diff --git a/sysdeps/l4/hurd/pt-sysdep.c b/sysdeps/l4/hurd/pt-sysdep.c index 265592ca..a05eb0a5 100644 --- a/sysdeps/l4/hurd/pt-sysdep.c +++ b/sysdeps/l4/hurd/pt-sysdep.c @@ -23,6 +23,20 @@ #include +int +sched_yield (void) +{ + l4_yield (); + return 0; +} + +int +sigprocmask (int HOW, const sigset_t *restrict SET, sigset_t *restrict OLDSET) +{ + /* Just ignore for now. */ + return 0; +} + /* Forward. */ static void *init_routine (void); @@ -36,23 +50,15 @@ void *(*_pthread_init_routine)(void) = &init_routine; static void * init_routine (void) { - struct __pthread *thread; - int err; - /* Initialize the library. */ __pthread_initialize (); + struct __pthread *thread; + int err; + /* Create the pthread structure for the main thread (i.e. us). */ err = __pthread_create_internal (&thread, 0, 0, 0); assert_perror (err); - __pthread_initialize (); - - /* Decrease the number of threads, to take into account that the - signal thread (which will be created by the startup code when we - return from here) shouldn't be seen as a user thread. */ -#warning Need to implement the signal thread. - // __pthread_total--; - return (void *) thread->mcontext.sp; } diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h index 0b5abb74..ca2c9015 100644 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -25,8 +25,8 @@ /* XXX */ #define _POSIX_THREAD_THREADS_MAX 64 -/* The default stack size. */ -#define PTHREAD_STACK_DEFAULT 4096 +/* The default stack size: 2MB. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) #define PTHREAD_SYSDEP_MEMBERS \ l4_thread_id_t threadid; \ diff --git a/sysdeps/l4/pt-thread-dealloc.c b/sysdeps/l4/pt-thread-dealloc.c new file mode 100644 index 00000000..c09e4860 --- /dev/null +++ b/sysdeps/l4/pt-thread-dealloc.c @@ -0,0 +1,32 @@ +/* Deallocate the kernel thread resources. L4 version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +void +__pthread_thread_dealloc (struct __pthread *thread) +{ +} diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c index 538d0444..144c58bb 100644 --- a/sysdeps/l4/pt-thread-start.c +++ b/sysdeps/l4/pt-thread-start.c @@ -27,8 +27,8 @@ int __pthread_thread_start (struct __pthread *thread) { - /* The main thread is already running of course. */ if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ { assert (__pthread_total == 1); assert (l4_is_thread_equal (l4_myself (), thread->threadid)); -- cgit v1.2.3 From d438eed871f875dcf4676b83c3d3ae62f32f491a Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Fri, 23 Nov 2007 13:47:05 +0000 Subject: 2007-11-23 Neal H. Walfield * pthread/pt-internal.h (__pthread_startup): Add declaration. * pthread/pt-create.c (entry_point): Call __pthread_startup. * sysdeps/l4/hurd/pt-sysdep.h: Include and . (PTHREAD_SYSDEP_MEMBERS): Add fields object, exception_handler_stack and exception_handler_sp. (__attribute__): Call munmap. * sysdeps/l4/hurd/ia32/pt-setup.c (__pthread_setup): Set up thread->exception_handler_sp. Don't set the user define handle here. * sysdeps/l4/hurd/pt-startup.c: New file. Do it here. * sysdeps/l4/hurd/pt-thread-alloc.c: New file. * sysdeps/l4/hurd/pt-thread-halt.c: New file. * sysdeps/l4/hurd/pt-thread-start.c: New file. * Makefile.am (libpthread_a_SOURCES): Add pt-startup.c. * sysdeps/l4/pt-block.c: Include . (__pthread_block): Detect IPC failure. Add debugging output. * sysdeps/l4/pt-wakeup.c: Include . (__pthread_wakeup): Detect IPC failure. Add debugging output. --- Makefile.am | 1 + pthread/pt-create.c | 2 + pthread/pt-internal.h | 4 ++ sysdeps/l4/hurd/ia32/pt-setup.c | 14 ++++--- sysdeps/l4/hurd/pt-startup.c | 30 ++++++++++++++ sysdeps/l4/hurd/pt-sysdep.h | 10 +++-- sysdeps/l4/hurd/pt-thread-alloc.c | 74 +++++++++++++++++++++++++++++++++ sysdeps/l4/hurd/pt-thread-halt.c | 87 +++++++++++++++++++++++++++++++++++++++ sysdeps/l4/hurd/pt-thread-start.c | 80 +++++++++++++++++++++++++++++++++++ sysdeps/l4/pt-block.c | 17 +++++++- sysdeps/l4/pt-stack-alloc.c | 1 + sysdeps/l4/pt-wakeup.c | 20 ++++++++- 12 files changed, 330 insertions(+), 10 deletions(-) create mode 100644 sysdeps/l4/hurd/pt-startup.c create mode 100644 sysdeps/l4/hurd/pt-thread-alloc.c create mode 100644 sysdeps/l4/hurd/pt-thread-halt.c create mode 100644 sysdeps/l4/hurd/pt-thread-start.c diff --git a/Makefile.am b/Makefile.am index 9249d937..9698b88e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -110,6 +110,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-thread-dealloc.c \ pt-thread-start.c \ pt-thread-halt.c \ + pt-startup.c \ pt-getconcurrency.c pt-setconcurrency.c \ pt-block.c \ pt-timedblock.c \ diff --git a/pthread/pt-create.c b/pthread/pt-create.c index 4f8d043f..5bb9f1f9 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -45,6 +45,8 @@ entry_point (void *(*start_routine)(void *), void *arg) uselocale (LC_GLOBAL_LOCALE); #endif + __pthread_startup (); + pthread_exit (start_routine (arg)); } diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 0dd4e9a8..6d34be13 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -218,6 +218,10 @@ extern void __pthread_thread_halt (struct __pthread *thread, int need_dealloc); +/* Called by a thread just before it calls the provided start + routine. */ +extern void __pthread_startup (void); + /* Block THREAD. */ extern void __pthread_block (struct __pthread *thread); diff --git a/sysdeps/l4/hurd/ia32/pt-setup.c b/sysdeps/l4/hurd/ia32/pt-setup.c index e244dc16..a179bdfd 100644 --- a/sysdeps/l4/hurd/ia32/pt-setup.c +++ b/sysdeps/l4/hurd/ia32/pt-setup.c @@ -63,10 +63,14 @@ __pthread_setup (struct __pthread *thread, thread->mcontext.pc = entry_point; thread->mcontext.sp = stack_setup (thread, start_routine, arg); - if (l4_same_threads (thread->threadid, l4_myself ())) - l4_set_user_defined_handle ((l4_word_t) thread); - else - l4_set_user_defined_handle_of (thread->threadid, - (l4_word_t) thread); + + if (__pthread_num_threads != 1) + { + assert (! ADDR_IS_VOID (thread->exception_handler_stack.addr)); + thread->exception_handler_sp + = ADDR_TO_PTR (addr_extend (thread->exception_handler_stack.addr, + 0, PAGESIZE_LOG2)); + } + return 0; } diff --git a/sysdeps/l4/hurd/pt-startup.c b/sysdeps/l4/hurd/pt-startup.c new file mode 100644 index 00000000..b6461de7 --- /dev/null +++ b/sysdeps/l4/hurd/pt-startup.c @@ -0,0 +1,30 @@ +/* Thread initialization. Hurd/L4 version. + Copyright (C) 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +void +__pthread_startup (void) +{ + struct __pthread *pthread = _pthread_self (); + pthread->threadid = l4_myself (); +} diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h index ca2c9015..1c51731c 100644 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2007 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 @@ -21,6 +21,8 @@ #define _PT_SYSDEP_H 1 #include +#include +#include /* XXX */ #define _POSIX_THREAD_THREADS_MAX 64 @@ -29,7 +31,10 @@ #define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) #define PTHREAD_SYSDEP_MEMBERS \ + struct storage object; \ l4_thread_id_t threadid; \ + struct storage exception_handler_stack; \ + l4_word_t exception_handler_sp; \ l4_word_t my_errno; extern inline struct __pthread * @@ -43,8 +48,7 @@ extern inline void __attribute__((__always_inline__)) __pthread_stack_dealloc (void *stackaddr, size_t stacksize) { - /* XXX: can only implement this once we have a working memory manager. */ - return; + munmap (stackaddr, stacksize); } #endif /* pt-sysdep.h */ diff --git a/sysdeps/l4/hurd/pt-thread-alloc.c b/sysdeps/l4/hurd/pt-thread-alloc.c new file mode 100644 index 00000000..2a421995 --- /dev/null +++ b/sysdeps/l4/hurd/pt-thread-alloc.c @@ -0,0 +1,74 @@ +/* Allocate kernel thread. Hurd/L4 version. + Copyright (C) 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include +#include + +#include + +extern struct hurd_startup_data *__hurd_startup_data; + +extern addr_t meta_data_activity; + +int +__pthread_thread_alloc (struct __pthread *thread) +{ + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + { + thread->object.addr = __hurd_startup_data->thread; + /* If the main thread exits, then we wait. Thus, we don't need + the shadow cap. */ + thread->object.cap = NULL; + thread->threadid = l4_myself (); + return 0; + } + else + { + struct storage storage; + + /* We can't don't use mmap as when the exception thread starts + running and it accesses its stack, it will fault, which we + naturally cannot handle. */ + storage = storage_alloc (ADDR_VOID, cap_page, + STORAGE_UNKNOWN, ADDR_VOID); + if (ADDR_IS_VOID (storage.addr)) + return EAGAIN; + + thread->exception_handler_stack = storage; + + + storage = storage_alloc (meta_data_activity, cap_thread, + /* Threads are rarely shortly lived. */ + STORAGE_MEDIUM_LIVED, ADDR_VOID); + if (ADDR_IS_VOID (storage.addr)) + { + storage_free (thread->exception_handler_stack.addr, false); + return EAGAIN; + } + + thread->object = storage; + } + + return 0; +} diff --git a/sysdeps/l4/hurd/pt-thread-halt.c b/sysdeps/l4/hurd/pt-thread-halt.c new file mode 100644 index 00000000..c6ae76f5 --- /dev/null +++ b/sysdeps/l4/hurd/pt-thread-halt.c @@ -0,0 +1,87 @@ +/* Deallocate the kernel thread resources. L4/Hurd version. + Copyright (C) 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* If we try to deallocate our self, we will end up causing a + deadlock. Thus, when a thread tries to free itself, we add it + here. The next thread to free a thread will free it. */ +static struct storage saved_object; + +void +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +{ + struct storage exception_handler_stack = thread->exception_handler_stack; + thread->exception_handler_stack.addr = ADDR_VOID; + + struct storage object = thread->object; + l4_thread_id_t tid = thread->threadid; + + if (need_dealloc) + __pthread_dealloc (thread); + + if (! ADDR_IS_VOID (saved_object.addr)) + { + storage_free (saved_object.addr, false); + saved_object.cap->type = cap_void; + saved_object.addr = ADDR_VOID; + } + + /* Stop the exception handler thread. */ + l4_word_t dummy = 0; + error_t err = rm_thread_exregs (ADDR_VOID, object.addr, + HURD_EXREGS_EXCEPTION_THREAD + | HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC, + ADDR_VOID, + 0, (struct cap_addr_trans) CAP_ADDR_TRANS_VOID, + ADDR_VOID, + 0, 0, 0, 0, + ADDR_VOID, ADDR_VOID, + &dummy, &dummy, &dummy, &dummy); + if (err) + panic ("Error stopping exception thread."); + + /* Free its stack. */ + assert (! ADDR_IS_VOID (exception_handler_stack.addr)); + storage_free (exception_handler_stack.addr, false); + exception_handler_stack.addr = ADDR_VOID; + + if (tid == l4_myself ()) + /* If we try to storage_free (storage.addr), we will freeze in the + middle. That's no good. Thus, we add ourself to the pool of + available objects. */ + saved_object = object; + else + { + storage_free (object.addr, false); + object.cap->type = cap_void; + } + + if (tid == l4_myself ()) + { + l4_send_timeout (l4_myself (), L4_NEVER); + panic ("Failed to stop thread %x.%x!", + l4_thread_no (l4_myself ()), l4_version (l4_myself ())); + } + else + thread_stop (object.addr); +} diff --git a/sysdeps/l4/hurd/pt-thread-start.c b/sysdeps/l4/hurd/pt-thread-start.c new file mode 100644 index 00000000..ae5dfa8c --- /dev/null +++ b/sysdeps/l4/hurd/pt-thread-start.c @@ -0,0 +1,80 @@ +/* Start thread. L4 version. + Copyright (C) 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#include + +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ + { + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); + l4_set_user_defined_handle_of (hurd_exception_thread (l4_myself ()), + (l4_word_t) thread); + l4_set_user_defined_handle ((l4_word_t) thread); + } + else + { + struct cap_addr_trans addr_trans = CAP_ADDR_TRANS_VOID; + + /* First, start the exception thread. */ + l4_word_t dummy; + err = rm_thread_exregs (ADDR_VOID, thread->object.addr, + HURD_EXREGS_EXCEPTION_THREAD + | HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_SET_USER_HANDLE + | HURD_EXREGS_START + | HURD_EXREGS_ABORT_IPC, + ADDR_VOID, 0, addr_trans, ADDR_VOID, + (l4_word_t) thread->exception_handler_sp, + (l4_word_t) exception_handler_loop, 0, + thread, + ADDR_VOID, ADDR_VOID, + &dummy, &dummy, &dummy, &dummy); + assert (err == 0); + + err = rm_thread_exregs (ADDR_VOID, thread->object.addr, + HURD_EXREGS_SET_ASPACE + | HURD_EXREGS_SET_ACTIVITY + | HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_SET_USER_HANDLE + | HURD_EXREGS_START + | HURD_EXREGS_ABORT_IPC, + ADDR (0, 0), + CAP_COPY_COPY_SOURCE_GUARD, addr_trans, + ADDR_VOID, + (l4_word_t) thread->mcontext.sp, + (l4_word_t) thread->mcontext.pc, 0, + thread, + ADDR_VOID, ADDR_VOID, + &dummy, &dummy, &dummy, &dummy); + assert (err == 0); + } + return 0; +} diff --git a/sysdeps/l4/pt-block.c b/sysdeps/l4/pt-block.c index 933cc285..df3fe85b 100644 --- a/sysdeps/l4/pt-block.c +++ b/sysdeps/l4/pt-block.c @@ -21,9 +21,24 @@ #include +#include + /* Block THREAD. */ void __pthread_block (struct __pthread *thread) { - L4_Receive (L4_anylocalthread); + debug (5, "%x.%x blocking", + l4_thread_no (thread->threadid), l4_version (thread->threadid)); + + l4_msg_tag_t tag = l4_receive (l4_anythread); + if (l4_ipc_failed (tag)) + { + int err = l4_error_code (); + debug (1, "%x.%x failed to block: %s (%d)", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_strerror (err), err); + } + else + debug (5, "%x.%x unblocked", + l4_thread_no (thread->threadid), l4_version (thread->threadid)); } diff --git a/sysdeps/l4/pt-stack-alloc.c b/sysdeps/l4/pt-stack-alloc.c index 2ede58fd..b7ec12b4 100644 --- a/sysdeps/l4/pt-stack-alloc.c +++ b/sysdeps/l4/pt-stack-alloc.c @@ -38,5 +38,6 @@ __pthread_stack_alloc (void **stackaddr, size_t stacksize) return EAGAIN; *stackaddr = buffer; + return 0; } diff --git a/sysdeps/l4/pt-wakeup.c b/sysdeps/l4/pt-wakeup.c index 342a2204..7ecc938d 100644 --- a/sysdeps/l4/pt-wakeup.c +++ b/sysdeps/l4/pt-wakeup.c @@ -21,9 +21,27 @@ #include +#include + /* Wakeup THREAD. */ void __pthread_wakeup (struct __pthread *thread) { - l4_send (thread->threadid); + debug (5, "%x.%x waking %x.%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid)); + + l4_msg_tag_t tag = l4_send (thread->threadid); + if (l4_ipc_failed (tag)) + { + int err = l4_error_code (); + debug (1, "%x.%x failed to wake %x.%x: %s (%d)", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + l4_strerror (err), err); + } + else + debug (5, "%x.%x woke %x.%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid)); } -- cgit v1.2.3 From 5be781e6a2096dc2011720156c31790b8fac0df6 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 4 Dec 2007 18:12:22 +0000 Subject: viengoos/ 2007-12-04 Neal H. Walfield Remove exception threads. Replace with support for activations. * thread.h (THREAD_SLOTS): Bump to 3. (struct thread): Add field exception_page. Remove fields have_exception and exception. (thread_exregs): Take additional arguments exception_page and exception_page_out. Update users. (thread_raise_exception): New declaration. * thread.c (THREAD_VERSION): Define. (thread_init): Remove code related to the exception thread. (thread_commission): Likewise. (thread_decommission): Likewise. (thread_exregs): Likewise. Take additional arguments EXCEPTION_PAGE and EXCEPTION_PAGE_OUT. If CONTROL contains HURD_EXREGS_GET_REGS and EXCEPTION_PAGE_OUT is not NULL, return a capability to THREAD's exception page in *EXCEPTION_PAGE_OUT. If CONTROL contains HURD_EXREGS_SET_EXCEPTION_PAGE, then set THREAD's exception page to EXCEPTION_PAGE. (thread_raise_exception): New function. * server.c (server_loop): Remove code related to handling the exception thread. Call thread_raise_exception to propagate exception. Reimplement the exception_collect method. Update implementation of the thread_exregs method to support the new argument passing scheme. Add support for setting and retrieving the exception page. (REPLYW): Only clear MSG here. * rm.h (exception_collect): Take an additional argument, the principal. * object.h (object_type): New function. hurd/ 2007-12-04 Neal H. Walfield Remove exception threads. Replace with support for activations. * thread.h: Include . (struct exception_page): New structure. (THREAD_EXCEPTION_PAGE_SLOT): Define. (HURD_EXREGS_EXCEPTION_THREAD): Don't define. (HURD_EXREGS_SET_EXCEPTION_PAGE): Define. (HURD_EXREGS_SET_REGS): Update. (hurd_exception_handler_t): New definition. (struct hurd_thread_exregs_in): New structure. (struct hurd_thread_exregs_out): New structure. (thread_exregs): Replace the bulk of the arguments with struct hurd_thread_exregs_in and struct hurd_thread_exregs_out. Update users. * exceptions.h (HURD_THREAD_MAIN_VERSION): Remove macro. (HURD_THREAD_EXCEPTION_VERSION): Likewise. (hurd_thread_is_exception_thread): Remove function. (hurd_thread_is_main_thread): Likewise. (hurd_exception_thread): Likewise. (hurd_main_thread): Likewise. (exception_handler_loop): Remove declaration. (exception_handler): New declaration. (exception_handler_entry): Likewise. (exception_handler_end): Likewise. libhurd-mm/ 2007-12-04 Neal H. Walfield Remove exception threads. Replace with support for activations. * Makefile.am (ARCH_SOURCES): New variable. [ARCH_IA32]: Add ia32-exception-entry.S. (libhurd_mm_a_SOURCES): Add $(ARCH_SOURCES). * ia32-exception-entry.S: New file. * exceptions.c: Include and . (ARG): Don't define. (ARG64): Likewise. (ARG_ADDR): Likewise. (CHECK): Likewise. (exception_handler_loop): Remove function. (exception_fetch_exception): New function. (exception_handler): New function. (STACK_SIZE): Don't define. (stack): Don't declare. (exception_handler_init): Set up the thread's exception page. libpthread/ 2007-12-04 Neal H. Walfield Remove exception threads. Replace with support for activations. * sysdeps/l4/hurd/pt-sysdep.h (PTHREAD_SYSDEP_MEMBERS): Remove fields exception_handler_stack and exception_handler_sp. Add field exception_page. * sysdeps/l4/hurd/pt-thread-alloc.c (__pthread_thread_alloc): Allocate a page for THREAD->EXCEPTION_PAGE, not THREAD->EXCEPTION_HANDLER_STACK. * sysdeps/l4/hurd/ia32/pt-setup.c: Include and . (__pthread_setup): Remove code dealing with the exception thread. Set up the exception page. * sysdeps/l4/hurd/pt-thread-start.c (__pthread_thread_start): Remove code dealing with the exception thread. Update to use new rm_thread_exregs interface. Also set the thread's exception page. * sysdeps/l4/hurd/pt-thread-halt.c (__pthread_thread_halt): Remove code to dealing with the exception thread. Free the THREAD->EXCEPTION_PAGE. ruth/ 2007-12-04 Neal H. Walfield * ruth.c (main): Update to use new rm_thread_exregs interface. --- sysdeps/l4/hurd/ia32/pt-setup.c | 22 ++++++++++++++------- sysdeps/l4/hurd/pt-sysdep.h | 3 +-- sysdeps/l4/hurd/pt-thread-alloc.c | 4 ++-- sysdeps/l4/hurd/pt-thread-halt.c | 25 +++++------------------- sysdeps/l4/hurd/pt-thread-start.c | 41 ++++++++++++++------------------------- 5 files changed, 38 insertions(+), 57 deletions(-) diff --git a/sysdeps/l4/hurd/ia32/pt-setup.c b/sysdeps/l4/hurd/ia32/pt-setup.c index a179bdfd..800d5b1b 100644 --- a/sysdeps/l4/hurd/ia32/pt-setup.c +++ b/sysdeps/l4/hurd/ia32/pt-setup.c @@ -20,6 +20,8 @@ #include #include +#include +#include /* The stack layout used on the i386 is: @@ -63,14 +65,20 @@ __pthread_setup (struct __pthread *thread, thread->mcontext.pc = entry_point; thread->mcontext.sp = stack_setup (thread, start_routine, arg); + if (__pthread_num_threads == 1) + return 0; - if (__pthread_num_threads != 1) - { - assert (! ADDR_IS_VOID (thread->exception_handler_stack.addr)); - thread->exception_handler_sp - = ADDR_TO_PTR (addr_extend (thread->exception_handler_stack.addr, - 0, PAGESIZE_LOG2)); - } + assert (! ADDR_IS_VOID (thread->exception_page.addr)); + + struct exception_page *exception_page + = ADDR_TO_PTR (addr_extend (thread->exception_page.addr, + 0, PAGESIZE_LOG2)); + + /* SP is set to the end of the exception page. */ + exception_page->exception_handler_sp = (l4_word_t) exception_page + PAGESIZE; + + exception_page->exception_handler_ip = (l4_word_t) &exception_handler_entry; + exception_page->exception_handler_end = (l4_word_t) &exception_handler_end; return 0; } diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h index 1c51731c..5c66330e 100644 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -33,8 +33,7 @@ #define PTHREAD_SYSDEP_MEMBERS \ struct storage object; \ l4_thread_id_t threadid; \ - struct storage exception_handler_stack; \ - l4_word_t exception_handler_sp; \ + struct storage exception_page; \ l4_word_t my_errno; extern inline struct __pthread * diff --git a/sysdeps/l4/hurd/pt-thread-alloc.c b/sysdeps/l4/hurd/pt-thread-alloc.c index 2a421995..9e2bc2a3 100644 --- a/sysdeps/l4/hurd/pt-thread-alloc.c +++ b/sysdeps/l4/hurd/pt-thread-alloc.c @@ -55,7 +55,7 @@ __pthread_thread_alloc (struct __pthread *thread) if (ADDR_IS_VOID (storage.addr)) return EAGAIN; - thread->exception_handler_stack = storage; + thread->exception_page = storage; storage = storage_alloc (meta_data_activity, cap_thread, @@ -63,7 +63,7 @@ __pthread_thread_alloc (struct __pthread *thread) STORAGE_MEDIUM_LIVED, ADDR_VOID); if (ADDR_IS_VOID (storage.addr)) { - storage_free (thread->exception_handler_stack.addr, false); + storage_free (thread->exception_page.addr, false); return EAGAIN; } diff --git a/sysdeps/l4/hurd/pt-thread-halt.c b/sysdeps/l4/hurd/pt-thread-halt.c index c6ae76f5..4aa112b1 100644 --- a/sysdeps/l4/hurd/pt-thread-halt.c +++ b/sysdeps/l4/hurd/pt-thread-halt.c @@ -30,8 +30,8 @@ static struct storage saved_object; void __pthread_thread_halt (struct __pthread *thread, int need_dealloc) { - struct storage exception_handler_stack = thread->exception_handler_stack; - thread->exception_handler_stack.addr = ADDR_VOID; + struct storage exception_page = thread->exception_page; + thread->exception_page.addr = ADDR_VOID; struct storage object = thread->object; l4_thread_id_t tid = thread->threadid; @@ -46,24 +46,9 @@ __pthread_thread_halt (struct __pthread *thread, int need_dealloc) saved_object.addr = ADDR_VOID; } - /* Stop the exception handler thread. */ - l4_word_t dummy = 0; - error_t err = rm_thread_exregs (ADDR_VOID, object.addr, - HURD_EXREGS_EXCEPTION_THREAD - | HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC, - ADDR_VOID, - 0, (struct cap_addr_trans) CAP_ADDR_TRANS_VOID, - ADDR_VOID, - 0, 0, 0, 0, - ADDR_VOID, ADDR_VOID, - &dummy, &dummy, &dummy, &dummy); - if (err) - panic ("Error stopping exception thread."); - - /* Free its stack. */ - assert (! ADDR_IS_VOID (exception_handler_stack.addr)); - storage_free (exception_handler_stack.addr, false); - exception_handler_stack.addr = ADDR_VOID; + /* Free the exception page. */ + assert (! ADDR_IS_VOID (exception_page.addr)); + storage_free (exception_page.addr, false); if (tid == l4_myself ()) /* If we try to storage_free (storage.addr), we will freeze in the diff --git a/sysdeps/l4/hurd/pt-thread-start.c b/sysdeps/l4/hurd/pt-thread-start.c index ae5dfa8c..f2d7ef59 100644 --- a/sysdeps/l4/hurd/pt-thread-start.c +++ b/sysdeps/l4/hurd/pt-thread-start.c @@ -35,45 +35,34 @@ __pthread_thread_start (struct __pthread *thread) { assert (__pthread_total == 1); assert (l4_is_thread_equal (l4_myself (), thread->threadid)); - l4_set_user_defined_handle_of (hurd_exception_thread (l4_myself ()), - (l4_word_t) thread); l4_set_user_defined_handle ((l4_word_t) thread); } else { - struct cap_addr_trans addr_trans = CAP_ADDR_TRANS_VOID; + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; - /* First, start the exception thread. */ - l4_word_t dummy; - err = rm_thread_exregs (ADDR_VOID, thread->object.addr, - HURD_EXREGS_EXCEPTION_THREAD - | HURD_EXREGS_SET_SP_IP - | HURD_EXREGS_SET_USER_HANDLE - | HURD_EXREGS_START - | HURD_EXREGS_ABORT_IPC, - ADDR_VOID, 0, addr_trans, ADDR_VOID, - (l4_word_t) thread->exception_handler_sp, - (l4_word_t) exception_handler_loop, 0, - thread, - ADDR_VOID, ADDR_VOID, - &dummy, &dummy, &dummy, &dummy); - assert (err == 0); + in.aspace = ADDR (0, 0); + in.aspace_addr_trans = CAP_ADDR_TRANS_VOID; + in.aspace_addr_trans_flags = CAP_COPY_COPY_SOURCE_GUARD; + + in.activity = ADDR_VOID; + + in.exception_page = thread->exception_page.addr; + + in.sp = (l4_word_t) thread->mcontext.sp; + in.ip = (l4_word_t) thread->mcontext.pc; + in.user_handle = (l4_word_t) thread; err = rm_thread_exregs (ADDR_VOID, thread->object.addr, HURD_EXREGS_SET_ASPACE | HURD_EXREGS_SET_ACTIVITY + | HURD_EXREGS_SET_EXCEPTION_PAGE | HURD_EXREGS_SET_SP_IP | HURD_EXREGS_SET_USER_HANDLE | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, - ADDR (0, 0), - CAP_COPY_COPY_SOURCE_GUARD, addr_trans, - ADDR_VOID, - (l4_word_t) thread->mcontext.sp, - (l4_word_t) thread->mcontext.pc, 0, - thread, - ADDR_VOID, ADDR_VOID, - &dummy, &dummy, &dummy, &dummy); + in, &out); assert (err == 0); } return 0; -- cgit v1.2.3 From b2412b7fe5c3b001fc5507f10471d343e530cf8e Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 12 Dec 2007 16:33:37 +0000 Subject: 2007-12-12 Neal H. Walfield * sysdeps/l4/pt-block.c (__pthread_block): Clear the acceptor. Improve debugging output. * sysdeps/l4/pt-wakeup.c (__pthread_wakeup): Load an empty message. Improve debugging output. --- sysdeps/l4/pt-block.c | 12 ++++++++---- sysdeps/l4/pt-wakeup.c | 13 ++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/sysdeps/l4/pt-block.c b/sysdeps/l4/pt-block.c index df3fe85b..e92ce91c 100644 --- a/sysdeps/l4/pt-block.c +++ b/sysdeps/l4/pt-block.c @@ -27,16 +27,20 @@ void __pthread_block (struct __pthread *thread) { - debug (5, "%x.%x blocking", - l4_thread_no (thread->threadid), l4_version (thread->threadid)); + debug (5, "%x.%x/%x blocking", + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + l4_accept (L4_UNTYPED_WORDS_ACCEPTOR); l4_msg_tag_t tag = l4_receive (l4_anythread); if (l4_ipc_failed (tag)) { int err = l4_error_code (); - debug (1, "%x.%x failed to block: %s (%d)", + debug (1, "%x.%x failed to block: %d, offset: %x", l4_thread_no (l4_myself ()), l4_version (l4_myself ()), - l4_strerror (err), err); + (l4_error_code () >> 1) & 0x7, + l4_error_code () >> 4); + assert (! l4_ipc_failed (tag)); } else debug (5, "%x.%x unblocked", diff --git a/sysdeps/l4/pt-wakeup.c b/sysdeps/l4/pt-wakeup.c index 7ecc938d..de378465 100644 --- a/sysdeps/l4/pt-wakeup.c +++ b/sysdeps/l4/pt-wakeup.c @@ -27,9 +27,16 @@ void __pthread_wakeup (struct __pthread *thread) { - debug (5, "%x.%x waking %x.%x", - l4_thread_no (l4_myself ()), l4_version (l4_myself ()), - l4_thread_no (thread->threadid), l4_version (thread->threadid)); + debug (5, "%x.%x/%x waking %x.%x/%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), l4_myself (), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + + /* Signal the waiter. */ + l4_msg_t msg; + l4_msg_clear (msg); + l4_msg_set_untyped_words (msg, 0); + l4_msg_load (msg); l4_msg_tag_t tag = l4_send (thread->threadid); if (l4_ipc_failed (tag)) -- cgit v1.2.3 From 7d83f98545fac33bcdb6e42914da1d9f2548d522 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 12 Dec 2007 23:32:52 +0000 Subject: hurd/ 2007-12-13 Neal H. Walfield * exceptions.h (exception_page_cleanup): New declaration. libhurd-mm/ 2007-12-13 Neal H. Walfield * exceptions.c (exception_frame_alloc): When allocating the first frame, set EXCEPTION_PAGE->EXCEPTION_STACK_BOTTOM. (exception_page_cleanup): New function. * ia32-exception-entry.S (_exception_handler_end): Correctly adjust the exception page's exception stack. libpthread/ 2007-12-13 Neal H. Walfield * sysdeps/l4/hurd/pt-thread-halt.c: Include . (__pthread_thread_halt): Call exception_page_cleanup. --- sysdeps/l4/hurd/pt-thread-halt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sysdeps/l4/hurd/pt-thread-halt.c b/sysdeps/l4/hurd/pt-thread-halt.c index 4aa112b1..1e9a8ee6 100644 --- a/sysdeps/l4/hurd/pt-thread-halt.c +++ b/sysdeps/l4/hurd/pt-thread-halt.c @@ -22,6 +22,8 @@ #include +#include + /* If we try to deallocate our self, we will end up causing a deadlock. Thus, when a thread tries to free itself, we add it here. The next thread to free a thread will free it. */ @@ -48,6 +50,8 @@ __pthread_thread_halt (struct __pthread *thread, int need_dealloc) /* Free the exception page. */ assert (! ADDR_IS_VOID (exception_page.addr)); + exception_page_cleanup (ADDR_TO_PTR (addr_extend (exception_page.addr, + 0, PAGESIZE_LOG2))); storage_free (exception_page.addr, false); if (tid == l4_myself ()) -- cgit v1.2.3 From b9ef8522bdb2b64bb5c5c73afe3dd17ba74e9d72 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sun, 23 Dec 2007 14:39:42 +0000 Subject: 2007-12-23 Neal H. Walfield * Makefile.am (AM_CPPFLAGS): Add "-std=gnu99 -Wall -g -O3". * sysdeps/l4/pt-block.c (__pthread_block): Remove unused variable err. * pthread/pt-join.c (pthread_join): Cast argument to pthread_cleanup_push to avoid warning. --- Makefile.am | 3 ++- pthread/pt-join.c | 3 ++- sysdeps/l4/hurd/pt-thread-start.c | 4 ++-- sysdeps/l4/pt-block.c | 1 - 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9698b88e..0b7a3750 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,7 +38,8 @@ SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ $(srcdir)/include vpath %.c $(SYSDEP_PATH) -AM_CPPFLAGS = -I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ +AM_CPPFLAGS = -std=gnu99 -Wall -g -O3 \ + -I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ -I$(top_srcdir)/libc-parts $(addprefix -I, $(SYSDEP_PATH)) \ -imacros $(srcdir)/include/libc-symbols.h diff --git a/pthread/pt-join.c b/pthread/pt-join.c index 698b6c9f..06e9f1f7 100644 --- a/pthread/pt-join.c +++ b/pthread/pt-join.c @@ -37,7 +37,8 @@ pthread_join (pthread_t thread, void **status) return ESRCH; __pthread_mutex_lock (&pthread->state_lock); - pthread_cleanup_push (__pthread_mutex_unlock, &pthread->state_lock); + pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock, + &pthread->state_lock); while (pthread->state == PTHREAD_JOINABLE) pthread_cond_wait (&pthread->state_cond, &pthread->state_lock); diff --git a/sysdeps/l4/hurd/pt-thread-start.c b/sysdeps/l4/hurd/pt-thread-start.c index f2d7ef59..131f59d6 100644 --- a/sysdeps/l4/hurd/pt-thread-start.c +++ b/sysdeps/l4/hurd/pt-thread-start.c @@ -43,8 +43,8 @@ __pthread_thread_start (struct __pthread *thread) struct hurd_thread_exregs_out out; in.aspace = ADDR (0, 0); - in.aspace_addr_trans = CAP_ADDR_TRANS_VOID; - in.aspace_addr_trans_flags = CAP_COPY_COPY_SOURCE_GUARD; + in.aspace_cap_properties = CAP_PROPERTIES_VOID; + in.aspace_cap_properties_flags = CAP_COPY_COPY_SOURCE_GUARD; in.activity = ADDR_VOID; diff --git a/sysdeps/l4/pt-block.c b/sysdeps/l4/pt-block.c index e92ce91c..69e1d358 100644 --- a/sysdeps/l4/pt-block.c +++ b/sysdeps/l4/pt-block.c @@ -35,7 +35,6 @@ __pthread_block (struct __pthread *thread) l4_msg_tag_t tag = l4_receive (l4_anythread); if (l4_ipc_failed (tag)) { - int err = l4_error_code (); debug (1, "%x.%x failed to block: %d, offset: %x", l4_thread_no (l4_myself ()), l4_version (l4_myself ()), (l4_error_code () >> 1) & 0x7, -- cgit v1.2.3 From b2fa14a54917b7f7d232688a37cc33b46ff9134e Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 1 Jan 2008 17:42:41 +0000 Subject: 2008-01-01 Neal H. Walfield * sysdeps/generic/pt-mutex-timedlock.c (__pthread_mutex_timedlock_internal): Add additional asserts. [! NDEBUG]: Keep MUTEX->OWNER up to date. * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock): Add additional asserts. [! NDEBUG]: Keep MUTEX->OWNER up to date. * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): Add additional asserts. [! NDEBUG]: Keep MUTEX->OWNER up to date. --- sysdeps/generic/pt-mutex-timedlock.c | 31 ++++++++++++++++++++++++++----- sysdeps/generic/pt-mutex-trylock.c | 14 +++++++++++++- sysdeps/generic/pt-mutex-unlock.c | 19 ++++++++++++++----- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index 5e222bd3..6db30c5d 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -1,5 +1,5 @@ /* Lock a mutex with a timeout. Generic version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2008 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 @@ -36,6 +36,18 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, if (__pthread_spin_trylock (&mutex->__held) == 0) /* Successfully acquired the lock. */ { +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif + if (mutex->attr) switch (mutex->attr->mutex_type) { @@ -59,12 +71,14 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, /* The lock is busy. */ self = _pthread_self (); + assert (self); if (mutex->attr) { switch (mutex->attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: + assert (mutex->owner != self); break; case PTHREAD_MUTEX_ERRORCHECK: @@ -88,6 +102,10 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, LOSE; } } + else + assert (mutex->owner != self); + + assert (mutex->owner); if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) return EINVAL; @@ -123,12 +141,15 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, else __pthread_block (self); - if (mutex->attr) + if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#ifndef NDEBUG + mutex->owner = self; +#endif + } + else switch (mutex->attr->mutex_type) { - case PTHREAD_MUTEX_NORMAL: - break; - case PTHREAD_MUTEX_RECURSIVE: assert (mutex->locks == 0); mutex->locks = 1; diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index d56f6e1c..5264dc7b 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -1,5 +1,5 @@ /* Try to Lock a mutex. Generic version. - Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2008 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 @@ -34,6 +34,18 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) if (__pthread_spin_trylock (&mutex->__held) == 0) /* Acquired the lock. */ { +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif + if (mutex->attr) switch (mutex->attr->mutex_type) { diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index 2f719d3e..a9872252 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -1,5 +1,5 @@ /* Unlock a mutex. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 @@ -31,12 +31,20 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) __pthread_spin_lock (&mutex->__lock); - if (mutex->attr) + if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#ifndef NDEBUG + if (_pthread_self ()) + { + assert (mutex->owner); + assert (mutex->owner == _pthread_self ()); + mutex->owner = NULL; + } +#endif + } + else switch (mutex->attr->mutex_type) { - case PTHREAD_MUTEX_NORMAL: - break; - case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_RECURSIVE: if (mutex->owner != _pthread_self ()) @@ -59,6 +67,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) LOSE; } + if (mutex->__queue == NULL) { __pthread_spin_unlock (&mutex->__held); -- cgit v1.2.3 From 05806c391ae537d445860d1154533731584ec206 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 17 Jan 2008 01:12:44 +0000 Subject: 2008-01-17 Neal H. Walfield * sysdeps/l4/hurd/pt-block.c: New file. * sysdeps/l4/hurd/pt-wakeup.c: Likewise. --- sysdeps/l4/hurd/pt-block.c | 30 ++++++++++++++++++++++++++++++ sysdeps/l4/hurd/pt-wakeup.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 sysdeps/l4/hurd/pt-block.c create mode 100644 sysdeps/l4/hurd/pt-wakeup.c diff --git a/sysdeps/l4/hurd/pt-block.c b/sysdeps/l4/hurd/pt-block.c new file mode 100644 index 00000000..2315b1c4 --- /dev/null +++ b/sysdeps/l4/hurd/pt-block.c @@ -0,0 +1,30 @@ +/* Block a thread. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + futex_wait (&thread->threadid, thread->threadid); +} diff --git a/sysdeps/l4/hurd/pt-wakeup.c b/sysdeps/l4/hurd/pt-wakeup.c new file mode 100644 index 00000000..2225cca0 --- /dev/null +++ b/sysdeps/l4/hurd/pt-wakeup.c @@ -0,0 +1,32 @@ +/* Wakeup a thread. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + long ret = futex_wake (&thread->threadid, INT_MAX); + assert (ret == 1); +} -- cgit v1.2.3 From d4147bbd4fdb997e4e370507dbc0cd9367864e22 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 23 Jan 2008 14:06:03 +0000 Subject: libpthread/ 2008-01-23 Neal H. Walfield * Makefile.am (AM_CPPFLAGS): Add -I$(LIBC)/include. libhurd-slab/ 2008-01-23 Neal H. Walfield * Makefile.am (AM_CPPFLAGS): Add -I$(LIBC)/include. libhurd-mm/ 2008-01-23 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Add -I$(LIBC)/include. libhurd-ihash/ 2008-01-23 Neal H. Walfield * Makefile.am (AM_CPPFLAGS): Add -I$(LIBC)/include. ruth/ 2008-01-23 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Add -I$(LIBC)/include. (ruth_SOURCES): Remove malloc-wrap.c, output.h and output.c. (ruth_LDADD): Set to $(top_builddir)/libc.a. * panic.c: Don't include "output.h". Include . * ruth.h: Likewise. * ruth.c (getpagesize): Return a size_t, not an int. --- Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0b7a3750..d9cc4239 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ # Makefile.am - Makefile template for libpthread. -# Copyright (C) 2003 Free Software Foundation, Inc. +# Copyright (C) 2003, 2008 Free Software Foundation, Inc. # # This file is part of the GNU Hurd. # @@ -38,10 +38,10 @@ SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ $(srcdir)/include vpath %.c $(SYSDEP_PATH) -AM_CPPFLAGS = -std=gnu99 -Wall -g -O3 \ - -I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ - -I$(top_srcdir)/libc-parts $(addprefix -I, $(SYSDEP_PATH)) \ - -imacros $(srcdir)/include/libc-symbols.h +AM_CPPFLAGS = -std=gnu99 -Wall -g -O3 -I$(LIBC)/include \ +-I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ +-I$(top_srcdir)/libc-parts $(addprefix -I, $(SYSDEP_PATH)) -imacros \ +$(srcdir)/include/libc-symbols.h # Sources. SYSDEPS := lockfile.c -- cgit v1.2.3 From fda6f4190a3429d588e46e4931764a971f567375 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Fri, 8 Feb 2008 10:01:41 +0000 Subject: libhurd-ihash/ 2008-02-08 Neal H. Walfield * ihash.h: Include . (hurd_ihash_key64_t): New definition. (struct _hurd_ihash_item64): New structure. (struct hurd_ihash): Change items's type void *. [__WORDSIZE == 32]: Add field large. (_HURD_IHASH_LARGE): New macro. (HURD_IHASH_INITIALIZER): Take additional argument large. Use it. (hurd_ihash_init): Take additional argument large. (hurd_ihash_buffer_size): Likewise. (hurd_ihash_init_with_buffer): Likewise. (hurd_ihash_create): Likewise. (hurd_ihash_replace): Change key's type to hurd_ihash_key64_t. (hurd_ihash_add): Likewise. (hurd_ihash_find): Likewise. (hurd_ihash_remove): Likewise. (HURD_IHASH_ITERATE): Rewrite to properly handle both 32- and 64-bit keys. * ihash.c (ITEM): New macro. (VALUE): Likewise. (KEY): Likewise. (ITEM_SIZE): Likewise. (index_empty): Use the above macros rather than accessing HT->ITEMS directly. (index_valid): Likewise and change key's type to a hurd_ihash_key64_t. (find_index): Likewise. (replace_one): Likewise. (hurd_ihash_replace): Likewise. (hurd_ihash_find): Likewise. (hurd_ihash_remove): Likewise. (hurd_ihash_init_internal): Take additional argument large. Use it. (hurd_ihash_init): Likewise. (hurd_ihash_init_with_buffer): Likewise. (hurd_ihash_create): Likewise. (hurd_ihash_buffer_size): Likewise. * t-ihash.c: Include . (main): Expect that TEST_LARGE is defined. Use it when calling hurd_ihash_init. If true, add some tests with 64-bit keys. * Makefile.am (TESTS): Add t-ihash64. (check_PROGRAMS): Likewise. (t_ihash_CPPFLAGS): Add -DTEST_LARGE=false. (t_ihash64_SOURCES): New variable. (t_ihash64_CPPFLAGS): Likewise. viengoos/ 2008-02-08 Neal H. Walfield * thread.c (thread_init): Update use of hurd_ihash_init_with_buffer to be consistent with new API. * object.c (object_init): Likewise. libpthread/ 2008-02-08 Neal H. Walfield * sysdeps/hurd/pt-setspecific.c (pthread_setspecific): Update use of hurd_ihash_create to be consistent with API changes. --- sysdeps/hurd/pt-setspecific.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sysdeps/hurd/pt-setspecific.c b/sysdeps/hurd/pt-setspecific.c index 89ca4d7f..d2d1157c 100644 --- a/sysdeps/hurd/pt-setspecific.c +++ b/sysdeps/hurd/pt-setspecific.c @@ -1,5 +1,5 @@ /* pthread_setspecific. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 @@ -30,7 +30,8 @@ pthread_setspecific (pthread_key_t key, const void *value) if (! self->thread_specifics) { - err = hurd_ihash_create (&self->thread_specifics, HURD_IHASH_NO_LOCP); + err = hurd_ihash_create (&self->thread_specifics, false, + HURD_IHASH_NO_LOCP); if (err) return ENOMEM; } -- cgit v1.2.3 From 8c337b1f1366ee29dbab6f1ce531957a4674b00c Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 11 Feb 2008 17:19:59 +0000 Subject: 2008-02-11 Neal H. Walfield * sysdeps/l4/hurd/ia32/pt-setup.c (_pthread_entry_point): New assembly function. (stack_setup): Take additional argument entry_point. Push it on the stack. (__pthread_setup): Set thread->mcontext.pc to &_pthread_entry_point. Pass ENTRY_POINT to stack_setup. --- sysdeps/l4/hurd/ia32/pt-setup.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/sysdeps/l4/hurd/ia32/pt-setup.c b/sysdeps/l4/hurd/ia32/pt-setup.c index 800d5b1b..9a3812fd 100644 --- a/sysdeps/l4/hurd/ia32/pt-setup.c +++ b/sysdeps/l4/hurd/ia32/pt-setup.c @@ -1,5 +1,5 @@ /* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 @@ -30,8 +30,33 @@ ----------------- | START_ROUTINE | ----------------- - | 0 | - ----------------- */ + | Return address | + ----------------- <- %ebp + | Frame pointer | + ----------------- + + We do the following: setup the stack to return to the entry routine. + + +*/ + +/* The stack contains: + + arg + start_routine + 0 <- fake return address + C entry_point +*/ +extern uintptr_t _pthread_entry_point; +__asm__ ("\t\n\ + .globl _pthread_entry_point, __pthread_entry_point\t\n\ +_pthread_entry_point:\t\n\ +__pthread_entry_point:\t\n\ + pushl $0\t\n\ + popf\t\n\ +\t\n\ + xor %ebp, %ebp\t\n\ + ret\t\n"); /* Set up the stack for THREAD, such that it appears as if START_ROUTINE and ARG were passed to the new thread's entry-point. @@ -39,7 +64,8 @@ opportunity to install THREAD in our utcb. */ static void * stack_setup (struct __pthread *thread, - void *(*start_routine)(void *), void *arg) + void *(*start_routine)(void *), void *arg, + void (*entry_point)(void *(*)(void *), void *)) { l4_word_t *top; @@ -52,6 +78,7 @@ stack_setup (struct __pthread *thread, *--top = (l4_word_t) arg; /* Argument to START_ROUTINE. */ *--top = (l4_word_t) start_routine; *--top = 0; /* Fake return address. */ + *--top = entry_point; } return top; @@ -62,8 +89,9 @@ __pthread_setup (struct __pthread *thread, void (*entry_point)(void *(*)(void *), void *), void *(*start_routine)(void *), void *arg) { - thread->mcontext.pc = entry_point; - thread->mcontext.sp = stack_setup (thread, start_routine, arg); + thread->mcontext.pc = (uintptr_t) &_pthread_entry_point; + thread->mcontext.sp = (uintptr_t) stack_setup (thread, start_routine, arg, + entry_point); if (__pthread_num_threads == 1) return 0; -- cgit v1.2.3 From ef79f627acbdeaf9a225d76aaebe4354eb1909e7 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 13 Feb 2008 10:38:57 +0000 Subject: libpthread/ 2008-02-13 Neal H. Walfield * sysdeps/l4/hurd/pt-sysdep.c (_pthread_init_routine): Change function signature to take a function pointer and an argument and to not return. (init_routine): Likewise. Pass entry and argument to __pthread_create_internal. Instead of returning, jump to the program counter and switch stacks. libc-parts/ 2008-02-13 Neal H. Walfield * ia32-cmain.c (cmain): Update user of _pthread_init_routine to reflect API change. --- sysdeps/l4/hurd/pt-sysdep.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sysdeps/l4/hurd/pt-sysdep.c b/sysdeps/l4/hurd/pt-sysdep.c index a05eb0a5..604f5bf2 100644 --- a/sysdeps/l4/hurd/pt-sysdep.c +++ b/sysdeps/l4/hurd/pt-sysdep.c @@ -38,17 +38,18 @@ sigprocmask (int HOW, const sigset_t *restrict SET, sigset_t *restrict OLDSET) } /* Forward. */ -static void *init_routine (void); +static void init_routine (void (*) (void *), void *) + __attribute__ ((noreturn)); /* OK, the name of this variable isn't really appropriate, but I don't want to change it yet. */ -void *(*_pthread_init_routine)(void) = &init_routine; +void (*_pthread_init_routine)(void (*) (void *), void *) = &init_routine; /* This function is called from the Hurd-specific startup code. It should return a new stack pointer for the main thread. The caller will switch to this new stack before doing anything serious. */ -static void * -init_routine (void) +static void +init_routine (void (*entry) (void *), void *arg) { /* Initialize the library. */ __pthread_initialize (); @@ -57,8 +58,11 @@ init_routine (void) int err; /* Create the pthread structure for the main thread (i.e. us). */ - err = __pthread_create_internal (&thread, 0, 0, 0); + err = __pthread_create_internal (&thread, 0, + (void *(*)(void *)) entry, arg); assert_perror (err); - return (void *) thread->mcontext.sp; + /* Switch stacks. */ + l4_start_sp_ip (l4_myself (), thread->mcontext.sp, + thread->mcontext.pc); } -- cgit v1.2.3 From e3ad421919c5f8c1677334d95df1438d52bcb665 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 13 Feb 2008 14:33:26 +0000 Subject: libhurd-mm/ 2008-02-13 Neal H. Walfield * storage.h (storage_alloc): Take additional parameter policy. Update callers. * storage.c (storage_alloc): Take additional parameter policy. Use it when allocating the object and updating the shadow capability slots. libpthread/ 2008-02-13 Neal H. Walfield * sysdeps/l4/hurd/pt-thread-alloc.c (__pthread_thread_alloc): Update use of storage_alloc to be consistent with new API. newlib/ 2008-02-13 Neal H. Walfield * addon/newlib/libc/sys/hurd/getreent.c (slab_alloc): Update use of storage_alloc to be consistent with new API. ruth/ 2008-02-13 Neal H. Walfield * ruth.c (main): Update use of storage_alloc to be consistent with new API. --- sysdeps/l4/hurd/pt-thread-alloc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sysdeps/l4/hurd/pt-thread-alloc.c b/sysdeps/l4/hurd/pt-thread-alloc.c index 9e2bc2a3..daa13dba 100644 --- a/sysdeps/l4/hurd/pt-thread-alloc.c +++ b/sysdeps/l4/hurd/pt-thread-alloc.c @@ -1,5 +1,5 @@ /* Allocate kernel thread. Hurd/L4 version. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2008 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 @@ -51,7 +51,8 @@ __pthread_thread_alloc (struct __pthread *thread) running and it accesses its stack, it will fault, which we naturally cannot handle. */ storage = storage_alloc (ADDR_VOID, cap_page, - STORAGE_UNKNOWN, ADDR_VOID); + STORAGE_UNKNOWN, OBJECT_POLICY_DEFAULT, + ADDR_VOID); if (ADDR_IS_VOID (storage.addr)) return EAGAIN; @@ -60,7 +61,8 @@ __pthread_thread_alloc (struct __pthread *thread) storage = storage_alloc (meta_data_activity, cap_thread, /* Threads are rarely shortly lived. */ - STORAGE_MEDIUM_LIVED, ADDR_VOID); + STORAGE_MEDIUM_LIVED, OBJECT_POLICY_DEFAULT, + ADDR_VOID); if (ADDR_IS_VOID (storage.addr)) { storage_free (thread->exception_page.addr, false); -- cgit v1.2.3 From 5cd8b44d0456addf77eaad7ba179e89e6eb1f5df Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sat, 16 Feb 2008 15:12:05 +0000 Subject: 2008-02-16 Neal H. Walfield * sysdeps/l4/hurd/ia32/pt-setup.c (stack_setup): Add correct casts to elide gcc warnings. (__pthread_setup): Likewise. --- sysdeps/l4/hurd/ia32/pt-setup.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/sysdeps/l4/hurd/ia32/pt-setup.c b/sysdeps/l4/hurd/ia32/pt-setup.c index 9a3812fd..f5987797 100644 --- a/sysdeps/l4/hurd/ia32/pt-setup.c +++ b/sysdeps/l4/hurd/ia32/pt-setup.c @@ -48,15 +48,15 @@ C entry_point */ extern uintptr_t _pthread_entry_point; -__asm__ ("\t\n\ - .globl _pthread_entry_point, __pthread_entry_point\t\n\ -_pthread_entry_point:\t\n\ -__pthread_entry_point:\t\n\ - pushl $0\t\n\ - popf\t\n\ -\t\n\ - xor %ebp, %ebp\t\n\ - ret\t\n"); +__asm__ ("\n\ + .globl _pthread_entry_point, __pthread_entry_point\n\ +_pthread_entry_point:\n\ +__pthread_entry_point:\n\ + pushl $0\n\ + popf\n\ +\n\ + xor %ebp, %ebp\n\ + ret\n"); /* Set up the stack for THREAD, such that it appears as if START_ROUTINE and ARG were passed to the new thread's entry-point. @@ -67,18 +67,18 @@ stack_setup (struct __pthread *thread, void *(*start_routine)(void *), void *arg, void (*entry_point)(void *(*)(void *), void *)) { - l4_word_t *top; + uintptr_t *top; /* Calculate top of the new stack. */ - top = (l4_word_t *) ((l4_word_t) thread->stackaddr + thread->stacksize); + top = (uintptr_t *) ((uintptr_t) thread->stackaddr + thread->stacksize); if (start_routine) { /* Set up call frame. */ - *--top = (l4_word_t) arg; /* Argument to START_ROUTINE. */ - *--top = (l4_word_t) start_routine; + *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + *--top = (uintptr_t) start_routine; *--top = 0; /* Fake return address. */ - *--top = entry_point; + *--top = (uintptr_t) entry_point; } return top; @@ -89,9 +89,9 @@ __pthread_setup (struct __pthread *thread, void (*entry_point)(void *(*)(void *), void *), void *(*start_routine)(void *), void *arg) { - thread->mcontext.pc = (uintptr_t) &_pthread_entry_point; - thread->mcontext.sp = (uintptr_t) stack_setup (thread, start_routine, arg, - entry_point); + thread->mcontext.pc = (void *) &_pthread_entry_point; + thread->mcontext.sp = (void *) stack_setup (thread, start_routine, arg, + entry_point); if (__pthread_num_threads == 1) return 0; @@ -103,10 +103,10 @@ __pthread_setup (struct __pthread *thread, 0, PAGESIZE_LOG2)); /* SP is set to the end of the exception page. */ - exception_page->exception_handler_sp = (l4_word_t) exception_page + PAGESIZE; + exception_page->exception_handler_sp = (uintptr_t) exception_page + PAGESIZE; - exception_page->exception_handler_ip = (l4_word_t) &exception_handler_entry; - exception_page->exception_handler_end = (l4_word_t) &exception_handler_end; + exception_page->exception_handler_ip = (uintptr_t) &exception_handler_entry; + exception_page->exception_handler_end = (uintptr_t) &exception_handler_end; return 0; } -- cgit v1.2.3 From 57f2488654f1407bb6f00a9551a799643b87c903 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 21 Feb 2008 15:09:04 +0000 Subject: / 2008-02-21 Neal H. Walfield * configure.ac (CFLAGS): Remove variable. (USER_CFLAGS): New variable. (USER_CPPFLAGS): Likewise. (USER_LDFLAGS): Likewise. (USER_LDADD): Likewise. (KERNEL_CFLAGS): Likewise. (KERNEL_CPPFLAGS): Likewise. * Makefile.am (SUBDIRS): Build . after building laden and viengoos. hieronymus/ 2008-02-21 Neal H. Walfield * Makefile.am (AM_CPPFLAGS): Remove variable. (AM_LDFLAGS): Likewise. (hieronymus_CPPFLAGS): New variable. (hieronymus_CFLAGS): Likewise. (hieronymus_LDFLAGS): Likewise. (hieronymus_LDADD): Don't include libc.a directly, use the value of $(USER_LDADD) instead. hurd/ 2008-02-21 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Remove variable. (t_addr_CPPFLAGS): Replace use of $(COMMON_CPPFLAGS) with use of $(CHECK_CPPFLAGS). (t_addr_trans_CPPFLAGS): Likewise. (t_rpc_CPPFLAGS): Likewise. libc-parts/ 2008-02-21 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Remove variable. (libc_parts_a_CPPFLAGS): Set to $(USER_CPPFLAGS). (libc_parts_a_CFLAGS): New variable. (libc_kernel_a_CPPFLAGS): Set to $(KERNEL_CPPFLAGS). (libc_kernel_a_CFLAGS): New variable. (t_setjmp_CPPFLAGS): Remove use of $(COMMON_CPPFLAGS) with $(CHECK_CPPFLAGS). libhurd-btree/ 2008-02-21 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Remove variable. (libhurd_btree_a_CPPFLAGS): Replace use of above with $(USER_CPPFLAGS). (libhurd_btree_a_CFLAGS): New variable. (btree_test_CPPFLAGS): Replace use $(COMMON_CPPFLAGS) with $(CHECK_CPPFLAGS). libhurd-ihash/ 2008-02-21 Neal H. Walfield * Makefile.am (AM_CPPFLAGS): Remove variable. (AM_CFLAGS): Likewise. (libhurd_ihash_a_CPPFLAGS): New variable. (libhurd_ihash_a_CFLAGS): Likewise. (libhurd_ihash_nomalloc_a_CPPFLAGS): Replace use of $(AM_CPPFLAGS) with $(USER_CPPFLAGS). (libhurd_ihash_nomalloc_a_CFLAGS): New variable. (t_ihash_CPPFLAGS): Remove use of $(AM_CPPFLAGS). (t_ihash64_CPPFLAGS): Likewise. (t_ihash_CFLAGS): New variable. (t_ihash64_CFLAGS): Likewise. * ihash.c: Don't include but "ihash.h". libhurd-mm/ 2008-02-21 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Remove variable. (libhurd_mm_a_CPPFLAGS): Replace use of above with $(USER_CPPFLAGS). (libhurd_mm_a_CFLAGS): New variable. libpthread/ 2008-02-21 Neal H. Walfield * Makefile.am (AM_CPPFLAGS): Replace use of includes with $(USER_CPPFLAGS). (AM_CFLAGS): New variable. newlib/ 2008-02-21 Neal H. Walfield * Makefile.am (patch_files): Add 05-newlib-newlib-libc-include-machine-setjmp-h.patch, 06-newlib-newlib-libc-machine-i386-i386mach-h.patch, and 07-newlib-newlib-libm-machine-i386-i386mach-h.patch. (ccheaders): Remove variable. (SYSINCLUDES): Likewise. (newlib-build/libc.a newlib-build/libm.a): Set TARGET_CFLAGS to "$(USER_CPPFLAGS) $(USER_CFLAGS) $(USER_LDFLAGS)". * newlib/patches/05-newlib-newlib-libc-include-machine-setjmp-h.patch: New file. * newlib/patches/06-newlib-newlib-libc-machine-i386-i386mach-h.patch: New file. * newlib/patches/07-newlib-newlib-libm-machine-i386-i386mach-h.patch: New file. ruth/ 2008-02-21 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Remove variable. (ruth_CPPFLAGS): Set to $(USER_CPPFLAGS). (ruth_CFLAGS): New variable. (ruth_LDFLAGS): Set to $(USER_LDFLAGS). (ruth_LDADD): Set to $(USER_LDADD). viengoos/ 2008-02-21 Neal H. Walfield * Makefile.am (COMMON_CPPFLAGS): Remove variable. (viengoos_CPPFLAGS): Set to $(KERNEL_CPPFLAGS). (viengoos_CFLAGS): New variable. (libhurd_cap_a_CPPFLAGS): Set to $(USER_CPPFLAGS). (libhurd_cap_a_CFLAGS): New variable. (t_as_CFLAGS): New variable. (t_activity_CFLAGS): Likewise. (t_link_CFLAGS): Likewise. --- Makefile.am | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index d9cc4239..df146dff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,10 +38,9 @@ SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ $(srcdir)/include vpath %.c $(SYSDEP_PATH) -AM_CPPFLAGS = -std=gnu99 -Wall -g -O3 -I$(LIBC)/include \ --I$(top_builddir)/include -D_GNU_SOURCE=1 -I$(srcdir)/pthread \ --I$(top_srcdir)/libc-parts $(addprefix -I, $(SYSDEP_PATH)) -imacros \ -$(srcdir)/include/libc-symbols.h +AM_CPPFLAGS = $(USER_CPPFLAGS) -I$(srcdir)/pthread \ + $(addprefix -I, $(SYSDEP_PATH)) -imacros $(srcdir)/include/libc-symbols.h +AM_CFLAGS = $(USER_CFLAGS) # Sources. SYSDEPS := lockfile.c @@ -130,4 +129,4 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ sem-close.c sem-init.c sem-timedwait.c sem-wait.c \ sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ - sem-post.c sem-unlink.c \ No newline at end of file + sem-post.c sem-unlink.c -- cgit v1.2.3 From 16de69f4d41a3105a3e14720f9ec81efaae5a78e Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sat, 1 Mar 2008 13:07:25 +0000 Subject: 2008-03-01 Neal H. Walfield Add signal implementation. * Makefile.am (SYSDEP_PATH): Add $(srcdir)/signal. (libpthread_a_SOURCES): Add pt-mutex-transfer-np.c, kill.c, killpg.c, pt-kill-siginfo-np.c, raise.c, sigaction.c, sigaddset.c, sigaltstack.c, sigdelset.c, sigemptyset.c, sigfillset.c, sig-internal.c, sig-internal.h, siginterrupt.c, sigismember.c, signal.c, signal-dispatch.c, signal.h, sigpending.c, sigprocmask.c, sigsuspend.c, sigtimedwait.c, sigwait.c, sigwaiter.c, sigwaitinfo.c, signal-dispatch-lowlevel.c, and sigprocmask.c. * headers.m4: Link libpthread/signal/signal.h into ../include. * sysdeps/generic/pt-mutex-transfer-np.c: New file. * signal/README: New file. * signal/TODO: Likewise. * signal/kill.c: Likewise. * signal/pt-kill-siginfo-np.c: Likewise. * signal/sig-internal.c: Likewise. * signal/sig-internal.h: Likewise. * signal/sigaction.c: Likewise. * signal/sigaltstack.c: Likewise. * signal/signal-dispatch.c: Likewise. * signal/signal.h: Likewise. * signal/sigpending.c: Likewise. * signal/sigsuspend.c: Likewise. * signal/sigtimedwait.c: Likewise. * signal/sigwaiter.c: Likewise. * signal/sigwaitinfo.c: Likewise. * sysdeps/l4/hurd/sig-sysdep.h: Likewise. * sysdeps/l4/hurd/sigprocmask.c: Likewise. * sysdeps/generic/killpg.c: Likewise. * sysdeps/generic/pt-kill.c: Likewise. * sysdeps/generic/raise.c: Likewise. * sysdeps/generic/sigaddset.c: Likewise. * sysdeps/generic/sigdelset.c: Likewise. * sysdeps/generic/sigemptyset.c: Likewise. * sysdeps/generic/sigfillset.c: Likewise. * sysdeps/generic/siginterrupt.c: Likewise. * sysdeps/generic/sigismember.c: Likewise. * sysdeps/generic/signal.c: Likewise. * sysdeps/generic/sigwait.c: Likewise. * sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c: Likewise. * sysdeps/l4/hurd/pt-sysdep.c (sigprocmask): Remove function. * sysdeps/l4/hurd/pt-sigstate.c (__pthread_sigstate): Implement it. * sysdeps/l4/hurd/pt-sigstate-init.c: Include . (__pthread_sigstate_init): Initialize THREAD->SS. * sysdeps/l4/hurd/pt-kill.c: Remove file. * pthread/pt-internal.h: Include . (PTHREAD_SIGNAL_MEMBERS) [! PTHREAD_SIGNAL_MEMBERS]: Define. (struct __pthread): Add PTHREAD_SIGNAL_MEMBERS. * pthread/pt-self.c (pthread_self): Assert that SELF is not NULL. --- Makefile.am | 33 ++- headers.m4 | 1 + pthread/pt-internal.h | 8 + pthread/pt-self.c | 7 +- signal/README | 4 + signal/TODO | 29 +++ signal/kill.c | 70 ++++++ signal/pt-kill-siginfo-np.c | 88 ++++++++ signal/sig-internal.c | 26 +++ signal/sig-internal.h | 177 +++++++++++++++ signal/sigaction.c | 72 +++++++ signal/sigaltstack.c | 69 ++++++ signal/signal-dispatch.c | 117 ++++++++++ signal/signal.h | 275 ++++++++++++++++++++++++ signal/sigpending.c | 38 ++++ signal/sigsuspend.c | 29 +++ signal/sigtimedwait.c | 30 +++ signal/sigwaiter.c | 91 ++++++++ signal/sigwaitinfo.c | 74 +++++++ sysdeps/generic/killpg.c | 27 +++ sysdeps/generic/pt-kill.c | 32 +++ sysdeps/generic/pt-mutex-transfer-np.c | 54 +++++ sysdeps/generic/raise.c | 41 ++++ sysdeps/generic/sigaddset.c | 35 +++ sysdeps/generic/sigdelset.c | 35 +++ sysdeps/generic/sigemptyset.c | 29 +++ sysdeps/generic/sigfillset.c | 29 +++ sysdeps/generic/siginterrupt.c | 36 ++++ sysdeps/generic/sigismember.c | 36 ++++ sysdeps/generic/signal.c | 44 ++++ sysdeps/generic/sigwait.c | 34 +++ sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c | 213 ++++++++++++++++++ sysdeps/l4/hurd/pt-sigstate-init.c | 18 +- sysdeps/l4/hurd/pt-sigstate.c | 52 ++++- sysdeps/l4/hurd/pt-sysdep.c | 9 +- sysdeps/l4/hurd/sig-sysdep.h | 69 ++++++ sysdeps/l4/hurd/sigprocmask.c | 41 ++++ 37 files changed, 2057 insertions(+), 15 deletions(-) create mode 100644 signal/README create mode 100644 signal/TODO create mode 100644 signal/kill.c create mode 100644 signal/pt-kill-siginfo-np.c create mode 100644 signal/sig-internal.c create mode 100644 signal/sig-internal.h create mode 100644 signal/sigaction.c create mode 100644 signal/sigaltstack.c create mode 100644 signal/signal-dispatch.c create mode 100644 signal/signal.h create mode 100644 signal/sigpending.c create mode 100644 signal/sigsuspend.c create mode 100644 signal/sigtimedwait.c create mode 100644 signal/sigwaiter.c create mode 100644 signal/sigwaitinfo.c create mode 100644 sysdeps/generic/killpg.c create mode 100644 sysdeps/generic/pt-kill.c create mode 100644 sysdeps/generic/pt-mutex-transfer-np.c create mode 100644 sysdeps/generic/raise.c create mode 100644 sysdeps/generic/sigaddset.c create mode 100644 sysdeps/generic/sigdelset.c create mode 100644 sysdeps/generic/sigemptyset.c create mode 100644 sysdeps/generic/sigfillset.c create mode 100644 sysdeps/generic/siginterrupt.c create mode 100644 sysdeps/generic/sigismember.c create mode 100644 sysdeps/generic/signal.c create mode 100644 sysdeps/generic/sigwait.c create mode 100644 sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c create mode 100644 sysdeps/l4/hurd/sig-sysdep.h create mode 100644 sysdeps/l4/hurd/sigprocmask.c diff --git a/Makefile.am b/Makefile.am index df146dff..89f4f297 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ if ARCH_POWERPC arch=powerpc endif -# The source files is scattered over several directories. Add +# The source files are scattered over several directories. Add # all these directories to the vpath. SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ $(srcdir)/sysdeps/l4/${arch} \ @@ -35,6 +35,7 @@ SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ $(srcdir)/sysdeps/generic \ $(srcdir)/sysdeps/posix \ $(srcdir)/pthread \ + $(srcdir)/signal \ $(srcdir)/include vpath %.c $(SYSDEP_PATH) @@ -87,6 +88,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-mutex-init.c pt-mutex-destroy.c \ pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ pt-mutex-unlock.c \ + pt-mutex-transfer-np.c \ pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ pt-rwlock-attr.c \ pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ @@ -129,4 +131,31 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ sem-close.c sem-init.c sem-timedwait.c sem-wait.c \ sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ - sem-post.c sem-unlink.c + sem-post.c sem-unlink.c \ + \ + kill.c \ + killpg.c \ + pt-kill-siginfo-np.c \ + raise.c \ + sigaction.c \ + sigaddset.c \ + sigaltstack.c \ + sigdelset.c \ + sigemptyset.c \ + sigfillset.c \ + sig-internal.c \ + sig-internal.h \ + siginterrupt.c \ + sigismember.c \ + signal.c \ + signal-dispatch.c \ + signal.h \ + sigpending.c \ + sigprocmask.c \ + sigsuspend.c \ + sigtimedwait.c \ + sigwait.c \ + sigwaiter.c \ + sigwaitinfo.c \ + signal-dispatch-lowlevel.c \ + sigprocmask.c diff --git a/headers.m4 b/headers.m4 index 3c907880..c04d3502 100644 --- a/headers.m4 +++ b/headers.m4 @@ -33,4 +33,5 @@ AC_CONFIG_LINKS([ include/bits/pthread-np.h:libpthread/sysdeps/l4/bits/pthread-np.h include/semaphore.h:libpthread/include/semaphore.h include/bits/semaphore.h:libpthread/sysdeps/generic/bits/semaphore.h + include/signal.h:libpthread/signal/signal.h ]) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 6d34be13..41fbc830 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -33,6 +33,8 @@ #include #include +#include + /* Thread state. */ enum pthread_state { @@ -50,6 +52,10 @@ enum pthread_state # define PTHREAD_SYSDEP_MEMBERS #endif +#ifndef PTHREAD_SIGNAL_MEMBERS +# define PTHREAD_SIGNAL_MEMBERS +#endif + /* This structure describes a POSIX thread. */ struct __pthread { @@ -85,6 +91,8 @@ struct __pthread PTHREAD_SYSDEP_MEMBERS + PTHREAD_SIGNAL_MEMBERS + struct __pthread *next, **prevp; }; diff --git a/pthread/pt-self.c b/pthread/pt-self.c index e14fe1eb..49768643 100644 --- a/pthread/pt-self.c +++ b/pthread/pt-self.c @@ -1,5 +1,5 @@ /* Get calling thread's ID. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2008 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 @@ -25,5 +25,8 @@ pthread_t pthread_self (void) { - return _pthread_self()->thread; + struct __pthread *self = _pthread_self (); + assert (self); + + return self->thread; } diff --git a/signal/README b/signal/README new file mode 100644 index 00000000..5487e2e3 --- /dev/null +++ b/signal/README @@ -0,0 +1,4 @@ +This directory provides a signal implementation, which is appropriate +for operating systems where signals are managed at user-level. It is +up to the run-time to catch the signals and forward them to the +implementation via, e.g., the pthread_kill_info_np call. diff --git a/signal/TODO b/signal/TODO new file mode 100644 index 00000000..1148abb3 --- /dev/null +++ b/signal/TODO @@ -0,0 +1,29 @@ +Unimplemented Functionality +--------------------------- + +We don't support interruptible functions. That is, if a signal is +delivered when a thread is in e.g. the write system call, then the +write function should be interrupted and return EINTR when the signal +handler is finished. To realize this behavior, we could have a thread +local interruptible flag and a setjmp buffer. A function that is +interruptible would fill the jump buffer and set the interruptible +flag. If a signal comes in and the interruptible flag is set, rather +than resuming the thread, we longjmp to the buffer. + +If a signal action has set the SA_SIGINFO, the third argument must be +a pointer to a ucontext describing the thread's interrupted state; +this implementation passes NULL. This isn't as bad as it sounds as +the the ucontext family of functions are marked obsolete in SUSv3 with +the advisory that any use of them should be replaced by the use of +pthread functionality (cf. makecontext rationale). + +stop and continue signals are not implemented (as we need to stop all +threads, this requires being in bed with libpthread). + +Implementation is not yet cancellation-safe. + +There are not even stubs for sighold, sigingore, sigpause, sigrelse, +however, according to posix: "Use of any of these functions is +unspecified in a multi-threaded process." + +Implement sigtimedwait, sigqueue. \ No newline at end of file diff --git a/signal/kill.c b/signal/kill.c new file mode 100644 index 00000000..27c9c32a --- /dev/null +++ b/signal/kill.c @@ -0,0 +1,70 @@ +/* kill.c - Generic kill implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +kill (pid_t pid, int signo) +{ + if (pid != getpid ()) + { + errno = EOPNOTSUPP; + return -1; + } + + /* "Signals generated for the process shall be delivered to exactly + one of those threads within the process which is in a call to a + sigwait() function selecting that signal or has not blocked + delivery of the signal. If there are no threads in a call to a + sigwait() function selecting that signal, and if all threads + within the process block delivery of the signal, the signal shall + remaing pending on the process" (2.4.1). */ + + /* First, see if there is a waiter, which is interested in this + signal. */ + pthread_mutex_lock (&sig_lock); + + struct sigwaiter *waiter; + for (waiter = sigwaiters; waiter; waiter = waiter->next) + if ((waiter->signals & sigmask (signo))) + /* Got a winner. */ + { + sigdelset (&process_pending, signo); + + pthread_mutex_lock (&waiter->ss->lock); + sigdelset (&waiter->ss->pending, signo); + + memset (&waiter->info, 0, sizeof (waiter->info)); + waiter->info.si_signo = signo; + + sigwaiter_unblock (waiter); + + return 0; + } + + pthread_mutex_unlock (&sig_lock); + + /* XXX: We just generate the signal for the current thread. If the + current thread has blocked the signal, the correct thing to do is + to iterate over all the other threads and find on that hasn't + blocked it. */ + return pthread_kill (pthread_self (), signo); +} + diff --git a/signal/pt-kill-siginfo-np.c b/signal/pt-kill-siginfo-np.c new file mode 100644 index 00000000..9bdf6cc4 --- /dev/null +++ b/signal/pt-kill-siginfo-np.c @@ -0,0 +1,88 @@ +/* pthread-kill-siginfo-np.c - Generic pthread_kill_siginfo_np implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "pt-internal.h" +#include "sig-internal.h" + +int +pthread_kill_siginfo_np (pthread_t tid, siginfo_t si) +{ + int sig = si.si_signo; + + if (sig < 0 || sig >= NSIG) + return EINVAL; + + if (sig == 0) + return 0; + + struct signal_state *ss = &__pthread_getid (tid)->ss; + + pthread_mutex_lock (&sig_lock); + pthread_mutex_lock (&ss->lock); + + if (ss->sigwaiter && (ss->sigwaiter->signals & sigmask (si.si_signo))) + /* The thread is in a call to sigwait. */ + { + ss->sigwaiter->info = si; + sigwaiter_unblock (ss->sigwaiter); + return 0; + } + + pthread_mutex_unlock (&sig_lock); + + if (ss->actions[sig - 1].sa_handler == (void *) SIG_IGN + || (ss->actions[sig - 1].sa_handler == (void *) SIG_DFL + && default_action (sig) == sig_ignore)) + /* It is unclear (to me) what is supposed to happen when a signal + is generated for a thread, which is blocking that signal and + ignoring it. POSIX does say that when the action associated + with a pending, blocked signal is set to SIG_IGN, the pending + signal is to be cleared. Thus, it makes sense that any signal + set to ignore is discarded at generation. */ + { + pthread_mutex_unlock (&ss->lock); + return 0; + } + + + if ((sigmask (sig) & ss->blocked)) + /* The signal is blocked. Mark it pending. */ + { + ss->pending |= sigmask (sig); + pthread_mutex_unlock (&ss->lock); + return 0; + } + + if (pthread_self () == tid + && (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) + || (ss->stack.ss_flags & SS_DISABLE) + || (ss->stack.ss_flags & SS_ONSTACK))) + /* We are sending a signal to ourself and we don't use an + alternate stack. */ + signal_dispatch (ss, &si); + else + signal_dispatch_lowlevel (ss, tid, si); + + /* Don't unlock ss: signal_dispatch and signal_dispatch_lowlevel + assume ownership of the lock. */ + + return 0; +} + diff --git a/signal/sig-internal.c b/signal/sig-internal.c new file mode 100644 index 00000000..f73f38b4 --- /dev/null +++ b/signal/sig-internal.c @@ -0,0 +1,26 @@ +/* sig-internal.c - Signal state functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +pthread_mutex_t sig_lock = PTHREAD_MUTEX_INITIALIZER; + +sigset_t process_pending; +siginfo_t process_pending_info[NSIG]; diff --git a/signal/sig-internal.h b/signal/sig-internal.h new file mode 100644 index 00000000..6c86c796 --- /dev/null +++ b/signal/sig-internal.h @@ -0,0 +1,177 @@ +/* sig-internal.h - Internal signal handling interface. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#ifndef SIG_INTERNAL_H +#define SIG_INTERNAL_H + +#include + +#include + +#define sigmask(sig) (1ULL << (sig - 1)) +#define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \ + sigmask (SIGSTOP) | sigmask (SIGTSTP)) + +/* General lock. Protects PROCESS_PENDING, PROCESS_PENDING_INFO, + SIGWAITERS. */ +extern pthread_mutex_t sig_lock; + +/* "Signals generated for the process shall be delivered to exactly + one of those threads within the process which is in a call to a + sigwait() function selecting that signal or has not blocked + delivery of the signal. If there are no threads in a call to a + sigwait() function selecting that signal, and if all threads within + the process block delivery of the signal, the signal shall remaing + pending on the process" (2.4.1). + + This variable is protected by SIG_LOCK. */ +extern sigset_t process_pending; +extern siginfo_t process_pending_info[NSIG]; + +struct sigwaiter; + +/* The per-thread signal state. */ +struct signal_state +{ + /* Protects the following fields. STACK.SA_FLAGS may be accessed + using atomic operations. */ + pthread_mutex_t lock; + + /* Pending signals. */ + sigset_t pending; + + /* Blocked signals (i.e., the signal mask). */ + sigset_t blocked; + + stack_t stack; + struct sigaction actions[NSIG]; + siginfo_t info[NSIG]; + + /* If the thread is blocked in a call to sigwait. */ + struct sigwaiter *sigwaiter; +}; + +#define PTHREAD_SIGNAL_MEMBERS struct signal_state ss; + +/* Arranges for thread TID to call signal_dispatch. Must not be + called if TID is the caller and an alternate stack is not required. + In this case, the caller should call signal_dispatch directly. */ +extern void signal_dispatch_lowlevel (struct signal_state *ss, + pthread_t tid, siginfo_t si); + +/* This is the signal handler entry point. A thread is forced into + this state when it receives a signal. We need to save the thread's + state and then invoke the high-level signal dispatcher. SS->LOCK + is locked by the caller. */ +extern void signal_dispatch (struct signal_state *ss, siginfo_t *si); + +#ifndef SIGNAL_DISPATCH_ENTRY +#define SIGNAL_DISPATCH_ENTRY +#endif + +#ifndef SIGNAL_DISPATCH_EXIT +#define SIGNAL_DISPATCH_EXIT +#endif + +/* When a thread calls sigwait and a requested signal is not pending, + it allocates the following structure, fills it in, adds it to + sigwaiters and sleeps. */ +struct sigwaiter +{ + struct sigwaiter *next; + struct sigwaiter *prev; + + /* Thread's signal state. */ + struct signal_state *ss; + + /* Signals this thread is waiting for. */ + sigset_t signals; + + /* The selected signal is returned here. The waiter also + futex_waits on this info.si_signo. */ + siginfo_t info; +}; + +/* This variable is protected by SIG_LOCK. */ +extern struct sigwaiter *sigwaiters; + +/* Block the caller waiting for a signal in set SET. SIG_LOCK and + SS->LOCK must be held and will be unlocked by this function before + blocking. */ +extern siginfo_t sigwaiter_block (struct signal_state *ss, + const sigset_t *restrict set); + +/* Unblock the waiter WAITER. SIG_LOCK and WAITER->SS->LOCK must be + held. Both will be dropped on return. */ +extern void sigwaiter_unblock (struct sigwaiter *waiter); + +enum sig_action { sig_core, sig_terminate, sig_ignore, sig_cont, sig_stop }; + +static inline enum sig_action +default_action (int signo) +{ + switch (signo) + { + case SIGABRT: + case SIGBUS: + case SIGFPE: + case SIGILL: + case SIGQUIT: + case SIGSEGV: + case SIGSTKFLT: + case SIGSYS: + case SIGTRAP: + case SIGXCPU: + case SIGXFSZ: + return sig_core; + + case SIGALRM: + case SIGHUP: + case SIGINT: + case SIGIO: /* Perhaps ignore? */ + case SIGKILL: + case SIGPIPE: + case SIGPROF: + case SIGTERM: + case SIGUSR1: + case SIGUSR2: + case SIGVTALRM: + return sig_terminate; + + case SIGCHLD: + case SIGPWR: + case SIGURG: + case SIGWINCH: + return sig_ignore; + + case SIGCONT: + return sig_cont; + + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + return sig_stop; + } + + panic ("Unknown signal number: %d", signo); +} + +#endif diff --git a/signal/sigaction.c b/signal/sigaction.c new file mode 100644 index 00000000..0126c99d --- /dev/null +++ b/signal/sigaction.c @@ -0,0 +1,72 @@ +/* sigaction.c - Generic sigaction implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" +#include "pt-internal.h" + +int +sigaction (int sig, const struct sigaction *restrict sa, + struct sigaction *restrict osa) +{ + if (sig <= 0 || sig >= NSIG) + { + errno = EINVAL; + return -1; + } + + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if (osa) + *osa = ss->actions[sig - 1]; + + if (sa) + { + ss->actions[sig - 1] = *sa; + + /* "The SIGKILL and SIGSTOP signals shall not be added to the + signal mask using this mechanism; this restriction shall be + enforced by the system without causing an error to be + indicated" (sigaction). */ + sigdelset (&ss->blocked, SIGKILL); + sigdelset (&ss->blocked, SIGSTOP); + + /* A "signal shall remain pending on the process until it is + unblocked, it is accepted when ..., or the action associated + with it is set to ignore the signal" (2.4.1). + + "Setting a signal action to SIG_DFL for a signal that is + pending, and whose default action is to ignore the signal, + ..., shall cause the pending signal to be discarded, whether + or not it is blocked" (2.4.3). */ + if (sa->sa_handler == SIG_IGN + || (sa->sa_handler == SIG_DFL && default_action (sig) == sig_ignore)) + { + sigdelset (&ss->pending, sig); + sigdelset (&process_pending, sig); + } + } + + pthread_mutex_unlock (&ss->lock); + + return 0; +} + diff --git a/signal/sigaltstack.c b/signal/sigaltstack.c new file mode 100644 index 00000000..8334811a --- /dev/null +++ b/signal/sigaltstack.c @@ -0,0 +1,69 @@ +/* sigaltstack.c - Generic sigaltstack implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" +#include "pt-internal.h" + +int +sigaltstack (const stack_t *restrict stack, stack_t *restrict old) +{ + int err = 0; + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if (old) + *old = ss->stack; + + if (stack) + { + if (stack->ss_size < MINSIGSTKSZ) + { + err = ENOMEM; + goto out; + } + + if ((stack->ss_flags & ~(SS_DISABLE))) + /* Flags contains a value other than SS_DISABLE. */ + { + err = EINVAL; + goto out; + } + + if ((ss->stack.ss_flags & SS_ONSTACK)) + /* Stack in use. */ + { + err = EPERM; + goto out; + } + + ss->stack = *stack; + } + + out: + pthread_mutex_unlock (&ss->lock); + + if (err) + { + errno = err; + return -1; + } + return 0; +} diff --git a/signal/signal-dispatch.c b/signal/signal-dispatch.c new file mode 100644 index 00000000..40440b70 --- /dev/null +++ b/signal/signal-dispatch.c @@ -0,0 +1,117 @@ +/* signal-dispatch.c - Signal dispatcher. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +/* This is the signal handler entry point. A thread is forced into + this state when it receives a signal. We need to save the thread's + state and then invoke the high-level signal dispatcher. SS->LOCK + is locked by the caller. */ +void +signal_dispatch (struct signal_state *ss, siginfo_t *si) +{ + SIGNAL_DISPATCH_ENTRY; + + int signo = si->si_signo; + + assert (signo > 0 && signo < NSIG); + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + do + { + if ((sigmask (signo) & STOPSIGS)) + /* Stop signals clear a pending SIGCONT even if they + are handled or ignored (but not if preempted). */ + { + sigdelset (&ss->pending, SIGCONT); + sigdelset (&process_pending, SIGCONT); + } + else if ((signo == SIGCONT)) + /* Even if handled or ignored (but not preempted), SIGCONT + clears stop signals and resumes the process. */ + { + ss->pending &= ~STOPSIGS; + process_pending &= ~STOPSIGS; + } + + void (*handler)(int, siginfo_t *, void *) + = ss->actions[signo - 1].sa_sigaction; + + /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot + be automatically reset when delivered; the system silently + enforces this restriction (sigaction). */ + if (ss->actions[signo - 1].sa_flags & SA_RESETHAND + && signo != SIGILL && signo != SIGTRAP) + ss->actions[signo - 1].sa_handler = SIG_DFL; + + sigset_t orig_blocked = ss->blocked; + /* Block requested signals while running the handler. */ + ss->blocked |= ss->actions[signo - 1].sa_mask; + + /* Block SIGNO unless we're asked not to. */ + if (! (ss->actions[signo - 1].sa_flags & (SA_RESETHAND | SA_NODEFER))) + sigaddset (&ss->blocked, signo); + + sigdelset (&ss->pending, signo); + pthread_mutex_unlock (&ss->lock); + + pthread_mutex_lock (&sig_lock); + sigdelset (&process_pending, signo); + pthread_mutex_unlock (&sig_lock); + + if (handler == (void *) SIG_DFL) + { + enum sig_action action = default_action (signo); + + if (action == sig_terminate || action == sig_core) + _exit (128 + signo); + + if (action == sig_stop) + /* XXX: Implement me. */ + panic ("Stopping process unimplemented."); + + if (action == sig_cont) + /* XXX: Implement me. */; + panic ("Continuing process unimplemented."); + } + else if (handler == (void *) SIG_IGN) + ; + else + handler (signo, si, NULL); + + pthread_mutex_lock (&ss->lock); + + /* "When a thread's signal mask is changed in a signal-catching + function that is installed by sigaction(), the restoration of + the signal mask on return from the signal-catching function + overrides that change (see sigaction())" (sigprocmask). */ + ss->blocked = orig_blocked; + + sigset_t pending = ~ss->blocked & ss->pending; + if (! pending) + pending = ~ss->blocked & process_pending; + signo = l4_lsb64 (pending); + } + while (signo); + + pthread_mutex_unlock (&ss->lock); + + SIGNAL_DISPATCH_EXIT; +} diff --git a/signal/signal.h b/signal/signal.h new file mode 100644 index 00000000..a33d995c --- /dev/null +++ b/signal/signal.h @@ -0,0 +1,275 @@ +/* signal.h - Signal handling interface. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#ifndef _SIGNAL_H +#define _SIGNAL_H 1 + +#include +#include + +typedef volatile int sig_atomic_t; + +typedef uint64_t sigset_t; + +int sigaddset (sigset_t *, int); +int sigdelset (sigset_t *, int); +int sigemptyset (sigset_t *); +int sigfillset (sigset_t *); +int sigismember (const sigset_t *, int); + +/* These values are consistent with Linux. */ +#define SIGRTMIN 34 +#define SIGRTMAX 64 + +enum + { + SIGHUP = 1, +#define SIGHUP SIGHUP + SIGINT, +#define SIGINT SIGINT + SIGQUIT, +#define SIGQUIT SIGQUIT + SIGILL, +#define SIGILL SIGILL + SIGTRAP, +#define SIGTRAP SIGTRAP + SIGABRT, +#define SIGABRT SIGABRT + SIGBUS, +#define SIGBUS SIGBUS + SIGFPE, +#define SIGFPE SIGFPE + SIGKILL, +#define SIGKILL SIGKILL + SIGUSR1, +#define SIGUSR1 SIGUSR1 + SIGSEGV, +#define SIGSEGV SIGSEGV + SIGUSR2, +#define SIGUSR2 SIGUSR2 + SIGPIPE, +#define SIGPIPE SIGPIPE + SIGALRM, +#define SIGALRM SIGALRM + SIGTERM, +#define SIGTERM SIGTERM + SIGSTKFLT, +#define SIGSTKFLT SIGSTKFLT + SIGCHLD, +#define SIGCHLD SIGCHLD + SIGCONT, +#define SIGCONT SIGCONT + SIGSTOP, +#define SIGSTOP SIGSTOP + SIGTSTP, +#define SIGTSTP SIGTSTP + SIGTTIN, +#define SIGTTIN SIGTTIN + SIGTTOU, +#define SIGTTOU SIGTTOU + SIGURG, +#define SIGURG SIGURG + SIGXCPU, +#define SIGXCPU SIGXCPU + SIGXFSZ, +#define SIGXFSZ SIGXFSZ + SIGVTALRM, +#define SIGVTALRM SIGVTALRM + SIGPROF, +#define SIGPROF SIGPROF + SIGWINCH, +#define SIGWINCH SIGWINCH + SIGIO, +#define SIGIO SIGIO + SIGPWR, +#define SIGPWR SIGPWR + SIGSYS, +#define SIGSYS SIGSYS + NSIG + }; + +/* The resulting set is the union of the current set and the signal + set pointed to by the argument set. */ +#define SIG_BLOCK 1 +/* The resulting set is the intersection of the current set and the + complement of the signal set pointed to by the argument set. */ +#define SIG_UNBLOCK 2 +/* The resulting set is the signal set pointed to by the argument + set. */ +#define SIG_SETMASK 3 + +int pthread_sigmask (int how, const sigset_t *mask, sigset_t *old); +int sigprocmask (int how, const sigset_t *restrict mask, + sigset_t *restrict old); + +/* Return set of pending signals. */ +int sigpending(sigset_t *set); + +union sigval +{ + int sival_int; + void *sival_ptr; +}; + +#define SIG_DFL ((void (*)(int)) (0)) +#define SIG_ERR ((void (*)(int)) (-1)) +#define SIG_IGN ((void (*)(int)) (1)) + +/* Causes signal delivery to occur on an alternate stack. */ +#define SA_ONSTACK (1 << 0) +/* Do not generate SIGCHLD when children stop or stopped children + continue. */ +#define SA_NOCLDSTOP (1 << 1) +/* Causes signal dispositions to be set to SIG_DFL on entry to signal + handlers. */ +#define SA_RESETHAND (1 << 2) +/* Causes certain functions to become restartable. */ +#define SA_RESTART (1 << 3) +/* Causes extra information to be passed to signal handlers at the + time of receipt of a signal. */ +#define SA_SIGINFO (1 << 4) +/* Causes implementations not to create zombie processes on child + death. */ +#define SA_NOCLDWAIT (1 << 5) +/* Causes signal not to be automatically blocked on entry to + signal handler. */ +#define SA_NODEFER (1 << 6) + +typedef struct +{ + int si_signo; + int si_code; + int si_errno; + pid_t si_pid; + uid_t si_uid; + void *si_addr; + int si_status; + long si_band; + union sigval si_value; +} siginfo_t; + +struct sigaction +{ + union + { + /* Pointer to a signal-catching function or one of the macros + SIG_IGN or SIG_DFL. */ + void (*sa_handler)(int); + + /* Pointer to a signal-catching function. */ + void (*sa_sigaction)(int, siginfo_t *, void *); + }; + + /* Set of signals to be blocked during execution of the signal + handling function. */ + sigset_t sa_mask; + + /* Special flags. */ + int sa_flags; +}; + +int sigaction (int signo, const struct sigaction *restrict newaction, + struct sigaction *restrict oldaction); + +void (*signal (int signo, void (*handler)(int)))(int); +void (*bsd_signal (int signo, void (*handler)(int)))(int); + +/* Process is executing on an alternate signal stack. */ +#define SS_ONSTACK (1 << 0) +/* Alternate signal stack is disabled. */ +#define SS_DISABLE (1 << 1) + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ PAGESIZE +/* Default size in bytes for the alternate signal stack. */ +#define SIGSTKSZ (16 * PAGESIZE) + +typedef struct +{ + void *ss_sp; + size_t ss_size; + int ss_flags; +} stack_t; + +int sigaltstack(const stack_t *restrict stack, stack_t *restrict old); + +#include + +/* Send SIGNO to the process PID. */ +int kill(pid_t pid, int signo); + +/* Send SIGNO to the process group PG. */ +int killpg(pid_t pg, int signo); + +/* Send SIGNO to thread TID. */ +int pthread_kill(pthread_t tid, int signo); + +/* Send a signal to thread TID using SIGINFO. */ +int pthread_kill_siginfo_np (pthread_t tid, siginfo_t siginfo); + +/* Send SIGNO to the calling thread. */ +int raise(int signo); + +typedef struct sigevent +{ + /* Notification type. */ + int sigev_notify; + + /* Signal number. */ + int sigev_signo; + + /* Signal value. */ + union sigval sigev_value; + + /* Notification function. */ + void (*sigev_notify_function) (union sigval); + + /* Notification attributes. */ + pthread_attr_t *sigev_notify_attributes; +} sigevent_t; + +enum + { + SIGEV_NONE = 0, +#define SIGEV_NONE SIGEV_NONE + SIGEV_SIGNAL, +#define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_THREAD +#define SIGEV_THREAD SIGEV_THREAD + }; + +#define SIG_HOLD + +int sighold (int); +int sigignore (int); +int siginterrupt (int, int); +int sigpause (int); +int sigqueue (pid_t, int, const union sigval); +int sigrelse (int); +void (*sigset (int, void (*)(int)))(int); +int sigsuspend (const sigset_t *); + +/* Wait for a signal. */ +int sigwait (const sigset_t *restrict set, int *restrict signo); +int sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info); +int sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, + const struct timespec *restrict timespec); + +#endif diff --git a/signal/sigpending.c b/signal/sigpending.c new file mode 100644 index 00000000..609b55d6 --- /dev/null +++ b/signal/sigpending.c @@ -0,0 +1,38 @@ +/* sigpending.c - Generic sigpending implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +int +sigpending (sigset_t *set) +{ + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + /* There is no need to lock SIG_LOCK for process_pending since we + just read it, which is atomic. */ + *set = (ss->pending | process_pending) & ss->blocked; + + pthread_mutex_unlock (&ss->lock); + + return 0; +} diff --git a/signal/sigsuspend.c b/signal/sigsuspend.c new file mode 100644 index 00000000..73cf12a1 --- /dev/null +++ b/signal/sigsuspend.c @@ -0,0 +1,29 @@ +/* sigsuspend.c - Generic sigsuspend implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigsuspend (const sigset_t *set) +{ + /* XXX: Implement me. */ + errno = EOPNOTSUPP; + return -1; +} diff --git a/signal/sigtimedwait.c b/signal/sigtimedwait.c new file mode 100644 index 00000000..52cd0176 --- /dev/null +++ b/signal/sigtimedwait.c @@ -0,0 +1,30 @@ +/* sigtimedwait.c - Generic sigtimedwait implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, + const struct timespec *restrict timeout) +{ + errno = EOPNOTSUPP; + return -1; +} + diff --git a/signal/sigwaiter.c b/signal/sigwaiter.c new file mode 100644 index 00000000..8d041ac1 --- /dev/null +++ b/signal/sigwaiter.c @@ -0,0 +1,91 @@ +/* sigwaiter.c - Signal handling functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +#include + +struct sigwaiter *sigwaiters; + +siginfo_t +sigwaiter_block (struct signal_state *ss, const sigset_t *restrict set) +{ + assert (pthread_mutex_trylock (&sig_lock) == EBUSY); + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + assert (! ss->sigwaiter); + + struct sigwaiter waiter; + + waiter.next = sigwaiters; + if (waiter.next) + { + assert (! waiter.next->prev); + waiter.next->prev = &waiter; + } + waiter.prev = 0; + sigwaiters = &waiter; + + waiter.ss = ss; + waiter.info.si_signo = 0; + waiter.signals = *set; + + ss->sigwaiter = &waiter; + + pthread_mutex_unlock (&ss->lock); + pthread_mutex_unlock (&sig_lock); + + futex_wait (&waiter.info.si_signo, 0); + +#ifndef NDEBUG + pthread_mutex_lock (&ss->lock); + ss->sigwaiter = 0; + pthread_mutex_unlock (&ss->lock); +#endif + + assert (waiter.info.si_signo); + return waiter.info; +} + +void +sigwaiter_unblock (struct sigwaiter *waiter) +{ + assert (pthread_mutex_trylock (&sig_lock) == EBUSY); + assert (pthread_mutex_trylock (&waiter->ss->lock) == EBUSY); + + struct sigwaiter *prev = waiter->prev; + struct sigwaiter *next = waiter->next; + + if (next) + next->prev = prev; + + if (prev) + prev->next = next; + else + sigwaiters = next; + + sigdelset (&process_pending, waiter->info.si_signo); + sigdelset (&waiter->ss->pending, waiter->info.si_signo); + + pthread_mutex_unlock (&waiter->ss->lock); + pthread_mutex_unlock (&sig_lock); + + futex_wake (&waiter->info.si_signo, 1); +} diff --git a/signal/sigwaitinfo.c b/signal/sigwaitinfo.c new file mode 100644 index 00000000..1b47079e --- /dev/null +++ b/signal/sigwaitinfo.c @@ -0,0 +1,74 @@ +/* sigwaitinfo.c - Generic sigwaitinfo implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +int +sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info) +{ + pthread_mutex_lock (&sig_lock); + + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if ((process_pending & *set) || (ss->pending & *set)) + /* There is at least one signal pending. */ + { + bool local = true; + sigset_t extant = process_pending & *set; + if (! extant) + { + local = false; + extant = ss->pending & *set; + } + + assert (extant); + + int signo = l4_msb64 (extant); + + if (info) + { + if (local) + *info = ss->info[signo - 1]; + else + *info = process_pending_info[signo - 1]; + info->si_signo = signo; + } + + sigdelset (&process_pending, signo); + sigdelset (&ss->pending, signo); + + pthread_mutex_unlock (&ss->lock); + pthread_mutex_unlock (&sig_lock); + return 0; + } + + siginfo_t i = sigwaiter_block (ss, set); + assert (i.si_signo); + assert ((sigmask (i.si_signo) & *set)); + + if (info) + *info = i; + + return 0; +} + diff --git a/sysdeps/generic/killpg.c b/sysdeps/generic/killpg.c new file mode 100644 index 00000000..7f7ed87d --- /dev/null +++ b/sysdeps/generic/killpg.c @@ -0,0 +1,27 @@ +/* killpg.c - Generic killpg implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +killpg (pid_t pid, int sig) +{ + return kill (-pid, sig); +} diff --git a/sysdeps/generic/pt-kill.c b/sysdeps/generic/pt-kill.c new file mode 100644 index 00000000..0dfac344 --- /dev/null +++ b/sysdeps/generic/pt-kill.c @@ -0,0 +1,32 @@ +/* pthread-kill.c - Generic pthread-kill implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +pthread_kill (pthread_t tid, int signo) +{ + siginfo_t si; + memset (&si, 0, sizeof (si)); + si.si_signo = signo; + + return pthread_kill_siginfo_np (tid, si); +} + diff --git a/sysdeps/generic/pt-mutex-transfer-np.c b/sysdeps/generic/pt-mutex-transfer-np.c new file mode 100644 index 00000000..bcb809dd --- /dev/null +++ b/sysdeps/generic/pt-mutex-transfer-np.c @@ -0,0 +1,54 @@ +/* Transfer ownership of a mutex. Generic version. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +#include + +int +__pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) +{ + assert (mutex->owner == _pthread_self ()); + + struct __pthread *thread = __pthread_getid (tid); + if (! thread) + return ESRCH; + + if (thread == _pthread_self ()) + return 0; + + if (mutex->attr && mutex->attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) + { + + if (mutex->owner != _pthread_self ()) + return EPERM; + + mutex->owner = thread; + } + +#ifndef NDEBUG + mutex->owner = thread; +#endif + + return 0; +} + +strong_alias (__pthread_mutex_transfer_np, pthread_mutex_transfer_np) diff --git a/sysdeps/generic/raise.c b/sysdeps/generic/raise.c new file mode 100644 index 00000000..410f557d --- /dev/null +++ b/sysdeps/generic/raise.c @@ -0,0 +1,41 @@ +/* raise.c - Generic raise implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +raise (int signo) +{ + /* According to POSIX, if we implement threads (and we do), then + "the effect of the raise() function shall be equivalent to + calling: pthread_kill(pthread_self(), sig);" */ + +debug (0, ""); + int err = pthread_kill (pthread_self (), signo); +debug (0, ""); + if (err) + { + errno = err; + return -1; + } + + return 0; +} + diff --git a/sysdeps/generic/sigaddset.c b/sysdeps/generic/sigaddset.c new file mode 100644 index 00000000..14edb71c --- /dev/null +++ b/sysdeps/generic/sigaddset.c @@ -0,0 +1,35 @@ +/* sigaddset.c - Generic sigaddset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigaddset (sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + *sigset |= sigmask (signo); + return 0; +} + diff --git a/sysdeps/generic/sigdelset.c b/sysdeps/generic/sigdelset.c new file mode 100644 index 00000000..5456467f --- /dev/null +++ b/sysdeps/generic/sigdelset.c @@ -0,0 +1,35 @@ +/* sigdelset.c - Generic sigdelset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigdelset (sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + *sigset &= ~sigmask (signo); + return 0; +} + diff --git a/sysdeps/generic/sigemptyset.c b/sysdeps/generic/sigemptyset.c new file mode 100644 index 00000000..690c15b6 --- /dev/null +++ b/sysdeps/generic/sigemptyset.c @@ -0,0 +1,29 @@ +/* sigemptyset.c - Generic sigemptyset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include + +int +sigemptyset (sigset_t *sigset) +{ + *sigset = 0; + return 0; +} + diff --git a/sysdeps/generic/sigfillset.c b/sysdeps/generic/sigfillset.c new file mode 100644 index 00000000..f0ac0781 --- /dev/null +++ b/sysdeps/generic/sigfillset.c @@ -0,0 +1,29 @@ +/* sigfillset.c - Generic sigfillset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include + +int +sigfillset (sigset_t *sigset) +{ + *sigset = (1ULL << (NSIG - 1)) - 1; + return 0; +} + diff --git a/sysdeps/generic/siginterrupt.c b/sysdeps/generic/siginterrupt.c new file mode 100644 index 00000000..0899efbb --- /dev/null +++ b/sysdeps/generic/siginterrupt.c @@ -0,0 +1,36 @@ +/* siginterrupt.c - Generic siginterrupt implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +siginterrupt (int sig, int flag) +{ + int ret; + struct sigaction act; + + sigaction (sig, NULL, &act); + if (flag) + act.sa_flags &= ~SA_RESTART; + else + act.sa_flags |= SA_RESTART; + ret = sigaction(sig, &act, NULL); + return ret; +} diff --git a/sysdeps/generic/sigismember.c b/sysdeps/generic/sigismember.c new file mode 100644 index 00000000..b3d65c97 --- /dev/null +++ b/sysdeps/generic/sigismember.c @@ -0,0 +1,36 @@ +/* sigismember.c - Generic sigismember implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigismember (const sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + if (*sigset & sigmask (signo)) + return 1; + else + return 0; +} diff --git a/sysdeps/generic/signal.c b/sysdeps/generic/signal.c new file mode 100644 index 00000000..7555d0a1 --- /dev/null +++ b/sysdeps/generic/signal.c @@ -0,0 +1,44 @@ +/* signal.c - Generic signal implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +void (*signal (int sig, void (*handler)(int)))(int) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sa.sa_flags = SA_RESTART; + + if (sigemptyset (&sa.sa_mask) < 0 + || sigaddset (&sa.sa_mask, sig) < 0) + return SIG_ERR; + + struct sigaction osa; + if (sigaction (sig, &sa, &osa) < 0) + return SIG_ERR; + + return osa.sa_handler; +} + +void (*bsd_signal (int sig, void (*func)(int)))(int) +{ + return signal (sig, func); +} diff --git a/sysdeps/generic/sigwait.c b/sysdeps/generic/sigwait.c new file mode 100644 index 00000000..7d10bf8b --- /dev/null +++ b/sysdeps/generic/sigwait.c @@ -0,0 +1,34 @@ +/* sigwait.c - Generic sigwait implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigwait (const sigset_t *restrict set, int *restrict signo) +{ + siginfo_t info; + + if (sigwaitinfo (set, &info) < 0) + return -1; + + *signo = info.si_signo; + return 0; +} + diff --git a/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c b/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c new file mode 100644 index 00000000..bb6ac2a5 --- /dev/null +++ b/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c @@ -0,0 +1,213 @@ +/* signal-dispatch-lowlevel.c - ia32 specific signal handling functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +#include +#include +#include +#include + +extern char _signal_dispatch_entry; +/* - 0(%esp) a pointer to the thread's struct signal_state. + - 4(%esp) a pointer to a siginfo_t. + - 8(%esp) is a pointer to the ss_flags field (or NULL). + - 12(%esp)+4 is the value of the sp when the thread was interrupted (intr_sp) + - 0(intr_sp) is the value of the ip when the thread was interrupted. + - 16(%esp) - 16 byte register save area +*/ +__asm__ ("\n\ + .globl _signal_dispatch_entry\n\ +_signal_dispatch_entry:\n\ + /* Save caller saved registers (16 bytes). */\n\ + mov %eax, 16(%esp)\n\ + mov %ecx, 16+4(%esp)\n\ + mov %edx, 16+8(%esp)\n\ + pushf\n\ + popl %eax\n\ + mov %eax, 16+12(%esp)\n\ +\n\ + /* Reset EFLAGS. */\n\ + cld\n\ + call signal_dispatch\n\ +\n\ + /* Get the original stack and begin restoration. */\n\ + mov 12(%esp), %edx\n\ +\n\ + /* Move the saved registers to the user stack. */\n\ + sub $16, %edx\n\ + /* eax. */\n\ + mov 16+0(%esp), %ecx\n\ + mov %ecx, 0(%edx)\n\ + /* ecx. */\n\ + mov 16+4(%esp), %ecx\n\ + mov %ecx, 4(%edx)\n\ + /* edx. */\n\ + mov 16+8(%esp), %ecx\n\ + mov %ecx, 8(%edx)\n\ + /* eflags. */\n\ + mov 16+12(%esp), %ecx\n\ + mov %ecx, 12(%edx)\n\ +\n\ + /* Get the pointer to the sigaltstack flags. */\n\ + mov 8(%esp), %ecx\n\ +\n\ + /* Restore the user stack. */\n\ + mov %edx, %esp\n\ +\n\ + /* Clear the SA_ONSTACK flag. */\n\ + and %ecx, %ecx\n\ + jz after_clear\n\ + lock; and $~1, 0(%ecx)\n\ +after_clear:\n\ +\n\ + /* Restore eflags, the scratch regs and the original sp and ip. */\n\ + popl %eax\n\ + popl %ecx\n\ + popl %edx\n\ + popf\n\ + ret\n"); + +extern char _signal_dispatch_entry_self; +/* - 0(%esp) is the return address (we ignore it) + - 4(%esp) is the sp to load + + Since we are returning to signal_dispatch_lowlevel's caller, we + also need to restore its frame pointer. */ +__asm__ ("\n\ + .globl _signal_dispatch_entry_self\n\ +_signal_dispatch_entry_self:\n\ + mov 0(%ebp), %ebp\n\ + mov 4(%esp), %esp\n\ + jmp _signal_dispatch_entry\n"); + +void +signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, + siginfo_t si) +{ + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + struct __pthread *thread = __pthread_getid (tid); + + bool self = tid == pthread_self (); + + uintptr_t intr_sp; + + if (self) + { + /* The return address is just before the first argument. */ + intr_sp = (uintptr_t) &ss - 4; + assert (* (void **) intr_sp == __builtin_return_address (0)); + } + else + { + struct hurd_thread_exregs_in in; + memset (&in, 0, sizeof (in)); + struct hurd_thread_exregs_out out; + + error_t err; + err = rm_thread_exregs (ADDR_VOID, thread->object.addr, + HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC + | HURD_EXREGS_GET_REGS, + in, &out); + if (err) + panic ("Failed to modify thread " ADDR_FMT, + ADDR_PRINTF (thread->object.addr)); + + intr_sp = out.sp; + + /* Push the ip on the user stack. */ + intr_sp -= 4; + * (uintptr_t *) intr_sp = out.ip; + } + + bool altstack = false; + uintptr_t sp; + if (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) + || (ss->stack.ss_flags & SS_DISABLE) + || (ss->stack.ss_flags & SS_ONSTACK)) + { + assert (! self); + sp = intr_sp; + } + else + { + /* The stack grows down. */ + sp = (uintptr_t) ss->stack.ss_sp + ss->stack.ss_size; + + /* We know intimately that SS_ONSTACK is the least significant + bit. */ + assert (SS_ONSTACK == 1); + atomic_bit_set (&ss->stack.ss_flags, 0); + + altstack = true; + } + + /* Set up the call frame for a call to signal_dispatch_entry. */ + + /* Allocate a siginfo structure on the stack. */ + sp = sp - sizeof (siginfo_t); + siginfo_t *sip = (void *) sp; + /* Copy the user supplied values. */ + *sip = si; + + /* Add space for the 4 caller saved registers. */ + sp -= 4 * sizeof (uintptr_t); + + /* Save the interrupted sp. */ + sp -= 4; + * (uintptr_t *) sp = intr_sp; + + /* Address of the ss_flags. */ + sp -= 4; + if (altstack) + * (uintptr_t *) sp = (uintptr_t) &ss->stack.ss_flags; + else + * (uintptr_t *) sp = 0; + + /* Push the parameters to signal_dispatch. */ + + /* signal info structure. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) sip; + + /* The ss. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) ss; + + pthread_mutex_transfer_np (&ss->lock, tid); + + if (self) + ((void (*) (uintptr_t)) &_signal_dispatch_entry_self) ((uintptr_t) sp); + else + { + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; + + in.sp = sp; + in.ip = (uintptr_t) &_signal_dispatch_entry; + + rm_thread_exregs (ADDR_VOID, thread->object.addr, + HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, + in, &out); + } +} diff --git a/sysdeps/l4/hurd/pt-sigstate-init.c b/sysdeps/l4/hurd/pt-sigstate-init.c index 25a3920c..4c40fdb3 100644 --- a/sysdeps/l4/hurd/pt-sigstate-init.c +++ b/sysdeps/l4/hurd/pt-sigstate-init.c @@ -1,5 +1,5 @@ /* Initialize the signal state. Hurd on L4 version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2008 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 @@ -20,9 +20,25 @@ #include #include +#include error_t __pthread_sigstate_init (struct __pthread *thread) { + struct signal_state *ss = &thread->ss; + + memset (ss, 0, sizeof (*ss)); + + ss->stack.ss_flags = SS_DISABLE; + + int signo; + for (signo = 1; signo < NSIG; ++signo) + { + sigemptyset (&ss->actions[signo - 1].sa_mask); + ss->actions[signo - 1].sa_flags = SA_RESTART; + ss->actions[signo - 1].sa_handler = SIG_DFL; + ss->lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + } + return 0; } diff --git a/sysdeps/l4/hurd/pt-sigstate.c b/sysdeps/l4/hurd/pt-sigstate.c index 8ab80347..66dd08cf 100644 --- a/sysdeps/l4/hurd/pt-sigstate.c +++ b/sysdeps/l4/hurd/pt-sigstate.c @@ -1,5 +1,5 @@ /* Set a thread's signal state. Hurd on L4 version. - Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2008 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 @@ -28,6 +28,54 @@ __pthread_sigstate (struct __pthread *thread, int how, const sigset_t *set, sigset_t *oset, int clear_pending) { - /* FIXME: Do the right thing here. */ + struct signal_state *ss = &thread->ss; + pthread_mutex_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + { + /* Mask out SIGKILL and SIGSTOP. */ + sigset_t s = *set; + sigdelset (&s, SIGKILL); + sigdelset (&s, SIGSTOP); + + switch (how) + { + case SIG_BLOCK: + ss->blocked |= s; + break; + case SIG_UNBLOCK: + ss->blocked &= ~s; + break; + case SIG_SETMASK: + ss->blocked = s; + break; + default: + errno = EINVAL; + pthread_mutex_unlock (&ss->lock); + return -1; + } + } + + if (clear_pending) + sigemptyset (&ss->pending); + + /* A "signal shall remain pending until it is unblocked" (2.4.1). + + "If there are any pending unblocked signals after the call to + sigprocmask(), at least one of those signals shall be delivered + before the call to sigprocmask() returns." + (pthread_sigmask). */ + sigset_t extant = ~ss->blocked & ss->pending; + if (! extant) + extant = ~ss->blocked & process_pending; + + pthread_mutex_unlock (&ss->lock); + + if (extant) + raise (l4_lsb64 (extant)); + return 0; } diff --git a/sysdeps/l4/hurd/pt-sysdep.c b/sysdeps/l4/hurd/pt-sysdep.c index 604f5bf2..c23364c7 100644 --- a/sysdeps/l4/hurd/pt-sysdep.c +++ b/sysdeps/l4/hurd/pt-sysdep.c @@ -1,5 +1,5 @@ /* System dependent pthreads code. Hurd version. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2008 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 @@ -30,13 +30,6 @@ sched_yield (void) return 0; } -int -sigprocmask (int HOW, const sigset_t *restrict SET, sigset_t *restrict OLDSET) -{ - /* Just ignore for now. */ - return 0; -} - /* Forward. */ static void init_routine (void (*) (void *), void *) __attribute__ ((noreturn)); diff --git a/sysdeps/l4/hurd/sig-sysdep.h b/sysdeps/l4/hurd/sig-sysdep.h new file mode 100644 index 00000000..33e13857 --- /dev/null +++ b/sysdeps/l4/hurd/sig-sysdep.h @@ -0,0 +1,69 @@ +/* sig-sysdep.h - Hurd system specific header file. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +struct utcb +{ + l4_word_t saved_sender; + l4_word_t saved_receiver; + l4_word_t saved_timeout; + l4_word_t saved_error_code; + l4_word_t saved_flags; + l4_word_t saved_br0; + l4_msg_t saved_message; +}; + +static inline void +utcb_state_save (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + buffer->saved_sender = utcb[_L4_UTCB_SENDER]; + buffer->saved_receiver = utcb[_L4_UTCB_RECEIVER]; + buffer->saved_timeout = utcb[_L4_UTCB_TIMEOUT]; + buffer->saved_error_code = utcb[_L4_UTCB_ERROR_CODE]; + buffer->saved_flags = utcb[_L4_UTCB_FLAGS]; + buffer->saved_br0 = utcb[_L4_UTCB_BR0]; + memcpy (&buffer->saved_message, + utcb, L4_NUM_MRS * sizeof (l4_word_t)); +} + +static inline void +utcb_state_restore (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + utcb[_L4_UTCB_SENDER] = buffer->saved_sender; + utcb[_L4_UTCB_RECEIVER] = buffer->saved_receiver; + utcb[_L4_UTCB_TIMEOUT] = buffer->saved_timeout; + utcb[_L4_UTCB_ERROR_CODE] = buffer->saved_error_code; + utcb[_L4_UTCB_FLAGS] = buffer->saved_flags; + utcb[_L4_UTCB_BR0] = buffer->saved_br0; + memcpy (utcb, &buffer->saved_message, + L4_NUM_MRS * sizeof (l4_word_t)); +} + +#define SIGNAL_DISPATCH_ENTRY \ + struct utcb buffer; utcb_state_save (&buffer); + +#define SIGNAL_DISPATCH_EXIT \ + utcb_state_restore (&buffer); diff --git a/sysdeps/l4/hurd/sigprocmask.c b/sysdeps/l4/hurd/sigprocmask.c new file mode 100644 index 00000000..a38b3795 --- /dev/null +++ b/sysdeps/l4/hurd/sigprocmask.c @@ -0,0 +1,41 @@ +/* sigprocmask.c - Generic sigprocmask implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +int +sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict old) +{ + struct __pthread *thread = _pthread_self (); + if (! thread) + /* Library is initializing. */ + { + assert (__pthread_num_threads == 1); + + /* We should get the default mask from the startup data structure. */ + if (old) + *old = 0; + + return 0; + } + + return pthread_sigmask (how, set, old); +} -- cgit v1.2.3 From 011bbc0bd66bfee2d479bad9ed1f971514e462ef Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sun, 6 Apr 2008 10:46:13 +0000 Subject: 2008-04-06 Neal H. Walfield * sysdeps/l4/hurd/pt-kill.c: Just include "../generic/pt-kill.c". --- sysdeps/l4/hurd/pt-kill.c | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/sysdeps/l4/hurd/pt-kill.c b/sysdeps/l4/hurd/pt-kill.c index 1e64af49..c72e82f4 100644 --- a/sysdeps/l4/hurd/pt-kill.c +++ b/sysdeps/l4/hurd/pt-kill.c @@ -1,30 +1,3 @@ -/* pthread_kill. Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -pthread_kill (pthread_t thread, int sig) -{ - return ESRCH; -} +/* The generic version is good enough for us, however, the generic + Hurd on Mach version supplies a specialized version */ +#include "../generic/pt-kill.c" -- cgit v1.2.3 From b80d473696a1664926a10af0f473237cde1c1cdb Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 21 May 2008 14:09:11 +0000 Subject: 2008-05-21 Neal H. Walfield * sysdeps/l4/hurd/bits/pthread-np.h: New file. * headers.m4: Don't link include/bits/pthread-np.h to libpthread/sysdeps/l4/bits/pthread-np.h but to libpthread/sysdeps/l4/hurd/bits/pthread-np.h. * include/pthread/pthread.h: Include . * sysdeps/l4/hurd/pt-setactivity-np.c (pthread_setactivity_np): New file. * Makefile.am (libpthread_a_SOURCES): Add pt-setactivity-np.c. --- Makefile.am | 2 ++ headers.m4 | 4 ++-- sysdeps/l4/hurd/bits/pthread-np.h | 31 +++++++++++++++++++++++++++++ sysdeps/l4/hurd/pt-setactivity-np.c | 39 +++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 sysdeps/l4/hurd/bits/pthread-np.h create mode 100644 sysdeps/l4/hurd/pt-setactivity-np.c diff --git a/Makefile.am b/Makefile.am index 89f4f297..0dae132a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -133,6 +133,8 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ sem-post.c sem-unlink.c \ \ + pt-setactivity-np.c \ + \ kill.c \ killpg.c \ pt-kill-siginfo-np.c \ diff --git a/headers.m4 b/headers.m4 index c04d3502..2fde3a62 100644 --- a/headers.m4 +++ b/headers.m4 @@ -1,5 +1,5 @@ # headers.m4 - Autoconf snippets to install links for header files. -# Copyright 2003 Free Software Foundation, Inc. +# Copyright 2003, 2008 Free Software Foundation, Inc. # Written by Marcus Brinkmann . # # This file is free software; as a special exception the author gives @@ -30,7 +30,7 @@ AC_CONFIG_LINKS([ include/bits/thread-attr.h:libpthread/sysdeps/generic/bits/thread-attr.h include/bits/thread-barrier.h:libpthread/sysdeps/generic/bits/thread-barrier.h include/bits/thread-specific.h:libpthread/sysdeps/generic/bits/thread-specific.h - include/bits/pthread-np.h:libpthread/sysdeps/l4/bits/pthread-np.h + include/bits/pthread-np.h:libpthread/sysdeps/l4/hurd/bits/pthread-np.h include/semaphore.h:libpthread/include/semaphore.h include/bits/semaphore.h:libpthread/sysdeps/generic/bits/semaphore.h include/signal.h:libpthread/signal/signal.h diff --git a/sysdeps/l4/hurd/bits/pthread-np.h b/sysdeps/l4/hurd/bits/pthread-np.h new file mode 100644 index 00000000..a90793df --- /dev/null +++ b/sysdeps/l4/hurd/bits/pthread-np.h @@ -0,0 +1,31 @@ +/* Non-portable functions. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include + +int pthread_setactivity_np (addr_t activity); + +#endif /* bits/pthread-np.h */ diff --git a/sysdeps/l4/hurd/pt-setactivity-np.c b/sysdeps/l4/hurd/pt-setactivity-np.c new file mode 100644 index 00000000..dbadb68f --- /dev/null +++ b/sysdeps/l4/hurd/pt-setactivity-np.c @@ -0,0 +1,39 @@ +/* Set a thread's activity activity. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +int +pthread_setactivity_np (addr_t activity) +{ + struct __pthread *self = _pthread_self (); + + struct hurd_thread_exregs_in in; + in.activity = activity; + + struct hurd_thread_exregs_out out; + int err = rm_thread_exregs (ADDR_VOID, self->object.addr, + HURD_EXREGS_SET_ACTIVITY, + in, &out); + + return err; +} -- cgit v1.2.3 From 9acc87073cfc18eaa2ea5b46fa81f239d6b32b31 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 27 May 2008 18:29:48 +0000 Subject: 2008-05-27 Neal H. Walfield * pthread/pt-internal.h (__pthread_queue_iterate): Before returning the current element, save its next pointer. (__pthread_dequeuing_iterate): Likewise. * sysdeps/l4/hurd/pt-wakeup.c (__pthread_wakeup): Loop until we successfully wake THREAD. --- pthread/pt-internal.h | 19 +++++++++++++------ sysdeps/l4/hurd/pt-wakeup.c | 18 ++++++++++++++++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 41fbc830..853d739d 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -122,15 +122,22 @@ __pthread_dequeue (struct __pthread *thread) } /* Iterate over QUEUE storing each element in ELEMENT. */ -#define __pthread_queue_iterate(queue, element) \ - for (element = queue; element; element = element->next) +#define __pthread_queue_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + true); \ + ) /* Iterate over QUEUE dequeuing each element, storing it in ELEMENT. */ -#define __pthread_dequeuing_iterate(queue, element) \ - for (element = queue; \ - element && ((element->prevp = 0), 1); \ - element = element->next) +#define __pthread_dequeuing_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + ((element)->prevp = 0), \ + true); \ + ) /* The total number of threads currently active. */ extern atomic_fast32_t __pthread_total; diff --git a/sysdeps/l4/hurd/pt-wakeup.c b/sysdeps/l4/hurd/pt-wakeup.c index 2225cca0..e568a6f9 100644 --- a/sysdeps/l4/hurd/pt-wakeup.c +++ b/sysdeps/l4/hurd/pt-wakeup.c @@ -27,6 +27,20 @@ void __pthread_wakeup (struct __pthread *thread) { - long ret = futex_wake (&thread->threadid, INT_MAX); - assert (ret == 1); + /* We need to loop here as the blocked thread may not yet be + blocked! Here's what happens when a thread blocks: it registers + itself as blocked, drops the relevant lock and then actually + blocks (via __pthread_block). This means that after dropping the + lock and before blocking, it may be interrupted and another + thread may try to wake it. */ + long ret; + do + { + ret = futex_wake (&thread->threadid, INT_MAX); + assertx (ret <= 1, "tid: %x, ret: %d", thread->threadid, ret); + + if (ret == 0) + l4_thread_switch (thread->threadid); + } + while (ret == 0); } -- cgit v1.2.3 From ba1501075d81ce42c88707021eb8c2befa0fe4a4 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 29 May 2008 20:45:48 +0000 Subject: libhurd-mm/ 2008-05-29 Neal H. Walfield * exceptions.c (exception_handler_activated): Assume the fault is on the stack if it is one page above or three pages below the stack pointer. (exception_handler_init): Allocate an area of address space EXCEPTION_STACK_SIZE bytes larges. Fill it with pages. Set the first page as the thread's exception page and the top of the area minus one word as the stack pointer. Set the last word to the location of the exception page. * ia32-exception-entry.S: Include . (PAGESIZE): Don't define. (_exception_handler_entry): Rewrite to not assume that the exception page is at the start of the page in which the stack pointer is, but at the location stored in the word after the bottom of the stack. * Makefile.am (libhurd_mm_a_CCASFLAGS): New variable. * pager.c (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE bytes large. Write to each page. libpthread/ 2008-05-29 Neal H. Walfield * sysdeps/l4/hurd/pt-sysdep.h Include . (EXCEPTION_AREA_SIZE): Define. (EXCEPTION_AREA_SIZE_LOG2): Likewise. (EXCEPTION_PAGE): Likewise. (PTHREAD_SYSDEP_MEMBERS): Change object's type to an addr_t. Update users. Remove field exception_page, replace with exception_area. Add field exception_area_va. * sysdeps/l4/hurd/pt-thread-alloc.c: Include and . (__pthread_thread_alloc): Allocate EXCEPTION_AREA_SIZE bytes of address space. Save it in THREAD->EXCEPTION_AREA_VA. Allocate a page for each page in that area. Save them in THREAD->EXCEPTION_AREA. * sysdeps/l4/hurd/ia32/pt-setup.c (__pthread_setup): Set EXCEPTION_PAGE->EXCEPTION_HANDLER_SP to the end of EXCEPTION_PAGE->EXCEPTION_HANDLER_SP minus one word, in which we save the address of the exception page. * sysdeps/l4/hurd/pt-thread-start.c (__pthread_thread_start): Set IN.EXCEPTION_PAGE to the first page in THREAD->EXCEPTION_AREA_VA. * sysdeps/l4/hurd/pt-thread-halt.c: Include , and . (saved_object_lock): New variable. (__pthread_thread_halt): Lock SAVED_OBJECT_LOCK when accessing SAVED_OBJECT. Free the address space used by the exception area (THREAD->EXCEPTION_AREA_VA) and its associated storage (THREAD->EXCEPTION_AREA). hurd/ 2008-05-29 Neal H. Walfield * exceptions.h: Include . [ASM]: Only define relevant macros. (EXCEPTION_STACK_SIZE_LOG2): Define. (EXCEPTION_STACK_SIZE): Define. * stddef.h [ASM]: Only define relevant macros. (PAGESIZE): Don't append C type specifier. (PAGESIZE_LOG2): Likewise. viengoos/ 2008-05-29 Neal H. Walfield * as.c: Include . (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE bytes large. Write to each page. * cap-lookup.c: Include . (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE bytes large. Write to each page. * zalloc.c (ZONE_SIZE): Add suffix the 1 with a U type qualifier. (ZONES): Include one less zone. --- sysdeps/l4/hurd/ia32/pt-setup.c | 16 +++--- sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c | 6 +-- sysdeps/l4/hurd/pt-setactivity-np.c | 2 +- sysdeps/l4/hurd/pt-sysdep.h | 16 ++++-- sysdeps/l4/hurd/pt-thread-alloc.c | 53 ++++++++++++------ sysdeps/l4/hurd/pt-thread-halt.c | 72 +++++++++++++++++-------- sysdeps/l4/hurd/pt-thread-start.c | 5 +- 7 files changed, 114 insertions(+), 56 deletions(-) diff --git a/sysdeps/l4/hurd/ia32/pt-setup.c b/sysdeps/l4/hurd/ia32/pt-setup.c index f5987797..cc2f0757 100644 --- a/sysdeps/l4/hurd/ia32/pt-setup.c +++ b/sysdeps/l4/hurd/ia32/pt-setup.c @@ -1,4 +1,4 @@ -/* Setup thread stack. Hurd/i386 version. +/* Setup thread stack. Viengoos/i386 version. Copyright (C) 2000, 2002, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -96,14 +96,16 @@ __pthread_setup (struct __pthread *thread, if (__pthread_num_threads == 1) return 0; - assert (! ADDR_IS_VOID (thread->exception_page.addr)); + assert (! ADDR_IS_VOID (thread->exception_area[0])); - struct exception_page *exception_page - = ADDR_TO_PTR (addr_extend (thread->exception_page.addr, - 0, PAGESIZE_LOG2)); + struct exception_page *exception_page = thread->exception_area_va; - /* SP is set to the end of the exception page. */ - exception_page->exception_handler_sp = (uintptr_t) exception_page + PAGESIZE; + /* SP is set to the end of the exception area minus one word, which + is the location of the exception page. */ + exception_page->exception_handler_sp + = (uintptr_t) thread->exception_area_va + EXCEPTION_AREA_SIZE; + exception_page->exception_handler_sp -= sizeof (void *); + * (void **) exception_page->exception_handler_sp = thread->exception_area_va; exception_page->exception_handler_ip = (uintptr_t) &exception_handler_entry; exception_page->exception_handler_end = (uintptr_t) &exception_handler_end; diff --git a/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c b/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c index bb6ac2a5..37ef8215 100644 --- a/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c +++ b/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c @@ -124,13 +124,13 @@ signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, struct hurd_thread_exregs_out out; error_t err; - err = rm_thread_exregs (ADDR_VOID, thread->object.addr, + err = rm_thread_exregs (ADDR_VOID, thread->object, HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC | HURD_EXREGS_GET_REGS, in, &out); if (err) panic ("Failed to modify thread " ADDR_FMT, - ADDR_PRINTF (thread->object.addr)); + ADDR_PRINTF (thread->object)); intr_sp = out.sp; @@ -205,7 +205,7 @@ signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, in.sp = sp; in.ip = (uintptr_t) &_signal_dispatch_entry; - rm_thread_exregs (ADDR_VOID, thread->object.addr, + rm_thread_exregs (ADDR_VOID, thread->object, HURD_EXREGS_SET_SP_IP | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, in, &out); diff --git a/sysdeps/l4/hurd/pt-setactivity-np.c b/sysdeps/l4/hurd/pt-setactivity-np.c index dbadb68f..f2f07233 100644 --- a/sysdeps/l4/hurd/pt-setactivity-np.c +++ b/sysdeps/l4/hurd/pt-setactivity-np.c @@ -31,7 +31,7 @@ pthread_setactivity_np (addr_t activity) in.activity = activity; struct hurd_thread_exregs_out out; - int err = rm_thread_exregs (ADDR_VOID, self->object.addr, + int err = rm_thread_exregs (ADDR_VOID, self->object, HURD_EXREGS_SET_ACTIVITY, in, &out); diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h index 5c66330e..08bcd143 100644 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ b/sysdeps/l4/hurd/pt-sysdep.h @@ -1,5 +1,5 @@ -/* Internal defenitions for pthreads library. - Copyright (C) 2000, 2002, 2005, 2007 Free Software Foundation, Inc. +/* Internal definitions for pthreads library. + Copyright (C) 2000, 2002, 2005, 2007, 2008 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 @@ -30,10 +30,18 @@ /* The default stack size: 2MB. */ #define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) +#include + +#define EXCEPTION_AREA_SIZE EXCEPTION_STACK_SIZE +#define EXCEPTION_AREA_SIZE_LOG2 EXCEPTION_STACK_SIZE_LOG2 +/* The exception page is the first object. */ +#define EXCEPTION_PAGE 0 + #define PTHREAD_SYSDEP_MEMBERS \ - struct storage object; \ + addr_t object; \ l4_thread_id_t threadid; \ - struct storage exception_page; \ + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; \ + void *exception_area_va; \ l4_word_t my_errno; extern inline struct __pthread * diff --git a/sysdeps/l4/hurd/pt-thread-alloc.c b/sysdeps/l4/hurd/pt-thread-alloc.c index daa13dba..6941e10e 100644 --- a/sysdeps/l4/hurd/pt-thread-alloc.c +++ b/sysdeps/l4/hurd/pt-thread-alloc.c @@ -1,4 +1,4 @@ -/* Allocate kernel thread. Hurd/L4 version. +/* Allocate kernel thread. Viengoos version. Copyright (C) 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -23,6 +23,8 @@ #include #include +#include +#include #include @@ -36,40 +38,57 @@ __pthread_thread_alloc (struct __pthread *thread) /* The main thread is already running of course. */ if (__pthread_num_threads == 1) { - thread->object.addr = __hurd_startup_data->thread; - /* If the main thread exits, then we wait. Thus, we don't need - the shadow cap. */ - thread->object.cap = NULL; + thread->object = __hurd_startup_data->thread; thread->threadid = l4_myself (); return 0; } else { - struct storage storage; + addr_t exception_area = as_alloc (EXCEPTION_AREA_SIZE_LOG2, 1, true); - /* We can't don't use mmap as when the exception thread starts - running and it accesses its stack, it will fault, which we - naturally cannot handle. */ - storage = storage_alloc (ADDR_VOID, cap_page, - STORAGE_UNKNOWN, OBJECT_POLICY_DEFAULT, - ADDR_VOID); - if (ADDR_IS_VOID (storage.addr)) - return EAGAIN; + thread->exception_area_va + = ADDR_TO_PTR (addr_extend (exception_area, + 0, EXCEPTION_AREA_SIZE_LOG2)); - thread->exception_page = storage; + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + addr_t slot = addr_chop (PTR_TO_ADDR (thread->exception_area_va + + i * PAGESIZE), + PAGESIZE_LOG2); + as_slot_ensure (slot); + struct storage storage = storage_alloc (ADDR_VOID, cap_page, + STORAGE_LONG_LIVED, + OBJECT_POLICY_DEFAULT, + slot); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < i; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + thread->exception_area[i] = storage.addr; + } + + struct storage storage; storage = storage_alloc (meta_data_activity, cap_thread, /* Threads are rarely shortly lived. */ STORAGE_MEDIUM_LIVED, OBJECT_POLICY_DEFAULT, ADDR_VOID); if (ADDR_IS_VOID (storage.addr)) { - storage_free (thread->exception_page.addr, false); + int j; + for (j = 0; j < EXCEPTION_AREA_SIZE / PAGESIZE; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); return EAGAIN; } - thread->object = storage; + thread->object = storage.addr; } return 0; diff --git a/sysdeps/l4/hurd/pt-thread-halt.c b/sysdeps/l4/hurd/pt-thread-halt.c index 1e9a8ee6..98fefaab 100644 --- a/sysdeps/l4/hurd/pt-thread-halt.c +++ b/sysdeps/l4/hurd/pt-thread-halt.c @@ -1,5 +1,5 @@ -/* Deallocate the kernel thread resources. L4/Hurd version. - Copyright (C) 2007 Software Foundation, Inc. +/* Deallocate the kernel thread resources. Viengoos version. + Copyright (C) 2007, 2008 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 @@ -23,47 +23,75 @@ #include #include +#include +#include +#include /* If we try to deallocate our self, we will end up causing a deadlock. Thus, when a thread tries to free itself, we add it here. The next thread to free a thread will free it. */ -static struct storage saved_object; +ss_mutex_t saved_object_lock; +static addr_t saved_object; void __pthread_thread_halt (struct __pthread *thread, int need_dealloc) { - struct storage exception_page = thread->exception_page; - thread->exception_page.addr = ADDR_VOID; + /* We may deallocate THREAD. First save any data we need. */ - struct storage object = thread->object; + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; + memcpy (exception_area, thread->exception_area, + sizeof (thread->exception_area)); + memset (thread->exception_area, 0, sizeof (thread->exception_area)); + + void *va = thread->exception_area_va; + + addr_t object = thread->object; l4_thread_id_t tid = thread->threadid; if (need_dealloc) __pthread_dealloc (thread); - if (! ADDR_IS_VOID (saved_object.addr)) + /* The THREAD data structure is no longer valid. */ + thread = NULL; + + /* Deallocate any saved object. */ + ss_mutex_lock (&saved_object_lock); + if (! ADDR_IS_VOID (saved_object)) + { + storage_free (saved_object, false); + saved_object = ADDR_VOID; + } + ss_mutex_unlock (&saved_object_lock); + + /* Free the exception area. */ + + /* Clean up the exception page. */ + exception_page_cleanup + (ADDR_TO_PTR (addr_extend (exception_area[EXCEPTION_PAGE], + 0, PAGESIZE_LOG2))); + + /* Free the storage. */ + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) { - storage_free (saved_object.addr, false); - saved_object.cap->type = cap_void; - saved_object.addr = ADDR_VOID; + assert (! ADDR_IS_VOID (exception_area[i])); + storage_free (exception_area[i], false); } - /* Free the exception page. */ - assert (! ADDR_IS_VOID (exception_page.addr)); - exception_page_cleanup (ADDR_TO_PTR (addr_extend (exception_page.addr, - 0, PAGESIZE_LOG2))); - storage_free (exception_page.addr, false); + /* And the address space. */ + as_free (addr_chop (PTR_TO_ADDR (va), EXCEPTION_AREA_SIZE_LOG2), false); if (tid == l4_myself ()) /* If we try to storage_free (storage.addr), we will freeze in the - middle. That's no good. Thus, we add ourself to the pool of - available objects. */ - saved_object = object; - else + middle. That's no good. We set SAVED_OBJECT to our thread + object and the next thread in will free us. */ { - storage_free (object.addr, false); - object.cap->type = cap_void; + ss_mutex_lock (&saved_object_lock); + saved_object = object; + ss_mutex_unlock (&saved_object_lock); } + else + storage_free (object, false); if (tid == l4_myself ()) { @@ -72,5 +100,5 @@ __pthread_thread_halt (struct __pthread *thread, int need_dealloc) l4_thread_no (l4_myself ()), l4_version (l4_myself ())); } else - thread_stop (object.addr); + thread_stop (object); } diff --git a/sysdeps/l4/hurd/pt-thread-start.c b/sysdeps/l4/hurd/pt-thread-start.c index 131f59d6..9db399ce 100644 --- a/sysdeps/l4/hurd/pt-thread-start.c +++ b/sysdeps/l4/hurd/pt-thread-start.c @@ -48,13 +48,14 @@ __pthread_thread_start (struct __pthread *thread) in.activity = ADDR_VOID; - in.exception_page = thread->exception_page.addr; + in.exception_page = addr_chop (PTR_TO_ADDR (thread->exception_area_va), + PAGESIZE_LOG2); in.sp = (l4_word_t) thread->mcontext.sp; in.ip = (l4_word_t) thread->mcontext.pc; in.user_handle = (l4_word_t) thread; - err = rm_thread_exregs (ADDR_VOID, thread->object.addr, + err = rm_thread_exregs (ADDR_VOID, thread->object, HURD_EXREGS_SET_ASPACE | HURD_EXREGS_SET_ACTIVITY | HURD_EXREGS_SET_EXCEPTION_PAGE -- cgit v1.2.3 From 0e6cde437729f8b7111284e43bed778b0745fd59 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Thu, 29 May 2008 21:56:09 +0000 Subject: 2008-05-29 Thomas Schwinge * sysdeps/generic/sem-timedwait.c: Don't include . --- sysdeps/generic/sem-timedwait.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sysdeps/generic/sem-timedwait.c b/sysdeps/generic/sem-timedwait.c index d01bfdb0..995cf099 100644 --- a/sysdeps/generic/sem-timedwait.c +++ b/sysdeps/generic/sem-timedwait.c @@ -1,5 +1,5 @@ /* Wait on a semaphore with a timeout. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2008 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 @@ -18,7 +18,6 @@ Boston, MA 02111-1307, USA. */ #include -#include #include #include -- cgit v1.2.3 From 61f38c39b247dd0e9fe980690db56c34ca1384ec Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 30 May 2008 00:34:53 +0000 Subject: 2008-05-29 Thomas Schwinge * headers.m4: Link files into `sysroot/include/' instead of `include/'. Create symbolic link to package's library in `sysroot/lib/'. * Makefile.am [ENABLE_TESTS]: Don't build package's library. --- Makefile.am | 3 +++ headers.m4 | 52 +++++++++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0dae132a..3c7e63db 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,7 +46,10 @@ AM_CFLAGS = $(USER_CFLAGS) # Sources. SYSDEPS := lockfile.c +if ! ENABLE_TESTS noinst_LIBRARIES = libpthread.a +endif + libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-attr-getguardsize.c pt-attr-getinheritsched.c \ pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ diff --git a/headers.m4 b/headers.m4 index 2fde3a62..1812e7d0 100644 --- a/headers.m4 +++ b/headers.m4 @@ -11,27 +11,33 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. AC_CONFIG_LINKS([ - include/pthread.h:libpthread/include/pthread.h - include/pthread/pthread.h:libpthread/include/pthread/pthread.h - include/bits/memory.h:libpthread/sysdeps/${arch}/bits/memory.h - include/bits/spin-lock.h:libpthread/sysdeps/${arch}/bits/spin-lock.h - include/bits/pthreadtypes.h:libpthread/sysdeps/generic/bits/pthreadtypes.h - include/bits/barrier-attr.h:libpthread/sysdeps/generic/bits/barrier-attr.h - include/bits/barrier.h:libpthread/sysdeps/generic/bits/barrier.h - include/bits/cancelation.h:libpthread/sysdeps/generic/bits/cancelation.h - include/bits/condition-attr.h:libpthread/sysdeps/generic/bits/condition-attr.h - include/bits/condition.h:libpthread/sysdeps/generic/bits/condition.h - include/bits/mutex-attr.h:libpthread/sysdeps/generic/bits/mutex-attr.h - include/bits/mutex.h:libpthread/sysdeps/generic/bits/mutex.h - include/bits/once.h:libpthread/sysdeps/generic/bits/once.h - include/bits/pthread.h:libpthread/sysdeps/generic/bits/pthread.h - include/bits/rwlock-attr.h:libpthread/sysdeps/generic/bits/rwlock-attr.h - include/bits/rwlock.h:libpthread/sysdeps/generic/bits/rwlock.h - include/bits/thread-attr.h:libpthread/sysdeps/generic/bits/thread-attr.h - include/bits/thread-barrier.h:libpthread/sysdeps/generic/bits/thread-barrier.h - include/bits/thread-specific.h:libpthread/sysdeps/generic/bits/thread-specific.h - include/bits/pthread-np.h:libpthread/sysdeps/l4/hurd/bits/pthread-np.h - include/semaphore.h:libpthread/include/semaphore.h - include/bits/semaphore.h:libpthread/sysdeps/generic/bits/semaphore.h - include/signal.h:libpthread/signal/signal.h + sysroot/include/pthread.h:libpthread/include/pthread.h + sysroot/include/pthread/pthread.h:libpthread/include/pthread/pthread.h + sysroot/include/bits/memory.h:libpthread/sysdeps/${arch}/bits/memory.h + sysroot/include/bits/spin-lock.h:libpthread/sysdeps/${arch}/bits/spin-lock.h + sysroot/include/bits/pthreadtypes.h:libpthread/sysdeps/generic/bits/pthreadtypes.h + sysroot/include/bits/barrier-attr.h:libpthread/sysdeps/generic/bits/barrier-attr.h + sysroot/include/bits/barrier.h:libpthread/sysdeps/generic/bits/barrier.h + sysroot/include/bits/cancelation.h:libpthread/sysdeps/generic/bits/cancelation.h + sysroot/include/bits/condition-attr.h:libpthread/sysdeps/generic/bits/condition-attr.h + sysroot/include/bits/condition.h:libpthread/sysdeps/generic/bits/condition.h + sysroot/include/bits/mutex-attr.h:libpthread/sysdeps/generic/bits/mutex-attr.h + sysroot/include/bits/mutex.h:libpthread/sysdeps/generic/bits/mutex.h + sysroot/include/bits/once.h:libpthread/sysdeps/generic/bits/once.h + sysroot/include/bits/pthread.h:libpthread/sysdeps/generic/bits/pthread.h + sysroot/include/bits/rwlock-attr.h:libpthread/sysdeps/generic/bits/rwlock-attr.h + sysroot/include/bits/rwlock.h:libpthread/sysdeps/generic/bits/rwlock.h + sysroot/include/bits/thread-attr.h:libpthread/sysdeps/generic/bits/thread-attr.h + sysroot/include/bits/thread-barrier.h:libpthread/sysdeps/generic/bits/thread-barrier.h + sysroot/include/bits/thread-specific.h:libpthread/sysdeps/generic/bits/thread-specific.h + sysroot/include/bits/pthread-np.h:libpthread/sysdeps/l4/hurd/bits/pthread-np.h + sysroot/include/semaphore.h:libpthread/include/semaphore.h + sysroot/include/bits/semaphore.h:libpthread/sysdeps/generic/bits/semaphore.h + sysroot/include/signal.h:libpthread/signal/signal.h +]) + +AC_CONFIG_COMMANDS_POST([ + mkdir -p sysroot/lib libpthread && + ln -sf ../../libpthread/libpthread.a sysroot/lib/ && + touch libpthread/libpthread.a ]) -- cgit v1.2.3 From 4a4fd9acc62e401c034717d0b5772c96291d24a2 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sun, 1 Jun 2008 20:25:36 +0000 Subject: 2008-06-01 Neal H. Walfield * include/pthread/pthread.h (PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP): New definition. * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_RECURSIVE_INITIALIZER): New definition. * sysdeps/generic/bits/mutex-attr.h (__pthread_recursive_mutexattr): New definition. * sysdeps/generic/pt-mutexattr.c (__pthread_recursive_mutexattr): New declaration. * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): If ATTR is &__PTHREAD_RECURSIVE_MUTEXATTR, don't allocate a copy, just save in MUTEX->ATTR. * sysdeps/generic/pt-mutex-destroy.c (_pthread_mutex_destroy): If MUTEX->ATTR is &__PTHREAD_RECURSIVE_MUTEXATTR, don't free it. --- sysdeps/generic/bits/mutex-attr.h | 5 ++++- sysdeps/generic/bits/mutex.h | 6 +++++- sysdeps/generic/pt-mutex-destroy.c | 7 +++++-- sysdeps/generic/pt-mutex-init.c | 11 ++++++++--- sysdeps/generic/pt-mutexattr.c | 10 +++++++++- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/sysdeps/generic/bits/mutex-attr.h b/sysdeps/generic/bits/mutex-attr.h index 883b0746..420d5d1c 100644 --- a/sysdeps/generic/bits/mutex-attr.h +++ b/sysdeps/generic/bits/mutex-attr.h @@ -1,5 +1,5 @@ /* Mutex attribute type. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2008 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 @@ -30,4 +30,7 @@ struct __pthread_mutexattr enum __pthread_mutex_type mutex_type; }; +/* Attributes for a recursive mutex. */ +extern const struct __pthread_mutexattr __pthread_recursive_mutexattr; + #endif /* bits/mutex-attr.h */ diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 1aaf80ed..e0ae3db1 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -1,5 +1,5 @@ /* Mutex type. Generic version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2008 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 @@ -54,6 +54,10 @@ struct __pthread_mutex # define __PTHREAD_MUTEX_INITIALIZER \ { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } +# define __PTHREAD_MUTEX_RECURSIVE_INITIALIZER \ + { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, \ + (struct __pthread_mutexattr *) &__pthread_recursive_mutexattr, 0, 0, 0 } + # endif #endif /* Not __pthread_mutex_defined. */ diff --git a/sysdeps/generic/pt-mutex-destroy.c b/sysdeps/generic/pt-mutex-destroy.c index 72faefe6..0c9d5140 100644 --- a/sysdeps/generic/pt-mutex-destroy.c +++ b/sysdeps/generic/pt-mutex-destroy.c @@ -1,5 +1,5 @@ /* Destroy a mutex. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000,02, 2008 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 @@ -26,7 +26,10 @@ int _pthread_mutex_destroy (pthread_mutex_t *mutex) { - if (mutex->attr) + if (mutex->attr == &__pthread_recursive_mutexattr) + /* Static attributes. */ + ; + else free (mutex->attr); return 0; diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c index da1781bf..83f5b185 100644 --- a/sysdeps/generic/pt-mutex-init.c +++ b/sysdeps/generic/pt-mutex-init.c @@ -1,5 +1,5 @@ /* Initialize a mutex. Generic version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2008 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 @@ -32,10 +32,15 @@ _pthread_mutex_init (pthread_mutex_t *mutex, if (! attr || memcmp (attr, &__pthread_default_mutexattr, sizeof (*attr) == 0)) - /* Use the default attributes. */ + /* The default attributes. */ return 0; - /* Non-default attributes. */ + if (attr == &__pthread_recursive_mutexattr) + /* Non-default but known attributes. */ + { + mutex->attr = attr; + return 0; + } mutex->attr = malloc (sizeof *attr); if (! mutex->attr) diff --git a/sysdeps/generic/pt-mutexattr.c b/sysdeps/generic/pt-mutexattr.c index 647db241..d80a7d74 100644 --- a/sysdeps/generic/pt-mutexattr.c +++ b/sysdeps/generic/pt-mutexattr.c @@ -1,5 +1,5 @@ /* Default mutex attributes. Generic version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 @@ -27,3 +27,11 @@ const struct __pthread_mutexattr __pthread_default_mutexattr = pshared: PTHREAD_PROCESS_PRIVATE, mutex_type: PTHREAD_MUTEX_DEFAULT }; + +const struct __pthread_mutexattr __pthread_recursive_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_RECURSIVE +}; -- cgit v1.2.3 From 7b6b0d0cb32b5501baee7277cedf66716e81e03f Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 5 Jun 2008 13:21:02 +0000 Subject: viengoos/ 2008-06-05 Neal H. Walfield * cap-lookup.c: Move from here... * ../libhurd-mm/as-lookup.c: ... to here. * as.c: Move from here... * ../libhurd-mm/as-build.c: ... to here. * as-custom.c: Move from here... * ../libhurd-mm/as-build-custom.c: ... to here. * as.h: Move contents... * ../libhurd-mm/as.h: ... to here... * ../libhurd-mm/as-compute-gbits.h: ... and to here. * bits.h: Move from here... * ../libhurd-mm/bits.h: ... to here. * Makefile.am (viengoos_SOURCES): Remove cap-lookup.c, as.h and as.c. (t_as_SOURCES): Likewise. (t_activity_SOURCES): Likewise. (viengoos_LDADD): Add ../libhurd-mm/libas-kernel.a. (t_as_LDADD): Add ../libhurd-mm/libas-check.a. (t_activity_LDADD): Likewise. (lib_LIBRARIES): Remove libhurd-cap.a. (libhurd_cap_a_CPPFLAGS): Remove variable. (libhurd_cap_a_CFLAGS): Likewise. (libhurd_cap_a_SOURCES): Likewise. * server.c (server_loop): Replace use of object_lookup_rel with as_object_lookup_rel. Replace use of slot_lookup_rel with as_slot_lookup_rel_use. Replace use of cap_lookup_rel with as_cap_lookup_rel. * viengoos.c: Don't include "as.h", include . * t-activity.c: Don't include "as.h", include . (allocate_object): Change return type to struct as_allocate_pt_ret. * t-as.c: Don't include "as.h", include . (allocate_object): Change return type to struct as_allocate_pt_ret. (allocate_page_table): New function. (try): Replace use of as_insert with as_insert_full. Replace use of slot_lookup_rel with as_slot_lookup_rel_use. Replace use of object_lookup_rel with as_object_lookup_rel. (test): Likewise. * t-guard.c: Don't include "as.h", include . Include "../libhurd-mm/as-compute-gbits.h". libhurd-mm/ 2008-06-05 Neal H. Walfield * as.h: Include . [! RM_INTERN]: Include and . (as_lock_ensure_stack) [! RM_INTERN]: New function. (as_lock): New function. (as_lock_readonly): Likewise. (as_unlock): Likewise. (meta_data_activity) [RM_INTERN]: Don't declare. (shadow_root) [RM_INTERN]: Don't declare. (struct as_insert_rt): Rename from this... (struct as_allocate_pt_ret): ... to this. Update users. (as_allocate_page_table_t): New typedef. (as_allocate_page_table): New declaration. (as_build): New declaration. (as_build_custom): Likewise. (as_slot_ensure): Remove declaration. (as_ensure_full): New macro. (as_ensure_use) [! RM_INTERN]: Likewise. (as_ensure) [! RM_INTERN]: New function. (as_insert): Rename from this... (as_insert_full): ... to this. Don't return the capability. Reverse the order of the source address and cap. Replace allocate_object parameter with an allocate_page_table parameter. Update users. (as_insert) [! RM_INTERN]: New function. (as_slot_ensure_full_custom): Rename from this... (as_ensure_full_custom): ... to this. Replace allocate_object parameter with an allocate_page_table parameter. (as_insert_custom): Likewise. (union as_lookup_ret): New definition. (as_lookup_want_cap): New definition. (as_lookup_want_slot): Likewise. (as_lookup_want_object): Likewise. (as_lookup_rel): New declaration. (slot_lookup): Remove declaration. (as_slot_lookup_rel_use): Replace it with this macro. (as_slot_lookup_use) [! RM_INTERN]: New macro. (as_cap_lookup_rel): New function. (cap_lookup): Rename from this... (as_cap_lookup) [! RM_INTERN]: ... to this. Remove activity parameter. Implement here as a static inline function. (as_object_lookup_rel): New function. (object_lookup): Rename from this... (as_object_lookup) [! RM_INTERN]: ... to this. Remove activity parameter. Implement here as a static inline function. (as_dump_from): New declaration. * as-compute-gbits.h: Include . * as.c (allocate_object): Rename from this... (as_allocate_page_table): ... to this. Remove static qualifier. Don't take parameter type, just allocate a cap_cappage. (as_slot_ensure): Remove function. (as_init): Replace use of slot_lookup_rel with as_slot_lookup_use or as_cap_lookup as appropriate. (cap_lookup): Remove function. (object_lookup): Likewise. (slot_lookup): Likewise. (as_dump): Likewise. * as-build.c: Don't include "as.h", but . Include , "as-compute-gbits.h". [RM_INTERN]: Don't include "object.h" but "../viengoos/object.h". (CUSTOM) [ID_SUFFIX]: Define. (as_build_internal): Rename from this... (as_build): ... to this. Remove static qualifier. Replace parameter allocate_object with allocate_page_table. Use it instead. (as_slot_ensure_full): Remove function. (as_insert): Likewise. * as-build-custom.c (as_object_index_t): Remove definition. (AS_LOCK): Don't define. (AS_UNLOCK): Don't define. (as_ensure_full_custom): New function. (as_insert_custom): Likewise. * as-lookup.c: Include . [RM_INTERN]: Don't include "object.h" but "../viengoos/object.h". [! RM_INTERN]: Include . (as_lock) [! RM_INTERN]: Rename from this... (as_rwlock) [! RM_INTERN]: ... to this. (ensure_stack) [! RM_INTERN]: Remove function. (AS_LOCK): Don't define. (AS_UNLOCK): Don't define. (lookup): Rename from this... (as_lookup_rel): ... to this. Change mode's type to an enum as_lookup_mode. Change rt's type to a union as_lookup_ret. Don't use want_object but as_lookup_want_object. Don't use want_slot but as_lookup_want_slot. Don't use want_cap but as_lookup_want_cap. (cap_lookup_rel): Remove function. (object_lookup_rel): Likewise. (slot_lookup_rel): Likewise. (print_nr): Move from here... * as-lookup.c (do_walk): Move from here... * as-dump.c (do_walk): ... to here. * as-lookup.c (as_dump_from): Move from here... * as-dump.c (as_dump_from): ... to here. * Makefile.am (lib_LIBRARIES) [ENABLE_TESTS]: Set to libas-check.a (lib_LIBRARIES) [! ENABLE_TESTS]: Add libas-kernel.a. (libhurd_mm_a_SOURCES): Add bits., as-build.c as-build-custom.c, as-lookup.c and as-dump.c. (libas_kernel_a_CPPFLAGS): New variable. (libas_kernel_a_CCASFLAGS): New variable. (libas_kernel_a_CFLAGS): New variable. (libas_kernel_a_SOURCES): New variable. (libas_check_a_CPPFLAGS): New variable. (libas_check_a_CCASFLAGS): New variable. (libas_check_a_CFLAGS): New variable. (libas_check_a_SOURCES): New variable. * anonymous.c (fault): Replace use of as_slot_ensure with as_ensure. * exceptions.c (exception_handler_init): Replace use of as_slot_ensure with as_ensure. * storage.c (storage_check_reserve_internal): Replace use of as_lock with as_rwlock. Replace use of as_slot_ensure with and slot_lookup with as_ensure and as_slot_lookup_use. (storage_alloc): Replace use of slot_lookup with as_slot_lookup_use. hurd/ 2008-06-05 Neal H. Walfield * cap.h: Don't include . (as_lock): Remove declaration. (cap_lookup_rel): Likewise. (object_lookup_rel): Likewise. (slot_lookup_rel): Likewise. / 2008-06-05 Neal H. Walfield * libc.a.in: Remove -lhurd-cap. * Makefile.am (libc-stmp): Remove dependency on viengoos/libhurd-cap.a. 2008-06-05 Neal H. Walfield * process-spawn.c (as_insert_custom): Replace use of as_insert with as_insert_full. (allocate_object): Change return type to struct as_allocate_pt_ret. Replace use of as_slot_ensure with as_ensure_use. (allocate_page_table): New function. (process_spawn): Update use of as_insert_custom to be consistent with new API, in particular, pass allocate_page_table instead of allocate_object. Replace use of object_lookup_rel with as_object_lookup_rel. libpthread/ 2008-06-05 Neal H. Walfield * sysdeps/l4/hurd/pt-thread-alloc.c (__pthread_thread_alloc): Replace use of as_slot_ensure with as_ensure. ruth/ 2008-06-05 Neal H. Walfield * ruth.c (main): Replace use of slot_lookup with as_cap_lookup. Replace use of as_slot_ensure with as_ensure_use. Replace use of slot_lookup with as_slot_lookup_use. --- sysdeps/l4/hurd/pt-thread-alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysdeps/l4/hurd/pt-thread-alloc.c b/sysdeps/l4/hurd/pt-thread-alloc.c index 6941e10e..ada7b3b8 100644 --- a/sysdeps/l4/hurd/pt-thread-alloc.c +++ b/sysdeps/l4/hurd/pt-thread-alloc.c @@ -56,7 +56,7 @@ __pthread_thread_alloc (struct __pthread *thread) addr_t slot = addr_chop (PTR_TO_ADDR (thread->exception_area_va + i * PAGESIZE), PAGESIZE_LOG2); - as_slot_ensure (slot); + as_ensure (slot); struct storage storage = storage_alloc (ADDR_VOID, cap_page, STORAGE_LONG_LIVED, -- cgit v1.2.3 From 087d4b47215d95828863334b96edaad262ff6d02 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sat, 7 Jun 2008 15:25:02 +0000 Subject: 2008-06-07 Neal H. Walfield * pthread/pt-internal.h (__pthread_queue_iterate): Use 1, not true. (__pthread_dequeuing_iterate): Likewise. --- pthread/pt-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 853d739d..53e49e02 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -126,7 +126,7 @@ __pthread_dequeue (struct __pthread *thread) for (struct __pthread *__pdi_next = (queue); \ ((element) = __pdi_next) \ && ((__pdi_next = __pdi_next->next), \ - true); \ + 1); \ ) /* Iterate over QUEUE dequeuing each element, storing it in @@ -136,7 +136,7 @@ __pthread_dequeue (struct __pthread *thread) ((element) = __pdi_next) \ && ((__pdi_next = __pdi_next->next), \ ((element)->prevp = 0), \ - true); \ + 1); \ ) /* The total number of threads currently active. */ -- cgit v1.2.3 From 6f18deca8f1d582f2d870c1431a83d1e47a3eac2 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sun, 22 Jun 2008 08:58:20 +0000 Subject: 2008-06-22 Neal H. Walfield * sysdeps/generic/pt-mutex-timedlock.c (__pthread_mutex_timedlock_internal): Don't set MUTEX->OWNER here. * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): Set it here to WAKEUP. --- sysdeps/generic/pt-mutex-timedlock.c | 11 ++++++----- sysdeps/generic/pt-mutex-unlock.c | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index 6db30c5d..265a4530 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -141,15 +141,16 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, else __pthread_block (self); - if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) - { #ifndef NDEBUG - mutex->owner = self; + assert (mutex->owner == self); #endif - } - else + + if (mutex->attr) switch (mutex->attr->mutex_type) { + case PTHREAD_MUTEX_NORMAL: + break; + case PTHREAD_MUTEX_RECURSIVE: assert (mutex->locks == 0); mutex->locks = 1; diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index a9872252..492dfcb5 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -78,6 +78,10 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) wakeup = mutex->__queue; __pthread_dequeue (wakeup); +#ifndef NDEBUG + mutex->owner = wakeup; +#endif + /* We do not unlock MUTEX->held: we are transferring the ownership to the thread that we are waking up. */ -- cgit v1.2.3 From 7b6f91d24d9dcf1f87ab66866bcad5e35afc9b98 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sun, 22 Jun 2008 09:16:45 +0000 Subject: viengoos/ 2008-06-22 Neal H. Walfield * thread.h: Include "list.h". (struct thread) [! NDEBUG]: Add field futex_waiter_node. [! NDEBUG]: Instantiate the futex_waiter list class. (futex_waiters) [! NDEBUG]: Declare. * server.c (futex_waiters) [! NDEBUG]: New variable. (server_loop) [! NDEBUG]: If we don't get an RPC for a while, dequeue all thread's enqueued on FUTEX_WAITERS and return EDEADLK. When blocking a thread on a futex, add THREAD to FUTEX_WAITERS. * object.c (object_wait_queue_dequeue) [! NDEBUG]: If THREAD->WAIT_REASON is THREAD_WAIT_FUTEX, unlink THREAD from FUTEX_WAITERS. hurd/ 2008-06-22 Neal H. Walfield * futex.h [! RM_INTERN]: Include . (futex_wait): On error, set ERRNO and return -1. (futex_timed_wait): Likewise. (futex_wake): Likewise. * mutex.h (ss_mutex_lock): If FUTEX_WAIT returns failure, print some debugging information. --- sysdeps/generic/pt-mutex-unlock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index 492dfcb5..d2a42570 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -37,7 +37,12 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) if (_pthread_self ()) { assert (mutex->owner); - assert (mutex->owner == _pthread_self ()); + assertx (mutex->owner == _pthread_self (), + "%p(%x) != %p(%x)", + mutex->owner, + ((struct __pthread *) mutex->owner)->threadid, + _pthread_self (), + _pthread_self ()->threadid); mutex->owner = NULL; } #endif -- cgit v1.2.3 From 4adf127763d39abcbaa67069ae4ddceaf9a6857b Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 12 Aug 2008 13:31:49 +0000 Subject: libpthread/ 2008-08-12 Neal H. Walfield * sysdeps/generic/bits/mutex.h (__PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Define. (__PTHREAD_MUTEX_RECURSIVE_INITIALIZER): Don't define. * include/pthread/pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) [__USE_GNU]: Define. (PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP): Don't define. libhurd-mm/ 2008-08-12 Neal H. Walfield * storage.c (storage_low_mutex): Use PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, not PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP. --- sysdeps/generic/bits/mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index f5f3fa94..15a83f49 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -57,7 +57,7 @@ struct __pthread_mutex # define __PTHREAD_MUTEX_INITIALIZER \ { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } -# define __PTHREAD_MUTEX_RECURSIVE_INITIALIZER \ +# define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, \ (struct __pthread_mutexattr *) &__pthread_recursive_mutexattr, 0, 0, 0 } -- cgit v1.2.3 From 70b389f511b78e5e52a6c1a7f699dece58d8e542 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 12 Aug 2008 14:00:52 +0000 Subject: 2008-08-12 Neal H. Walfield * sysdeps/generic/pt-startup.c (__pthread_startup): New file. --- sysdeps/generic/pt-startup.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 sysdeps/generic/pt-startup.c diff --git a/sysdeps/generic/pt-startup.c b/sysdeps/generic/pt-startup.c new file mode 100644 index 00000000..c21a1819 --- /dev/null +++ b/sysdeps/generic/pt-startup.c @@ -0,0 +1,25 @@ +/* Thread initialization. Generic version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +void +__pthread_startup (void) +{ +} -- cgit v1.2.3 From d4fb1c786dd502cee6135e0debd29a12f7746520 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 12 Aug 2008 14:03:34 +0000 Subject: 2006-03-04 Samuel Thibault * sysdeps/ia32/machine-sp.h (thread_stack_pointer): Optimize esp read. --- sysdeps/ia32/machine-sp.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sysdeps/ia32/machine-sp.h b/sysdeps/ia32/machine-sp.h index 39a8b69a..cef6ab72 100644 --- a/sysdeps/ia32/machine-sp.h +++ b/sysdeps/ia32/machine-sp.h @@ -23,8 +23,7 @@ /* Return the current stack pointer. */ #define __thread_stack_pointer() ({ \ - void *__sp__; \ - __asm__ ("movl %%esp, %0" : "=r" (__sp__)); \ + register void *__sp__ asm("esp"); \ __sp__; \ }) -- cgit v1.2.3 From 63dd6dd8f1d546d0b180fc4baf1e1fbd32deaa4d Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 12 Aug 2008 14:34:18 +0000 Subject: 2008-08-12 Neal H. Walfield * sysdeps/generic/bits/pthread-np.h: New file. --- sysdeps/generic/bits/pthread-np.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 sysdeps/generic/bits/pthread-np.h diff --git a/sysdeps/generic/bits/pthread-np.h b/sysdeps/generic/bits/pthread-np.h new file mode 100644 index 00000000..d5ddbb05 --- /dev/null +++ b/sysdeps/generic/bits/pthread-np.h @@ -0,0 +1,27 @@ +/* Non-portable functions. Generic version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#endif /* bits/pthread-np.h */ -- cgit v1.2.3 From bd70818a914257c32ca47623206632ed4a484802 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 12 Aug 2008 15:07:50 +0000 Subject: 2008-08-12 Neal H. Walfield Merge changes from hurd-l4 fork. * Makefile (SRCS): Add pt-startup.c and pt-mutex-transfer-np.c. (sysdeps_headers): Add pthread-np.h. 2008-08-12 Neal H. Walfield * sysdeps/generic/bits/pthread-np.h: New file. 2008-08-12 Neal H. Walfield * sysdeps/generic/pt-startup.c: New file. 2008-08-12 Neal H. Walfield * sysdeps/generic/bits/mutex.h (__PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Define. (__PTHREAD_MUTEX_RECURSIVE_INITIALIZER): Don't define. * include/pthread/pthread.h (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) [__USE_GNU]: Define. (PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP): Don't define. 2008-08-12 Neal H. Walfield * include/pthread/pthread.h: Include . (__extern_inline): If not defined, define appropriately. 2008-06-01 Neal H. Walfield * include/pthread/pthread.h (PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP): New definition. * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_RECURSIVE_INITIALIZER): New definition. * sysdeps/generic/bits/mutex-attr.h (__pthread_recursive_mutexattr): New definition. * sysdeps/generic/pt-mutexattr.c (__pthread_recursive_mutexattr): New declaration. * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): If ATTR is &__PTHREAD_RECURSIVE_MUTEXATTR, don't allocate a copy, just save in MUTEX->ATTR. * sysdeps/generic/pt-mutex-destroy.c (_pthread_mutex_destroy): If MUTEX->ATTR is &__PTHREAD_RECURSIVE_MUTEXATTR, don't free it. 2008-05-29 Thomas Schwinge * sysdeps/generic/sem-timedwait.c: Don't include . 2008-05-21 Neal H. Walfield * include/pthread/pthread.h: Include . 2008-03-01 Neal H. Walfield * sysdeps/generic/pt-mutex-transfer-np.c: New file. * pthread/pt-self.c (pthread_self): Assert that SELF is not NULL. 2007-12-23 Neal H. Walfield * pthread/pt-join.c (pthread_join): Cast argument to pthread_cleanup_push to avoid warning. 2007-11-23 Neal H. Walfield * pthread/pt-internal.h (__pthread_startup): Add declaration. * pthread/pt-create.c (entry_point): Call __pthread_startup. --- pthread/pt-alloc.c | 18 +++++------ pthread/pt-create.c | 8 ++--- pthread/pt-dealloc.c | 12 +++---- pthread/pt-exit.c | 4 +-- pthread/pt-internal.h | 12 ++----- sysdeps/generic/pt-mutex-unlock.c | 7 +---- sysdeps/hurd/pt-setspecific.c | 5 ++- sysdeps/ia32/bits/atomic.h | 66 +++++++++++++++++++++++++++++++++++++++ sysdeps/posix/pt-spin.c | 2 +- 9 files changed, 90 insertions(+), 44 deletions(-) create mode 100644 sysdeps/ia32/bits/atomic.h diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index 6cf9106b..30dcede0 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -1,5 +1,5 @@ /* Allocate a new thread structure. - Copyright (C) 2000, 2002, 2005, 2007 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 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 @@ -25,7 +25,7 @@ #include -#include +#include /* This braindamage is necessary because the standard says that some of the threads functions "shall fail" if "No thread could be found @@ -46,7 +46,7 @@ pthread_rwlock_t __pthread_threads_lock; /* List of thread structures corresponding to free thread IDs. */ -atomicptr_t __pthread_free_threads; +__atomicptr_t __pthread_free_threads; static inline error_t initialize_pthread (struct __pthread *new, int recycling) @@ -97,10 +97,8 @@ __pthread_alloc (struct __pthread **pthread) /* Try to re-use a thread structure before creating a new one. */ while ((new = (struct __pthread *)__pthread_free_threads)) { - if (atomic_compare_and_exchange_val_acq (&__pthread_free_threads, - (uintptr_t) new->next, - (uintptr_t) new) - == (uintptr_t) new) + if (__atomicptr_compare_and_swap (&__pthread_free_threads, + new, new->next)) { /* Yes, we managed to get one. The thread number in the thread structure still refers to the correct slot. */ @@ -112,10 +110,8 @@ __pthread_alloc (struct __pthread **pthread) while (1) { new->next = (struct __pthread *)__pthread_free_threads; - if (atomic_compare_and_exchange_val_acq - (&__pthread_free_threads, - (uintptr_t) new, (uintptr_t) new->next) - == (uintptr_t) new->next) + if (__atomicptr_compare_and_swap (&__pthread_free_threads, + new->next, new)) break; } diff --git a/pthread/pt-create.c b/pthread/pt-create.c index 5bb9f1f9..210f9672 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include @@ -33,7 +33,7 @@ /* The total number of pthreads currently active. This is defined here since it would be really stupid to have a threads-using program that doesn't call `pthread_create'. */ -atomic_fast32_t __pthread_total; +__atomic_t __pthread_total; /* The entry-point for new threads. */ @@ -163,7 +163,7 @@ __pthread_create_internal (struct __pthread **thread, the number of threads from within the new thread isn't an option since this thread might return and call `pthread_exit' before the new thread runs. */ - atomic_increment (&__pthread_total); + __atomic_inc (&__pthread_total); /* Store a pointer to this thread in the thread ID lookup table. We could use __thread_setid, however, we only lock for reading as no @@ -190,7 +190,7 @@ __pthread_create_internal (struct __pthread **thread, failed_starting: __pthread_setid (pthread->thread, NULL); - atomic_decrement (&__pthread_total); + __atomic_dec (&__pthread_total); failed_sigstate: __pthread_sigstate_destroy (pthread); failed_setup: diff --git a/pthread/pt-dealloc.c b/pthread/pt-dealloc.c index 879608b9..1fc7a7b3 100644 --- a/pthread/pt-dealloc.c +++ b/pthread/pt-dealloc.c @@ -23,10 +23,10 @@ #include -#include +#include /* List of thread structures corresponding to free thread IDs. */ -extern atomicptr_t __pthread_free_threads; +extern __atomicptr_t __pthread_free_threads; /* Deallocate the thread structure for PTHREAD and the resources associated with it. */ @@ -54,11 +54,9 @@ __pthread_dealloc (struct __pthread *pthread) while (1) { pthread->next = (struct __pthread *)__pthread_free_threads; - if (atomic_compare_and_exchange_val_acq (&__pthread_free_threads, - (uintptr_t) pthread, - (uintptr_t) pthread->next) - == (uintptr_t) pthread->next) - break; + if (__atomicptr_compare_and_swap (&__pthread_free_threads, + pthread->next, pthread)) + return; } /* NOTREACHED */ diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c index a8f85b1a..7484ffd1 100644 --- a/pthread/pt-exit.c +++ b/pthread/pt-exit.c @@ -24,7 +24,7 @@ #include -#include +#include /* Terminate the current thread and make STATUS available to any @@ -57,7 +57,7 @@ pthread_exit (void *status) /* Decrease the number of threads. We use an atomic operation to make sure that only the last thread calls `exit'. */ - if (atomic_decrement_and_test (&__pthread_total)) + if (__atomic_dec_and_test (&__pthread_total)) /* We are the last thread. */ exit (0); diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 9eb84ed1..0fd7920f 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -26,15 +26,13 @@ #include #include -#include +#include #include #include #include -#include - /* Thread state. */ enum pthread_state { @@ -52,10 +50,6 @@ enum pthread_state # define PTHREAD_SYSDEP_MEMBERS #endif -#ifndef PTHREAD_SIGNAL_MEMBERS -# define PTHREAD_SIGNAL_MEMBERS -#endif - /* This structure describes a POSIX thread. */ struct __pthread { @@ -91,8 +85,6 @@ struct __pthread PTHREAD_SYSDEP_MEMBERS - PTHREAD_SIGNAL_MEMBERS - struct __pthread *next, **prevp; }; @@ -140,7 +132,7 @@ __pthread_dequeue (struct __pthread *thread) ) /* The total number of threads currently active. */ -extern atomic_fast32_t __pthread_total; +extern __atomic_t __pthread_total; /* The total number of thread IDs currently in use, or on the list of available thread IDs. */ diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index d2a42570..492dfcb5 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -37,12 +37,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) if (_pthread_self ()) { assert (mutex->owner); - assertx (mutex->owner == _pthread_self (), - "%p(%x) != %p(%x)", - mutex->owner, - ((struct __pthread *) mutex->owner)->threadid, - _pthread_self (), - _pthread_self ()->threadid); + assert (mutex->owner == _pthread_self ()); mutex->owner = NULL; } #endif diff --git a/sysdeps/hurd/pt-setspecific.c b/sysdeps/hurd/pt-setspecific.c index d2d1157c..89ca4d7f 100644 --- a/sysdeps/hurd/pt-setspecific.c +++ b/sysdeps/hurd/pt-setspecific.c @@ -1,5 +1,5 @@ /* pthread_setspecific. Generic version. - Copyright (C) 2002, 2008 Free Software Foundation, Inc. + Copyright (C) 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 @@ -30,8 +30,7 @@ pthread_setspecific (pthread_key_t key, const void *value) if (! self->thread_specifics) { - err = hurd_ihash_create (&self->thread_specifics, false, - HURD_IHASH_NO_LOCP); + err = hurd_ihash_create (&self->thread_specifics, HURD_IHASH_NO_LOCP); if (err) return ENOMEM; } diff --git a/sysdeps/ia32/bits/atomic.h b/sysdeps/ia32/bits/atomic.h new file mode 100644 index 00000000..0dfc1f60 --- /dev/null +++ b/sysdeps/ia32/bits/atomic.h @@ -0,0 +1,66 @@ +/* Atomic operations. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +typedef __volatile int __atomic_t; + +static inline void +__atomic_inc (__atomic_t *__var) +{ + __asm__ __volatile ("lock; incl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline void +__atomic_dec (__atomic_t *__var) +{ + __asm__ __volatile ("lock; decl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline int +__atomic_dec_and_test (__atomic_t *__var) +{ + unsigned char __ret; + + __asm__ __volatile ("lock; decl %0; sete %1" + : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); + return __ret != 0; +} + +/* We assume that an __atomicptr_t is only used for pointers to + word-aligned objects, and use the lowest bit for a simple lock. */ +typedef __volatile int * __atomicptr_t; + +/* Actually we don't implement that yet, and assume that we run on + something that has the i486 instruction set. */ +static inline int +__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, + void * __newval) +{ + char __ret; + int __dummy; + + __asm__ __volatile ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (__ret), "=m" (*__ptr), "=a" (__dummy) + : "r" (__newval), "m" (*__ptr), "a" (__oldval)); + return __ret; +} + +#endif diff --git a/sysdeps/posix/pt-spin.c b/sysdeps/posix/pt-spin.c index 26793b08..cb809c64 100644 --- a/sysdeps/posix/pt-spin.c +++ b/sysdeps/posix/pt-spin.c @@ -1,5 +1,5 @@ /* Spin locks. - Copyright (C) 2000, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2005 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 -- cgit v1.2.3 From 437dc507644e3067cac5899b00b6eb074997cd1c Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Sat, 16 Aug 2008 13:13:07 +0000 Subject: 2008-08-16 Neal H. Walfield * pthread/pt-alloc.c: Don't include . (__pthread_free_threads): Change to a struct __pthread *. (__pthread_free_threads_lock): New variable. (__pthread_alloc): When looking for a TCB to reuse, iterate over __pthread_free_threads taking the first for which the STATE field is PTHREAD_TERMINATED. When reusing a TCB, first call __pthread_thread_halt on it. * pthread/pt-dealloc.c: Don't include . (__pthread_free_threads): Change to a struct __pthread *. (__pthread_free_threads_lock): New declaration. (__pthread_dealloc): Enqueue PTHREAD on __PTHREAD_FREE_THREADS. Set PTHREAD->STATE to PTHREAD_TERMINATED after everything else. * pthread/pt-join.c (pthread_join): Call __pthread_thread_halt before destroying the thread. When destroying the thread, call __pthread_thread_dealloc on it. * pthread/pt-detach.c (pthread_detach): If destroying the thread, call __pthread_thread_halt before deallocating the stack. In this case, also call __pthread_thread_dealloc on the tcb. * pthread/pt-exit.c (pthread_exit): Call __pthread_dealloc only if the thread is detached and then as the last thing we do before calling __pthread_thread_halt. * pthread/pt-internal.h (__pthread_thread_halt): Remove argument NEED_DEALLOC. Update users. * sysdeps/mach/pt-thread-halt.c (__pthread_thread_halt): Remove argument need_dealloc. * sysdeps/mach/hurd/pt-sysdep.h (PTHREAD_SYSDEP_MEMBERS): Add field have_kernel_resources. * sysdeps/mach/hurd/pt-thread-alloc.c (__pthread_thread_alloc): If THREAD->HAVE_KERNEL_RESOURCES is true, just return. After allocating the resources, set THREAD->HAVE_KERNEL_RESOURCES to true. --- pthread/pt-alloc.c | 56 +++++++++++++++++++++--------------------- pthread/pt-create.c | 2 +- pthread/pt-dealloc.c | 33 +++++++++++++------------ pthread/pt-detach.c | 10 ++++++++ pthread/pt-exit.c | 10 +++----- pthread/pt-internal.h | 26 +++++++++++--------- pthread/pt-join.c | 12 +++++++-- sysdeps/mach/hurd/pt-sysdep.h | 5 ++-- sysdeps/mach/pt-thread-alloc.c | 5 ++++ sysdeps/mach/pt-thread-halt.c | 10 ++------ 10 files changed, 95 insertions(+), 74 deletions(-) diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index 30dcede0..6af2da92 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -1,5 +1,5 @@ /* Allocate a new thread structure. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2007, 2008 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 @@ -25,8 +25,6 @@ #include -#include - /* This braindamage is necessary because the standard says that some of the threads functions "shall fail" if "No thread could be found corresponding to that specified by the given thread ID." */ @@ -44,9 +42,9 @@ int __pthread_num_threads; /* A lock for the table, and the other variables above. */ pthread_rwlock_t __pthread_threads_lock; - /* List of thread structures corresponding to free thread IDs. */ -__atomicptr_t __pthread_free_threads; +struct __pthread *__pthread_free_threads; +pthread_mutex_t __pthread_free_threads_lock; static inline error_t initialize_pthread (struct __pthread *new, int recycling) @@ -94,33 +92,35 @@ __pthread_alloc (struct __pthread **pthread) int max_threads; int new_max_threads; - /* Try to re-use a thread structure before creating a new one. */ - while ((new = (struct __pthread *)__pthread_free_threads)) + pthread_mutex_lock (&__pthread_free_threads_lock); + for (new = __pthread_free_threads; new; new = new->next) { - if (__atomicptr_compare_and_swap (&__pthread_free_threads, - new, new->next)) + /* There is no need to take NEW->STATE_LOCK: if NEW is on this + list, then it is protected by __PTHREAD_FREE_THREADS_LOCK + except in __pthread_dealloc where after it is added to the + list (with the lock held), it drops the lock and then sets + NEW->STATE and immediately stops using NEW. */ + if (new->state == PTHREAD_TERMINATED) { - /* Yes, we managed to get one. The thread number in the - thread structure still refers to the correct slot. */ - err = initialize_pthread (new, 1); - if (err) - /* An error occured, however, we cannot just free NEW as - there may be resources attached to it. We must return - it to the free list. */ - while (1) - { - new->next = (struct __pthread *)__pthread_free_threads; - if (__atomicptr_compare_and_swap (&__pthread_free_threads, - new->next, new)) - break; - } - - if (! err) - *pthread = new; - - return err; + __pthread_dequeue (new); + break; } } + pthread_mutex_unlock (&__pthread_free_threads_lock); + + if (new) + { + /* The thread may still be running. Make sure it is stopped. + If this is the case, then the thread is either at the end of + __pthread_dealloc or in __pthread_thread_halt. In both + cases, we are interrupt it. */ + __pthread_thread_halt (new); + + err = initialize_pthread (new, 1); + if (! err) + *pthread = new; + return err; + } /* Allocate a new thread structure. */ new = malloc (sizeof (struct __pthread)); diff --git a/pthread/pt-create.c b/pthread/pt-create.c index 210f9672..8f62b78e 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -195,7 +195,7 @@ __pthread_create_internal (struct __pthread **thread, __pthread_sigstate_destroy (pthread); failed_setup: __pthread_thread_dealloc (pthread); - __pthread_thread_halt (pthread, 0); + __pthread_thread_halt (pthread); failed_thread_alloc: __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); pthread->stack = 0; diff --git a/pthread/pt-dealloc.c b/pthread/pt-dealloc.c index 1fc7a7b3..92fe1fda 100644 --- a/pthread/pt-dealloc.c +++ b/pthread/pt-dealloc.c @@ -1,5 +1,5 @@ /* Deallocate a thread structure. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2008 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 @@ -23,13 +23,12 @@ #include -#include - /* List of thread structures corresponding to free thread IDs. */ -extern __atomicptr_t __pthread_free_threads; +extern struct __pthread *__pthread_free_threads; +extern pthread_mutex_t __pthread_free_threads_lock; + -/* Deallocate the thread structure for PTHREAD and the resources - associated with it. */ +/* Deallocate the thread structure for PTHREAD. */ void __pthread_dealloc (struct __pthread *pthread) { @@ -44,20 +43,22 @@ __pthread_dealloc (struct __pthread *pthread) pthread_join is completely bogus, but unfortunately allowed by the standards. */ __pthread_mutex_lock (&pthread->state_lock); - pthread->state = PTHREAD_TERMINATED; if (pthread->state != PTHREAD_EXITED) pthread_cond_broadcast (&pthread->state_cond); __pthread_mutex_unlock (&pthread->state_lock); /* We do not actually deallocate the thread structure, but add it to a list of re-usable thread structures. */ - while (1) - { - pthread->next = (struct __pthread *)__pthread_free_threads; - if (__atomicptr_compare_and_swap (&__pthread_free_threads, - pthread->next, pthread)) - return; - } - - /* NOTREACHED */ + pthread_mutex_lock (&__pthread_free_threads_lock); + __pthread_enqueue (&__pthread_free_threads, pthread); + pthread_mutex_unlock (&__pthread_free_threads_lock); + + /* Setting PTHREAD->STATE to PTHREAD_TERMINATED makes this TCB + available for reuse. After that point, we can no longer assume + that PTHREAD is valid. + + Note that it is safe to not lock this update to PTHREAD->STATE: + the only way that it can now be accessed is in __pthread_alloc, + which reads this variable. */ + pthread->state = PTHREAD_TERMINATED; } diff --git a/pthread/pt-detach.c b/pthread/pt-detach.c index 42a84080..1e42c452 100644 --- a/pthread/pt-detach.c +++ b/pthread/pt-detach.c @@ -58,10 +58,20 @@ pthread_detach (pthread_t thread) __pthread_mutex_unlock (&pthread->state_lock); + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ assert (pthread->stack); __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); pthread->stack = 0; + __pthread_thread_dealloc (pthread); + __pthread_dealloc (pthread); break; diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c index 7484ffd1..5fe0ba86 100644 --- a/pthread/pt-exit.c +++ b/pthread/pt-exit.c @@ -28,7 +28,7 @@ /* Terminate the current thread and make STATUS available to any - thread that might join us. */ + thread that might join it. */ void pthread_exit (void *status) { @@ -70,8 +70,6 @@ pthread_exit (void *status) if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) status = PTHREAD_CANCELED; - __pthread_thread_dealloc (self); - switch (self->state) { default: @@ -86,7 +84,8 @@ pthread_exit (void *status) deallocate our own stack. However, it will eventually be reused when this thread structure is recycled. */ __pthread_mutex_unlock (&self->state_lock); - need_dealloc = 1; + + __pthread_dealloc (self); break; @@ -103,7 +102,6 @@ pthread_exit (void *status) waiting to join us. */ pthread_cond_broadcast (&self->state_cond); __pthread_mutex_unlock (&self->state_lock); - need_dealloc = 0; break; } @@ -113,7 +111,7 @@ pthread_exit (void *status) This means that before freeing any resources, such a thread should make sure that this thread is really halted. */ - __pthread_thread_halt (self, need_dealloc); + __pthread_thread_halt (self); /* NOTREACHED */ abort (); diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 0fd7920f..cb441d09 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -36,9 +36,13 @@ /* Thread state. */ enum pthread_state { + /* The thread is running and joinable. */ PTHREAD_JOINABLE = 0, + /* The thread is running and detached. */ PTHREAD_DETACHED, + /* A joinable thread exited and its return code is available. */ PTHREAD_EXITED, + /* The thread structure is unallocated and available for reuse. */ PTHREAD_TERMINATED }; @@ -207,22 +211,22 @@ extern int __pthread_setup (struct __pthread *__restrict thread, resources) for THREAD; it must not be placed on the run queue. */ extern int __pthread_thread_alloc (struct __pthread *thread); -/* Deallocate any kernel resources associated with THREAD except don't - halt the thread itself. On return, the thread will be marked as - dead and __pthread_halt will be called. */ +/* Deallocate any kernel resources associated with THREAD. The thread + must not be running (that is, if __pthread_thread_start was called, + __pthread_thread_halt must first be called). This function will + never be called by a thread on itself. In the case that a thread + exits, its thread structure will be cached and cleaned up + later. */ extern void __pthread_thread_dealloc (struct __pthread *thread); /* Start THREAD making it eligible to run. */ extern int __pthread_thread_start (struct __pthread *thread); -/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is - true, the function must call __pthread_dealloc on THREAD. - - NB: The thread executing this function may be the thread which is - being halted, thus the last action should be halting the thread - itself. */ -extern void __pthread_thread_halt (struct __pthread *thread, - int need_dealloc); +/* Stop the kernel thread associated with THREAD. This function may + be called by two threads in parallel. In particular, by the thread + itself and another thread trying to join it. This function must be + implemented such that this is safe. */ +extern void __pthread_thread_halt (struct __pthread *thread); /* Called by a thread just before it calls the provided start diff --git a/pthread/pt-join.c b/pthread/pt-join.c index 06e9f1f7..153058b5 100644 --- a/pthread/pt-join.c +++ b/pthread/pt-join.c @@ -54,12 +54,20 @@ pthread_join (pthread_t thread, void **status) if (status) *status = pthread->status; - /* Make sure nobody can reference it anymore, and mark it as - terminated. */ + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ assert (pthread->stack); __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); pthread->stack = 0; + __pthread_thread_dealloc (pthread); + __pthread_dealloc (pthread); break; diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h index 83bad963..f14a1366 100644 --- a/sysdeps/mach/hurd/pt-sysdep.h +++ b/sysdeps/mach/hurd/pt-sysdep.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 @@ -32,7 +32,8 @@ #define PTHREAD_SYSDEP_MEMBERS \ thread_t kernel_thread; \ - mach_msg_header_t wakeupmsg; + mach_msg_header_t wakeupmsg; \ + int have_kernel_resources; #define _HURD_THREADVAR_THREAD _HURD_THREADVAR_DYNAMIC_USER diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c index 1acba98a..7706a2bd 100644 --- a/sysdeps/mach/pt-thread-alloc.c +++ b/sysdeps/mach/pt-thread-alloc.c @@ -63,6 +63,9 @@ create_wakeupmsg (struct __pthread *thread) int __pthread_thread_alloc (struct __pthread *thread) { + if (thread->have_kernel_resources) + return 0; + error_t err; err = create_wakeupmsg (thread); @@ -97,5 +100,7 @@ __pthread_thread_alloc (struct __pthread *thread) return EAGAIN; } + thread->have_kernel_resources = true; + return 0; } diff --git a/sysdeps/mach/pt-thread-halt.c b/sysdeps/mach/pt-thread-halt.c index 9f860247..973cde1e 100644 --- a/sysdeps/mach/pt-thread-halt.c +++ b/sysdeps/mach/pt-thread-halt.c @@ -30,14 +30,8 @@ being halted, thus the last action should be halting the thread itself. */ void -__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +__pthread_thread_halt (struct __pthread *thread) { - error_t err; - thread_t tid = thread->kernel_thread; - - if (need_dealloc) - __pthread_dealloc (thread); - - err = __thread_terminate (tid); + error_t err = __thread_terminate (thread->kernel_thread); assert_perror (err); } -- cgit v1.2.3 From f4808bce7c79f08f2866dde95a4b58ea63b62a94 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 26 Aug 2008 13:58:29 +0000 Subject: 2008-08-26 Neal H. Walfield MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * sysdeps/mach/pt-thread-alloc.c (__pthread_thread_alloc): Set THREAD->HAVE_KERNEL_RESOURCES to 1, not true. Reported by Flávio Cruz . --- sysdeps/mach/pt-thread-alloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c index 7706a2bd..3d7c0465 100644 --- a/sysdeps/mach/pt-thread-alloc.c +++ b/sysdeps/mach/pt-thread-alloc.c @@ -1,5 +1,5 @@ /* Start thread. Mach version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2008 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 @@ -100,7 +100,7 @@ __pthread_thread_alloc (struct __pthread *thread) return EAGAIN; } - thread->have_kernel_resources = true; + thread->have_kernel_resources = 1; return 0; } -- cgit v1.2.3 From 67401f7b39a10eb3c4eedabecf180ff587d6c95b Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Wed, 27 Aug 2008 16:05:20 +0000 Subject: 2008-08-27 Neal H. Walfield * pthread/cthreads-compat.c: Don't include . (cthread_t): New type definition. (cthread_fn_t): Likewise. (cthread_key_t): Likewise. (CTHREAD_KEY_INVALID): Define. --- pthread/cthreads-compat.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pthread/cthreads-compat.c b/pthread/cthreads-compat.c index ccea03c9..e0536ef2 100644 --- a/pthread/cthreads-compat.c +++ b/pthread/cthreads-compat.c @@ -1,5 +1,5 @@ /* Compatibility routines for cthreads. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2008 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 @@ -20,7 +20,11 @@ #include #include -#include +typedef void *cthread_t; +typedef void *(*cthread_fn_t) (void *arg); +typedef int cthread_key_t; + +#define CTHREAD_KEY_INVALID (cthread_key_t) -1 void cthread_detach (cthread_t thread) -- cgit v1.2.3 From 4ce7b9d66e58f2330f5428e63f70a79a0eb225ec Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Thu, 2 Oct 2008 12:00:44 +0000 Subject: 2008-10-02 Neal H. Walfield * sysdeps/generic/pt-mutex-timedlock.c (__pthread_mutex_timedlock_internal) [! ALWAYS_TRACK_MUTEX_OWNER]: Don't update MUTEX->OWNER or assert MUTEX->OWNER for normal mutexes. * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock) [! ALWAYS_TRACK_MUTEX_OWNER]: Don't update MUTEX->OWNER or assert MUTEX->OWNER for normal mutexes. * sysdeps/generic/pt-mutex-transfer-np.c (__pthread_mutex_transfer_np) [! ALWAYS_TRACK_MUTEX_OWNER]: Don't update MUTEX->OWNER for normal mutexes. --- sysdeps/generic/pt-mutex-timedlock.c | 28 ++++++++++++++++++---------- sysdeps/generic/pt-mutex-transfer-np.c | 7 ++++++- sysdeps/generic/pt-mutex-unlock.c | 11 +++++++++-- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index 265a4530..ee432192 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -36,6 +36,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, if (__pthread_spin_trylock (&mutex->__held) == 0) /* Successfully acquired the lock. */ { +#ifdef ALWAYS_TRACK_MUTEX_OWNER #ifndef NDEBUG self = _pthread_self (); if (self) @@ -46,6 +47,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, assert (! mutex->owner); mutex->owner = _pthread_self (); } +#endif #endif if (mutex->attr) @@ -73,14 +75,16 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, self = _pthread_self (); assert (self); - if (mutex->attr) + if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) + assert (mutex->owner != self); +#endif + } + else { switch (mutex->attr->mutex_type) { - case PTHREAD_MUTEX_NORMAL: - assert (mutex->owner != self); - break; - case PTHREAD_MUTEX_ERRORCHECK: if (mutex->owner == self) { @@ -102,10 +106,11 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, LOSE; } } - else - assert (mutex->owner != self); - assert (mutex->owner); +#if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) +#endif + assert (mutex->owner); if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) return EINVAL; @@ -141,9 +146,12 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, else __pthread_block (self); -#ifndef NDEBUG - assert (mutex->owner == self); +#if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) #endif + { + assert (mutex->owner == self); + } if (mutex->attr) switch (mutex->attr->mutex_type) diff --git a/sysdeps/generic/pt-mutex-transfer-np.c b/sysdeps/generic/pt-mutex-transfer-np.c index bcb809dd..7796ac4f 100644 --- a/sysdeps/generic/pt-mutex-transfer-np.c +++ b/sysdeps/generic/pt-mutex-transfer-np.c @@ -45,7 +45,12 @@ __pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) } #ifndef NDEBUG - mutex->owner = thread; +# if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) +# endif + { + mutex->owner = thread; + } #endif return 0; diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index 492dfcb5..7645fd4c 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -33,13 +33,15 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) { -#ifndef NDEBUG +#if defined(ALWAYS_TRACK_MUTEX_OWNER) +# ifndef NDEBUG if (_pthread_self ()) { assert (mutex->owner); assert (mutex->owner == _pthread_self ()); mutex->owner = NULL; } +# endif #endif } else @@ -79,7 +81,12 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) __pthread_dequeue (wakeup); #ifndef NDEBUG - mutex->owner = wakeup; +# if !defined (ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) +# endif + { + mutex->owner = wakeup; + } #endif /* We do not unlock MUTEX->held: we are transferring the ownership -- cgit v1.2.3 From 0cdc7a47609ad58922221e490b09cdba599e2b25 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 21 Dec 2008 17:05:41 +0000 Subject: 2008-12-21 Samuel Thibault * sysdeps/mach/pt-timedblock.c (__pthread_timedblock): Fix timeout computation from abstime and now. --- sysdeps/mach/pt-timedblock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sysdeps/mach/pt-timedblock.c b/sysdeps/mach/pt-timedblock.c index ddb8baec..6f547265 100644 --- a/sysdeps/mach/pt-timedblock.c +++ b/sysdeps/mach/pt-timedblock.c @@ -51,11 +51,11 @@ __pthread_timedblock (struct __pthread *thread, timeout = (abstime->tv_sec - now.tv_sec) * 1000; if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec) - timeout -= (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000; + timeout += (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000; else /* Need to do a carry. */ - timeout -= 1000 + ((abstime->tv_nsec + 999999) / 1000000) - - (now.tv_usec + 999) / 1000; + timeout -= (now.tv_usec + 999) / 1000 - + ((abstime->tv_nsec + 999999) / 1000000); err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, sizeof msg, thread->wakeupmsg.msgh_remote_port, -- cgit v1.2.3 From fa0f7d1afb65bf077edfcc0f8977f95fca5656b9 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 10 Jan 2009 13:22:27 +0000 Subject: 2009-01-10 Samuel Thibault * sysdeps/i386/bits/spin-lock.h (__SPIN_LOCK_INITIALIZER): Rename macro to... (__PTHREAD_SPIN_LOCK_INITIALIZER): ... this. * sysdeps/mach/bits/spin-lock.h (__SPIN_LOCK_INITIALIZER): Rename macro to... (__PTHREAD_SPIN_LOCK_INITIALIZER): ... this. * include/pthread/pthread.h (PTHREAD_SPINLOCK_INITIALIZER): Use __PTHREAD_SPIN_LOCK_INITIALIZER instead of __SPIN_LOCK_INITIALIZER. * sysdeps/generic/bits/condition.h (__PTHREAD_COND_INITIALIZER): Likewise. * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_INITIALIZER, __PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Likewise. * sysdeps/generic/bits/once.h (__PTHREAD_ONCE_INIT): Likewise. * sysdeps/generic/bits/rwlock.h (__PTHREAD_RWLOCK_INITIALIZER): Likewise. * sysdeps/generic/bits/semaphore.h (__SEMAPHORE_INITIALIZER): Likewise. * sysdeps/i386/bits/spin-lock-inline.h (__pthread_spin_init): Likewise. * sysdeps/i386/mach/spin-lock-inline.h (__pthread_spin_init): Likewise. --- sysdeps/generic/bits/condition.h | 4 ++-- sysdeps/generic/bits/mutex.h | 6 +++--- sysdeps/generic/bits/once.h | 4 ++-- sysdeps/generic/bits/rwlock.h | 4 ++-- sysdeps/generic/bits/semaphore.h | 4 ++-- sysdeps/ia32/bits/spin-lock-inline.h | 4 ++-- sysdeps/ia32/bits/spin-lock.h | 4 ++-- sysdeps/mach/bits/spin-lock-inline.h | 4 ++-- sysdeps/mach/bits/spin-lock.h | 6 +++--- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/sysdeps/generic/bits/condition.h b/sysdeps/generic/bits/condition.h index f3b09be4..bf13adab 100644 --- a/sysdeps/generic/bits/condition.h +++ b/sysdeps/generic/bits/condition.h @@ -1,5 +1,5 @@ /* Condition type. Generic version. - Copyright (C) 2000, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2005, 2009 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 @@ -34,6 +34,6 @@ struct __pthread_cond /* Initializer for a condition variable. */ #define __PTHREAD_COND_INITIALIZER \ - { __SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL } + { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL } #endif /* bits/condition.h */ diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 15a83f49..86068cf5 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -1,6 +1,6 @@ /* Mutex type. Generic version. - Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008 + Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -55,10 +55,10 @@ struct __pthread_mutex /* Initializer for a mutex. N.B. this also happens to be compatible with the cthread mutex initializer. */ # define __PTHREAD_MUTEX_INITIALIZER \ - { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } # define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ - { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ (struct __pthread_mutexattr *) &__pthread_recursive_mutexattr, 0, 0, 0 } # endif diff --git a/sysdeps/generic/bits/once.h b/sysdeps/generic/bits/once.h index 7f572faf..f4985d6f 100644 --- a/sysdeps/generic/bits/once.h +++ b/sysdeps/generic/bits/once.h @@ -1,5 +1,5 @@ /* Dynamic package initialization data structures. Generic version. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2009 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 @@ -29,6 +29,6 @@ struct __pthread_once }; #define __PTHREAD_ONCE_INIT \ - { 0, __SPIN_LOCK_INITIALIZER } + { 0, __PTHREAD_SPIN_LOCK_INITIALIZER } #endif /* bits/once.h */ diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h index 3d600ec3..af6b1c86 100644 --- a/sysdeps/generic/bits/rwlock.h +++ b/sysdeps/generic/bits/rwlock.h @@ -1,5 +1,5 @@ /* rwlock type. Generic version. - Copyright (C) 2002, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2006, 2007, 2009 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 @@ -40,7 +40,7 @@ struct __pthread_rwlock /* Initializer for a rwlock. */ #define __PTHREAD_RWLOCK_INITIALIZER \ - { __SPIN_LOCK_INITIALIZER, __SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } #endif /* bits/rwlock.h */ diff --git a/sysdeps/generic/bits/semaphore.h b/sysdeps/generic/bits/semaphore.h index b53f47e3..5e987c15 100644 --- a/sysdeps/generic/bits/semaphore.h +++ b/sysdeps/generic/bits/semaphore.h @@ -1,5 +1,5 @@ /* Semaphore type. Generic version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2009 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 @@ -38,6 +38,6 @@ struct __semaphore /* Initializer for a semaphore. */ #define __SEMAPHORE_INITIALIZER(pshared, value) \ - { __SPIN_LOCK_INITIALIZER, NULL, (pshared), (value), NULL } + { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, (pshared), (value), NULL } #endif /* bits/mutex.h */ diff --git a/sysdeps/ia32/bits/spin-lock-inline.h b/sysdeps/ia32/bits/spin-lock-inline.h index 0f3ca581..e5ed3def 100644 --- a/sysdeps/ia32/bits/spin-lock-inline.h +++ b/sysdeps/ia32/bits/spin-lock-inline.h @@ -1,5 +1,5 @@ /* Machine-specific definitions for spin locks. i386 version. - Copyright (C) 2000, 2005, 2008 Free Software Foundation, Inc. + Copyright (C) 2000, 2005, 2008, 2009 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 @@ -54,7 +54,7 @@ __PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, __PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) { - *__lock = __SPIN_LOCK_INITIALIZER; + *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; return 0; } diff --git a/sysdeps/ia32/bits/spin-lock.h b/sysdeps/ia32/bits/spin-lock.h index 71af1631..5ae81e18 100644 --- a/sysdeps/ia32/bits/spin-lock.h +++ b/sysdeps/ia32/bits/spin-lock.h @@ -1,5 +1,5 @@ /* Machine-specific definitions for spin locks. i386 version. - Copyright (C) 2000, 2005, 2008 Free Software Foundation, Inc. + Copyright (C) 2000, 2005, 2008, 2009 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 @@ -32,7 +32,7 @@ __BEGIN_DECLS typedef __volatile int __pthread_spinlock_t; /* Initializer for a spin lock object. */ -# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) +# define __PTHREAD_SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) __END_DECLS diff --git a/sysdeps/mach/bits/spin-lock-inline.h b/sysdeps/mach/bits/spin-lock-inline.h index bb066d0b..f9f7c299 100644 --- a/sysdeps/mach/bits/spin-lock-inline.h +++ b/sysdeps/mach/bits/spin-lock-inline.h @@ -1,5 +1,5 @@ /* Definitions of user-visible names for spin locks. - Copyright (C) 1994, 1997, 2002, 2008 Free Software Foundation, Inc. + Copyright (C) 1994, 1997, 2002, 2008, 2009 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 @@ -51,7 +51,7 @@ __PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, __PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) { - *__lock = __SPIN_LOCK_INITIALIZER; + *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; return 0; } diff --git a/sysdeps/mach/bits/spin-lock.h b/sysdeps/mach/bits/spin-lock.h index 54425cc6..537dac9d 100644 --- a/sysdeps/mach/bits/spin-lock.h +++ b/sysdeps/mach/bits/spin-lock.h @@ -1,5 +1,5 @@ /* Definitions of user-visible names for spin locks. - Copyright (C) 1994, 1997, 2002, 2008 Free Software Foundation, Inc. + Copyright (C) 1994, 1997, 2002, 2008, 2009 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 @@ -29,8 +29,8 @@ __BEGIN_DECLS typedef __spin_lock_t __pthread_spinlock_t; /* Initializer for a spin lock object. */ -#ifndef __SPIN_LOCK_INITIALIZER -#error __SPIN_LOCK_INITIALIZER undefined: should be defined by . +#ifndef __PTHREAD_SPIN_LOCK_INITIALIZER +#error __PTHREAD_SPIN_LOCK_INITIALIZER undefined: should be defined by . #endif __END_DECLS -- cgit v1.2.3 From 2cddc873d21695166265d4c87c1939e5269a5108 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 23 Aug 2009 19:28:22 +0200 Subject: Fix assertion failure in pthread_mutex_trylock * sysdeps/generic/pt-mutex-trylock.c [!ALWAYS_TRACK_MUTEX_OWNER] (__pthread_mutex_trylock): Disable owner tracking. --- sysdeps/generic/pt-mutex-trylock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index 5264dc7b..3c8cd03c 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -34,6 +34,7 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) if (__pthread_spin_trylock (&mutex->__held) == 0) /* Acquired the lock. */ { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) #ifndef NDEBUG self = _pthread_self (); if (self) @@ -44,6 +45,7 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) assert (! mutex->owner); mutex->owner = _pthread_self (); } +#endif #endif if (mutex->attr) -- cgit v1.2.3 From 9c989b58f694567e214deed700708f3ba9901270 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 23 Aug 2009 19:38:06 +0200 Subject: Fix pthread_mutex_t static initializers Fix pthread_mutex_t static initializers by not leaving references to __pthread_recursive_mutexattr. * include/pthread/pthread.h.orig (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): New macro. * sysdeps/generic/pt-mutex-destroy.c (_pthread_mutex_destroy): Compare mutex->attr with __PTHREAD_ERRORCHECK_MUTEXATTR and __PTHREAD_RECURSIVE_MUTEXATTR instead of __pthread_recursive_mutexattr. * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): Likewise. * sysdeps/generic/pt-mutex-timedlock.c (__pthread_mutex_timedlock_internal): Likewise. * sysdeps/generic/pt-mutex-transfer-np.c (__pthread_mutex_transfer_np): Likewise. * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock): Likewise. * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): Likewise. * sysdeps/generic/pt-mutexattr.c (__pthread_errorcheck_mutexattr): New const. * sysdeps/generic/bits/mutex-attr.h (__pthread_errorcheck_mutexattr): Declare const. * sysdeps/generic/bits/mutex.h (__PTHREAD_ERRORCHECK_MUTEXATTR, __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER, __PTHREAD_RECURSIVE_MUTEXATTR): New macros. (__PTHREAD_RECURSIVE_MUTEX_INITIALIZER): Use __PTHREAD_RECURSIVE_MUTEXATTR macro instead of &__pthread_recursive_mutexattr. --- sysdeps/generic/bits/mutex-attr.h | 1 + sysdeps/generic/bits/mutex.h | 10 +++++++++- sysdeps/generic/pt-mutex-destroy.c | 3 ++- sysdeps/generic/pt-mutex-init.c | 13 +++++-------- sysdeps/generic/pt-mutex-timedlock.c | 22 ++++++++++++++-------- sysdeps/generic/pt-mutex-transfer-np.c | 11 +++++++++-- sysdeps/generic/pt-mutex-trylock.c | 14 ++++++++++---- sysdeps/generic/pt-mutex-unlock.c | 16 +++++++++++----- sysdeps/generic/pt-mutexattr.c | 8 ++++++++ 9 files changed, 69 insertions(+), 29 deletions(-) diff --git a/sysdeps/generic/bits/mutex-attr.h b/sysdeps/generic/bits/mutex-attr.h index 9161cdab..8514ebe8 100644 --- a/sysdeps/generic/bits/mutex-attr.h +++ b/sysdeps/generic/bits/mutex-attr.h @@ -35,6 +35,7 @@ struct __pthread_mutexattr }; /* Attributes for a recursive mutex. */ +extern const struct __pthread_mutexattr __pthread_errorcheck_mutexattr; extern const struct __pthread_mutexattr __pthread_recursive_mutexattr; #endif /* bits/mutex-attr.h */ diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h index 86068cf5..c734c393 100644 --- a/sysdeps/generic/bits/mutex.h +++ b/sysdeps/generic/bits/mutex.h @@ -57,9 +57,17 @@ struct __pthread_mutex # define __PTHREAD_MUTEX_INITIALIZER \ { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } +# define __PTHREAD_ERRORCHECK_MUTEXATTR ((struct __pthread_mutexattr *) ((unsigned long) __PTHREAD_MUTEX_ERRORCHECK + 1)) + +# define __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ + __PTHREAD_ERRORCHECK_MUTEXATTR, 0, 0, 0 } + +# define __PTHREAD_RECURSIVE_MUTEXATTR ((struct __pthread_mutexattr *) ((unsigned long) __PTHREAD_MUTEX_RECURSIVE + 1)) + # define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ - (struct __pthread_mutexattr *) &__pthread_recursive_mutexattr, 0, 0, 0 } + __PTHREAD_RECURSIVE_MUTEXATTR, 0, 0, 0 } # endif #endif /* Not __pthread_mutex_defined. */ diff --git a/sysdeps/generic/pt-mutex-destroy.c b/sysdeps/generic/pt-mutex-destroy.c index b0ca00f7..3bbc73fe 100644 --- a/sysdeps/generic/pt-mutex-destroy.c +++ b/sysdeps/generic/pt-mutex-destroy.c @@ -26,7 +26,8 @@ int _pthread_mutex_destroy (pthread_mutex_t *mutex) { - if (mutex->attr == &__pthread_recursive_mutexattr) + if (mutex->attr == __PTHREAD_ERRORCHECK_MUTEXATTR + || mutex->attr == __PTHREAD_RECURSIVE_MUTEXATTR) /* Static attributes. */ ; else diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c index a818fe3a..2f960286 100644 --- a/sysdeps/generic/pt-mutex-init.c +++ b/sysdeps/generic/pt-mutex-init.c @@ -35,14 +35,11 @@ _pthread_mutex_init (pthread_mutex_t *mutex, /* The default attributes. */ return 0; - if (attr == &__pthread_recursive_mutexattr) - /* Non-default but known attributes. */ - { - mutex->attr = attr; - return 0; - } - - mutex->attr = malloc (sizeof *attr); + if (! mutex->attr + || mutex->attr == __PTHREAD_ERRORCHECK_MUTEXATTR + || mutex->attr == __PTHREAD_RECURSIVE_MUTEXATTR) + mutex->attr = malloc (sizeof *attr); + if (! mutex->attr) return ENOMEM; diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c index ee432192..883e50af 100644 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ b/sysdeps/generic/pt-mutex-timedlock.c @@ -31,6 +31,12 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, const struct timespec *abstime) { struct __pthread *self; + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; __pthread_spin_lock (&mutex->__lock); if (__pthread_spin_trylock (&mutex->__held) == 0) @@ -50,8 +56,8 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, #endif #endif - if (mutex->attr) - switch (mutex->attr->mutex_type) + if (attr) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; @@ -75,7 +81,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, self = _pthread_self (); assert (self); - if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + if (! attr || attr->mutex_type == PTHREAD_MUTEX_NORMAL) { #if defined(ALWAYS_TRACK_MUTEX_OWNER) assert (mutex->owner != self); @@ -83,7 +89,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, } else { - switch (mutex->attr->mutex_type) + switch (attr->mutex_type) { case PTHREAD_MUTEX_ERRORCHECK: if (mutex->owner == self) @@ -108,7 +114,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, } #if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) #endif assert (mutex->owner); @@ -147,14 +153,14 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, __pthread_block (self); #if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) #endif { assert (mutex->owner == self); } - if (mutex->attr) - switch (mutex->attr->mutex_type) + if (attr) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; diff --git a/sysdeps/generic/pt-mutex-transfer-np.c b/sysdeps/generic/pt-mutex-transfer-np.c index 7796ac4f..967f1c7c 100644 --- a/sysdeps/generic/pt-mutex-transfer-np.c +++ b/sysdeps/generic/pt-mutex-transfer-np.c @@ -29,13 +29,20 @@ __pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) assert (mutex->owner == _pthread_self ()); struct __pthread *thread = __pthread_getid (tid); + const struct __pthread_mutexattr *attr = mutex->attr; + if (! thread) return ESRCH; if (thread == _pthread_self ()) return 0; - if (mutex->attr && mutex->attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + + if (attr && attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) { if (mutex->owner != _pthread_self ()) @@ -46,7 +53,7 @@ __pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) #ifndef NDEBUG # if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) # endif { mutex->owner = thread; diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c index 3c8cd03c..7a54cc9a 100644 --- a/sysdeps/generic/pt-mutex-trylock.c +++ b/sysdeps/generic/pt-mutex-trylock.c @@ -29,6 +29,12 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) { int err; struct __pthread *self; + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; __pthread_spin_lock (&mutex->__lock); if (__pthread_spin_trylock (&mutex->__held) == 0) @@ -48,8 +54,8 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) #endif #endif - if (mutex->attr) - switch (mutex->attr->mutex_type) + if (attr) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; @@ -70,10 +76,10 @@ __pthread_mutex_trylock (struct __pthread_mutex *mutex) err = EBUSY; - if (mutex->attr) + if (attr) { self = _pthread_self (); - switch (mutex->attr->mutex_type) + switch (attr->mutex_type) { case PTHREAD_MUTEX_NORMAL: break; diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c index 7645fd4c..09d70f8f 100644 --- a/sysdeps/generic/pt-mutex-unlock.c +++ b/sysdeps/generic/pt-mutex-unlock.c @@ -28,10 +28,16 @@ int __pthread_mutex_unlock (pthread_mutex_t *mutex) { struct __pthread *wakeup; - + const struct __pthread_mutexattr *attr = mutex->attr; + + if (attr == __PTHREAD_ERRORCHECK_MUTEXATTR) + attr = &__pthread_errorcheck_mutexattr; + if (attr == __PTHREAD_RECURSIVE_MUTEXATTR) + attr = &__pthread_recursive_mutexattr; + __pthread_spin_lock (&mutex->__lock); - if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + if (! attr || attr->mutex_type == PTHREAD_MUTEX_NORMAL) { #if defined(ALWAYS_TRACK_MUTEX_OWNER) # ifndef NDEBUG @@ -45,7 +51,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) #endif } else - switch (mutex->attr->mutex_type) + switch (attr->mutex_type) { case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_RECURSIVE: @@ -55,7 +61,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) return EPERM; } - if (mutex->attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) + if (attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) if (--mutex->locks > 0) { __pthread_spin_unlock (&mutex->__lock); @@ -82,7 +88,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) #ifndef NDEBUG # if !defined (ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) + if (attr && attr->mutex_type != PTHREAD_MUTEX_NORMAL) # endif { mutex->owner = wakeup; diff --git a/sysdeps/generic/pt-mutexattr.c b/sysdeps/generic/pt-mutexattr.c index d80a7d74..5ebde6ea 100644 --- a/sysdeps/generic/pt-mutexattr.c +++ b/sysdeps/generic/pt-mutexattr.c @@ -28,6 +28,14 @@ const struct __pthread_mutexattr __pthread_default_mutexattr = mutex_type: PTHREAD_MUTEX_DEFAULT }; +const struct __pthread_mutexattr __pthread_errorcheck_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_ERRORCHECK +}; + const struct __pthread_mutexattr __pthread_recursive_mutexattr = { prioceiling: 0, -- cgit v1.2.3 From 25cbe85eafc3d4155a59f4690a3b581ead14d938 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 23 Aug 2009 19:47:05 +0200 Subject: Fix pthread_setcancelstate/type crash * pthread/pt-setcancelstate.c (pthread_setcancelstate): Check whether OLDSTATE is NULL before filling it. * pthread/pt-setcanceltype.c (pthread_setcanceltype): Likewise. --- pthread/pt-setcancelstate.c | 3 ++- pthread/pt-setcanceltype.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pthread/pt-setcancelstate.c b/pthread/pt-setcancelstate.c index ded58922..e2d81833 100644 --- a/pthread/pt-setcancelstate.c +++ b/pthread/pt-setcancelstate.c @@ -35,7 +35,8 @@ pthread_setcancelstate (int state, int *oldstate) break; } - *oldstate = p->cancel_state; + if (oldstate) + *oldstate = p->cancel_state; p->cancel_state = state; return 0; diff --git a/pthread/pt-setcanceltype.c b/pthread/pt-setcanceltype.c index 9511c991..3ce4259c 100644 --- a/pthread/pt-setcanceltype.c +++ b/pthread/pt-setcanceltype.c @@ -35,7 +35,8 @@ pthread_setcanceltype (int type, int *oldtype) break; } - *oldtype = p->cancel_type; + if (oldtype) + *oldtype = p->cancel_type; p->cancel_type = type; return 0; -- cgit v1.2.3 From 97998cd4d4a3be935bfa373c50c2624bbabd7d02 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 13 Oct 2009 20:15:08 +0200 Subject: Fix pthread_cleanup_push old-gcc-style initializer sysdeps/generic/bits/cancelation.h (__pthread_cleanup_push): For better portability to various compilation flags, use standard initializer for struct __pthread_cancelation_handler __handler instead of old-gcc-style. --- sysdeps/generic/bits/cancelation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sysdeps/generic/bits/cancelation.h b/sysdeps/generic/bits/cancelation.h index f446d595..db9169a9 100644 --- a/sysdeps/generic/bits/cancelation.h +++ b/sysdeps/generic/bits/cancelation.h @@ -38,9 +38,9 @@ struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); = __pthread_get_cleanup_stack (); \ struct __pthread_cancelation_handler __handler = \ { \ - handler: (rt), \ - arg: (rtarg), \ - next: *__handlers \ + (rt), \ + (rtarg), \ + *__handlers \ }; \ *__handlers = &__handler; -- cgit v1.2.3 From 75380300dc22bf3a8fbd89cf5a2358a9c29deaeb Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 18 Oct 2009 00:24:19 +0200 Subject: Fix pthread_kill(thread, 0) * sysdeps/hurd/pt-kill.c (pthread_kill): Return immediately after checks without calling _hurd_raise_signal if sig is 0. --- sysdeps/hurd/pt-kill.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sysdeps/hurd/pt-kill.c b/sysdeps/hurd/pt-kill.c index f970e065..d204e3f6 100644 --- a/sysdeps/hurd/pt-kill.c +++ b/sysdeps/hurd/pt-kill.c @@ -39,6 +39,9 @@ pthread_kill (pthread_t thread, int sig) ss = _hurd_thread_sigstate (pthread->kernel_thread); assert (ss); + if (!sig) + return 0; + detail.exc = 0; detail.code = sig; detail.error = 0; -- cgit v1.2.3 From 90dd2d73435a8e1bbcccf5ed99a91b2c438557f4 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 19 May 2010 08:32:16 +0200 Subject: Add pthread_yield function * pthread/pt-yield.c: New file. * Makefile (SRCS): Add pt-yield.c * Makefile.am (libpthread_a_SOURCES): Add pt-yield.c --- Makefile.am | 1 + pthread/pt-yield.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 pthread/pt-yield.c diff --git a/Makefile.am b/Makefile.am index e59c9460..e1c062c1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -133,6 +133,7 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ pt-kill.c \ pt-getcpuclockid.c \ pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ + pt-yield.c \ sem-close.c sem-init.c sem-timedwait.c sem-wait.c \ sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ sem-post.c sem-unlink.c \ diff --git a/pthread/pt-yield.c b/pthread/pt-yield.c new file mode 100644 index 00000000..27848bb7 --- /dev/null +++ b/pthread/pt-yield.c @@ -0,0 +1,26 @@ +/* Yield the processor to another thread or process. + Copyright (C) 2010 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int pthread_yield(void) +{ + return sched_yield (); +} -- cgit v1.2.3 From 68567b88ee8f9e395e0c1f0a565affe8a1d4d68b Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 1 Aug 2010 01:05:53 +0200 Subject: Move files to libpthread/ for inclusion along hurd --- Makefile.am | 167 -- headers.m4 | 45 - libpthread.a | 20 - libpthread/ChangeLog | 2201 ++++++++++++++++++++ libpthread/Makefile | 247 +++ libpthread/Makefile.am | 167 ++ libpthread/TODO | 174 ++ libpthread/headers.m4 | 45 + libpthread/include/libc-symbols.h | 395 ++++ libpthread/include/pthread.h | 7 + libpthread/include/pthread/pthread.h | 744 +++++++ libpthread/include/pthread/pthreadtypes.h | 136 ++ libpthread/include/semaphore.h | 69 + libpthread/include/set-hooks.h | 72 + libpthread/libpthread.a | 20 + libpthread/libpthread_pic.a | 20 + libpthread/lockfile.c | 65 + libpthread/not-in-libc.h | 11 + libpthread/pthread/Versions | 15 + libpthread/pthread/cthreads-compat.c | 104 + libpthread/pthread/pt-alloc.c | 215 ++ libpthread/pthread/pt-cancel.c | 40 + libpthread/pthread/pt-cleanup.c | 28 + libpthread/pthread/pt-create.c | 206 ++ libpthread/pthread/pt-dealloc.c | 64 + libpthread/pthread/pt-detach.c | 92 + libpthread/pthread/pt-exit.c | 118 ++ libpthread/pthread/pt-getattr.c | 49 + libpthread/pthread/pt-initialize.c | 33 + libpthread/pthread/pt-internal.h | 290 +++ libpthread/pthread/pt-join.c | 88 + libpthread/pthread/pt-self.c | 32 + libpthread/pthread/pt-setcancelstate.c | 42 + libpthread/pthread/pt-setcanceltype.c | 42 + libpthread/pthread/pt-sigmask.c | 33 + libpthread/pthread/pt-spin-inlines.c | 34 + libpthread/pthread/pt-testcancel.c | 31 + libpthread/signal/README | 4 + libpthread/signal/TODO | 29 + libpthread/signal/kill.c | 70 + libpthread/signal/pt-kill-siginfo-np.c | 88 + libpthread/signal/sig-internal.c | 26 + libpthread/signal/sig-internal.h | 177 ++ libpthread/signal/sigaction.c | 72 + libpthread/signal/sigaltstack.c | 69 + libpthread/signal/signal-dispatch.c | 117 ++ libpthread/signal/signal.h | 275 +++ libpthread/signal/sigpending.c | 38 + libpthread/signal/sigsuspend.c | 29 + libpthread/signal/sigtimedwait.c | 30 + libpthread/signal/sigwaiter.c | 91 + libpthread/signal/sigwaitinfo.c | 74 + libpthread/sysdeps/generic/bits/barrier-attr.h | 32 + libpthread/sysdeps/generic/bits/barrier.h | 39 + libpthread/sysdeps/generic/bits/cancelation.h | 54 + libpthread/sysdeps/generic/bits/condition-attr.h | 34 + libpthread/sysdeps/generic/bits/condition.h | 39 + libpthread/sysdeps/generic/bits/mutex-attr.h | 40 + libpthread/sysdeps/generic/bits/mutex.h | 67 + libpthread/sysdeps/generic/bits/once.h | 34 + libpthread/sysdeps/generic/bits/pthread-np.h | 27 + libpthread/sysdeps/generic/bits/pthread.h | 38 + libpthread/sysdeps/generic/bits/pthreadtypes.h | 29 + libpthread/sysdeps/generic/bits/rwlock-attr.h | 32 + libpthread/sysdeps/generic/bits/rwlock.h | 46 + libpthread/sysdeps/generic/bits/semaphore.h | 43 + libpthread/sysdeps/generic/bits/thread-attr.h | 43 + libpthread/sysdeps/generic/bits/thread-specific.h | 25 + libpthread/sysdeps/generic/killpg.c | 27 + libpthread/sysdeps/generic/pt-atfork.c | 29 + libpthread/sysdeps/generic/pt-attr-destroy.c | 27 + .../sysdeps/generic/pt-attr-getdetachstate.c | 29 + libpthread/sysdeps/generic/pt-attr-getguardsize.c | 29 + .../sysdeps/generic/pt-attr-getinheritsched.c | 29 + libpthread/sysdeps/generic/pt-attr-getschedparam.c | 31 + .../sysdeps/generic/pt-attr-getschedpolicy.c | 29 + libpthread/sysdeps/generic/pt-attr-getscope.c | 29 + libpthread/sysdeps/generic/pt-attr-getstack.c | 31 + libpthread/sysdeps/generic/pt-attr-getstackaddr.c | 29 + libpthread/sysdeps/generic/pt-attr-getstacksize.c | 29 + libpthread/sysdeps/generic/pt-attr-init.c | 28 + .../sysdeps/generic/pt-attr-setdetachstate.c | 38 + libpthread/sysdeps/generic/pt-attr-setguardsize.c | 29 + .../sysdeps/generic/pt-attr-setinheritsched.c | 38 + libpthread/sysdeps/generic/pt-attr-setschedparam.c | 38 + .../sysdeps/generic/pt-attr-setschedpolicy.c | 42 + libpthread/sysdeps/generic/pt-attr-setscope.c | 41 + libpthread/sysdeps/generic/pt-attr-setstack.c | 51 + libpthread/sysdeps/generic/pt-attr-setstackaddr.c | 29 + libpthread/sysdeps/generic/pt-attr-setstacksize.c | 41 + libpthread/sysdeps/generic/pt-attr.c | 41 + libpthread/sysdeps/generic/pt-barrier-destroy.c | 27 + libpthread/sysdeps/generic/pt-barrier-init.c | 53 + libpthread/sysdeps/generic/pt-barrier-wait.c | 61 + libpthread/sysdeps/generic/pt-barrier.c | 26 + .../sysdeps/generic/pt-barrierattr-destroy.c | 27 + .../sysdeps/generic/pt-barrierattr-getpshared.c | 29 + libpthread/sysdeps/generic/pt-barrierattr-init.c | 28 + .../sysdeps/generic/pt-barrierattr-setpshared.c | 39 + libpthread/sysdeps/generic/pt-cond-brdcast.c | 42 + libpthread/sysdeps/generic/pt-cond-destroy.c | 27 + libpthread/sysdeps/generic/pt-cond-init.c | 45 + libpthread/sysdeps/generic/pt-cond-signal.c | 54 + libpthread/sysdeps/generic/pt-cond-timedwait.c | 106 + libpthread/sysdeps/generic/pt-cond-wait.c | 37 + libpthread/sysdeps/generic/pt-cond.c | 29 + libpthread/sysdeps/generic/pt-condattr-destroy.c | 27 + libpthread/sysdeps/generic/pt-condattr-getclock.c | 31 + .../sysdeps/generic/pt-condattr-getpshared.c | 29 + libpthread/sysdeps/generic/pt-condattr-init.c | 28 + libpthread/sysdeps/generic/pt-condattr-setclock.c | 33 + .../sysdeps/generic/pt-condattr-setpshared.c | 39 + libpthread/sysdeps/generic/pt-destroy-specific.c | 28 + libpthread/sysdeps/generic/pt-equal.c | 29 + libpthread/sysdeps/generic/pt-getconcurrency.c | 27 + libpthread/sysdeps/generic/pt-getcpuclockid.c | 34 + libpthread/sysdeps/generic/pt-getschedparam.c | 28 + libpthread/sysdeps/generic/pt-getspecific.c | 27 + libpthread/sysdeps/generic/pt-init-specific.c | 27 + libpthread/sysdeps/generic/pt-key-create.c | 27 + libpthread/sysdeps/generic/pt-key-delete.c | 27 + libpthread/sysdeps/generic/pt-key.h | 22 + libpthread/sysdeps/generic/pt-kill.c | 32 + libpthread/sysdeps/generic/pt-mutex-destroy.c | 38 + .../sysdeps/generic/pt-mutex-getprioceiling.c | 28 + libpthread/sysdeps/generic/pt-mutex-init.c | 53 + libpthread/sysdeps/generic/pt-mutex-lock.c | 37 + .../sysdeps/generic/pt-mutex-setprioceiling.c | 28 + libpthread/sysdeps/generic/pt-mutex-timedlock.c | 181 ++ libpthread/sysdeps/generic/pt-mutex-transfer-np.c | 59 + libpthread/sysdeps/generic/pt-mutex-trylock.c | 104 + libpthread/sysdeps/generic/pt-mutex-unlock.c | 102 + libpthread/sysdeps/generic/pt-mutexattr-destroy.c | 27 + .../sysdeps/generic/pt-mutexattr-getprioceiling.c | 28 + .../sysdeps/generic/pt-mutexattr-getprotocol.c | 29 + .../sysdeps/generic/pt-mutexattr-getpshared.c | 29 + libpthread/sysdeps/generic/pt-mutexattr-gettype.c | 28 + libpthread/sysdeps/generic/pt-mutexattr-init.c | 28 + .../sysdeps/generic/pt-mutexattr-setprioceiling.c | 28 + .../sysdeps/generic/pt-mutexattr-setprotocol.c | 42 + .../sysdeps/generic/pt-mutexattr-setpshared.c | 39 + libpthread/sysdeps/generic/pt-mutexattr-settype.c | 37 + libpthread/sysdeps/generic/pt-mutexattr.c | 37 + libpthread/sysdeps/generic/pt-once.c | 43 + libpthread/sysdeps/generic/pt-rwlock-attr.c | 26 + libpthread/sysdeps/generic/pt-rwlock-destroy.c | 29 + libpthread/sysdeps/generic/pt-rwlock-init.c | 45 + libpthread/sysdeps/generic/pt-rwlock-rdlock.c | 32 + libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c | 113 + libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c | 95 + libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c | 56 + libpthread/sysdeps/generic/pt-rwlock-trywrlock.c | 46 + libpthread/sysdeps/generic/pt-rwlock-unlock.c | 90 + libpthread/sysdeps/generic/pt-rwlock-wrlock.c | 34 + libpthread/sysdeps/generic/pt-rwlockattr-destroy.c | 27 + .../sysdeps/generic/pt-rwlockattr-getpshared.c | 29 + libpthread/sysdeps/generic/pt-rwlockattr-init.c | 28 + .../sysdeps/generic/pt-rwlockattr-setpshared.c | 39 + libpthread/sysdeps/generic/pt-setconcurrency.c | 34 + libpthread/sysdeps/generic/pt-setschedparam.c | 28 + libpthread/sysdeps/generic/pt-setschedprio.c | 27 + libpthread/sysdeps/generic/pt-setspecific.c | 27 + libpthread/sysdeps/generic/pt-startup.c | 25 + libpthread/sysdeps/generic/raise.c | 41 + libpthread/sysdeps/generic/sem-close.c | 32 + libpthread/sysdeps/generic/sem-destroy.c | 38 + libpthread/sysdeps/generic/sem-getvalue.c | 33 + libpthread/sysdeps/generic/sem-init.c | 46 + libpthread/sysdeps/generic/sem-open.c | 32 + libpthread/sysdeps/generic/sem-post.c | 62 + libpthread/sysdeps/generic/sem-timedwait.c | 91 + libpthread/sysdeps/generic/sem-trywait.c | 42 + libpthread/sysdeps/generic/sem-unlink.c | 32 + libpthread/sysdeps/generic/sem-wait.c | 32 + libpthread/sysdeps/generic/sigaddset.c | 35 + libpthread/sysdeps/generic/sigdelset.c | 35 + libpthread/sysdeps/generic/sigemptyset.c | 29 + libpthread/sysdeps/generic/sigfillset.c | 29 + libpthread/sysdeps/generic/siginterrupt.c | 36 + libpthread/sysdeps/generic/sigismember.c | 36 + libpthread/sysdeps/generic/signal.c | 44 + libpthread/sysdeps/generic/sigwait.c | 34 + libpthread/sysdeps/hurd/pt-destroy-specific.c | 79 + libpthread/sysdeps/hurd/pt-getspecific.c | 37 + libpthread/sysdeps/hurd/pt-init-specific.c | 30 + libpthread/sysdeps/hurd/pt-key-create.c | 109 + libpthread/sysdeps/hurd/pt-key-delete.c | 45 + libpthread/sysdeps/hurd/pt-key.h | 76 + libpthread/sysdeps/hurd/pt-kill.c | 49 + libpthread/sysdeps/hurd/pt-setspecific.c | 43 + libpthread/sysdeps/ia32/bits/atomic.h | 66 + libpthread/sysdeps/ia32/bits/memory.h | 40 + libpthread/sysdeps/ia32/bits/spin-lock-inline.h | 98 + libpthread/sysdeps/ia32/bits/spin-lock.h | 39 + libpthread/sysdeps/ia32/machine-sp.h | 30 + libpthread/sysdeps/ia32/pt-machdep.h | 29 + libpthread/sysdeps/l4/bits/pthread-np.h | 35 + libpthread/sysdeps/l4/hurd/bits/pthread-np.h | 31 + libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c | 20 + libpthread/sysdeps/l4/hurd/ia32/pt-setup.c | 117 ++ .../l4/hurd/ia32/signal-dispatch-lowlevel.c | 213 ++ libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c | 20 + libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c | 93 + libpthread/sysdeps/l4/hurd/pt-block.c | 30 + libpthread/sysdeps/l4/hurd/pt-kill.c | 3 + libpthread/sysdeps/l4/hurd/pt-setactivity-np.c | 39 + libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c | 28 + libpthread/sysdeps/l4/hurd/pt-sigstate-init.c | 44 + libpthread/sysdeps/l4/hurd/pt-sigstate.c | 81 + libpthread/sysdeps/l4/hurd/pt-startup.c | 30 + libpthread/sysdeps/l4/hurd/pt-sysdep.c | 61 + libpthread/sysdeps/l4/hurd/pt-sysdep.h | 61 + libpthread/sysdeps/l4/hurd/pt-thread-alloc.c | 95 + libpthread/sysdeps/l4/hurd/pt-thread-halt.c | 104 + libpthread/sysdeps/l4/hurd/pt-thread-start.c | 70 + libpthread/sysdeps/l4/hurd/pt-wakeup.c | 46 + libpthread/sysdeps/l4/hurd/sig-sysdep.h | 69 + libpthread/sysdeps/l4/hurd/sigprocmask.c | 41 + libpthread/sysdeps/l4/pt-block.c | 47 + libpthread/sysdeps/l4/pt-docancel.c | 42 + libpthread/sysdeps/l4/pt-pool-np.c | 54 + libpthread/sysdeps/l4/pt-spin.c | 63 + libpthread/sysdeps/l4/pt-stack-alloc.c | 43 + libpthread/sysdeps/l4/pt-thread-alloc.c | 43 + libpthread/sysdeps/l4/pt-thread-dealloc.c | 32 + libpthread/sysdeps/l4/pt-thread-halt.c | 45 + libpthread/sysdeps/l4/pt-thread-start.c | 40 + libpthread/sysdeps/l4/pt-timedblock.c | 35 + libpthread/sysdeps/l4/pt-wakeup.c | 54 + libpthread/sysdeps/mach/bits/spin-lock-inline.h | 90 + libpthread/sysdeps/mach/bits/spin-lock.h | 38 + libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c | 54 + libpthread/sysdeps/mach/hurd/ia32/pt-setup.c | 105 + .../sysdeps/mach/hurd/pt-attr-setstackaddr.c | 35 + .../sysdeps/mach/hurd/pt-attr-setstacksize.c | 35 + libpthread/sysdeps/mach/hurd/pt-docancel.c | 64 + libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c | 28 + libpthread/sysdeps/mach/hurd/pt-sigstate-init.c | 37 + libpthread/sysdeps/mach/hurd/pt-sigstate.c | 69 + libpthread/sysdeps/mach/hurd/pt-sysdep.c | 72 + libpthread/sysdeps/mach/hurd/pt-sysdep.h | 70 + libpthread/sysdeps/mach/pt-block.c | 39 + libpthread/sysdeps/mach/pt-spin.c | 36 + libpthread/sysdeps/mach/pt-stack-alloc.c | 74 + libpthread/sysdeps/mach/pt-thread-alloc.c | 106 + libpthread/sysdeps/mach/pt-thread-dealloc.c | 41 + libpthread/sysdeps/mach/pt-thread-halt.c | 37 + libpthread/sysdeps/mach/pt-thread-start.c | 49 + libpthread/sysdeps/mach/pt-timedblock.c | 68 + libpthread/sysdeps/mach/pt-wakeup.c | 38 + libpthread/sysdeps/posix/pt-spin.c | 54 + libpthread/sysdeps/powerpc/bits/machine-lock.h | 78 + libpthread/sysdeps/powerpc/bits/memory.h | 36 + libpthread/sysdeps/powerpc/bits/spin-lock.h | 108 + libpthread/sysdeps/powerpc/machine-sp.h | 31 + libpthread/sysdeps/powerpc/pt-machdep.h | 29 + libpthread/tests/.cvsignore | 1 + libpthread/tests/Makefile | 29 + libpthread/tests/test-1.c | 49 + libpthread/tests/test-10.c | 46 + libpthread/tests/test-11.c | 143 ++ libpthread/tests/test-12.c | 29 + libpthread/tests/test-13.c | 66 + libpthread/tests/test-14.c | 44 + libpthread/tests/test-15.c | 87 + libpthread/tests/test-16.c | 71 + libpthread/tests/test-2.c | 39 + libpthread/tests/test-3.c | 55 + libpthread/tests/test-4.c | 86 + libpthread/tests/test-5.c | 75 + libpthread/tests/test-6.c | 95 + libpthread/tests/test-7.c | 66 + libpthread/tests/test-8.c | 60 + libpthread/tests/test-9.c | 88 + libpthread_pic.a | 20 - lockfile.c | 65 - not-in-libc.h | 11 - pthread/Versions | 15 - pthread/cthreads-compat.c | 104 - pthread/pt-alloc.c | 215 -- pthread/pt-cancel.c | 40 - pthread/pt-cleanup.c | 28 - pthread/pt-create.c | 206 -- pthread/pt-dealloc.c | 64 - pthread/pt-detach.c | 92 - pthread/pt-exit.c | 118 -- pthread/pt-getattr.c | 49 - pthread/pt-initialize.c | 33 - pthread/pt-internal.h | 290 --- pthread/pt-join.c | 88 - pthread/pt-self.c | 32 - pthread/pt-setcancelstate.c | 42 - pthread/pt-setcanceltype.c | 42 - pthread/pt-sigmask.c | 33 - pthread/pt-spin-inlines.c | 34 - pthread/pt-testcancel.c | 31 - signal/README | 4 - signal/TODO | 29 - signal/kill.c | 70 - signal/pt-kill-siginfo-np.c | 88 - signal/sig-internal.c | 26 - signal/sig-internal.h | 177 -- signal/sigaction.c | 72 - signal/sigaltstack.c | 69 - signal/signal-dispatch.c | 117 -- signal/signal.h | 275 --- signal/sigpending.c | 38 - signal/sigsuspend.c | 29 - signal/sigtimedwait.c | 30 - signal/sigwaiter.c | 91 - signal/sigwaitinfo.c | 74 - sysdeps/generic/bits/barrier-attr.h | 32 - sysdeps/generic/bits/barrier.h | 39 - sysdeps/generic/bits/cancelation.h | 54 - sysdeps/generic/bits/condition-attr.h | 34 - sysdeps/generic/bits/condition.h | 39 - sysdeps/generic/bits/mutex-attr.h | 40 - sysdeps/generic/bits/mutex.h | 67 - sysdeps/generic/bits/once.h | 34 - sysdeps/generic/bits/pthread-np.h | 27 - sysdeps/generic/bits/pthread.h | 38 - sysdeps/generic/bits/pthreadtypes.h | 29 - sysdeps/generic/bits/rwlock-attr.h | 32 - sysdeps/generic/bits/rwlock.h | 46 - sysdeps/generic/bits/semaphore.h | 43 - sysdeps/generic/bits/thread-attr.h | 43 - sysdeps/generic/bits/thread-specific.h | 25 - sysdeps/generic/killpg.c | 27 - sysdeps/generic/pt-atfork.c | 29 - sysdeps/generic/pt-attr-destroy.c | 27 - sysdeps/generic/pt-attr-getdetachstate.c | 29 - sysdeps/generic/pt-attr-getguardsize.c | 29 - sysdeps/generic/pt-attr-getinheritsched.c | 29 - sysdeps/generic/pt-attr-getschedparam.c | 31 - sysdeps/generic/pt-attr-getschedpolicy.c | 29 - sysdeps/generic/pt-attr-getscope.c | 29 - sysdeps/generic/pt-attr-getstack.c | 31 - sysdeps/generic/pt-attr-getstackaddr.c | 29 - sysdeps/generic/pt-attr-getstacksize.c | 29 - sysdeps/generic/pt-attr-init.c | 28 - sysdeps/generic/pt-attr-setdetachstate.c | 38 - sysdeps/generic/pt-attr-setguardsize.c | 29 - sysdeps/generic/pt-attr-setinheritsched.c | 38 - sysdeps/generic/pt-attr-setschedparam.c | 38 - sysdeps/generic/pt-attr-setschedpolicy.c | 42 - sysdeps/generic/pt-attr-setscope.c | 41 - sysdeps/generic/pt-attr-setstack.c | 51 - sysdeps/generic/pt-attr-setstackaddr.c | 29 - sysdeps/generic/pt-attr-setstacksize.c | 41 - sysdeps/generic/pt-attr.c | 41 - sysdeps/generic/pt-barrier-destroy.c | 27 - sysdeps/generic/pt-barrier-init.c | 53 - sysdeps/generic/pt-barrier-wait.c | 61 - sysdeps/generic/pt-barrier.c | 26 - sysdeps/generic/pt-barrierattr-destroy.c | 27 - sysdeps/generic/pt-barrierattr-getpshared.c | 29 - sysdeps/generic/pt-barrierattr-init.c | 28 - sysdeps/generic/pt-barrierattr-setpshared.c | 39 - sysdeps/generic/pt-cond-brdcast.c | 42 - sysdeps/generic/pt-cond-destroy.c | 27 - sysdeps/generic/pt-cond-init.c | 45 - sysdeps/generic/pt-cond-signal.c | 54 - sysdeps/generic/pt-cond-timedwait.c | 106 - sysdeps/generic/pt-cond-wait.c | 37 - sysdeps/generic/pt-cond.c | 29 - sysdeps/generic/pt-condattr-destroy.c | 27 - sysdeps/generic/pt-condattr-getclock.c | 31 - sysdeps/generic/pt-condattr-getpshared.c | 29 - sysdeps/generic/pt-condattr-init.c | 28 - sysdeps/generic/pt-condattr-setclock.c | 33 - sysdeps/generic/pt-condattr-setpshared.c | 39 - sysdeps/generic/pt-destroy-specific.c | 28 - sysdeps/generic/pt-equal.c | 29 - sysdeps/generic/pt-getconcurrency.c | 27 - sysdeps/generic/pt-getcpuclockid.c | 34 - sysdeps/generic/pt-getschedparam.c | 28 - sysdeps/generic/pt-getspecific.c | 27 - sysdeps/generic/pt-init-specific.c | 27 - sysdeps/generic/pt-key-create.c | 27 - sysdeps/generic/pt-key-delete.c | 27 - sysdeps/generic/pt-key.h | 22 - sysdeps/generic/pt-kill.c | 32 - sysdeps/generic/pt-mutex-destroy.c | 38 - sysdeps/generic/pt-mutex-getprioceiling.c | 28 - sysdeps/generic/pt-mutex-init.c | 53 - sysdeps/generic/pt-mutex-lock.c | 37 - sysdeps/generic/pt-mutex-setprioceiling.c | 28 - sysdeps/generic/pt-mutex-timedlock.c | 181 -- sysdeps/generic/pt-mutex-transfer-np.c | 59 - sysdeps/generic/pt-mutex-trylock.c | 104 - sysdeps/generic/pt-mutex-unlock.c | 102 - sysdeps/generic/pt-mutexattr-destroy.c | 27 - sysdeps/generic/pt-mutexattr-getprioceiling.c | 28 - sysdeps/generic/pt-mutexattr-getprotocol.c | 29 - sysdeps/generic/pt-mutexattr-getpshared.c | 29 - sysdeps/generic/pt-mutexattr-gettype.c | 28 - sysdeps/generic/pt-mutexattr-init.c | 28 - sysdeps/generic/pt-mutexattr-setprioceiling.c | 28 - sysdeps/generic/pt-mutexattr-setprotocol.c | 42 - sysdeps/generic/pt-mutexattr-setpshared.c | 39 - sysdeps/generic/pt-mutexattr-settype.c | 37 - sysdeps/generic/pt-mutexattr.c | 37 - sysdeps/generic/pt-once.c | 43 - sysdeps/generic/pt-rwlock-attr.c | 26 - sysdeps/generic/pt-rwlock-destroy.c | 29 - sysdeps/generic/pt-rwlock-init.c | 45 - sysdeps/generic/pt-rwlock-rdlock.c | 32 - sysdeps/generic/pt-rwlock-timedrdlock.c | 113 - sysdeps/generic/pt-rwlock-timedwrlock.c | 95 - sysdeps/generic/pt-rwlock-tryrdlock.c | 56 - sysdeps/generic/pt-rwlock-trywrlock.c | 46 - sysdeps/generic/pt-rwlock-unlock.c | 90 - sysdeps/generic/pt-rwlock-wrlock.c | 34 - sysdeps/generic/pt-rwlockattr-destroy.c | 27 - sysdeps/generic/pt-rwlockattr-getpshared.c | 29 - sysdeps/generic/pt-rwlockattr-init.c | 28 - sysdeps/generic/pt-rwlockattr-setpshared.c | 39 - sysdeps/generic/pt-setconcurrency.c | 34 - sysdeps/generic/pt-setschedparam.c | 28 - sysdeps/generic/pt-setschedprio.c | 27 - sysdeps/generic/pt-setspecific.c | 27 - sysdeps/generic/pt-startup.c | 25 - sysdeps/generic/raise.c | 41 - sysdeps/generic/sem-close.c | 32 - sysdeps/generic/sem-destroy.c | 38 - sysdeps/generic/sem-getvalue.c | 33 - sysdeps/generic/sem-init.c | 46 - sysdeps/generic/sem-open.c | 32 - sysdeps/generic/sem-post.c | 62 - sysdeps/generic/sem-timedwait.c | 91 - sysdeps/generic/sem-trywait.c | 42 - sysdeps/generic/sem-unlink.c | 32 - sysdeps/generic/sem-wait.c | 32 - sysdeps/generic/sigaddset.c | 35 - sysdeps/generic/sigdelset.c | 35 - sysdeps/generic/sigemptyset.c | 29 - sysdeps/generic/sigfillset.c | 29 - sysdeps/generic/siginterrupt.c | 36 - sysdeps/generic/sigismember.c | 36 - sysdeps/generic/signal.c | 44 - sysdeps/generic/sigwait.c | 34 - sysdeps/hurd/pt-destroy-specific.c | 79 - sysdeps/hurd/pt-getspecific.c | 37 - sysdeps/hurd/pt-init-specific.c | 30 - sysdeps/hurd/pt-key-create.c | 109 - sysdeps/hurd/pt-key-delete.c | 45 - sysdeps/hurd/pt-key.h | 76 - sysdeps/hurd/pt-kill.c | 49 - sysdeps/hurd/pt-setspecific.c | 43 - sysdeps/ia32/bits/atomic.h | 66 - sysdeps/ia32/bits/memory.h | 40 - sysdeps/ia32/bits/spin-lock-inline.h | 98 - sysdeps/ia32/bits/spin-lock.h | 39 - sysdeps/ia32/machine-sp.h | 30 - sysdeps/ia32/pt-machdep.h | 29 - sysdeps/l4/bits/pthread-np.h | 35 - sysdeps/l4/hurd/bits/pthread-np.h | 31 - sysdeps/l4/hurd/ia32/pt-machdep.c | 20 - sysdeps/l4/hurd/ia32/pt-setup.c | 117 -- sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c | 213 -- sysdeps/l4/hurd/powerpc/pt-machdep.c | 20 - sysdeps/l4/hurd/powerpc/pt-setup.c | 93 - sysdeps/l4/hurd/pt-block.c | 30 - sysdeps/l4/hurd/pt-kill.c | 3 - sysdeps/l4/hurd/pt-setactivity-np.c | 39 - sysdeps/l4/hurd/pt-sigstate-destroy.c | 28 - sysdeps/l4/hurd/pt-sigstate-init.c | 44 - sysdeps/l4/hurd/pt-sigstate.c | 81 - sysdeps/l4/hurd/pt-startup.c | 30 - sysdeps/l4/hurd/pt-sysdep.c | 61 - sysdeps/l4/hurd/pt-sysdep.h | 61 - sysdeps/l4/hurd/pt-thread-alloc.c | 95 - sysdeps/l4/hurd/pt-thread-halt.c | 104 - sysdeps/l4/hurd/pt-thread-start.c | 70 - sysdeps/l4/hurd/pt-wakeup.c | 46 - sysdeps/l4/hurd/sig-sysdep.h | 69 - sysdeps/l4/hurd/sigprocmask.c | 41 - sysdeps/l4/pt-block.c | 47 - sysdeps/l4/pt-docancel.c | 42 - sysdeps/l4/pt-pool-np.c | 54 - sysdeps/l4/pt-spin.c | 63 - sysdeps/l4/pt-stack-alloc.c | 43 - sysdeps/l4/pt-thread-alloc.c | 43 - sysdeps/l4/pt-thread-dealloc.c | 32 - sysdeps/l4/pt-thread-halt.c | 45 - sysdeps/l4/pt-thread-start.c | 40 - sysdeps/l4/pt-timedblock.c | 35 - sysdeps/l4/pt-wakeup.c | 54 - sysdeps/mach/bits/spin-lock-inline.h | 90 - sysdeps/mach/bits/spin-lock.h | 38 - sysdeps/mach/hurd/ia32/pt-machdep.c | 54 - sysdeps/mach/hurd/ia32/pt-setup.c | 105 - sysdeps/mach/hurd/pt-attr-setstackaddr.c | 35 - sysdeps/mach/hurd/pt-attr-setstacksize.c | 35 - sysdeps/mach/hurd/pt-docancel.c | 64 - sysdeps/mach/hurd/pt-sigstate-destroy.c | 28 - sysdeps/mach/hurd/pt-sigstate-init.c | 37 - sysdeps/mach/hurd/pt-sigstate.c | 69 - sysdeps/mach/hurd/pt-sysdep.c | 72 - sysdeps/mach/hurd/pt-sysdep.h | 70 - sysdeps/mach/pt-block.c | 39 - sysdeps/mach/pt-spin.c | 36 - sysdeps/mach/pt-stack-alloc.c | 74 - sysdeps/mach/pt-thread-alloc.c | 106 - sysdeps/mach/pt-thread-dealloc.c | 41 - sysdeps/mach/pt-thread-halt.c | 37 - sysdeps/mach/pt-thread-start.c | 49 - sysdeps/mach/pt-timedblock.c | 68 - sysdeps/mach/pt-wakeup.c | 38 - sysdeps/posix/pt-spin.c | 54 - sysdeps/powerpc/bits/machine-lock.h | 78 - sysdeps/powerpc/bits/memory.h | 36 - sysdeps/powerpc/bits/spin-lock.h | 108 - sysdeps/powerpc/machine-sp.h | 31 - sysdeps/powerpc/pt-machdep.h | 29 - tests/.cvsignore | 1 - tests/Makefile | 29 - tests/test-1.c | 49 - tests/test-10.c | 46 - tests/test-11.c | 143 -- tests/test-12.c | 29 - tests/test-13.c | 66 - tests/test-14.c | 44 - tests/test-15.c | 87 - tests/test-16.c | 71 - tests/test-2.c | 39 - tests/test-3.c | 55 - tests/test-4.c | 86 - tests/test-5.c | 75 - tests/test-6.c | 95 - tests/test-7.c | 66 - tests/test-8.c | 60 - tests/test-9.c | 88 - 533 files changed, 17492 insertions(+), 13447 deletions(-) delete mode 100644 Makefile.am delete mode 100644 headers.m4 delete mode 100644 libpthread.a create mode 100644 libpthread/ChangeLog create mode 100644 libpthread/Makefile create mode 100644 libpthread/Makefile.am create mode 100644 libpthread/TODO create mode 100644 libpthread/headers.m4 create mode 100644 libpthread/include/libc-symbols.h create mode 100644 libpthread/include/pthread.h create mode 100644 libpthread/include/pthread/pthread.h create mode 100644 libpthread/include/pthread/pthreadtypes.h create mode 100644 libpthread/include/semaphore.h create mode 100644 libpthread/include/set-hooks.h create mode 100644 libpthread/libpthread.a create mode 100644 libpthread/libpthread_pic.a create mode 100644 libpthread/lockfile.c create mode 100644 libpthread/not-in-libc.h create mode 100644 libpthread/pthread/Versions create mode 100644 libpthread/pthread/cthreads-compat.c create mode 100644 libpthread/pthread/pt-alloc.c create mode 100644 libpthread/pthread/pt-cancel.c create mode 100644 libpthread/pthread/pt-cleanup.c create mode 100644 libpthread/pthread/pt-create.c create mode 100644 libpthread/pthread/pt-dealloc.c create mode 100644 libpthread/pthread/pt-detach.c create mode 100644 libpthread/pthread/pt-exit.c create mode 100644 libpthread/pthread/pt-getattr.c create mode 100644 libpthread/pthread/pt-initialize.c create mode 100644 libpthread/pthread/pt-internal.h create mode 100644 libpthread/pthread/pt-join.c create mode 100644 libpthread/pthread/pt-self.c create mode 100644 libpthread/pthread/pt-setcancelstate.c create mode 100644 libpthread/pthread/pt-setcanceltype.c create mode 100644 libpthread/pthread/pt-sigmask.c create mode 100644 libpthread/pthread/pt-spin-inlines.c create mode 100644 libpthread/pthread/pt-testcancel.c create mode 100644 libpthread/signal/README create mode 100644 libpthread/signal/TODO create mode 100644 libpthread/signal/kill.c create mode 100644 libpthread/signal/pt-kill-siginfo-np.c create mode 100644 libpthread/signal/sig-internal.c create mode 100644 libpthread/signal/sig-internal.h create mode 100644 libpthread/signal/sigaction.c create mode 100644 libpthread/signal/sigaltstack.c create mode 100644 libpthread/signal/signal-dispatch.c create mode 100644 libpthread/signal/signal.h create mode 100644 libpthread/signal/sigpending.c create mode 100644 libpthread/signal/sigsuspend.c create mode 100644 libpthread/signal/sigtimedwait.c create mode 100644 libpthread/signal/sigwaiter.c create mode 100644 libpthread/signal/sigwaitinfo.c create mode 100644 libpthread/sysdeps/generic/bits/barrier-attr.h create mode 100644 libpthread/sysdeps/generic/bits/barrier.h create mode 100644 libpthread/sysdeps/generic/bits/cancelation.h create mode 100644 libpthread/sysdeps/generic/bits/condition-attr.h create mode 100644 libpthread/sysdeps/generic/bits/condition.h create mode 100644 libpthread/sysdeps/generic/bits/mutex-attr.h create mode 100644 libpthread/sysdeps/generic/bits/mutex.h create mode 100644 libpthread/sysdeps/generic/bits/once.h create mode 100644 libpthread/sysdeps/generic/bits/pthread-np.h create mode 100644 libpthread/sysdeps/generic/bits/pthread.h create mode 100644 libpthread/sysdeps/generic/bits/pthreadtypes.h create mode 100644 libpthread/sysdeps/generic/bits/rwlock-attr.h create mode 100644 libpthread/sysdeps/generic/bits/rwlock.h create mode 100644 libpthread/sysdeps/generic/bits/semaphore.h create mode 100644 libpthread/sysdeps/generic/bits/thread-attr.h create mode 100644 libpthread/sysdeps/generic/bits/thread-specific.h create mode 100644 libpthread/sysdeps/generic/killpg.c create mode 100644 libpthread/sysdeps/generic/pt-atfork.c create mode 100644 libpthread/sysdeps/generic/pt-attr-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getdetachstate.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getguardsize.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getinheritsched.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getschedparam.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getschedpolicy.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getscope.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getstack.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getstackaddr.c create mode 100644 libpthread/sysdeps/generic/pt-attr-getstacksize.c create mode 100644 libpthread/sysdeps/generic/pt-attr-init.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setdetachstate.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setguardsize.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setinheritsched.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setschedparam.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setschedpolicy.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setscope.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setstack.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setstackaddr.c create mode 100644 libpthread/sysdeps/generic/pt-attr-setstacksize.c create mode 100644 libpthread/sysdeps/generic/pt-attr.c create mode 100644 libpthread/sysdeps/generic/pt-barrier-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-barrier-init.c create mode 100644 libpthread/sysdeps/generic/pt-barrier-wait.c create mode 100644 libpthread/sysdeps/generic/pt-barrier.c create mode 100644 libpthread/sysdeps/generic/pt-barrierattr-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-barrierattr-getpshared.c create mode 100644 libpthread/sysdeps/generic/pt-barrierattr-init.c create mode 100644 libpthread/sysdeps/generic/pt-barrierattr-setpshared.c create mode 100644 libpthread/sysdeps/generic/pt-cond-brdcast.c create mode 100644 libpthread/sysdeps/generic/pt-cond-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-cond-init.c create mode 100644 libpthread/sysdeps/generic/pt-cond-signal.c create mode 100644 libpthread/sysdeps/generic/pt-cond-timedwait.c create mode 100644 libpthread/sysdeps/generic/pt-cond-wait.c create mode 100644 libpthread/sysdeps/generic/pt-cond.c create mode 100644 libpthread/sysdeps/generic/pt-condattr-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-condattr-getclock.c create mode 100644 libpthread/sysdeps/generic/pt-condattr-getpshared.c create mode 100644 libpthread/sysdeps/generic/pt-condattr-init.c create mode 100644 libpthread/sysdeps/generic/pt-condattr-setclock.c create mode 100644 libpthread/sysdeps/generic/pt-condattr-setpshared.c create mode 100644 libpthread/sysdeps/generic/pt-destroy-specific.c create mode 100644 libpthread/sysdeps/generic/pt-equal.c create mode 100644 libpthread/sysdeps/generic/pt-getconcurrency.c create mode 100644 libpthread/sysdeps/generic/pt-getcpuclockid.c create mode 100644 libpthread/sysdeps/generic/pt-getschedparam.c create mode 100644 libpthread/sysdeps/generic/pt-getspecific.c create mode 100644 libpthread/sysdeps/generic/pt-init-specific.c create mode 100644 libpthread/sysdeps/generic/pt-key-create.c create mode 100644 libpthread/sysdeps/generic/pt-key-delete.c create mode 100644 libpthread/sysdeps/generic/pt-key.h create mode 100644 libpthread/sysdeps/generic/pt-kill.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-getprioceiling.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-init.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-lock.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-setprioceiling.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-timedlock.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-transfer-np.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-trylock.c create mode 100644 libpthread/sysdeps/generic/pt-mutex-unlock.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-getprotocol.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-getpshared.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-gettype.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-init.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-setprotocol.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-setpshared.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr-settype.c create mode 100644 libpthread/sysdeps/generic/pt-mutexattr.c create mode 100644 libpthread/sysdeps/generic/pt-once.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-attr.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-init.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-rdlock.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-trywrlock.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-unlock.c create mode 100644 libpthread/sysdeps/generic/pt-rwlock-wrlock.c create mode 100644 libpthread/sysdeps/generic/pt-rwlockattr-destroy.c create mode 100644 libpthread/sysdeps/generic/pt-rwlockattr-getpshared.c create mode 100644 libpthread/sysdeps/generic/pt-rwlockattr-init.c create mode 100644 libpthread/sysdeps/generic/pt-rwlockattr-setpshared.c create mode 100644 libpthread/sysdeps/generic/pt-setconcurrency.c create mode 100644 libpthread/sysdeps/generic/pt-setschedparam.c create mode 100644 libpthread/sysdeps/generic/pt-setschedprio.c create mode 100644 libpthread/sysdeps/generic/pt-setspecific.c create mode 100644 libpthread/sysdeps/generic/pt-startup.c create mode 100644 libpthread/sysdeps/generic/raise.c create mode 100644 libpthread/sysdeps/generic/sem-close.c create mode 100644 libpthread/sysdeps/generic/sem-destroy.c create mode 100644 libpthread/sysdeps/generic/sem-getvalue.c create mode 100644 libpthread/sysdeps/generic/sem-init.c create mode 100644 libpthread/sysdeps/generic/sem-open.c create mode 100644 libpthread/sysdeps/generic/sem-post.c create mode 100644 libpthread/sysdeps/generic/sem-timedwait.c create mode 100644 libpthread/sysdeps/generic/sem-trywait.c create mode 100644 libpthread/sysdeps/generic/sem-unlink.c create mode 100644 libpthread/sysdeps/generic/sem-wait.c create mode 100644 libpthread/sysdeps/generic/sigaddset.c create mode 100644 libpthread/sysdeps/generic/sigdelset.c create mode 100644 libpthread/sysdeps/generic/sigemptyset.c create mode 100644 libpthread/sysdeps/generic/sigfillset.c create mode 100644 libpthread/sysdeps/generic/siginterrupt.c create mode 100644 libpthread/sysdeps/generic/sigismember.c create mode 100644 libpthread/sysdeps/generic/signal.c create mode 100644 libpthread/sysdeps/generic/sigwait.c create mode 100644 libpthread/sysdeps/hurd/pt-destroy-specific.c create mode 100644 libpthread/sysdeps/hurd/pt-getspecific.c create mode 100644 libpthread/sysdeps/hurd/pt-init-specific.c create mode 100644 libpthread/sysdeps/hurd/pt-key-create.c create mode 100644 libpthread/sysdeps/hurd/pt-key-delete.c create mode 100644 libpthread/sysdeps/hurd/pt-key.h create mode 100644 libpthread/sysdeps/hurd/pt-kill.c create mode 100644 libpthread/sysdeps/hurd/pt-setspecific.c create mode 100644 libpthread/sysdeps/ia32/bits/atomic.h create mode 100644 libpthread/sysdeps/ia32/bits/memory.h create mode 100644 libpthread/sysdeps/ia32/bits/spin-lock-inline.h create mode 100644 libpthread/sysdeps/ia32/bits/spin-lock.h create mode 100644 libpthread/sysdeps/ia32/machine-sp.h create mode 100644 libpthread/sysdeps/ia32/pt-machdep.h create mode 100644 libpthread/sysdeps/l4/bits/pthread-np.h create mode 100644 libpthread/sysdeps/l4/hurd/bits/pthread-np.h create mode 100644 libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c create mode 100644 libpthread/sysdeps/l4/hurd/ia32/pt-setup.c create mode 100644 libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c create mode 100644 libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c create mode 100644 libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-block.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-kill.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-setactivity-np.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-sigstate-init.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-sigstate.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-startup.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-sysdep.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-sysdep.h create mode 100644 libpthread/sysdeps/l4/hurd/pt-thread-alloc.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-thread-halt.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-thread-start.c create mode 100644 libpthread/sysdeps/l4/hurd/pt-wakeup.c create mode 100644 libpthread/sysdeps/l4/hurd/sig-sysdep.h create mode 100644 libpthread/sysdeps/l4/hurd/sigprocmask.c create mode 100644 libpthread/sysdeps/l4/pt-block.c create mode 100644 libpthread/sysdeps/l4/pt-docancel.c create mode 100644 libpthread/sysdeps/l4/pt-pool-np.c create mode 100644 libpthread/sysdeps/l4/pt-spin.c create mode 100644 libpthread/sysdeps/l4/pt-stack-alloc.c create mode 100644 libpthread/sysdeps/l4/pt-thread-alloc.c create mode 100644 libpthread/sysdeps/l4/pt-thread-dealloc.c create mode 100644 libpthread/sysdeps/l4/pt-thread-halt.c create mode 100644 libpthread/sysdeps/l4/pt-thread-start.c create mode 100644 libpthread/sysdeps/l4/pt-timedblock.c create mode 100644 libpthread/sysdeps/l4/pt-wakeup.c create mode 100644 libpthread/sysdeps/mach/bits/spin-lock-inline.h create mode 100644 libpthread/sysdeps/mach/bits/spin-lock.h create mode 100644 libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c create mode 100644 libpthread/sysdeps/mach/hurd/ia32/pt-setup.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-attr-setstackaddr.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-attr-setstacksize.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-docancel.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-sigstate-init.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-sigstate.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-sysdep.c create mode 100644 libpthread/sysdeps/mach/hurd/pt-sysdep.h create mode 100644 libpthread/sysdeps/mach/pt-block.c create mode 100644 libpthread/sysdeps/mach/pt-spin.c create mode 100644 libpthread/sysdeps/mach/pt-stack-alloc.c create mode 100644 libpthread/sysdeps/mach/pt-thread-alloc.c create mode 100644 libpthread/sysdeps/mach/pt-thread-dealloc.c create mode 100644 libpthread/sysdeps/mach/pt-thread-halt.c create mode 100644 libpthread/sysdeps/mach/pt-thread-start.c create mode 100644 libpthread/sysdeps/mach/pt-timedblock.c create mode 100644 libpthread/sysdeps/mach/pt-wakeup.c create mode 100644 libpthread/sysdeps/posix/pt-spin.c create mode 100644 libpthread/sysdeps/powerpc/bits/machine-lock.h create mode 100644 libpthread/sysdeps/powerpc/bits/memory.h create mode 100644 libpthread/sysdeps/powerpc/bits/spin-lock.h create mode 100644 libpthread/sysdeps/powerpc/machine-sp.h create mode 100644 libpthread/sysdeps/powerpc/pt-machdep.h create mode 100644 libpthread/tests/.cvsignore create mode 100644 libpthread/tests/Makefile create mode 100644 libpthread/tests/test-1.c create mode 100644 libpthread/tests/test-10.c create mode 100644 libpthread/tests/test-11.c create mode 100644 libpthread/tests/test-12.c create mode 100644 libpthread/tests/test-13.c create mode 100644 libpthread/tests/test-14.c create mode 100644 libpthread/tests/test-15.c create mode 100644 libpthread/tests/test-16.c create mode 100644 libpthread/tests/test-2.c create mode 100644 libpthread/tests/test-3.c create mode 100644 libpthread/tests/test-4.c create mode 100644 libpthread/tests/test-5.c create mode 100644 libpthread/tests/test-6.c create mode 100644 libpthread/tests/test-7.c create mode 100644 libpthread/tests/test-8.c create mode 100644 libpthread/tests/test-9.c delete mode 100644 libpthread_pic.a delete mode 100644 lockfile.c delete mode 100644 not-in-libc.h delete mode 100644 pthread/Versions delete mode 100644 pthread/cthreads-compat.c delete mode 100644 pthread/pt-alloc.c delete mode 100644 pthread/pt-cancel.c delete mode 100644 pthread/pt-cleanup.c delete mode 100644 pthread/pt-create.c delete mode 100644 pthread/pt-dealloc.c delete mode 100644 pthread/pt-detach.c delete mode 100644 pthread/pt-exit.c delete mode 100644 pthread/pt-getattr.c delete mode 100644 pthread/pt-initialize.c delete mode 100644 pthread/pt-internal.h delete mode 100644 pthread/pt-join.c delete mode 100644 pthread/pt-self.c delete mode 100644 pthread/pt-setcancelstate.c delete mode 100644 pthread/pt-setcanceltype.c delete mode 100644 pthread/pt-sigmask.c delete mode 100644 pthread/pt-spin-inlines.c delete mode 100644 pthread/pt-testcancel.c delete mode 100644 signal/README delete mode 100644 signal/TODO delete mode 100644 signal/kill.c delete mode 100644 signal/pt-kill-siginfo-np.c delete mode 100644 signal/sig-internal.c delete mode 100644 signal/sig-internal.h delete mode 100644 signal/sigaction.c delete mode 100644 signal/sigaltstack.c delete mode 100644 signal/signal-dispatch.c delete mode 100644 signal/signal.h delete mode 100644 signal/sigpending.c delete mode 100644 signal/sigsuspend.c delete mode 100644 signal/sigtimedwait.c delete mode 100644 signal/sigwaiter.c delete mode 100644 signal/sigwaitinfo.c delete mode 100644 sysdeps/generic/bits/barrier-attr.h delete mode 100644 sysdeps/generic/bits/barrier.h delete mode 100644 sysdeps/generic/bits/cancelation.h delete mode 100644 sysdeps/generic/bits/condition-attr.h delete mode 100644 sysdeps/generic/bits/condition.h delete mode 100644 sysdeps/generic/bits/mutex-attr.h delete mode 100644 sysdeps/generic/bits/mutex.h delete mode 100644 sysdeps/generic/bits/once.h delete mode 100644 sysdeps/generic/bits/pthread-np.h delete mode 100644 sysdeps/generic/bits/pthread.h delete mode 100644 sysdeps/generic/bits/pthreadtypes.h delete mode 100644 sysdeps/generic/bits/rwlock-attr.h delete mode 100644 sysdeps/generic/bits/rwlock.h delete mode 100644 sysdeps/generic/bits/semaphore.h delete mode 100644 sysdeps/generic/bits/thread-attr.h delete mode 100644 sysdeps/generic/bits/thread-specific.h delete mode 100644 sysdeps/generic/killpg.c delete mode 100644 sysdeps/generic/pt-atfork.c delete mode 100644 sysdeps/generic/pt-attr-destroy.c delete mode 100644 sysdeps/generic/pt-attr-getdetachstate.c delete mode 100644 sysdeps/generic/pt-attr-getguardsize.c delete mode 100644 sysdeps/generic/pt-attr-getinheritsched.c delete mode 100644 sysdeps/generic/pt-attr-getschedparam.c delete mode 100644 sysdeps/generic/pt-attr-getschedpolicy.c delete mode 100644 sysdeps/generic/pt-attr-getscope.c delete mode 100644 sysdeps/generic/pt-attr-getstack.c delete mode 100644 sysdeps/generic/pt-attr-getstackaddr.c delete mode 100644 sysdeps/generic/pt-attr-getstacksize.c delete mode 100644 sysdeps/generic/pt-attr-init.c delete mode 100644 sysdeps/generic/pt-attr-setdetachstate.c delete mode 100644 sysdeps/generic/pt-attr-setguardsize.c delete mode 100644 sysdeps/generic/pt-attr-setinheritsched.c delete mode 100644 sysdeps/generic/pt-attr-setschedparam.c delete mode 100644 sysdeps/generic/pt-attr-setschedpolicy.c delete mode 100644 sysdeps/generic/pt-attr-setscope.c delete mode 100644 sysdeps/generic/pt-attr-setstack.c delete mode 100644 sysdeps/generic/pt-attr-setstackaddr.c delete mode 100644 sysdeps/generic/pt-attr-setstacksize.c delete mode 100644 sysdeps/generic/pt-attr.c delete mode 100644 sysdeps/generic/pt-barrier-destroy.c delete mode 100644 sysdeps/generic/pt-barrier-init.c delete mode 100644 sysdeps/generic/pt-barrier-wait.c delete mode 100644 sysdeps/generic/pt-barrier.c delete mode 100644 sysdeps/generic/pt-barrierattr-destroy.c delete mode 100644 sysdeps/generic/pt-barrierattr-getpshared.c delete mode 100644 sysdeps/generic/pt-barrierattr-init.c delete mode 100644 sysdeps/generic/pt-barrierattr-setpshared.c delete mode 100644 sysdeps/generic/pt-cond-brdcast.c delete mode 100644 sysdeps/generic/pt-cond-destroy.c delete mode 100644 sysdeps/generic/pt-cond-init.c delete mode 100644 sysdeps/generic/pt-cond-signal.c delete mode 100644 sysdeps/generic/pt-cond-timedwait.c delete mode 100644 sysdeps/generic/pt-cond-wait.c delete mode 100644 sysdeps/generic/pt-cond.c delete mode 100644 sysdeps/generic/pt-condattr-destroy.c delete mode 100644 sysdeps/generic/pt-condattr-getclock.c delete mode 100644 sysdeps/generic/pt-condattr-getpshared.c delete mode 100644 sysdeps/generic/pt-condattr-init.c delete mode 100644 sysdeps/generic/pt-condattr-setclock.c delete mode 100644 sysdeps/generic/pt-condattr-setpshared.c delete mode 100644 sysdeps/generic/pt-destroy-specific.c delete mode 100644 sysdeps/generic/pt-equal.c delete mode 100644 sysdeps/generic/pt-getconcurrency.c delete mode 100644 sysdeps/generic/pt-getcpuclockid.c delete mode 100644 sysdeps/generic/pt-getschedparam.c delete mode 100644 sysdeps/generic/pt-getspecific.c delete mode 100644 sysdeps/generic/pt-init-specific.c delete mode 100644 sysdeps/generic/pt-key-create.c delete mode 100644 sysdeps/generic/pt-key-delete.c delete mode 100644 sysdeps/generic/pt-key.h delete mode 100644 sysdeps/generic/pt-kill.c delete mode 100644 sysdeps/generic/pt-mutex-destroy.c delete mode 100644 sysdeps/generic/pt-mutex-getprioceiling.c delete mode 100644 sysdeps/generic/pt-mutex-init.c delete mode 100644 sysdeps/generic/pt-mutex-lock.c delete mode 100644 sysdeps/generic/pt-mutex-setprioceiling.c delete mode 100644 sysdeps/generic/pt-mutex-timedlock.c delete mode 100644 sysdeps/generic/pt-mutex-transfer-np.c delete mode 100644 sysdeps/generic/pt-mutex-trylock.c delete mode 100644 sysdeps/generic/pt-mutex-unlock.c delete mode 100644 sysdeps/generic/pt-mutexattr-destroy.c delete mode 100644 sysdeps/generic/pt-mutexattr-getprioceiling.c delete mode 100644 sysdeps/generic/pt-mutexattr-getprotocol.c delete mode 100644 sysdeps/generic/pt-mutexattr-getpshared.c delete mode 100644 sysdeps/generic/pt-mutexattr-gettype.c delete mode 100644 sysdeps/generic/pt-mutexattr-init.c delete mode 100644 sysdeps/generic/pt-mutexattr-setprioceiling.c delete mode 100644 sysdeps/generic/pt-mutexattr-setprotocol.c delete mode 100644 sysdeps/generic/pt-mutexattr-setpshared.c delete mode 100644 sysdeps/generic/pt-mutexattr-settype.c delete mode 100644 sysdeps/generic/pt-mutexattr.c delete mode 100644 sysdeps/generic/pt-once.c delete mode 100644 sysdeps/generic/pt-rwlock-attr.c delete mode 100644 sysdeps/generic/pt-rwlock-destroy.c delete mode 100644 sysdeps/generic/pt-rwlock-init.c delete mode 100644 sysdeps/generic/pt-rwlock-rdlock.c delete mode 100644 sysdeps/generic/pt-rwlock-timedrdlock.c delete mode 100644 sysdeps/generic/pt-rwlock-timedwrlock.c delete mode 100644 sysdeps/generic/pt-rwlock-tryrdlock.c delete mode 100644 sysdeps/generic/pt-rwlock-trywrlock.c delete mode 100644 sysdeps/generic/pt-rwlock-unlock.c delete mode 100644 sysdeps/generic/pt-rwlock-wrlock.c delete mode 100644 sysdeps/generic/pt-rwlockattr-destroy.c delete mode 100644 sysdeps/generic/pt-rwlockattr-getpshared.c delete mode 100644 sysdeps/generic/pt-rwlockattr-init.c delete mode 100644 sysdeps/generic/pt-rwlockattr-setpshared.c delete mode 100644 sysdeps/generic/pt-setconcurrency.c delete mode 100644 sysdeps/generic/pt-setschedparam.c delete mode 100644 sysdeps/generic/pt-setschedprio.c delete mode 100644 sysdeps/generic/pt-setspecific.c delete mode 100644 sysdeps/generic/pt-startup.c delete mode 100644 sysdeps/generic/raise.c delete mode 100644 sysdeps/generic/sem-close.c delete mode 100644 sysdeps/generic/sem-destroy.c delete mode 100644 sysdeps/generic/sem-getvalue.c delete mode 100644 sysdeps/generic/sem-init.c delete mode 100644 sysdeps/generic/sem-open.c delete mode 100644 sysdeps/generic/sem-post.c delete mode 100644 sysdeps/generic/sem-timedwait.c delete mode 100644 sysdeps/generic/sem-trywait.c delete mode 100644 sysdeps/generic/sem-unlink.c delete mode 100644 sysdeps/generic/sem-wait.c delete mode 100644 sysdeps/generic/sigaddset.c delete mode 100644 sysdeps/generic/sigdelset.c delete mode 100644 sysdeps/generic/sigemptyset.c delete mode 100644 sysdeps/generic/sigfillset.c delete mode 100644 sysdeps/generic/siginterrupt.c delete mode 100644 sysdeps/generic/sigismember.c delete mode 100644 sysdeps/generic/signal.c delete mode 100644 sysdeps/generic/sigwait.c delete mode 100644 sysdeps/hurd/pt-destroy-specific.c delete mode 100644 sysdeps/hurd/pt-getspecific.c delete mode 100644 sysdeps/hurd/pt-init-specific.c delete mode 100644 sysdeps/hurd/pt-key-create.c delete mode 100644 sysdeps/hurd/pt-key-delete.c delete mode 100644 sysdeps/hurd/pt-key.h delete mode 100644 sysdeps/hurd/pt-kill.c delete mode 100644 sysdeps/hurd/pt-setspecific.c delete mode 100644 sysdeps/ia32/bits/atomic.h delete mode 100644 sysdeps/ia32/bits/memory.h delete mode 100644 sysdeps/ia32/bits/spin-lock-inline.h delete mode 100644 sysdeps/ia32/bits/spin-lock.h delete mode 100644 sysdeps/ia32/machine-sp.h delete mode 100644 sysdeps/ia32/pt-machdep.h delete mode 100644 sysdeps/l4/bits/pthread-np.h delete mode 100644 sysdeps/l4/hurd/bits/pthread-np.h delete mode 100644 sysdeps/l4/hurd/ia32/pt-machdep.c delete mode 100644 sysdeps/l4/hurd/ia32/pt-setup.c delete mode 100644 sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c delete mode 100644 sysdeps/l4/hurd/powerpc/pt-machdep.c delete mode 100644 sysdeps/l4/hurd/powerpc/pt-setup.c delete mode 100644 sysdeps/l4/hurd/pt-block.c delete mode 100644 sysdeps/l4/hurd/pt-kill.c delete mode 100644 sysdeps/l4/hurd/pt-setactivity-np.c delete mode 100644 sysdeps/l4/hurd/pt-sigstate-destroy.c delete mode 100644 sysdeps/l4/hurd/pt-sigstate-init.c delete mode 100644 sysdeps/l4/hurd/pt-sigstate.c delete mode 100644 sysdeps/l4/hurd/pt-startup.c delete mode 100644 sysdeps/l4/hurd/pt-sysdep.c delete mode 100644 sysdeps/l4/hurd/pt-sysdep.h delete mode 100644 sysdeps/l4/hurd/pt-thread-alloc.c delete mode 100644 sysdeps/l4/hurd/pt-thread-halt.c delete mode 100644 sysdeps/l4/hurd/pt-thread-start.c delete mode 100644 sysdeps/l4/hurd/pt-wakeup.c delete mode 100644 sysdeps/l4/hurd/sig-sysdep.h delete mode 100644 sysdeps/l4/hurd/sigprocmask.c delete mode 100644 sysdeps/l4/pt-block.c delete mode 100644 sysdeps/l4/pt-docancel.c delete mode 100644 sysdeps/l4/pt-pool-np.c delete mode 100644 sysdeps/l4/pt-spin.c delete mode 100644 sysdeps/l4/pt-stack-alloc.c delete mode 100644 sysdeps/l4/pt-thread-alloc.c delete mode 100644 sysdeps/l4/pt-thread-dealloc.c delete mode 100644 sysdeps/l4/pt-thread-halt.c delete mode 100644 sysdeps/l4/pt-thread-start.c delete mode 100644 sysdeps/l4/pt-timedblock.c delete mode 100644 sysdeps/l4/pt-wakeup.c delete mode 100644 sysdeps/mach/bits/spin-lock-inline.h delete mode 100644 sysdeps/mach/bits/spin-lock.h delete mode 100644 sysdeps/mach/hurd/ia32/pt-machdep.c delete mode 100644 sysdeps/mach/hurd/ia32/pt-setup.c delete mode 100644 sysdeps/mach/hurd/pt-attr-setstackaddr.c delete mode 100644 sysdeps/mach/hurd/pt-attr-setstacksize.c delete mode 100644 sysdeps/mach/hurd/pt-docancel.c delete mode 100644 sysdeps/mach/hurd/pt-sigstate-destroy.c delete mode 100644 sysdeps/mach/hurd/pt-sigstate-init.c delete mode 100644 sysdeps/mach/hurd/pt-sigstate.c delete mode 100644 sysdeps/mach/hurd/pt-sysdep.c delete mode 100644 sysdeps/mach/hurd/pt-sysdep.h delete mode 100644 sysdeps/mach/pt-block.c delete mode 100644 sysdeps/mach/pt-spin.c delete mode 100644 sysdeps/mach/pt-stack-alloc.c delete mode 100644 sysdeps/mach/pt-thread-alloc.c delete mode 100644 sysdeps/mach/pt-thread-dealloc.c delete mode 100644 sysdeps/mach/pt-thread-halt.c delete mode 100644 sysdeps/mach/pt-thread-start.c delete mode 100644 sysdeps/mach/pt-timedblock.c delete mode 100644 sysdeps/mach/pt-wakeup.c delete mode 100644 sysdeps/posix/pt-spin.c delete mode 100644 sysdeps/powerpc/bits/machine-lock.h delete mode 100644 sysdeps/powerpc/bits/memory.h delete mode 100644 sysdeps/powerpc/bits/spin-lock.h delete mode 100644 sysdeps/powerpc/machine-sp.h delete mode 100644 sysdeps/powerpc/pt-machdep.h delete mode 100644 tests/.cvsignore delete mode 100644 tests/Makefile delete mode 100644 tests/test-1.c delete mode 100644 tests/test-10.c delete mode 100644 tests/test-11.c delete mode 100644 tests/test-12.c delete mode 100644 tests/test-13.c delete mode 100644 tests/test-14.c delete mode 100644 tests/test-15.c delete mode 100644 tests/test-16.c delete mode 100644 tests/test-2.c delete mode 100644 tests/test-3.c delete mode 100644 tests/test-4.c delete mode 100644 tests/test-5.c delete mode 100644 tests/test-6.c delete mode 100644 tests/test-7.c delete mode 100644 tests/test-8.c delete mode 100644 tests/test-9.c diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index e59c9460..00000000 --- a/Makefile.am +++ /dev/null @@ -1,167 +0,0 @@ -# Makefile.am - Makefile template for libpthread. -# Copyright (C) 2003, 2008 Free Software Foundation, Inc. -# -# This file is part of the GNU Hurd. -# -# The GNU Hurd is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# The GNU Hurd 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 General Public License for more details. -# -# You should have received a copy of the GNU 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 - -if ARCH_IA32 - arch=ia32 -endif -if ARCH_POWERPC - arch=powerpc -endif - -# The source files are scattered over several directories. Add -# all these directories to the vpath. -SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ - $(srcdir)/sysdeps/l4/${arch} \ - $(srcdir)/sysdeps/${arch} \ - $(srcdir)/sysdeps/l4/hurd \ - $(srcdir)/sysdeps/l4 \ - $(srcdir)/sysdeps/hurd \ - $(srcdir)/sysdeps/generic \ - $(srcdir)/sysdeps/posix \ - $(srcdir)/pthread \ - $(srcdir)/signal \ - $(srcdir)/include -vpath %.c $(SYSDEP_PATH) - -AM_CPPFLAGS = $(USER_CPPFLAGS) -I$(srcdir)/pthread \ - $(addprefix -I, $(SYSDEP_PATH)) -imacros $(srcdir)/include/libc-symbols.h -AM_CFLAGS = $(USER_CFLAGS) - -# Sources. -SYSDEPS := lockfile.c - -if ! ENABLE_TESTS -noinst_LIBRARIES = libpthread.a -endif - -libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ - pt-attr-getguardsize.c pt-attr-getinheritsched.c \ - pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ - pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ - pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ - pt-attr-setinheritsched.c pt-attr-setschedparam.c \ - pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ - pt-attr-setstackaddr.c pt-attr-setstacksize.c pt-attr.c \ - pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ - pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ - pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ - pt-destroy-specific.c pt-init-specific.c \ - pt-key-create.c pt-key-delete.c \ - pt-getspecific.c pt-setspecific.c \ - pt-once.c \ - pt-alloc.c \ - pt-create.c \ - pt-getattr.c \ - pt-pool-np.c \ - pt-equal.c \ - pt-dealloc.c \ - pt-detach.c \ - pt-exit.c \ - pt-initialize.c \ - pt-join.c \ - pt-self.c \ - pt-sigmask.c \ - pt-spin-inlines.c \ - pt-cleanup.c \ - pt-setcancelstate.c \ - pt-setcanceltype.c \ - pt-testcancel.c \ - pt-cancel.c \ - pt-mutexattr.c \ - pt-mutexattr-destroy.c pt-mutexattr-init.c \ - pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ - pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ - pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ - pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ - pt-mutex-init.c pt-mutex-destroy.c \ - pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ - pt-mutex-unlock.c \ - pt-mutex-transfer-np.c \ - pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ - pt-rwlock-attr.c \ - pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ - pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ - pt-rwlock-init.c pt-rwlock-destroy.c \ - pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ - pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ - pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ - pt-rwlock-unlock.c \ - pt-cond.c \ - pt-condattr-init.c pt-condattr-destroy.c \ - pt-condattr-getclock.c pt-condattr-getpshared.c \ - pt-condattr-setclock.c pt-condattr-setpshared.c \ - pt-cond-destroy.c pt-cond-init.c \ - pt-cond-brdcast.c \ - pt-cond-signal.c \ - pt-cond-wait.c \ - pt-cond-timedwait.c \ - pt-stack-alloc.c \ - pt-thread-alloc.c \ - pt-thread-dealloc.c \ - pt-thread-start.c \ - pt-thread-halt.c \ - pt-startup.c \ - pt-getconcurrency.c pt-setconcurrency.c \ - pt-block.c \ - pt-timedblock.c \ - pt-wakeup.c \ - pt-docancel.c \ - pt-sysdep.c \ - pt-setup.c \ - pt-machdep.c \ - pt-spin.c \ - pt-sigstate-init.c \ - pt-sigstate-destroy.c \ - pt-sigstate.c \ - pt-atfork.c \ - pt-kill.c \ - pt-getcpuclockid.c \ - pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ - sem-close.c sem-init.c sem-timedwait.c sem-wait.c \ - sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ - sem-post.c sem-unlink.c \ - \ - pt-setactivity-np.c \ - \ - kill.c \ - killpg.c \ - pt-kill-siginfo-np.c \ - raise.c \ - sigaction.c \ - sigaddset.c \ - sigaltstack.c \ - sigdelset.c \ - sigemptyset.c \ - sigfillset.c \ - sig-internal.c \ - sig-internal.h \ - siginterrupt.c \ - sigismember.c \ - signal.c \ - signal-dispatch.c \ - signal.h \ - sigpending.c \ - sigprocmask.c \ - sigsuspend.c \ - sigtimedwait.c \ - sigwait.c \ - sigwaiter.c \ - sigwaitinfo.c \ - signal-dispatch-lowlevel.c \ - sigprocmask.c diff --git a/headers.m4 b/headers.m4 deleted file mode 100644 index 5a58b9bf..00000000 --- a/headers.m4 +++ /dev/null @@ -1,45 +0,0 @@ -# headers.m4 - Autoconf snippets to install links for header files. -# Copyright 2003, 2008 Free Software Foundation, Inc. -# Written by Marcus Brinkmann . -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This file is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -AC_CONFIG_LINKS([ - sysroot/include/pthread.h:libpthread/include/pthread.h - sysroot/include/pthread/pthread.h:libpthread/include/pthread/pthread.h - sysroot/include/pthread/pthreadtypes.h:libpthread/include/pthread/pthreadtypes.h - sysroot/include/bits/memory.h:libpthread/sysdeps/${arch}/bits/memory.h - sysroot/include/bits/spin-lock.h:libpthread/sysdeps/${arch}/bits/spin-lock.h - sysroot/include/bits/spin-lock-inline.h:libpthread/sysdeps/${arch}/bits/spin-lock-inline.h - sysroot/include/bits/pthreadtypes.h:libpthread/sysdeps/generic/bits/pthreadtypes.h - sysroot/include/bits/barrier-attr.h:libpthread/sysdeps/generic/bits/barrier-attr.h - sysroot/include/bits/barrier.h:libpthread/sysdeps/generic/bits/barrier.h - sysroot/include/bits/cancelation.h:libpthread/sysdeps/generic/bits/cancelation.h - sysroot/include/bits/condition-attr.h:libpthread/sysdeps/generic/bits/condition-attr.h - sysroot/include/bits/condition.h:libpthread/sysdeps/generic/bits/condition.h - sysroot/include/bits/mutex-attr.h:libpthread/sysdeps/generic/bits/mutex-attr.h - sysroot/include/bits/mutex.h:libpthread/sysdeps/generic/bits/mutex.h - sysroot/include/bits/once.h:libpthread/sysdeps/generic/bits/once.h - sysroot/include/bits/pthread.h:libpthread/sysdeps/generic/bits/pthread.h - sysroot/include/bits/rwlock-attr.h:libpthread/sysdeps/generic/bits/rwlock-attr.h - sysroot/include/bits/rwlock.h:libpthread/sysdeps/generic/bits/rwlock.h - sysroot/include/bits/thread-attr.h:libpthread/sysdeps/generic/bits/thread-attr.h - sysroot/include/bits/thread-barrier.h:libpthread/sysdeps/generic/bits/thread-barrier.h - sysroot/include/bits/thread-specific.h:libpthread/sysdeps/generic/bits/thread-specific.h - sysroot/include/bits/pthread-np.h:libpthread/sysdeps/l4/hurd/bits/pthread-np.h - sysroot/include/semaphore.h:libpthread/include/semaphore.h - sysroot/include/bits/semaphore.h:libpthread/sysdeps/generic/bits/semaphore.h - sysroot/include/signal.h:libpthread/signal/signal.h -]) - -AC_CONFIG_COMMANDS_POST([ - mkdir -p sysroot/lib libpthread && - ln -sf ../../libpthread/libpthread.a sysroot/lib/ && - touch libpthread/libpthread.a -]) diff --git a/libpthread.a b/libpthread.a deleted file mode 100644 index d0e689e9..00000000 --- a/libpthread.a +++ /dev/null @@ -1,20 +0,0 @@ -/* pthread initializer is weak in glibc. It must be included if glibc - is to start threading. */ -EXTERN(_cthread_init_routine) - -/* Weak references in glibc that must be filled if glibc is to be - thread safe. */ -EXTERN(cthread_detach) -EXTERN(cthread_fork) -EXTERN(cthread_keycreate) -EXTERN(cthread_getspecific) -EXTERN(__libc_getspecific) -EXTERN(cthread_setspecific) -EXTERN(__mutex_lock_solid) -EXTERN(__mutex_unlock_solid) -/* For libio stream locking. */ -EXTERN(_cthreads_flockfile) -EXTERN(_cthreads_funlockfile) -EXTERN(_cthreads_ftrylockfile) - -GROUP(-lpthread2 -lihash) diff --git a/libpthread/ChangeLog b/libpthread/ChangeLog new file mode 100644 index 00000000..2dcc1777 --- /dev/null +++ b/libpthread/ChangeLog @@ -0,0 +1,2201 @@ +2009-01-10 Samuel Thibault + + * sysdeps/i386/bits/spin-lock.h (__SPIN_LOCK_INITIALIZER): Rename + macro to... + (__PTHREAD_SPIN_LOCK_INITIALIZER): ... this. + * sysdeps/mach/bits/spin-lock.h (__SPIN_LOCK_INITIALIZER): Rename + macro to... + (__PTHREAD_SPIN_LOCK_INITIALIZER): ... this. + + * include/pthread/pthread.h (PTHREAD_SPINLOCK_INITIALIZER): Use + __PTHREAD_SPIN_LOCK_INITIALIZER instead of + __SPIN_LOCK_INITIALIZER. + * sysdeps/generic/bits/condition.h (__PTHREAD_COND_INITIALIZER): + Likewise. + * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_INITIALIZER, + __PTHREAD_RECURSIVE_MUTEX_INITIALIZER): + Likewise. + * sysdeps/generic/bits/once.h (__PTHREAD_ONCE_INIT): Likewise. + * sysdeps/generic/bits/rwlock.h (__PTHREAD_RWLOCK_INITIALIZER): + Likewise. + * sysdeps/generic/bits/semaphore.h (__SEMAPHORE_INITIALIZER): + Likewise. + * sysdeps/i386/bits/spin-lock-inline.h (__pthread_spin_init): + Likewise. + * sysdeps/i386/mach/spin-lock-inline.h (__pthread_spin_init): + Likewise. + +2008-12-21 Samuel Thibault + + * sysdeps/mach/pt-timedblock.c (__pthread_timedblock): Fix timeout + computation from abstime and now. + * include/pthread/pthread.h (PTHREAD_RWLOCK_INITIALIZER): New macro. + +2008-10-02 Neal H. Walfield + + * sysdeps/generic/pt-mutex-timedlock.c + (__pthread_mutex_timedlock_internal) [! ALWAYS_TRACK_MUTEX_OWNER]: + Don't update MUTEX->OWNER or assert MUTEX->OWNER for normal + mutexes. + * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock) + [! ALWAYS_TRACK_MUTEX_OWNER]: Don't update MUTEX->OWNER or assert + MUTEX->OWNER for normal mutexes. + * sysdeps/generic/pt-mutex-transfer-np.c + (__pthread_mutex_transfer_np) [! ALWAYS_TRACK_MUTEX_OWNER]: Don't + update MUTEX->OWNER for normal mutexes. + +2008-08-27 Neal H. Walfield + + * pthread/cthreads-compat.c: Don't include . + (cthread_t): New type definition. + (cthread_fn_t): Likewise. + (cthread_key_t): Likewise. + (CTHREAD_KEY_INVALID): Define. + +2008-08-26 Neal H. Walfield + + * sysdeps/mach/pt-thread-alloc.c (__pthread_thread_alloc): Set + THREAD->HAVE_KERNEL_RESOURCES to 1, not true. Reported by Flávio + Cruz . + +2008-08-16 Neal H. Walfield + + * pthread/pt-alloc.c: Don't include . + (__pthread_free_threads): Change to a struct __pthread *. + (__pthread_free_threads_lock): New variable. + (__pthread_alloc): When looking for a TCB to reuse, iterate over + __pthread_free_threads taking the first for which the STATE field + is PTHREAD_TERMINATED. When reusing a TCB, first call + __pthread_thread_halt on it. + * pthread/pt-dealloc.c: Don't include . + (__pthread_free_threads): Change to a struct __pthread *. + (__pthread_free_threads_lock): New declaration. + (__pthread_dealloc): Enqueue PTHREAD on __PTHREAD_FREE_THREADS. + Set PTHREAD->STATE to PTHREAD_TERMINATED after everything else. + * pthread/pt-join.c (pthread_join): Call __pthread_thread_halt + before destroying the thread. When destroying the thread, call + __pthread_thread_dealloc on it. + * pthread/pt-detach.c (pthread_detach): If destroying the thread, + call __pthread_thread_halt before deallocating the stack. In this + case, also call __pthread_thread_dealloc on the tcb. + * pthread/pt-exit.c (pthread_exit): Call __pthread_dealloc only if + the thread is detached and then as the last thing we do before + calling __pthread_thread_halt. + * pthread/pt-internal.h (__pthread_thread_halt): Remove argument + NEED_DEALLOC. Update users. + * sysdeps/mach/pt-thread-halt.c (__pthread_thread_halt): Remove + argument need_dealloc. + * sysdeps/mach/hurd/pt-sysdep.h (PTHREAD_SYSDEP_MEMBERS): Add field + have_kernel_resources. + * sysdeps/mach/hurd/pt-thread-alloc.c (__pthread_thread_alloc): If + THREAD->HAVE_KERNEL_RESOURCES is true, just return. After + allocating the resources, set THREAD->HAVE_KERNEL_RESOURCES to + true. + +2008-08-12 Neal H. Walfield + + Merge changes from hurd-l4 fork. + + * Makefile (SRCS): Add pt-startup.c and pt-mutex-transfer-np.c. + (sysdeps_headers): Add pthread-np.h. + +2008-08-12 Neal H. Walfield + + * sysdeps/generic/bits/pthread-np.h: New file. + +2008-08-12 Neal H. Walfield + + * sysdeps/generic/pt-startup.c: New file. + +2008-08-12 Neal H. Walfield + + * sysdeps/generic/bits/mutex.h (__PTHREAD_RECURSIVE_MUTEX_INITIALIZER): + Define. + (__PTHREAD_MUTEX_RECURSIVE_INITIALIZER): Don't define. + * include/pthread/pthread.h + (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) [__USE_GNU]: Define. + (PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP): Don't define. + +2008-08-12 Neal H. Walfield + + * include/pthread/pthread.h: Include . + (__extern_inline): If not defined, define appropriately. + +2008-06-01 Neal H. Walfield + + * include/pthread/pthread.h (PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP): + New definition. + * sysdeps/generic/bits/mutex.h + (__PTHREAD_MUTEX_RECURSIVE_INITIALIZER): New definition. + * sysdeps/generic/bits/mutex-attr.h (__pthread_recursive_mutexattr): + New definition. + * sysdeps/generic/pt-mutexattr.c (__pthread_recursive_mutexattr): + New declaration. + * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): If ATTR + is &__PTHREAD_RECURSIVE_MUTEXATTR, don't allocate a copy, just + save in MUTEX->ATTR. + * sysdeps/generic/pt-mutex-destroy.c (_pthread_mutex_destroy): If + MUTEX->ATTR is &__PTHREAD_RECURSIVE_MUTEXATTR, don't free it. + +2008-05-29 Thomas Schwinge + + * sysdeps/generic/sem-timedwait.c: Don't include . + +2008-05-21 Neal H. Walfield + + * include/pthread/pthread.h: Include . + +2008-03-01 Neal H. Walfield + + * sysdeps/generic/pt-mutex-transfer-np.c: New file. + + * pthread/pt-self.c (pthread_self): Assert that SELF is not NULL. + +2007-12-23 Neal H. Walfield + + * pthread/pt-join.c (pthread_join): Cast argument to + pthread_cleanup_push to avoid warning. + +2007-11-23 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_startup): Add declaration. + * pthread/pt-create.c (entry_point): Call __pthread_startup. + +2008-08-12 Neal H. Walfield + + * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): + Remove dead code. + +2008-08-11 Neal H. Walfield + + * sysdeps/l4/pt-docancel.c: Remove file. + * sysdeps/l4/pt-thread-alloc.c: Likewise. + * sysdeps/l4/pt-wakeup.c: Likewise. + * sysdeps/l4/pt-thread-halt.c: Likewise. + * sysdeps/l4/pt-start.c: Likewise. + * sysdeps/l4/pt-stack-alloc.c: Likewise. + * sysdeps/l4/pt-thread-start.c: Likewise. + * sysdeps/l4/pt-block.c: Likewise. + * sysdeps/l4/hurd/pt-sysdep.h: Likewise. + * sysdeps/l4/hurd/pt-sysdep.c: Likewise. + * sysdeps/l4/hurd/i386/pt-setup.c: Likewise. + * sysdeps/l4/hurd/i386/pt-machdep.c: Likewise. + +2008-08-04 Samuel Thibault + + * include/pthread/pthreadtypes.h (__pthread_inheritsched): Remove + comma at end of enumeration. + +2008-08-03 Samuel Thibault + + * Makefile (sysdeps_headers): Add spin-lock-inline.h. + (SYSDEP_PATH): Move sysdeps/i386 right after + sysdeps/$(MICROKERNEL)/i386. + * include/pthread/pthread.h: Include . + * sysdeps/i386/bits/spin-lock.h: Move inlines to... + * sysdeps/i386/bits/spin-lock-inline.h: ... new file. + * sysdeps/mach/bits/spin-lock.h: Move inlines to... + * sysdeps/mach/bits/spin-lock-inline.h: ... new file. + +2008-08-02 Samuel Thibault + + * sysdeps/generic/bits/mutex.h: Do not include and + + * sysdeps/i386/bits/memory.h (__memory_barrier): Add memory clobber. + * sysdeps/i386/bits/spin-lock.h (__pthread_spin_trylock, + __pthread_spin_unlock): Add memory clobbers. + * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Fix cast from + thread to integer. Fix reservation of stack room for initial frame. + * sysdeps/l4/hurd/i386/pt-setup.c (stack_setup): Fix reservation of + stack room for initial frame. + +2008-07-18 Samuel Thibault + + * Makefile (sysdeps_headers): add pthread/pthreadtypes.h + +2008-06-29 Samuel Thibault + + * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): + Do not use assertx and threadid. + +2008-06-27 Samuel Thibault + + * include/pthread/pthread.h: Do not define __need_clockid_t, include + , and define clockid_t if __clockid_defined is not defined. + Include + (pthread_equal): New extern inline. + (pthread_cleanup_push, pthread_cleanup_pop): New macros. + (__pthread_process_shared, __pthread_inheritsched, + __pthread_contentionscope, __pthread_detachstate, + __pthread_mutex_protocol, __pthread_mutex_type, + pthread_attr_t, pthread_mutex_attr_t, pthread_mutex_t, + pthread_condattr_t, pthread_cond_t, pthread_spinlock_t, + pthread_rwlockattr_t, pthread_rwlock_t, pthread_barrierattr_t, + pthread_barrier_t, pthread_key_t, pthread_once_t): Move enums and + typedefs to... + * include/pthread/pthreadtypes.h: ... new file. + * sysdeps/generic/bits/cancelation.h (pthread_cleanup_push): Rename + macro to __pthread_cleanup_push. + (pthread_cleanup_pop): Rename macro to __pthread_cleanup_pop. + * sysdeps/generic/bits/barrier-attr.h (__pthread_process_shared): + Forward-declare enum. + * sysdeps/generic/bits/condition-attr.h (__pthread_process_shared): + Likewise. + * sysdeps/generic/bits/mutex-attr.h (__pthread_mutex_protocol, + __pthread_process_shared, __pthread_mutex_type): + Likewise. + * sysdeps/generic/bits/rwlock-attr.h (__pthread_process_shared): + Likewise. + * sysdeps/generic/bits/thread-attr.h (__pthread_detachstate, + __pthread_inheritsched, __pthread_contentionscope): + Likewise. + * sysdeps/generic/bits/pthread.h (pthread_t): Rename type to + __pthread_t. + (pthread_equal): Rename to __pthread_equal. + +2008-06-27 Samuel Thibault + + * sysdeps/generic/bits/thread-barrier.h: Remove unused file. + +2008-06-22 Neal H. Walfield + + * sysdeps/generic/pt-mutex-timedlock.c + (__pthread_mutex_timedlock_internal) [! NDEBUG]: Set MUTEX->OWNER + appropriately and assert that it is consistent. + * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock) [! + NDEBUG]: Set MUTEX->OWNER appropriately and assert that it is + consistent. + * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock) [! + NDEBUG]: Set MUTEX->OWNER. + +2008-06-07 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_queue_iterate): Use 1, not + true. + (__pthread_dequeuing_iterate): Likewise. + +2008-05-27 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_queue_iterate): Before + returning the current element, save its next pointer. + (__pthread_dequeuing_iterate): Likewise. + +2008-05-27 Neal H. Walfield + + * sysdeps/mach/hurd/pt-docancel.c (__pthread_do_cancel): Fix + assert. + +2008-05-17 Samuel Thibault + + * include/pthread/pthread.h (pthread_getattr_np): New declaration. + * pthread/pt-getattr.c: New file. + * Makefile (SRCS): Add pt-getattr.c. + +2008-03-16 Samuel Thibault + + * include/libc-symbols.h (HAVE_ASM_PREVIOUS_DIRECTIVE): Define. + +2008-02-29 Samuel Thibault + + * sysdeps/l4/hurd/i386/pt-setup.c (stack_setup): Align stack on 0x10 + for MMX operations. + * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Likewise. + +2008-01-01 Samuel Thibault + + * include/pthread/pthread.h (pthread_spin_destroy, pthread_spin_init, + pthread_spin_lock, pthread_spin_trylock, pthread_spin_unlock): Use + __extern_inline macro instead of extern __inline. + * sysdeps/i386/bits/spin-lock.h (__PT_SPIN_INLINE, + __pthread_spin_lock): Likewise + * sysdeps/mach/bits/spin-lock.h (__PT_SPIN_INLINE, + __pthread_spin_lock): Likewise + * sysdeps/generic/bits/pthread.h (pthread_equal): Declare ; only + provide inline when __USE_EXTERN_INLINES is defined. Use __extern_inline + macro instead of extern __inline. + * sysdeps/i386/bits/memory.h (__memory_barrier): Add static to inline. + +2007-11-19 Thomas Schwinge + + * Makefile (CFLAGS): Don't set and instead... + (CPPFLAGS): ... append the inclusion stuff to these. + +2007-08-02 Samuel Thibault + + * sysdeps/generic/bits/mutex.h (pthread_mutex_init) + (pthread_mutex_destroy, __pthread_mutex_lock, __pthread_mutex_trylock) + (pthread_mutex_lock, pthread_mutex_trylock): Remove inline + definitions. + * sysdeps/generic/bits/rwlock.h (pthread_rwlock_init) + (pthread_rwlock_destroy): Likewise. + +2007-06-24 Samuel Thibault + + * include/semaphore.h (sem_timedwait): Declare only if __USE_XOPEN2K + is defined. + * include/pthread/pthread.h (pthread_attr_getstack) + (pthread_attr_setstack, pthread_mutex_timedlock) + (pthread_condattr_getclock, pthread_condattr_setclock) + (pthread_rwlock_timedrdlock, pthread_rwlock_timedwrlock) + (pthread_barrierattr_t, pthread_barrierattr_init) + (pthread_barrierattr_destroy, pthread_barrierattr_getpshared) + (pthread_barrierattr_setpshared, pthread_barrier_t) + (PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_init) + (pthread_barrier_destroy, pthread_barrier_wait) + (pthread_getcpuclockid): Declare only if __USE_XOPEN2K is defined. + (pthread_mutexattr_getprioceiling, pthread_mutexattr_setprioceiling) + (pthread_mutexattr_getprotocol, pthread_mutexattr_setprotocol) + (pthread_mutexattr_gettype, pthread_mutexattr_settype) + (pthread_mutex_getprioceiling, pthread_mutex_setprioceiling) + (pthread_setconcurrency, pthread_getconcurrency): Declare only if + __USE_UNIX98 is defined. + (pthread_rwlockattr_t, pthread_rwlockattr_init) + (pthread_rwlockattr_destroy, pthread_rwlockattr_getpshared) + (pthread_rwlockattr_setpshared, pthread_rwlock_t, pthread_rwlock_init) + (pthread_rwlock_destroy, pthread_rwlock_rdlock) + (pthread_rwlock_tryrdlock, pthread_rwlock_wrlock) + (pthread_rwlock_trywrlock, pthread_rwlock_unlock): Declare only if + __USE_UNIX98 or __USE_XOPEN2K are defined. + (PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, PTHREAD_PRIO_PROTECT) + (PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_ERRORCHECK) + (PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_DEFAULT): + Define only if __USE_UNIX98 is defined. + (PTHREAD_MUTEX_FAST_NP): Define for compatibility when __USE_GNU is + defined. + * sysdeps/generic/bits/rwlock.h (pthread_rwlock_init) + (pthread_rwlock_destroy): Declare only if __USE_UNIX98 or + __USE_XOPEN2K are defined. + * TODO: Drop that TODO item. + +2006-03-04 Samuel Thibault + + * sysdeps/i386/machine-sp.h (thread_stack_pointer): + Optimize esp read. + * include/pthread/pthread.h: Add the restrict keyword where + appropriate for full compliance. + * pthread/pt-internal.h: Likewise. + * sysdeps/generic/bits/mutex.h: Likewise. + * sysdeps/generic/bits/rwlock.h: Likewise. + * TODO: Drop that TODO item. + +2006-01-20 Samuel Thibault + + Do not let other libraries (like libX11) override libpthread's + pthread_mutex_*, pthread_rwlock_* and sem_* dynamic symbols. + * sysdeps/generic/pt-mutex-destroy.c + (pthread_mutex_destroy): Make the alias strong. + * sysdeps/generic/pt-mutex-init.c + (pthread_mutex_init): Likewise. + * sysdeps/generic/pt-mutex-lock.c + (_pthread_mutex_lock, pthread_mutex_lock): Likewise. + * sysdeps/generic/pt-mutex-trylock.c + (_pthread_mutex_trylock, pthread_mutex_trylock): Likewise. + * sysdeps/generic/pt-mutex-unlock.c + (_pthread_mutex_lock, pthread_mutex_unlock): Likewise. + * sysdeps/generic/pt-rwlock-destroy.c + (pthread_rwlock_destroy): Likewise. + * sysdeps/generic/pt-rwlock-init.c + (pthread_rwlock_init): Likewise. + * sysdeps/generic/sem-destroy.c (sem_destroy): Likewise. + * sysdeps/generic/sem-getvalue.c (sem_getvalue): Likewise. + * sysdeps/generic/sem-init.c (sem_init): Likewise. + * sysdeps/generic/sem-open.c (sem_open): Likewise. + * sysdeps/generic/sem-post.c (sem_post): Likewise. + * sysdeps/generic/sem-timedwait.c (sem_timedwait): Likewise. + * sysdeps/generic/sem-trywait.c (sem_trywait): Likewise. + * sysdeps/generic/sem-unlink.c (sem_unlink): Likewise. + * sysdeps/generic/sem-wait.c (sem_wait): Likewise. + +2006-03-27 Thomas Schwinge + + * Makefile (SRCS): Don't define two times and only list `pt-attr.c' + once. Reported by Jeff Bailey . + +2005-08-28 Neal H. Walfield + + * include/semaphore.h: Use __restrict, not restrict. + +2005-05-31 Neal H. Walfield + + * include/pthread/pthread.h: If clockid_t is still not defined + after including , define it manually. + +2005-05-17 Neal H. Walfield + + * include/pthread/pthread.h: Define __need_clockid_t before + including . + +2005-05-12 Neal H. Walfield + + * include/pthread/pthread.h (pthread_exit): Add noreturn + attribute. + + * sysdeps/generic/bits/condition.h (__PTHREAD_COND_INITIALIZER): + Don't create a compound literal. + * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_INITIALIZER): + Don't create a compound literal. + (pthread_mutex_init): Don't assign to *__MUTEX directly. + Initialize an intermediate local variable and then copy the + result. + * sysdeps/generic/bits/rwlock.h (__PTHREAD_RWLOCK_INITIALIZER): + Don't create a compound literal. + (pthread_rwlock_init): Don't assign to *__RWLOCK directly. + Initialize an intermediate local variable and then copy the + result. + * sysdeps/i386/bits/spin-lock.h (__SPIN_LOCK_INITIALIZER): + Don't create a compound literal. + + * pthread/pt-alloc.c (initialize_pthread): Cast + PTHREAD_MUTEX_INITIALIZER and PTHREAD_COND_INITIALIZER to create a + compound literal. + * tests/test-1.c (main): Use pthread_mutex_init, not + PTHREAD_MUTEX_INIT for mutex initialization + + * sysdeps/generic/pt-barrier-init.c (pthread_barrier_init): Remove + assert. Copy ATTR if non-defaults are used. + * sysdeps/generic/pt-cond-init.c (pthread_cond_init): Include + . Remove assert. Copy ATTR if non-defaults are used. + * sysdeps/generic/pt-mutex-init.c (_pthread_mutex_init): Cast + PTHREAD_MUTEX_INITIALIZER to create a compound literal. + * sysdeps/generic/pt-rwlock-init.c: Include . + (_pthread_rwlock_init): Cast __PTHREAD_RWLOCK_INITIALIZER to + create a compound literal. Copy ATTR if non-defaults are used. + + * sysdeps/generic/pt-cond-timedwait.c + (__pthread_cond_timedwait_internal): Check that ABSTIME->TV_NSEC + is valid. Don't shadow ERR. Don't return before cleaning up. + * sysdeps/generic/pt-mutex-timedlock.c (pthread_mutex_timedlock): + Move after __pthread_mutex_timedlock_internal. Check that + ABSTIME->TV_NSEC is valid. + * sysdeps/generic/pt-rwlock-timedrdlock.c + (pthread_rwlock_timedrdlock): Move after. + __pthread_rwlock_timedrdlock_internal. + (__pthread_rwlock_timedrdlock_internal): Check that + ABSTIME->TV_NSEC is valid. + * sysdeps/generic/pt-rwlock-timedwrlock.c + (pthread_rwlock_timedwrlock): Move after + __pthread_rwlock_timedwrlock_internal. + (__pthread_rwlock_timedwrlock_internal): Check that + ABSTIME->TV_NSEC is valid. + * sysdeps/generic/sem-timedwait.c (__sem_timedwait_internal): + Check that TIMEOUT->TV_NSEC is valid before enqueuing the thread. + + * sysdeps/generic/pt-rwlock-rdlock.c + (__pthread_rwlock_timedrdlock_internal): Fix declaration. + + * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock): + Don't return EDEADLK. POSIX does not allow it. + + * sysdeps/mach/pt-timedblock.c (__pthread_timedblock): Calculate + the relative timeout without overflowing. + + * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Cast THREAD. + +2005-05-12 Neal H. Walfield + + * Makefile (SRCS): Add sem-close.c, sem-destroy.c, sem-getvalue.c, + sem-init.c, sem-open.c, sem-post.c, sem-timedwait.c, sem-trywait.c, + sem-unlink.c and sem-wait.c. + (sysdeps_headers): Add semaphore.h and bits/semaphore.h. + * include/semaphore.h: New file. + * sysdeps/generic/sem-close.c: New file. + * sysdeps/generic/sem-destroy.c: New file. + * sysdeps/generic/sem-getvalue.c: New file. + * sysdeps/generic/sem-init.c: New file. + * sysdeps/generic/sem-open.c: New file. + * sysdeps/generic/sem-post.c: New file. + * sysdeps/generic/sem-timedwait.c: New file. + * sysdeps/generic/sem-trywait.c: New file. + * sysdeps/generic/sem-unlink.c: New file. + * sysdeps/generic/sem-wait.c: New file. + * sysdeps/generic/bits/semaphore.h: New file. + +2005-05-04 Neal H. Walfield + + * Makefile (SRCS): Add pt-thread_dealloc.c. + * sysdeps/mach/pt-thread-dealloc.c: New file. + * pthread/pt-internal.h (__pthread_thread_dealloc): New + declaration. + (__pthread_thread_halt): Add parameter NEED_DEALLOC. Update + callers. + * sysdeps/mach/pt-thread-halt.c (__pthread_thread_halt): Respect + new NEED_DEALLOC parameter. Move code which deallocates kernel + resources from here ... + * sysdeps/mach/pt-thread-dealloc.c (__pthread_thread_dealloc): + ...to here. + * pthread/pt-create.c (__pthread_create_internal): Call + __pthread_thread_dealloc on failure. + * pthread/pt-exit.c (pthread_exit): Call __pthread_thread_dealloc. + + * sysdeps/mach/pt-thread-alloc.c (create_wakeupmsg): Call + __mach_port_destroy to deallocate the receive right. + __mach_port_deallocate won't do it. + + * pthread/pt-detach.c (pthread_detach): Don't call + __pthread_thread_halt a second time. + + * sysdeps/mach/hurd/pt-sysdep.c (_cthread_init_routine): Fix + declaration. + (init_routine): Update declaration and remove gratuitous cast. + +2005-05-02 Neal H. Walfield + + * pthread/pt-alloc.c (__pthread_alloc): Set the thread id to the + table index plus one. + * pthread/pt-internal.h (__pthread_getid): Index __pthread_threads + using THREAD - 1, not THREAD. + (__pthread_setid): Likewise. + * pthread/pt-create.c (__pthread_create_internal): Likewise. + + * sysdeps/generic/pt-mutex-trylock.c (__pthread_mutex_trylock): + When returning EBUSY, don't forget to first unlock MUTEX->__HELD. + +2005-04-20 Neal H. Walfield + + * sysdeps/generic/pt-setschedparam.c: policy's type is int, not + int *. + * include/pthread/pthread.h: Likewise. + Reported by Christopher `Physicman' Bodenstein . + +2005-01-21 Michael Banck + + * Makefile ($(libdir)/libpthread2.a): Install linker script + from $(srcdir) instead of current directory. + ($(libdir)/libpthread2_pic.a): Likewise. + +2005-02-08 Neal H. Walfield + + * sysdeps/mach/pt-spin.c (__pthread_spin_lock): Make a weak alias + to _pthread_spin_lock. + * sysdeps/posix/pt-spin.c (__pthread_spin_lock): Likewise. + +2005-01-18 Neal H. Walfield + + * sysdeps/mach/hurd/pt-sysdep.h (__pthread_stack_dealloc): Add + __always_inline__ attribute. + * sysdeps/l4/hurd/pt-sysdep.h (_pthread_self): Likewise. + (__pthread_stack_dealloc): Likewise. + +2005-01-12 Pietro Ferrari + + * include/pthread/pthread.h (pthread_spin_destroy): Replace extern + inline with extern __inline. + (pthread_spin_init): Likewise. + (pthread_spin_lock): Likewise. + (pthread_spin_trylock): Likewise. + (pthread_spin_unlock): Likewise. + * sysdeps/mach/bits/spin-lock.h (__pthread_spin_lock): Likewise. + * sysdeps/i386/bits/spin-lock.h (__pthread_spin_lock): Likewise. + * sysdeps/generic/bits/mutex.h (__pthread_mutex_trylock): + Likewise. + (pthread_mutex_lock): Likewise. + (pthread_mutex_trylock): Likewise. + * sysdeps/generic/bits/pthread.h (pthread_equal): Likewise. + +2003-08-17 Marcus Brinkmann + + * sysdeps/hurd/pt-key.h (PTHREAD_KEY_MEMBERS): Change type of + THREAD_SPECIFICS to hurd_ihash_t. + * sysdeps/hurd/pt-setspecific.c (pthread_setspecific): Call + hurd_ihash_create instead ihash_create, and hurd_ihash_add instead + ihash_add. + * sysdeps/hurd/pt-getspecific.c (pthread_getspecific): Call + hurd_ihash_find instead of ihash_find. + * sysdeps/hurd/pt-destroy-specific.c (__pthread_destroy_specific): + Call hurd_ihash_find instead of ihash_find, hurd_ihash_remove + instead of ihash_remove, and hurd_ihash_free instead of + ihash_free. + +2003-08-03 Marco Gerards + + * Makefile (install): Do not install from $(srcdir). + +2002-11-26 Neal H. Walfield + + * pthread/pt-create.c [HAVE_USELOCAL]: Include . + (entry_point) [HAVE_USELOCALE]: Initialize the thread to the + global locale. + +2002-11-25 Neal H. Walfield + + * sysdeps/mach/hurd/i386/pt-setup.c (__pthread_setup): Fix last + change. + +2002-11-18 Neal H. Walfield + + * sysdeps/mach/pt-wakeup.c (__pthread_wakeup): Use the size of + THREAD->wakeupmsg which may not be a mach_msg_header_t. + + * sysdeps/generic/pt-mutex-timedlock.c + (__pthread_mutex_timedlock_internal): Really test for equality. + * sysdeps/generic/pt-rwlock-timedrdlock.c + (__pthread_rwlock_timedrdlock_internal): Likewise. + * sysdeps/generic/pt-rwlock-timedwrlock.c + (__pthread_rwlock_timedwrlock_internal): Likewise. + + * sysdeps/generic/pt-cond-timedwait.c + (__pthread_cond_timedwait_internal): On timeout, remove our thread + structure from the wait queue if necessary. + + * sysdeps/l4/pt-start.c (__pthread_start): Call L4_Myself, not + __mach_thread_self. + + * sysdeps/mach/hurd/i386/pt-setup.c: Include . + (__pthread_setup): Do not leak references from __mach_thread_self. + * sysdeps/mach/hurd/pt-docancel.c (__pthread_do_cancel): Likewise. + * sysdeps/mach/hurd/pt-sysdep.h (_pthread_self): Likewise. + * sysdeps/mach/pt-thread-alloc.c (__pthread_thread_alloc): Likewise. + * sysdeps/mach/pt-thread-start.c (__pthread_thread_start): Likewise. + + * sysdeps/mach/pt-start.c: Remove dead file. + +2002-11-09 Roland McGrath + + * include/pthread/pthread.h: Avoid `__thread' as an identifier, + since it might be a keyword. + +2002-11-02 Alfred M. Szmidt + + * sysdeps/generic/pt-key-delete.c, sysdeps/hurd/pt-key-delete.c + (pthread_key_delete): Renamed from pthread_key_destroy. + Reported by Michael Koch + +2002-10-12 Neal H. Walfield + + * sysdeps/hurd/pt-destroy-specific.c (__pthread_destroy_specific): + Only call the destructor if there is one set. + +2002-10-10 Neal H. Walfield + + * libpthread.a: It is _cthread_init_routine, not _cthread_init. + Add -lihash. + * libpthread_pic.a: Likewise but add -lihash_pic. + + * tests/Makefile (%-static): New rule. + (CHECK_PROGS): Build static test programs. + +2002-10-10 Neal H. Walfield + + * Makefile (install): Add $(libdir)/libpthread2.a and + $(libdir)/libpthread2_pic.a. + (.PHONY): Likewise. + ($(libdir)/libpthread2.a): New rule. + ($(libdir)/libpthread2_pic.a): Likewise. + + * libpthread_pic.a: New file. + * libpthread.a: New file. + +2002-10-10 Neal H. Walfield + + * Makefile (SRCS): Remove pt-errno.c. + * sysdeps/mach/hurd/pt-errno.c: Removed. + * sysdeps/l4/hurd/pt-errno.c: Removed. + +2002-10-10 Neal H. Walfield + + * include/lock-intern.h: Removed. Use the one provided by glibc. + * Makefile (sysdeps_headers): Remove lock-intern.h. + +2002-10-10 Neal H. Walfield + + * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Save the thread + pointer using the __hurd_threadvar routines; not a the top of the + stack. + * sysdeps/mach/hurd/pt-sysdep.h (_HURD_THREADVAR_THREAD): New + marcro. + (_pthread_self): Use __hurd_threadvar_location to access the self + pointer. + * sysdeps/mach/hurd/pt-sysdep.c (init_routine): Likewise. Update + the calculation of __hurd_threadvar_stack_offset. + +2002-10-10 Neal H. Walfield + + * pthread/pt-alloc.c (alloc_init): Removed. + (__pthread_alloc): Allocate __pthread_threads lazily. + + * sysdeps/hurd/pt-getspecific.c (pthread_getspecific): Add an + assert. + +2002-09-28 Neal H. Walfield + + * sysdeps/generic/pt-cond-timedwait.c + (__pthread_cond_timedwait_internal): Add definition. + * sysdeps/generic/pt-rwlock-rdlock.c + (__pthread_rwlock_timedrdlock_internal): Define this ... + (__pthread_mutex_timedlock_internal): ... not this. + * sysdeps/generic/pt-rwlock-wrlock.c + (__pthread_rwlock_timedwrlock_internal): Add an extern. + +2002-09-28 Neal H. Walfield + + * sysdeps/mach/hurd/pt-sysdep.h (_pthread_self): Assert that + __pthread_threads is initialized. + + (__pthread_self): Beautify. + +2002-09-28 Neal H. Walfield + + * sysdeps/mach/hurd/pt-sysdep.c (init_routine): Only call + __pthread_initialize once. + +2002-09-28 Neal H. Walfield + + * sysdeps/generic/pt-cond-init.c (pthread_cond_init): Only assert + that ATTR->pshared is PTHREAD_PROCESS_PRIVATE if ATTR is not NULL. + Reported by Manuel Menal . + +2002-09-27 Neal H. Walfield + + * sysdeps/generic/bits/mutex.h (__PTHREAD_MUTEX_INITIALIZER): + Initialize the LOCKS member of struct __pthread_mutex to 0, not + NULL. + +2002-09-27 Neal H. Walfield + + * sysdeps/generic/bits/mutex.h (struct __pthread_mutex): New + field, cthreadcompat1: cthreads does not initialize the third + field of a mutex and as a result, neither does glibc. Avoid + this pit. + (__PTHREAD_MUTEX_INITIALIZER): Initialize cthreadcompat1 to 0. + +2002-09-27 Neal H. Walfield + + * Makefile ($(addprefix $(includedir)/, $(sysdeps_headers))): Do + not prepend ${srcdir}. + +2002-09-27 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_enqueue): New function. + (__pthread_dequeue): New function. + (__pthread_queue_iterate): New macro. + (__pthread_dequeuing_iterate): New macro. + + * sysdeps/generic/pt-barrier-wait.c (pthread_barrier_wait): Use + the new convenience functions. + * sysdeps/generic/pt-cond-brdcast.c (pthread_cond_broadcast): + Likewise. + * sysdeps/generic/pt-cond-signal.c (cond_signal): Likewise. + * sysdeps/generic/pt-cond-timedwait.c + (__pthread_cond_timedwait_internal): Likewise. + * sysdeps/generic/pt-mutex-timedlock.c + (__pthread_mutex_timedlock_internal): Likewise. + * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): + Likewise. + * sysdeps/generic/pt-rwlock-timedrdlock.c + (__pthread_rwlock_timedrdlock_internal): Likewise. + * sysdeps/generic/pt-rwlock-timedwrlock.c + (__pthread_rwlock_timedwrlock_internal): Likewise. + * sysdeps/generic/pt-rwlock-unlock.c (pthread_rwlock_unlock): + Likewise. + + * pthread/pt-alloc.c (initialize_pthread): Initialize the next and + prevp pointers to 0. + +2002-09-27 Neal H. Walfield + + * tests/Makefile (CFLAGS): New variable. + +2002-09-27 Neal H. Walfield + + * sysdeps/generic/pt-mutex-timedlock.c (pthread_mutex_timedlock): + Call __pthread_mutex_timedlock_internal, not + pthread_mutex_timedlock. + +2002-09-27 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_rwlock_unlock): Remove obsolete + definition. + * pthread/pt-alloc.c (__pthread_alloc): Use pthread_rwlock_wrlock + and pthread_rwlock_unlock, not __pthread_rwlock_wrlock and + __pthread_rwlock_unlock. + * pthread/pt-create.c (__pthread_create_internal): Use + pthread_rwlock_rdlock and pthread_rwlock_unlock, not + __pthread_rwlock_rdlock and __pthread_rwlock_unlock. + * sysdeps/generic/pt-cond-timedwait.c (pthread_cond_timedwait): + Call __pthread_cond_timedwait_internal, not + __pthread_cond_timedwait. + +2002-09-27 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_mutex_timedlock): Remove + definition. + (__pthread_rwlock_timedrdlock): Likewise. + (__pthread_rwlock_timedwrlock): Likewise. + (__pthread_cond_timedwait): Likewise. + * include/pthread/pthread.h (pthread_mutex_timedlock): Remove + verbage about GNU extension. + (pthread_cond_timedwait): Likewise. + (pthread_rwlock_timedrdlock): Likewise. + (pthread_rwlock_timedwrlock): Likewise. + + * sysdeps/generic/pt-rwlock-timedrdlock.c + (__pthread_rwlock_timedrdlock_internal): Renamed from + __pthread_rwlock_timedrdlock. + (pthread_rwlock_timedrdlock): New function. Remove weak alias. + * sysdeps/generic/pt-rwlock-rdlock.c + (__pthread_mutex_timedlock_internal): New definition. + (pthread_rwlock_rdlock): Renamed from __pthread_rwlock_rdlock. + Use __pthread_rwlock_timedlock_internal. Remove weak alias. + + * sysdeps/generic/pt-cond-timedwait.c + (__pthread_cond_timedwait_internal): Rename from + __pthread_cond_timedwait. Remove weak aliases. + (pthread_cond_timedwait): New function. + * sysdeps/generic/pt-cond-wait.c + (__pthread_cond_timedwait_internal): New definition. + (pthread_cond_wait): Use it. + + * sysdeps/generic/pt-mutex-timedlock.c + (__pthread_mutex_timedlock_internal): Rename from + __pthread_mutex_timedlock. Remove weak alias. + (pthread_mutex_timedlock): New function. + * sysdeps/generic/pt-mutex-lock.c + (__pthread_mutex_timedlock_internal): New definition. + (__pthread_mutex_lock): Use it. + + * sysdeps/generic/pt-rwlock-timedwrlock.c + (__pthread_rwlock_timedwrlock_internal): Rename from + __pthread_rwlock_timedwrlock. + (pthread_rwlock_timedwrlock): New function. Remove weak alias. + * sysdeps/generic/pt-rwlock-wrlock.c + (__pthread_mutex_timedlock_internal): New definition. + (pthread_rwlock_wrlock): Renamed from __pthread_rwlock_wrlock. + Use __pthread_rwlock_timedlock_internal. Remove weak alias. + + * sysdeps/generic/pt-rwlock-tryrdlock.c + (pthread_rwlock_tryrdlock): Rename from + __pthread_rwlock_tryrdlock. Remove weak alias. + * sysdeps/generic/pt-rwlock-trywrlock.c + (pthread_rwlock_trywrlock): Rename from + __pthread_rwlock_trywrlock. Remove weak alias. + + * sysdeps/hurd/pt-kill.c (pthread_kill): Rename from + __pthread_kill. Remove weak alias. + * sysdeps/generic/pt-atfork.c (pthread_atfork): Rename from + __pthread_atfork. Remove weak alias. + +2002-09-27 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_create_internal): Renamed from + __pthread_create. Updated all callers. Suggested by Roland + McGrath. + +2002-09-27 Neal H. Walfield + + * Makefile: New file. + * tests/Makefile: New file. + +2002-09-27 Neal H. Walfield + + * sysdeps/generic/bits/barrier.h: Include . + (struct __pthread_barrier): Change lock to a __pthread_spinlock_t: + pthread_spinlock_t may not be defined in this context. + +2002-09-26 Neal H. Walfield + + * sysdeps/generic/bits/once.h (__PTHREAD_ONCE_INIT): Be standards + compliant: do not cast the result. + +2002-09-26 Neal H. Walfield + + * pthread/pt-join.c (pthread_join): Fix typo in previous change. + +2002-09-26 Neal H. Walfield + + * sysdeps/generic/bits/barrier.h (struct __pthread_barrier): Add + new members attr and data. + * sysdeps/generic/pt-barrier-init.c: Inlucde . + (pthread_barrier_init): Set *BARRIER to zero. + + * sysdeps/generic/bits/condition.h (__PTHREAD_COND_INITIALIZER): + Initialize all fields. + + * sysdeps/generic/bits/mutex.h (__pthread_mutex): Rename + cthread_compat1 to data. + (pthread_mutex_destroy): Avoid + inline version if __MUTEX->data is not NULL. + (__pthread_mutex_lock): Likewise. + (__pthread_mutex_trylock): Likewise. + + * sysdeps/generic/bits/rwlock.h: New member __attr. + (__PTHREAD_RWLOCK_INITIALIZER): Initialize it to zero. + (pthread_rwlock_destroy): Avoid inline version if __RWLOCK->__data + is not NULL. + +2002-09-26 Neal H. Walfield + + * pthread/pt-join.c (pthread_join): Protect PTHREAD->state_lock + inconsistency due to cancelation. + +2002-09-26 Neal H. Walfield + + * sysdeps/generic/bits/pthread.h (pthread_equal): Change from + static inline to extern inline. + * sysdeps/generic/pt-equal.c: New file. + * Makefile.am (libpthread_a_SOURCES): Add pt-equal.c. + +2002-09-26 Neal H. Walfield + + * include/pthread/pthread.h (pthread_mutex_getprioceiling): New + definition. + (pthread_mutex_setprioceiling): New definition. + (pthread_getschedparam): New definition. + (pthread_setschedparam): New definition. + (pthread_setschedprio): New definition. + + * sysdeps/generic/pt-getschedparam.c: New file. + * sysdeps/generic/pt-mutex-getprioceiling.c: New file. + * sysdeps/generic/pt-mutex-setprioceiling.c: New file. + * sysdeps/generic/pt-setschedparam.c: New file. + * sysdeps/generic/pt-setschedprio.c: New file. + * Makefile.am (libpthread_a_SOURCES): Add pt-getschedparam.c, + pt-mutex-getprioceiling.c, pt-mutex-setprioceiling.c, + pt-setschedparam.c and pt-setschedprio.c. + +2002-09-26 Neal H. Walfield + + * pthread/Makefile.glibc: Removed. + * pthread/pthread.patch: Removed. + +2002-09-26 Neal H. Walfield + + * include/pthread/pthread.h (pthread_getcpuclockid): New + definition. + * sysdeps/generic/pt-getcpuclockid.c: New file. + * Makefile.am (libpthread_a_SOURCES): Add pt-getcpuclockid.c. + +2002-09-25 Neal H. Walfield + + * include/pthread/pthread.h (pthread_kill): New definition. + * sysdeps/hurd/pt-kill.c (__pthread_kill): New file. + * Makefile.am (libpthread_a_SOURCES): Add pt-kill.c. + + * tests/Makefile.am (check_PROGRAMS): Add test-16. + (TEST_COUNT): Bump to 16. + (MOSTLYCLEANFILES): Add test-16.out. + (test_16_SOURCES): New variable. + + * tests/test-16.c: New file. + +2002-09-25 Neal H. Walfield + + * sysdeps/generic/pt-attr.c: Include . + +2002-09-25 Neal H. Walfield + + * tests/Makefile.am (check_PROGRAMS): Remove test-5. + Unintentionally checked in. + +2002-09-25 Neal H. Walfield + + * include/pthread/pthread.h (pthread_atfork): New definition. + * sysdeps/generic/pt-atfork.c: New file. + + * Makefile.am (libpthread_a_SOURCES): Add pt-atfork.c. + +2002-09-25 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_rwlock_rdlock): New definition. + (__pthread_rwlock_timedrdlock): New definition. + (__pthread_rwlock_wrlock): New definition. + (__pthread_rwlock_timedwrlock): New definition. + (__pthread_rwlock_unlock): New definition. + +2002-09-25 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_timedblock): New definition. + * sysdeps/mach/pt-timedblock.c: New file. + + * include/pthread/pthread.h (pthread_mutex_timedlock): New + definition. + (pthread_cond_timedwait): Enable unconditionally. + (pthread_rwlock_timedrdlock): New definition. + (pthread_rwlock_timedwrlock): New definition. + + * sysdeps/generic/pt-mutex-timedlock.c: New file. + * sysdeps/generic/pt-mutex-lock.c (__pthread_mutex_lock): + Reimplement in terms of __pthread_mutex_timedlock. + + * sysdeps/generic/pt-cond-timedwait.c: New file. + * sysdeps/generic/pt-cond-wait.c (pthread_cond_wait): Reimplement + in terms of pthread_cond_timedwait. + + * sysdeps/generic/pt-rwlock-timedrdlock.c: New file. + * sysdeps/generic/pt-rwlock-rdlock.c + (__pthread_rwlock_rdlock): Reimplement in terms of + __pthread_rwlock_timedrdlock. + + * sysdeps/generic/pt-rwlock-timedwrlock.c: New file. + * sysdeps/generic/pt-rwlock-wrlock.c (__pthread_rwlock_wrlock): + Reimplement in terms of __pthread_rwlock_timedwrlock. + + * sysdeps/generic/pt-cond-signal.c (cond_signal): Clear the + previous pointer of the thread which we decide to wake up. + + * Makefile.am (libpthread_a_SOURCES): Add pt-mutex-lock.c, + pt-mutex-trylock.c, pt-mutex-timedlock.c, pt-rwlock-timedrdlock.c, + pt-rwlock-timedwrlock.c, pt-cond-timedwait.c and pt-timedblock.c. + + * tests/Makefile.am (check_PROGRAMS): Add test-13, test-14 and + test-15. + (TEST_COUNT): Bump to 15. + (MOSTLYCLEANFILES): Add test-13.out, test-14.out and test-15.out. + (test_13_SOURCES): New variable. + (test_14_SOURCES): New variable. + (test_15_SOURCES): New variable. + * tests/test-13.c: New file. + * tests/test-14.c: New file. + * tests/test-15.c: New file. + +2002-09-25 Neal H. Walfield + + * include/pthread/pthread.h: Include + (pthread_condattr_t): New type. + (pthread_condattr_init): New definition. + (pthread_condattr_destroy): New definition. + (pthread_condattr_getclock): New definition. + (pthread_condattr_setclock): New definition. + (pthread_condattr_getpshared): New definition. + (pthread_condattr_setpshared): New definition. + (pthread_cond_init): New definition. + (pthread_cond_destroy): New definition. + * pthread/pt-internal.h (__pthread_default_condattr): New + definition. + + * sysdeps/generic/pt-cond-destroy.c: New file. + * sysdeps/generic/pt-cond-init.c: New file. + * sysdeps/generic/pt-cond.c: New file. + * sysdeps/generic/pt-condattr-destroy.c: New file. + * sysdeps/generic/pt-condattr-getclock.c: New file. + * sysdeps/generic/pt-condattr-getpshared.c: New file. + * sysdeps/generic/pt-condattr-init.c: New file. + * sysdeps/generic/pt-condattr-setclock.c: New file. + * sysdeps/generic/pt-condattr-setpshared.c: New file. + * sysdeps/generic/bits/condition-attr.h: New file. + * Makefile.am (libpthread_a_SOURCES): Add pt-cond.c, + pt-condattr-init.c, pt-condattr-destroy.c, pt-condattr-getclock.c, + pt-condattr-getpshared.c, pt-condattr-setclock.c, + pt-condattr-setpshared.c, pt-cond-destroy.c and pt-cond-init.c. + * headers.m4 (hurd_SYSDEPS): Add bits/condition-attr.h. + +2002-09-24 Neal H. Walfield + + * sysdeps/generic/pt-cond-wait.c (pthread_cond_wait): If canceled, + be sure to disconnect ourself from the waiters' queue. + +2002-09-24 Neal H. Walfield + + * sysdeps/mach/hurd/pt-docancel.c (__pthread_do_cancel): Before + overwriting the thread's state, abort any system call in progress. + +2002-09-24 Neal H. Walfield + + * sysdeps/generic/pt-cond-wait.c (pthread_cond_wait): Rewrite + cancelation support. + +2002-09-24 Neal H. Walfield + + * sysdeps/generic/pt-cond-wait.c (pthread_cond_wait): Before + returning add a cancelation point. + +2002-09-24 Neal H. Walfield + + * include/pthread/pthread.h (pthread_setconcurrency): New + definition. + (pthread_getconcurrency): New definition. + + * pthread/pt-internal.h (__pthread_concurrency): New definition. + + * sysdeps/generic/pt-getconcurrency.c: New file. + * sysdeps/generic/pt-setconcurrency.c: New file. + + * Makefile.am (libpthread_a_SOURCES): Add pt-getconcurrency.c and + pt-setconcurrency.c. + + * tests/Makefile.am (check_PROGRAMS): Add test-12. + (TEST_COUNT): Bump to 12. + (MOSTLYCLEANFILES): Add test-12.out. + (test_12_SOURCES): New variable. + * tests/test-12.c: New file. + +2002-09-24 Neal H. Walfield + + * sysdeps/hurd/pt-key.h (__pthread_key_lock_ready): New function. + Initialize the __pthread_key_lock. + * sysdeps/hurd/pt-key-create.c (__pthread_key_lock): Do not + initialize it. + (pthread_key_create): Do it here by calling + __pthread_key_lock_ready. + * sysdeps/hurd/pt-key-delete.c (pthread_key_destory): Call + __pthread_key_lock_ready. + * sysdeps/hurd/pt-destroy-specific.c (__pthread_destroy_specific): + Likewise. + +2002-09-24 Neal H. Walfield + + * include/pthread/pthread.h: Include . + (pthread_rwlockattr_t): New type. + (pthread_rwlockattr_init): New definition. + (pthread_rwlockattr_destroy): New definition. + (pthread_rwlockattr_getpshared): New definition. + (pthread_rwlockattr_setpshared): New definition. + + Include . + (pthread_rwlock_t): New type. + + (pthread_rwlock_init): New definition. + (pthread_rwlock_destroy): New definition. + (pthread_rwlock_rdlock): New definition. + (pthread_rwlock_tryrdlock): New definition. + (pthread_rwlock_wrlock): New definition. + (pthread_rwlock_trywrlock): New definition. + (pthread_rwlock_unlock): New definition. + + * pthread/pt-internal.h (pthread_rwlock_t): Remove macro. + (__pthread_rwlock_rlock): Remove macro. + (__pthread_rwlock_wlock): Remove macro. + (__pthread_rwlock_unlock): Remove macro. + + (__pthread_default_rwlockattr): New definition. + + * pthread/pt-alloc.c (__pthread_alloc): Use + __pthread_rwlock_wrlock, not __pthread_rwlock_wlock. + * pthread/pt-create.c (__pthread_create): Use + __pthread_rwlock_rdlock, not __pthread_rwlock_rlock. + + * sysdeps/generic/pt-rwlock-attr.c: New file. + * sysdeps/generic/pt-rwlock-destroy.c: New file. + * sysdeps/generic/pt-rwlock-init.c: New file. + * sysdeps/generic/pt-rwlock-rdlock.c: New file. + * sysdeps/generic/pt-rwlock-tryrdlock.c: New file. + * sysdeps/generic/pt-rwlock-trywrlock.c: New file. + * sysdeps/generic/pt-rwlock-unlock.c: New file. + * sysdeps/generic/pt-rwlock-wrlock.c: New file. + * sysdeps/generic/pt-rwlockattr-destroy.c: New file. + * sysdeps/generic/pt-rwlockattr-getpshared.c: New file. + * sysdeps/generic/pt-rwlockattr-init.c: New file. + * sysdeps/generic/pt-rwlockattr-setpshared.c: New file. + * sysdeps/generic/bits/rwlock-attr.h: New file. + * sysdeps/generic/bits/rwlock.h: New file. + + * headers.m4 [hurd_SYSDEPS]: Add bits/rwlock.h and + bits/rwlock-attr.h. + + * Makefile.am (libpthread_a_SOURCES): Add pt-rwlock-attr.c, + pt-rwlockattr-init.c, pt-rwlockattr-destroy.c, + pt-rwlockattr-getpshared.c, pt-rwlockattr-setpshared.c, + pt-rwlock-init.c, pt-rwlock-destroy.c, pt-rwlock-rdlock.c, + pt-rwlock-tryrdlock.c, pt-rwlock-trywrlock.c, pt-rwlock-wrlock.c + and pt-rwlock-unlock.c. + + * tests/Makefile.am (check_PROGRAMS): Add test-11. + (TEST_COUNT): Bump to 11. + (MOSTLYCLEANFILES): Add test-11.out. + (test_11_SOURCES): New variable. + * tests/test-11.c: New file. + +2002-09-24 Neal H. Walfield + + * Makefile.am (SYSDEPS) [L4]: Removed crt0.c. + + * crt0.c: Moved to ../libc/crt0.c. + +2002-09-23 Neal H. Walfield + + * Makefile.am (libpthread_a_SOURCES): Add pt-mutexattr.c, + pt-mutexattr-destroy.c, pt-mutexattr-init.c, + pt-mutexattr-getprioceiling.c, pt-mutexattr-getprotocol.c, + pt-mutexattr-getpshared.c, pt-mutexattr-gettype.c, + pt-mutexattr-setprioceiling.c, pt-mutexattr-setprotocol.c, + pt-mutexattr-setpshared.c, pt-mutexattr-settype.c, + pt-mutex-init.c, pt-mutex-destroy.c and pt-mutex-trylock.c. + + * headers.m4 [hurd_SYSDEPS]: Add bits/mutex-attr.h. + + * include/pthread/pthread.h: Include . + (__pthread_mutex_protocol): New enumeration. + (__pthread_mutex_type): New enumeration. + (pthread_mutexattr_t): New type. + (pthread_mutexattr_init): New definition. + (pthread_mutexattr_destroy): New definition. + (pthread_mutexattr_getprioceiling): New definition. + (pthread_mutexattr_setprioceiling): New definition. + (pthread_mutexattr_getprotocol): New definition. + (pthread_mutexattr_setprotocol): New definition. + (pthread_mutexattr_getpshared): New definition. + (pthread_mutexattr_setpshared): New definition. + (pthread_mutexattr_gettype): New definition. + (pthread_mutexattr_settype): New definition. + + * pthread/pt-internal.h (__pthread_default_mutexattr): New + definition. + + * sysdeps/generic/bits/mutex.h: Include . + (struct __pthread_mutex): Add member OWNER and member LOCKS to + support error checking and recursive mutexes. Renamed __attr to + attr, updated users. + (pthread_mutexattr_t): Removed. + (__PTHREAD_MUTEX_INITIALIZER): Add initializers for new members. + (pthread_mutex_init): If ATTR, call _pthread_mutex_init. + (pthread_mutex_destroy): If __MUTEX has an attribute, call + _pthread_mutex_destroy. + * sysdeps/generic/pt-mutex-lock.c (__pthread_mutex_lock): Grok + mutex attribute. + * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): + Likewise. + Add a weak alias to _pthread_mutex_unlock. + + * sysdeps/generic/pt-mutex-destroy.c: New file. + * sysdeps/generic/pt-mutex-init.c: New file. + * sysdeps/generic/pt-mutex-trylock.c: New file. + * sysdeps/generic/pt-mutexattr-destroy.c: New file. + * sysdeps/generic/pt-mutexattr-getprioceiling.c: New file. + * sysdeps/generic/pt-mutexattr-getprotocol.c: New file. + * sysdeps/generic/pt-mutexattr-getpshared.c: New file. + * sysdeps/generic/pt-mutexattr-gettype.c: New file. + * sysdeps/generic/pt-mutexattr-init.c: New file. + * sysdeps/generic/pt-mutexattr-setprioceiling.c: New file. + * sysdeps/generic/pt-mutexattr-setprotocol.c: New file. + * sysdeps/generic/pt-mutexattr-setpshared.c: New file. + * sysdeps/generic/pt-mutexattr-settype.c: New file. + * sysdeps/generic/pt-mutexattr.c: New file. + * sysdeps/generic/bits/mutex-attr.h: New file. + + * tests/Makefile.am (AM_LDFLAGS): Add `-u__pthread_mutex_trylock + -u__pthread_mutex_unlock -u__pthread_mutex_unlock'. + (check_PROGRAMS): Add test-9 and test-10. + (TEST_COUNT): Bump to 10. + (MOSTLYCLEANFILES): Add test-9.out and test-10.out. + (test_9_SOURCES): New variable. + (test_10_SOURCES): Likewise. + * tests/test-9.c: New file. + * tests/test-10.c: New file. + +2002-09-23 Neal H. Walfield + + * pthread/pt-exit.c (pthread_exit): Call pthread_setcancelstate + correctly: NULL is not a legal value for the oldstate parameter. + +2002-09-21 Neal H. Walfield + + * pthread/pt-exit.c: Remove dead code. + (pthread_exit): When running the cancelation handlers, disable + cancelation. + +2002-09-21 Neal H. Walfield + + * tests/test-5.c (main): Fork a child. Do not dump a core. + (thr): Renamed from foo. + +2002-09-21 Neal H. Walfield + + * pthread/pt-initialize.c (__pthread_init): Fully prototype it. + +2002-09-21 Neal H. Walfield + + * Makefile.am (libpthread_a_SOURCES): Add pt-sigmask.c, + pt-stack-alloc.c, pt-thread-alloc.c, pt-thread-dealloc.c, + pt-thread-start.c, pt-sigstate-init.c, pt-sigstate-destroy.c + pt-sigstate.c. + Remove pt-stack.c and pt-start.c. + + * pthread/pt-create.c (__pthread_create): Instead of calling + __pthread_start, first call __pthread_thread_alloc, then setup the + signal state and finally start the thread by calling + __pthread_thread_start. + + * pthread/pt-exit.c (pthread_exit): Destroy any signal state by + calling __pthread_sigstate_destroy. + + * pthread/pt-sigmask.c: New file. + + * pthread/pt-internal.c (__pthread_thread_halt): New definition to + replace __pthread_halt macro. Update all callers. + * sysdeps/mach/hurd/pt-sysdep.h (__pthread_halt): Renamed to + __pthread_thread_halt and moved from here ... + * sysdeps/mach/pt-thread-halt.c: ... to here. + * sysdeps/l4/hurd/pt-sysdep.h (__pthread_halt): Renamed to + __pthread_thread_halt and moved from here ... + * sysdeps/l4/pt-thread-halt.c: ... to here. + + * pthread/pt-internal.h (__pthread_start): Split into + __pthread_thread_alloc and __pthread_thread_start. Update all + callers. + (__pthread_thread_alloc): New definition. + (__pthread_thread_start): Likewise. + * sysdeps/l4/pt-start.c: Split file into ... + * sysdeps/l4/pt-thread-alloc.c: ... this ... + * sysdeps/l4/pt-thread-start.c: ... and this. + * sysdeps/mach/pt-start.c: Split file into ... + * sysdeps/mach/pt-thread-alloc.c: ... this ... + * sysdeps/mach/pt-thread-start.c: ... and this. + + * sysdeps/l4/pt-stack.c: Moved from here ... + * sysdeps/l4/pt-stack-alloc.c: ... to here. + * sysdeps/mach/pt-stack.c: Moved from here ... + * sysdeps/mach/pt-stack-alloc.c: ... to here. + + * pt-internal.h: Include . + (__pthread_sigstate_init): New definition. + (__pthread_sigstate_destroy): Likewise. + (__pthread_sigstate): Likewise. + * sysdeps/mach/hurd/pt-sigstate-destroy.c: New file. + * sysdeps/mach/hurd/pt-sigstate-init.c: New file. + * sysdeps/mach/hurd/pt-sigstate.c: New file. + + * sysdeps/mach/hurd/i386/pt-setup.c (__pthread_setup): Setup the + initial thread state but only if THREAD is not the main thread. + +2002-09-17 Neal H. Walfield + + Get signals working. + + * sysdeps/mach/hurd/pt-destroy-signal-state.c: Likewise. + * sysdeps/mach/hurd/pt-init-signal-state.c: Likewise. + * sysdeps/mach/hurd/pt-sigstate.c: Likewise. + + + * pthread/pt-internal.h: Include . + (__pthread_init_signal_state): New definition. + (__pthread_destroy_signal_state): Likewise. + (__pthread_sigstate): Likewise. + + * pthread/pt-create.c (pthread_create): Call + __pthread_init_signal_state (and __pthread_destroy_signal_state on + a failure). Also set the new thread's sigmask and pending signal + state appropriately. + + * pthread/pt-exit.c (pthread_exit): Call + __pthread_destroy_signal_state as appropriate. + +2002-09-21 Neal H. Walfield + + * pthread/pt-alloc.c (__pthread_alloc): Factor out initialization + code into ... + (initialize_pthread): ... this new function. + + (__pthread_alloc): If reusing a thread structure fails, clean up + the mess correctly. + +2002-09-21 Neal H. Walfield + + * pthread/pt-alloc.c (__pthread_alloc): Revert last change. + +2002-09-21 Neal H. Walfield + + * pthread/pt-alloc.c (__pthread_alloc): Remove assert. + +2002-09-21 Neal H. Walfield + + * pthread/pt-initialize.c (__pthread_main): Removed. The added + convenience does not help initialization and severely complicates + the library if the the main thread calls pthread_exit. + (__pthread_init): Remove parameter, thread. + (__pthread_initialize): Updated to reflect new semantics. + * pthread/pt-alloc.c (alloc_init): Update to new semantics. Do + not try to initialize the main thread. + + * pthread/pt-create.c (__pthread_total): The main thread is now + created explicitly, initialize to zero. + + * pthread/pt-internal.h (__pthread_num_threads): Add definition. + (__pthread_main): Removed. + + * pthread/pt-internal.h (__pthread_create): New definition. + * pthread/pt-create.c (pthread_create): Move functionality from + here ... + (__pthread_create): ... to here. + (pthread_create): Use __pthread_create. + + * sysdeps/mach/hurd/pt-sysdep.c (init_routine): Use + __pthread_create directly rather than rewriting the functionality + here. + * sysdeps/l4/hurd/pt-sysdep.c (init_routine): Likewise. + + * sysdeps/mach/pt-start.c (__pthread_start): Do not detect the + main thread using __pthread_main. If main thread, set the kernel + thread id. + * sysdeps/l4/pt-start.c (__pthread_start): Likewise. + +2002-09-21 Neal H. Walfield + + * sysdeps/l4/hurd/pt-save-self.c (__pthread_save_self): Move + functionality from here ... + * sysdeps/l4/hurd/i386/pt-setup.c (__pthread_setup): ... to here + where it belongs. + + * sysdeps/l4/hurd/pt-sysdep.c (init_routine): Do not save pthread + self pointer here, it will be done automatically in + __pthread_setup. + + __pthread_save_self is now obsolete. + + * pthread/pt-internal.h (__pthread_save_self): Remove definition. + * sysdeps/mach/hurd/pt-save-self.c: Removed file. + * sysdeps/l4/hurd/pt-save-self.c: Removed file. + * Makefile.am (libpthread_a_SOURCES): Remove pt-save-self.c. + +2002-09-21 Neal H. Walfield + + * pthread/pt-create.c (pthread_create): Do not call + __pthread_save_self. This is completely bogus. + + * pthread/pt-internal.h: Permit _pthread_self to be a macro. + + * sysdeps/mach/hurd/pt-sysdep.h (__pthread_self): Renamed from + _pthread_self. + (_pthread_self): New marcro. Do some sanity checks. + +2002-09-21 Neal H. Walfield + + * sysdeps/mach/hurd/pt-sysdep.c (init_routine): We cannot use + __hurd_threadvar_location with the initial stack. This is + completely bogus; removed. Neither can we use the TSD on the new + stack: once the initial thread returns to the libc initialization + code, libc overwrites it. Thus, we shift the TSD by a pointer and + use the first word of the stack to store the self pointer. + * sysdeps/mach/hurd/pt-sysdep.h (_HURD_THREADVAR_THREAD): Removed. + (_pthread_self): Update to reflect new semantics. + * sysdeps/mach/hurd/pt-save-self.c (__pthread_save_self): + Likewise. + * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Likewise. + +2002-09-17 Neal H. Walfield + + * Makefile.am (AM_CPPFLAGS): Add -D_IO_MTSAFE_IO. + (SYSDEPS) [MACH]: Add lockfile.c. + + * lockfile.c: Include . + + * tests/Makefile.am (AM_LDFLAGS): Add -u_cthreads_flockfile to + force the inclusion of lockfile.c. + +2002-09-16 Neal H. Walfield + + * tests/test-7.c: Include . + +2002-09-16 Neal H. Walfield + + * pthread/cthreads-compat.c (__mutex_lock_solid): New function. + (__mutex_unlock_solid): Likewise. + + * sysdeps/mach/pt-spin.c: New file. + * sysdeps/mach/bits: New directory. + * sysdeps/mach/bits/spin-lock.h: New file. + + * sysdeps/generic/bits/mutex.h: Add comments. + + * sysdeps/posix/pt-spin.c (_pthread_spin_lock): Renamed from + __pthread_spin_lock. Update weak aliases to point to _pthread_spin + lock in lieu of __pthread_spin_lock. + +2002-09-16 Neal H. Walfield + + * Makefile.am (AM_CPPFLAGS): Order more appropriately. + (VPATH): Likewise. + +2002-09-16 Neal H. Walfield + + * sysdeps/generic/bits/spin-lock.h: Move from here ... + * sysdeps/i386/bits/spin-lock.h: ... to here. + +2002-09-16 Neal H. Walfield + + * pthread/cthreads-compat.c (__libc_getspecific): New function. + +2002-09-16 Neal H. Walfield + + * pthread/cthreads-compat.c (cthread_keycreate): New function. + (cthread_getspecific): Likewise. + (cthread_setspecific): Likewise. + +2002-09-16 Neal H. Walfield + + * sysdeps/generic/bits/pthread.h (pthread_equal): Add comments. + +2002-09-16 Neal H. Walfield + + * tests/test-6.c: Include . + (main): Remove superfluous sleep. + +2002-09-16 Neal H. Walfield + + * Makefile.am (libpthread_a_SOURCES): Add pt-once.c. + * headers.m4 [hurd_SYSDEPS]: Add bits/once.h. + + * sysdeps/generic/pt-once.c: New file. + * sysdeps/generic/bits/once.h: New file. + * sysdeps/i386/bits/memory.h: New file. + + * include/pthread/pthread.h: Include . + (PTHREAD_ONCE_INIT): New macro. + (pthread_once): New definition. + + * tests/Makefile.am (AM_CFLAGS): Set to -Wall. + (check_PROGRAMS): Add test-8. + (TEST_COUNT): Bump to 8. + (MOSTLYCLEANFILES): Add test-8.out. + (test_8_SOURCES): New variable. + + * tests/test-8.c (main): New file. + +2002-09-15 Neal H. Walfield + + * sysdeps/mach/pt-stack.c (__pthread_stack_alloc): If we reach the + end of the virtual address space, do not just fail but wrap + around. + +2002-09-15 Neal H. Walfield + + * sysdeps/generic/pt-destroy-specific.c: New file. + * sysdeps/generic/pt-getspecific.c: Likewise. + * sysdeps/generic/pt-init-specific.c: Likewise. + * sysdeps/generic/pt-key-create.c: Likewise. + * sysdeps/generic/pt-key-delete.c: Likewise. + * sysdeps/generic/pt-key.h: Likewise. + * sysdeps/generic/pt-setspecific.c: Likewise. + * sysdeps/generic/bits/thread-specific.h: Likewise. + + * sysdeps/hurd: New directory for files that only depend on a Hurd + personality (and not the underlying microkernel). + + * sysdeps/hurd/pt-destroy-specific.c: New file. + * sysdeps/hurd/pt-getspecific.c: Likewise. + * sysdeps/hurd/pt-init-specific.c: Likewise. + * sysdeps/hurd/pt-key-create.c: Likewise. + * sysdeps/hurd/pt-key-delete.c: Likewise. + * sysdeps/hurd/pt-key.h: Likewise. + * sysdeps/hurd/pt-setspecific.c: Likewise. + + * Makefile.am (AM_CPPFLAGS): Add -I$(srcdir)/sysdeps/hurd. + (VPATH): Add $(srcdir)/sysdeps/hurd. + (libpthread_a_SOURCES): Add pt-key.h, pt-destroy-specific.c, + pt-init-specific.c, pt-key-create.c, pt-key-delete.c, + pt-getspecific.c and pt-setspecific.c. + + * headers.m4 (hurd_SYSDEPS): Add thread_specific.h. + + * include/pthread/pthread.h: Include . + (pthread_key_t): New definition. + (pthread_key_create): Likewise. + (pthread_key_delete): Likewise. + (pthread_getspecific): Likewise. + (pthread_setspecific): Likewise. + + * pthread/pt-internal.h: Include + [! PTHREAD_KEY_MEMBERS]: Define it to be empty. + (struct __pthread): Include the value of PTHREAD_KEY_MEMBERS. + + (__pthread_init_specific): New definition. + (__pthread_destroy_specific): Likewise. + + * pthread/pt-alloc.c (__pthread_alloc): Call + __pthread_init_specific. + * pthread/pt-exit.c (pthread_exit): Call + __pthread_destroy_specific. + + * tests/Makefile.am (LDADD): Add -lihash. + (check_PROGRAMS): Add test-7. + (MOSTLYCLEANFILES): Add test-7.out. + (TEST_COUNT): Bump to 7. + (test_7_SOURCES): New variable. + * tests/test-7.c: New file. + +2002-09-15 Neal H. Walfield + + * tests/test-6.c: Improve test; iterate WAIT times over + pthread_barrier_wait rather than just once. + +2002-09-14 Neal H. Walfield + + Add support for barrier attributes and barriers. + + * sysdeps/generic/pt-barrier-destroy.c: New file. + * sysdeps/generic/pt-barrier-init.c: Likewise. + * sysdeps/generic/pt-barrier-wait.c: Likewise. + * sysdeps/generic/pt-barrier.c: Likewise. + * sysdeps/generic/pt-barrierattr-destroy.c: Likewise. + * sysdeps/generic/pt-barrierattr-getpshared.c: Likewise. + * sysdeps/generic/pt-barrierattr-init.c: Likewise. + * sysdeps/generic/pt-barrierattr-setpshared.c: Likewise. + * sysdeps/generic/bits/barrier-attr.h: Likewise. + * sysdeps/generic/bits/barrier.h: Likewise. + * sysdeps/generic/bits/thread-barrier.h: Likewise. + + * Makefile.am (libpthread_a_SOURCES): Added pt-barrier-destroy.c, + pt-barrier-init.c, pt-barrier-wait.c, pt-barrier.c, + pt-barrierattr-destroy.c, pt-barrierattr-init.c, + pt-barrierattr-getpshared.c and pt-barrierattr-setpshared.c. + + * headers.m4 (hurd_SYSDEPS): Added bits/barrier-attr.h and + bits/barrier.h. + + * include/pthread/pthread.h: Include and + . + + (__pthread_process_shared): New enumeration. + (PTHREAD_PROCESS_PRIVATE): New macro. + (PTHREAD_PROCESS_SHARED): Likewise. + (pthread_barrierattr_t): New typedef. + + (pthread_barrierattr_init): New definition. + (pthread_barrierattr_destroy): Likewise. + (pthread_barrierattr_getpshared): Likewise. + (pthread_barrierattr_setpshared): Likewise. + + (pthread_barrier_t): New typedef. + (PTHREAD_BARRIER_SERIAL_THREAD): New macro. + (pthread_barrier_init): New declaration. + (pthread_barrier_destroy): Likewise. + (pthread_barrier_wait): Likewise. + + * pthread/pt-internal.h (__pthread_default_barrierattr): New + definition. + + * tests/test-6.c: New file. + * tests/Makefile.am (check_PROGRAMS): Add test-6. + (MOSTLYCLEANFILES): Add test-6.out. + (test_6_SOURCES): New variable. + (TEST_COUNT): Update. + +2002-09-12 Neal H. Walfield + + * tests/Makefile.am + (check_PROGRAMS): Add test test-3 and test-5. + (MOSTLYCLEANFILES): Add test-3.out, test-4.out and test-5.out. + (TEST_COUNT): Change to 5. + (test_3_SOURCES): New variable. + (test_5_SOURCES): New variable. + (check): Fix typo. + + * tests/test-3.c: New file. + * tests/test-4.c: New file. + * tests/test-5.c: New file. + +2002-09-12 Neal H. Walfield + + * sysdeps/mach/hurd/pt-attr-setstackaddr.c: New file. + * sysdeps/mach/hurd/pt-attr-setstacksize.c: New file. + * sysdeps/mach/hurd/i386/pt-setup.c: New file. + + * sysdeps/mach/hurd/i386/pt-setup.c (stack_setup): Setup the stack + guard if necessary. + +2002-09-12 Neal H. Walfield + + Generic attributes. + + * sysdeps/generic/pt-attr-destroy.c: New file. + * sysdeps/generic/pt-attr-getdetachstate.c: New file. + * sysdeps/generic/pt-attr-getguardsize.c: New file. + * sysdeps/generic/pt-attr-getinheritsched.c: New file. + * sysdeps/generic/pt-attr-getschedparam.c: New file. + * sysdeps/generic/pt-attr-getschedpolicy.c: New file. + * sysdeps/generic/pt-attr-getscope.c: New file. + * sysdeps/generic/pt-attr-getstack.c: New file. + * sysdeps/generic/pt-attr-getstackaddr.c: New file. + * sysdeps/generic/pt-attr-getstacksize.c: New file. + * sysdeps/generic/pt-attr-init.c: New file. + * sysdeps/generic/pt-attr-setdetachstate.c: New file. + * sysdeps/generic/pt-attr-setguardsize.c: New file. + * sysdeps/generic/pt-attr-setinheritsched.c: New file. + * sysdeps/generic/pt-attr-setschedparam.c: New file. + * sysdeps/generic/pt-attr-setschedpolicy.c: New file. + * sysdeps/generic/pt-attr-setscope.c: New file. + * sysdeps/generic/pt-attr-setstack.c: New file. + * sysdeps/generic/pt-attr-setstackaddr.c: New file. + * sysdeps/generic/pt-attr-setstacksize.c: New file. + * sysdeps/generic/pt-attr.c: New file. + + * sysdeps/generic/bits/thread-attr.h: New file. + + * Makefile.am (libpthread_a_SOURCES): Add pt-attr.c, + pt-attr-destroy.c, pt-attr-getdetachstate.c, + pt-attr-getguardsize.c, pt-attr-getinheritsched.c, + pt-attr-getschedparam.c, pt-attr-getschedpolicy.c, + pt-attr-getscope.c, pt-attr-getstack.c, pt-attr-getstackaddr.c, + pt-attr-getstacksize.c, pt-attr-init.c, pt-attr-setdetachstate.c, + pt-attr-setguardsize.c, pt-attr-setinheritsched.c, + pt-attr-setschedparam.c, pt-attr-setschedpolicy.c, + pt-attr-setscope.c, pt-attr-setstack.c, pt-attr-setstackaddr.c, + pt-attr-setstacksize.c and pt-attr.c. + + * headers.m4: Add bits/thread-attr.h. + + * include/pthread/pthread.h: Inlucde . + (__pthread_inheritsched): New enumeration. + (__pthread_contentionscop): Likewise. + (__pthread_detachstate): Beautify. + + (pthread_attr_t): Update declaration. + + (pthread_attr_init): New definition. + (pthread_attr_destroy): Likewise. + (pthread_attr_getinheritsched): Likewise. + (pthread_attr_setinheritsched): Likewise. + (pthread_attr_getschedparam): Likewise. + (pthread_attr_setschedparam): Likewise. + (pthread_attr_getschedpolicy): Likewise. + (pthread_attr_setschedpolicy): Likewise. + (pthread_attr_getscope): Likewise. + (pthread_attr_setscope): Likewise. + (pthread_attr_getstackaddr): Likewise. + (pthread_attr_setstackaddr): Likewise. + (pthread_attr_getstack): Likewise. + (pthread_attr_setstack): Likewise. + (pthread_attr_getdetachstate): Likewise. + (pthread_attr_setdetachstate): Likewise. + (pthread_attr_getguardsize): Likewise. + (pthread_attr_setguardsize): Likewise. + (pthread_attr_getstacksize): Likewise. + (pthread_attr_setstacksize): Likewise. + + * pthread/pt-internal.h (struct __pthread): New member, guardsize. + (__pthread_default_attr): Make constant. + (struct __pthread_attr): Moved definition from here ... + * sysdeps/generic/bits/thread-attr.h: ... to here. + (struct __pthread_attr): Add new members: guardsize, inheritsched, + contentionscope and schedpolicy. + + * pthread/pt-attr.c: Moved from here ... + * sysdeps/generic/pt-attr.c: ... to here. + (__pthread_default_attr): Initialize new members guardsize, + inheritsched, contentionscope and schedpolicy. + + * pthread/pt-create.c (pthread_create): Make SETUP constant. + Sync with pthread_attr_t type change. + Set PTHREAD->guardsize appropriately. + +2002-09-12 Neal H. Walfield + + * tests/Makefile.am (AM_CPPFLAGS): Learn to spel. + +2002-09-12 Neal H. Walfield + + * tests/test-2.c: Implement it. + +2002-09-11 Neal H. Walfield + + * Makefile.am (SUBDIRS): New variable. + + * tests/Makefile.am: New file. + * tests/test-1.c: file. + * tests/test-2.c: file. + +2002-09-11 Neal H. Walfield + + * include/libc-symbols.h: Do not define SHARED. + * not-in-libc.h (__mach_port_allocate): New macro. + + * pthread/pt-alloc.c (__pthread_alloc): Add an assert. + + * sysdeps/generic/pt-mutex-unlock.c (__pthread_mutex_unlock): + Simplify logic: WAKEUP is known not to be NULL after it is tested. + + * sysdeps/mach/pt-start.c (create_wakeupmsg): Do not allocate a + reply port; use a normal port. + If __mach_port_insert_right fails, deallocate + THREAD->wakeupmsg.msgh_remote_port. + +2002-09-11 Neal H. Walfield + + * Makefile.am (libpthread_a_SOURCES): Add cthreads-compat.c. + +2002-08-26 Neal H. Walfield + + * sysdeps/mach/hurd/pt-errno.c: New file. + +2002-08-26 Neal H. Walfield + + * include/pthread/pthread.h (pthread_mutexattr_t): Moved from here + .. + * sysdeps/generic/bits/mutex.h: ... to here. + +2002-08-26 Neal H. Walfield + + * Makefile.am (SYSDEPS) [MACH]: Do not built lockfile.c. + (include_HEADERS): List headers to be installed. Leave commented + until it works with VPATH. + +2002-08-26 Neal H. Walfield + + * sysdeps/l4/pt-stack.c (allocate_page): Fix typo. + +2002-08-22 Neal H. Walfield + + * sysdeps/l4/pt-stack.c (allocate_page): Request the correct + permissions for the request memory. + +2002-08-22 Neal H. Walfield + + * pthread/Makefile: Moved from here ... + * pthread/Makefile.glibc: ... to here to avoid confusing automake. + +2002-08-22 Neal H. Walfield + + * Makefile.am (AM_CPPFLAGS): Fix the include paths. + Implicitly include include/libc-symbols.h. + (SYSDEPS) [L4]: Add crt0.c. + (libpthread_a_SOURCES): Remove crt0.c. + + (VPATH): New variable. + (libpthread_a_SOURCES): Depend on the VPATH; do not use absolute + paths. + +2002-08-22 Neal H. Walfield + + * sysdeps/generic/pt-cond-wait.c: Doc fix thanks to Marcus + Brinkmann for pointing this out. + * sysdeps/generic/pt-mutex-lock.c: Likewise. + +2002-08-22 Neal H. Walfield + + * sysdeps/mach/hurd/pt-sysdep.h (__thread_set_pcsp): Prototype new + function. + * sysdeps/mach/hurd/i386/pt-machdep.c (__thread_set_pcsp): + Implement it. + * sysdeps/mach/pt-start.c (__pthread_start): Use it. + +2002-08-22 Neal H. Walfield + + * sysdeps/l4/pt-stack.c: Remove comment about next_stack_base. + This is baggage carried over from the Mach version. + (allocate_page): Use L4_FpageLog2 properly. + +2002-08-22 Neal H. Walfield + + * pthread/pt-internal.h (struct __pthread_attr): Add schedparam + field. + * pthread/pt-attr.c (__pthread_default_attr): Initialize + schedparam field. + +2002-08-22 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_do_cancel): Add prototype. + +2002-08-22 Neal H. Walfield + + * pthread/pt-alloc.c (alloc_init): Make static and use RUN_HOOK. + * pthread/pt-initialize.c (__pthread_initialize): Remove the hack + and use RUN_HOOK. + +2002-08-22 Neal H. Walfield + + * pthread/pt-create.c: Include . + +2002-08-22 Neal H. Walfield + + * sysdeps/mach/hurd/pt-docancel.c: New file. + * sysdeps/mach/hurd/pt-save-self.c: New file. + +2002-08-22 Neal H. Walfield + + * include/pthread/pthread.h: Include and . + (pthread_mutexattr_t): Add prototype. + (pthread_mutex_init): Likewise. + (pthread_mutex_destroy): Likewise. + + * sysdeps/generic/bits/mutex.h (pthread_mutex_init): New function. + (pthread_mutex_destroy): New function. + + * sysdeps/generic/bits/pthread.h (pthread_equal): New function. + +2002-08-22 Neal H. Walfield + + * pthread/pt-setcancelstate.c (pthread_setcancelstate): Add + explicit break to elide gcc warning. + * pthread/pt-setcanceltype.c (pthread_setcanceltype): Likewise. + +2002-08-22 Neal H. Walfield + + * include/libc-symbols.h: Do not define _LIBC as we are not + actually compiling glibc. + (HAVE_ASM_WEAKEXT_DIRECTIVE): Do not define it. + (HAVE_ASM_SET_DIRECTIVE): Define it. + (HAVE_BUILTIN_EXPECT): Likewise. + (HAVE_GNU_LD): Likewise. + (HAVE_ELF): Likewise. + (HAVE_SECTION_QUOTES): Likewise. + (HAVE_VISIBILITY_ATTRIBUTE): Likewise. + (SHARED): Likewise. + + * not-in-libc.h: New file. + * Makefile.am (AM_CPPFLAGS): Include not-in-libc.h implicitly. + + * lockfile.c: New file. + * Makefile.am (SYSDEPS) [MACH]: Add lockfile.c. + +2002-08-22 Neal H. Walfield + + * sysdeps/mach/hurd/bits/pthread.h: Removed. Used the generic + version. + +2002-08-21 Neal H. Walfield + + * headers.m4: Fix typo. + +2002-08-21 Neal H. Walfield + + * include: Moved from libc/include except for include/sched.h and + include/time.h. + * pthread: Moved from libc/pthread. + * sysdeps: Moved from libc/sysdeps except for + sysdeps/i386/bits/atomic.h and sysdeps/hurd/hurd/threadvar.h. + * crt0.c: Moved from libc/crt0.c. + + * sysdeps/generic/bits: Moved from include/bits except + include/bits/wordsize.h. + * include/pthread: Moved from include/pthread. + * include/lock-intern.h: Moved from include/lock-intern.h. + * include/pthread.h: Moved from include/pthread.h. + + * headers.m4: New file. + +2002-08-19 Neal H. Walfield + + * sysdeps/l4/pt-start.c [WORKING_EXREGS]: Ideal implementation. + +2002-08-05 Neal H. Walfield + + * pthread/pthread.h (PTHREAD_SPINLOCK_INITIALIZER): New + declaration. + +2002-08-03 Neal H. Walfield + + * sysdeps/l4/hurd/pt-sysdep.h (PTHREAD_SYSDEP_MEMBERS): Add + my_errno. + * sysdeps/l4/hurd/pt-errno.c: New file. + * Makefile.am (libc_a_SOURCES): Added sysdeps/l4/hurd/pt-errno.c. + +2002-07-29 Neal H. Walfield + + * pthread/pt-internal.h (__pthread_save_self): New declaration. + Dual of _pthread_self (). + * sysdeps/l4/pt-save-self.c: New file. + * Makefile.am (libc_a_SOURCES): Added + sysdeps/l4/hurd/pt-save-self.c. + + * pthread/pt-create.c (pthread_create): Save the new thread's + control block explicitly using __pthread_save_self. + * sysdeps/l4/hurd/pt-sysdep.c (init_routine): Replace Hurd's + threadvar code with __pthread_save_self. + * sysdeps/l4/hurd/pt-sysdep.h (_pthread_self): Likewise. + (_HURD_THREADVAR_THREAD): Removed macro. + * sysdeps/l4/hurd/i386/pt-setup.c (stack_setup): Remove Hurd's + threadvar code. Mechanism is now in _pthread_save_self. + +2002-07-29 Neal H. Walfield + + * pthread/pt-internal.h (struct __pthread): Add fields + cancel_state, cancel_type, cancel_pending and + cancelation_handlers to support cancelation. + * pthread/pt-alloc.c (__pthread_alloc): Initialize + NEW->cancel_state, NEW->cancel_type, NEW->cancel_pending and + NEW->cancelation_handlers. + * pthread/pt-exit.c (pthread_exit): Run registered cleanup + handlers. If thread was canceled, set the status to + PTHREAD_CANCELED. + * pthread/pt-cleanup.c: New file. + * pthread/pt-setcancelstate.c: New file. + * pthread/pt-setcanceltype.c: New file. + * pthread/pt-testcancel.c: New file. + * sysdeps/l4/pt-docancel.c: New file. + + * Makefile.am (libc_a_SOURCES): Add pthread/pt-cleanup.c, + pthread/pt-setcancelstate.c, pthread/pt-setcanceltype.c, + pthread/pt-testcancel.c and sysdeps/l4/pt-docancel.c. + +2002-07-29 Neal H. Walfield + + * pthread/pthread.h (pthread_cleanup_push): Moved from here ... + * bits/cancelation.h: ... to here. + * pthread/pthread.h (pthread_cleanup_pop): Moved from here ... + * bits/cancelation.h: ... to here. + + * pthread/pthread.h (pthread_cleanup_push): New definition. + * pthread/pthread.h (pthread_cleanup_pop): New definition. + + * bits/cancelation.h: Include . + * pthread/pthread.h: Do not include . + +2002-07-29 Neal H. Walfield + + * bits/condition.h (__PTHREAD_COND_INITIALIZER): Cast result. + * bits/mutex.h (__PTHREAD_MUTEX_INITIALIZER): Likewise. + * bits/spin-lock.h (__SPIN_LOCK_INITIALIZER): Likewise. + +2002-07-29 Neal H. Walfield + + * pthread/pthread.h: Include and . + (PTHREAD_CANCEL_DISABLE): New macro. + (PTHREAD_CANCEL_ENABLE): New macro. + (PTHREAD_CANCEL_DEFERRED): New macro. + (PTHREAD_CANCEL_ASYNCHRONOUS): New macro. + (PTHREAD_CANCELED): New macro. + (pthread_setcancelstate): New definition. + (pthread_setcanceltype): New definition. + (pthread_cancel): New definition. + (pthread_testcancel): New definition. + (pthread_cleanup_push): New macro. + (pthread_cleanup_pop): New macro. + * bit/condition.h: New file. + +2002-07-25 Neal H. Walfield + + * sysdeps/l4/pt-block.c (__pthread_block): Receive from any local + thread, not any thread. + +2002-07-25 Neal H. Walfield + + * crt0.c (exit): Print the exit value for debugging purposes. + +2002-07-25 Neal H. Walfield + + * pthread/pt-alloc.c (__pthread_alloc): Improve comments. When + allocating a new pthread, really initialize it. + * pthread/pt-create.c (pthread_create): Reuse the old stacks when + possible. If allocating the thread structure fails, do not try to + free anything. Clear the thread id on failure. Beautify and add + comments. + + * pthread/pt-dealloc.c (__pthread_dealloc): Rewritten to be the + dual of __pthread_alloc rather than an all-in-one. + * pthread/pt-detach.c (pthread_detach): Factor out code that is in + __pthread_dealloc. Unlock PTHREAD->state_lock before calling + __pthread_dealloc. + * pthread/pt-exit.c (pthread_exit): Likewise. + * pthread/pt-join.c (pthread_join): Likewise. + +2002-07-25 Neal H. Walfield + + * pthread/pt-internal.h: Beautify and fix comments. + (__pthread_setid): Get a write lock, not a read lock. + +2002-07-25 Neal H. Walfield + + * pthread/pt-alloc.c (__pthread_alloc): (alloc_init): Make it an + external, not static as RUN_HOOKS does not work yet. + * pthread/pt-initialize.c (__pthread_initialize): Call alloc_init + directly as RUN_HOOK does not yet work. + +2002-07-25 Neal H. Walfield + + * sysdeps/l4/hurd/pt-sysdep.c (init_routine): Be sure that + __hurd_threadvar_stack_mask and __hurd_threadvar_stack_offset are + set before calling __pthread_setup. + * sysdeps/l4/hurd/i386/pt-setup.c (stack_setup): Elide hack and + use __hurd_threadvar_location_from-sp. + +2002-07-25 Neal H. Walfield + + * sysdeps/generic/pt-cond-wait.c (pthread_cond_wait): Add + comment about a race condition. + * sysdeps/generic/pt-mutex-lock.c (__pthread_mutex_lock): + Likewise. + +2002-07-25 Neal H. Walfield + + * sysdeps/l4/pt-start.c (send_startup_ipc): Use task_server (which + is now also the thread_server). Do smarter casting. + * sysdeps/l4/hurd/pt-sysdep.h (__pthread_halt): Likewise. + +2002-07-25 Neal H. Walfield + + * sysdeps/l4/pt-wakeup.c: Fix comment. + +2002-07-24 Neal H. Walfield + + * pthread/Makefile: New file. Imported from Mark's pthread + package with local modifications. + * pthread/Versions: Likewise. + * pthread/cthreads-compat.c: Likewise. + * pthread/pt-alloc.c: Likewise. + * pthread/pt-attr.c: Likewise. + * pthread/pt-create.c: Likewise. + * pthread/pt-dealloc.c: Likewise. + * pthread/pt-detach.c: Likewise. + * pthread/pt-exit.c: Likewise. + * pthread/pt-initialize.c: Likewise. + * pthread/pt-internal.h: Likewise. + * pthread/pt-join.c: Likewise. + * pthread/pt-self.c: Likewise. + * pthread/pt-spin-inlines.c: Likewise. + * pthread/pthread.patch: Likewise. + * sysdeps/generic/pt-cond-brdcast.c: Likewise. + * sysdeps/generic/pt-cond-signal.c: Likewise. + * sysdeps/generic/pt-cond-wait.c: Likewise. + * sysdeps/generic/pt-mutex-lock.c: Likewise. + * sysdeps/generic/pt-mutex-unlock.c: Likewise. + * sysdeps/hurd/hurd/threadvar.h: Likewise. + * sysdeps/i386/machine-sp.h: Likewise. + * sysdeps/i386/pt-machdep.h: Likewise. + * sysdeps/i386/bits/atomic.h: Likewise. + * sysdeps/l4/pt-block.c: Likewise. + * sysdeps/l4/pt-stack.c: Likewise. + * sysdeps/l4/pt-start.c: Likewise. + * sysdeps/l4/pt-wakeup.c: Likewise. + * sysdeps/l4/hurd/pt-sysdep.c: Likewise. + * sysdeps/l4/hurd/pt-sysdep.h: Likewise. + * sysdeps/l4/hurd/i386/pt-machdep.c: Likewise. + * sysdeps/l4/hurd/i386/pt-setup.c: Likewise. + * sysdeps/mach/pt-block.c: Likewise. + * sysdeps/mach/pt-stack.c: Likewise. + * sysdeps/mach/pt-start.c: Likewise. + * sysdeps/mach/pt-wakeup.c: Likewise. + * sysdeps/mach/hurd/pt-sysdep.c: Likewise. + * sysdeps/mach/hurd/pt-sysdep.h: Likewise. + * sysdeps/mach/hurd/bits/pthread.h: Likewise. + * sysdeps/mach/hurd/i386/pt-machdep.c: Likewise. + * sysdeps/mach/hurd/i386/pt-setup.c: Likewise. + * sysdeps/posix/pt-spin.c: Likewise. + + * include/libc-symbols.h: Imported from glibc with local + modifications for pthread port. + * include/set-hooks.h: Likewise. + + * include/sched.h: Glue code for pthread port until a real + implementation is available. + * include/time.h: Likewise. + + * Makefile.am (libc_a_SOURCES): Added most of the above c files. + (CFLAGS): Build up the include paths the way that glibc does. + + * TODO: New file. + + * crt0.c: Rewritten to include support for initializing pthreads + and dealing with the new stack layout. + +2002-07-24 Neal H. Walfield + + * pthread/pthread.h: Define pthread_spinlock_t. + (pthread_spin_destroy): Use it, not __pthread_spinlock_t. + (pthread_spin_init): Likewise. + (pthread_spin_lock): Likewise. + (pthread_spin_trylock): Likewise. + (pthread_spin_unlock): Likewise. + + * features.h (__USE_XOPEN2K): Define it. + +2002-07-24 Neal H. Walfield + + * pthread/pthread.h: New file imported from Mark's pthead package. + +2002-07-24 Neal H. Walfield + + * bits/condition.h: New file imported from Mark's pthead package. + * bits/mutex.h: Likewise. + * bits/pthread.h: Likewise. + * bits/spin-lock.h: Likewise. + +2002-07-23 Jeff Bailey + + * .cvsignore: New File + +2002-07-21 Neal H. Walfield + + * crt0.c (_start): Put in .START section, not in the text. + +2002-07-17 Neal H. Walfield + + * Makefile.am (AM_CFLAGS): Library is no longer called libcrt0 but + libc. Adjust accordingly. diff --git a/libpthread/Makefile b/libpthread/Makefile new file mode 100644 index 00000000..04dfb26d --- /dev/null +++ b/libpthread/Makefile @@ -0,0 +1,247 @@ +# +# Copyright (C) 1994, 1995, 1996, 1997, 2000, 2002, 2004, 2005, 2006, 2007, +# 2008 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2, 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +dir := libpthread +makemode := library + +MICROKERNEL := mach +SYSDEPS := lockfile.c + +LCLHDRS := + +SRCS := pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ + pt-attr-getguardsize.c pt-attr-getinheritsched.c \ + pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ + pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ + pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ + pt-attr-setinheritsched.c pt-attr-setschedparam.c \ + pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ + pt-attr-setstackaddr.c pt-attr-setstacksize.c \ + \ + pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ + pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ + pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ + \ + pt-destroy-specific.c pt-init-specific.c \ + pt-key-create.c pt-key-delete.c \ + pt-getspecific.c pt-setspecific.c \ + \ + pt-once.c \ + \ + pt-alloc.c \ + pt-create.c \ + pt-getattr.c \ + pt-equal.c \ + pt-dealloc.c \ + pt-detach.c \ + pt-exit.c \ + pt-initialize.c \ + pt-join.c \ + pt-self.c \ + pt-sigmask.c \ + pt-spin-inlines.c \ + pt-cleanup.c \ + pt-setcancelstate.c \ + pt-setcanceltype.c \ + pt-testcancel.c \ + pt-cancel.c \ + \ + pt-mutexattr.c \ + pt-mutexattr-destroy.c pt-mutexattr-init.c \ + pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ + pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ + pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ + pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ + \ + pt-mutex-init.c pt-mutex-destroy.c \ + pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ + pt-mutex-unlock.c \ + pt-mutex-transfer-np.c \ + pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ + \ + pt-rwlock-attr.c \ + pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ + pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ + \ + pt-rwlock-init.c pt-rwlock-destroy.c \ + pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ + pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ + pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ + pt-rwlock-unlock.c \ + \ + pt-cond.c \ + pt-condattr-init.c pt-condattr-destroy.c \ + pt-condattr-getclock.c pt-condattr-getpshared.c \ + pt-condattr-setclock.c pt-condattr-setpshared.c \ + \ + pt-cond-destroy.c pt-cond-init.c \ + pt-cond-brdcast.c \ + pt-cond-signal.c \ + pt-cond-wait.c \ + pt-cond-timedwait.c \ + \ + pt-stack-alloc.c \ + pt-thread-alloc.c \ + pt-thread-dealloc.c \ + pt-thread-start.c \ + pt-thread-halt.c \ + pt-startup.c \ + \ + pt-getconcurrency.c pt-setconcurrency.c \ + \ + pt-block.c \ + pt-timedblock.c \ + pt-wakeup.c \ + pt-docancel.c \ + pt-sysdep.c \ + pt-setup.c \ + pt-machdep.c \ + pt-spin.c \ + \ + pt-sigstate-init.c \ + pt-sigstate-destroy.c \ + pt-sigstate.c \ + \ + pt-atfork.c \ + pt-kill.c \ + pt-getcpuclockid.c \ + \ + pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ + \ + sem-close.c sem-destroy.c sem-getvalue.c sem-init.c sem-open.c \ + sem-post.c sem-timedwait.c sem-trywait.c sem-unlink.c \ + sem-wait.c \ + \ + cthreads-compat.c \ + $(SYSDEPS) + +OBJS = $(addsuffix .o,$(basename $(notdir $(SRCS)))) + +OTHERTAGS = + +libname = libpthread + +sysdeps_headers = \ + pthread.h \ + pthread/pthread.h \ + pthread/pthreadtypes.h \ + semaphore.h \ + \ + bits/pthread.h \ + bits/pthread-np.h \ + bits/mutex.h \ + bits/condition.h \ + bits/condition-attr.h \ + bits/spin-lock.h \ + bits/spin-lock-inline.h \ + bits/cancelation.h \ + bits/thread-attr.h \ + bits/barrier-attr.h \ + bits/barrier.h \ + bits/thread-specific.h \ + bits/once.h \ + bits/mutex-attr.h \ + bits/rwlock.h \ + bits/rwlock-attr.h \ + bits/semaphore.h + +SYSDEP_PATH = $(srcdir)/sysdeps/$(MICROKERNEL)/hurd/ia32 \ + $(srcdir)/sysdeps/$(MICROKERNEL)/ia32 \ + $(srcdir)/sysdeps/ia32 \ + $(srcdir)/sysdeps/$(MICROKERNEL)/hurd \ + $(srcdir)/sysdeps/$(MICROKERNEL) \ + $(srcdir)/sysdeps/hurd \ + $(srcdir)/sysdeps/generic \ + $(srcdir)/sysdeps/posix \ + $(srcdir)/pthread \ + $(srcdir)/include + +VPATH += $(SYSDEP_PATH) + +HURDLIBS = ihash + +installhdrs := +installhdrsubdir := . + +include ../Makeconf + +CPPFLAGS += \ + $(addprefix -I, $(SYSDEP_PATH)) \ + -imacros $(srcdir)/include/libc-symbols.h \ + -imacros $(srcdir)/not-in-libc.h + + +install: install-headers $(libdir)/libpthread2.a $(libdir)/libpthread2_pic.a +install-headers: $(addprefix $(includedir)/, $(sysdeps_headers)) + +# XXX: If $(libdir)/libpthread2.a is installed and +# $(libdir)/libpthread is not, we can have some issues. +.PHONY: $(libdir)/libpthread.a $(libdir)/libpthread_pic.a + +# XXX: These rules are a hack. But it is better than messing with +# ../Makeconf at the moment. Note that the linker scripts +# $(srcdir)/libpthread.a and $(srcdir)/libpthread_pic.a get overwritten +# when building in $(srcdir) and not a seperate build directory. +$(libdir)/libpthread2.a: $(libdir)/libpthread.a + mv $< $@ + $(INSTALL_DATA) $(srcdir)/libpthread.a $< + +$(libdir)/libpthread2_pic.a: $(libdir)/libpthread_pic.a + mv $< $@ + $(INSTALL_DATA) $(srcdir)/libpthread_pic.a $< + +.PHONY: $(addprefix $(includedir)/, $(sysdeps_headers)) + +$(addprefix $(includedir)/, $(sysdeps_headers)): + @set -e; \ + t="$@"; \ + t=$${t#$(includedir)/}; \ + header_ok=0; \ + for dir in $(SYSDEP_PATH); \ + do \ + if test -e "$$dir/$$t"; \ + then \ + tdir=`dirname "$@"`; \ + if test ! -e $$tdir; \ + then \ + mkdir $$tdir; \ + fi; \ + echo $(INSTALL_DATA) "$$dir/$$t" "$@"; \ + $(INSTALL_DATA) "$$dir/$$t" "$@"; \ + header_ok=1; \ + break; \ + fi; \ + done; \ + if test "$${header_ok}" -ne 1; \ + then \ + echo; \ + echo '*** 'The header file \`$@\' is required, but not \ +provided, by; \ + echo '*** 'this configuration. Please report this to the \ +maintainer.; \ + echo; \ + false; \ + fi + +# ifeq ($(VERSIONING),yes) +# +# # Adding this dependency gets it included in the command line, +# # where ld will read it as a linker script. +# $(libname).so.$(hurd-version): $(srcdir)/$(libname).map +# +# endif diff --git a/libpthread/Makefile.am b/libpthread/Makefile.am new file mode 100644 index 00000000..e59c9460 --- /dev/null +++ b/libpthread/Makefile.am @@ -0,0 +1,167 @@ +# Makefile.am - Makefile template for libpthread. +# Copyright (C) 2003, 2008 Free Software Foundation, Inc. +# +# This file is part of the GNU Hurd. +# +# The GNU Hurd is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU Hurd 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 General Public License for more details. +# +# You should have received a copy of the GNU 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 + +if ARCH_IA32 + arch=ia32 +endif +if ARCH_POWERPC + arch=powerpc +endif + +# The source files are scattered over several directories. Add +# all these directories to the vpath. +SYSDEP_PATH = $(srcdir)/sysdeps/l4/hurd/${arch} \ + $(srcdir)/sysdeps/l4/${arch} \ + $(srcdir)/sysdeps/${arch} \ + $(srcdir)/sysdeps/l4/hurd \ + $(srcdir)/sysdeps/l4 \ + $(srcdir)/sysdeps/hurd \ + $(srcdir)/sysdeps/generic \ + $(srcdir)/sysdeps/posix \ + $(srcdir)/pthread \ + $(srcdir)/signal \ + $(srcdir)/include +vpath %.c $(SYSDEP_PATH) + +AM_CPPFLAGS = $(USER_CPPFLAGS) -I$(srcdir)/pthread \ + $(addprefix -I, $(SYSDEP_PATH)) -imacros $(srcdir)/include/libc-symbols.h +AM_CFLAGS = $(USER_CFLAGS) + +# Sources. +SYSDEPS := lockfile.c + +if ! ENABLE_TESTS +noinst_LIBRARIES = libpthread.a +endif + +libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \ + pt-attr-getguardsize.c pt-attr-getinheritsched.c \ + pt-attr-getschedparam.c pt-attr-getschedpolicy.c pt-attr-getscope.c \ + pt-attr-getstack.c pt-attr-getstackaddr.c pt-attr-getstacksize.c \ + pt-attr-init.c pt-attr-setdetachstate.c pt-attr-setguardsize.c \ + pt-attr-setinheritsched.c pt-attr-setschedparam.c \ + pt-attr-setschedpolicy.c pt-attr-setscope.c pt-attr-setstack.c \ + pt-attr-setstackaddr.c pt-attr-setstacksize.c pt-attr.c \ + pt-barrier-destroy.c pt-barrier-init.c pt-barrier-wait.c \ + pt-barrier.c pt-barrierattr-destroy.c pt-barrierattr-init.c \ + pt-barrierattr-getpshared.c pt-barrierattr-setpshared.c \ + pt-destroy-specific.c pt-init-specific.c \ + pt-key-create.c pt-key-delete.c \ + pt-getspecific.c pt-setspecific.c \ + pt-once.c \ + pt-alloc.c \ + pt-create.c \ + pt-getattr.c \ + pt-pool-np.c \ + pt-equal.c \ + pt-dealloc.c \ + pt-detach.c \ + pt-exit.c \ + pt-initialize.c \ + pt-join.c \ + pt-self.c \ + pt-sigmask.c \ + pt-spin-inlines.c \ + pt-cleanup.c \ + pt-setcancelstate.c \ + pt-setcanceltype.c \ + pt-testcancel.c \ + pt-cancel.c \ + pt-mutexattr.c \ + pt-mutexattr-destroy.c pt-mutexattr-init.c \ + pt-mutexattr-getprioceiling.c pt-mutexattr-getprotocol.c \ + pt-mutexattr-getpshared.c pt-mutexattr-gettype.c \ + pt-mutexattr-setprioceiling.c pt-mutexattr-setprotocol.c \ + pt-mutexattr-setpshared.c pt-mutexattr-settype.c \ + pt-mutex-init.c pt-mutex-destroy.c \ + pt-mutex-lock.c pt-mutex-trylock.c pt-mutex-timedlock.c \ + pt-mutex-unlock.c \ + pt-mutex-transfer-np.c \ + pt-mutex-getprioceiling.c pt-mutex-setprioceiling.c \ + pt-rwlock-attr.c \ + pt-rwlockattr-init.c pt-rwlockattr-destroy.c \ + pt-rwlockattr-getpshared.c pt-rwlockattr-setpshared.c \ + pt-rwlock-init.c pt-rwlock-destroy.c \ + pt-rwlock-rdlock.c pt-rwlock-tryrdlock.c \ + pt-rwlock-trywrlock.c pt-rwlock-wrlock.c \ + pt-rwlock-timedrdlock.c pt-rwlock-timedwrlock.c \ + pt-rwlock-unlock.c \ + pt-cond.c \ + pt-condattr-init.c pt-condattr-destroy.c \ + pt-condattr-getclock.c pt-condattr-getpshared.c \ + pt-condattr-setclock.c pt-condattr-setpshared.c \ + pt-cond-destroy.c pt-cond-init.c \ + pt-cond-brdcast.c \ + pt-cond-signal.c \ + pt-cond-wait.c \ + pt-cond-timedwait.c \ + pt-stack-alloc.c \ + pt-thread-alloc.c \ + pt-thread-dealloc.c \ + pt-thread-start.c \ + pt-thread-halt.c \ + pt-startup.c \ + pt-getconcurrency.c pt-setconcurrency.c \ + pt-block.c \ + pt-timedblock.c \ + pt-wakeup.c \ + pt-docancel.c \ + pt-sysdep.c \ + pt-setup.c \ + pt-machdep.c \ + pt-spin.c \ + pt-sigstate-init.c \ + pt-sigstate-destroy.c \ + pt-sigstate.c \ + pt-atfork.c \ + pt-kill.c \ + pt-getcpuclockid.c \ + pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \ + sem-close.c sem-init.c sem-timedwait.c sem-wait.c \ + sem-destroy.c sem-open.c sem-trywait.c sem-getvalue.c \ + sem-post.c sem-unlink.c \ + \ + pt-setactivity-np.c \ + \ + kill.c \ + killpg.c \ + pt-kill-siginfo-np.c \ + raise.c \ + sigaction.c \ + sigaddset.c \ + sigaltstack.c \ + sigdelset.c \ + sigemptyset.c \ + sigfillset.c \ + sig-internal.c \ + sig-internal.h \ + siginterrupt.c \ + sigismember.c \ + signal.c \ + signal-dispatch.c \ + signal.h \ + sigpending.c \ + sigprocmask.c \ + sigsuspend.c \ + sigtimedwait.c \ + sigwait.c \ + sigwaiter.c \ + sigwaitinfo.c \ + signal-dispatch-lowlevel.c \ + sigprocmask.c diff --git a/libpthread/TODO b/libpthread/TODO new file mode 100644 index 00000000..45b4cdc2 --- /dev/null +++ b/libpthread/TODO @@ -0,0 +1,174 @@ +-*- Mode: outline -*- + +* Interfaces +** All interfaces specified by IEEE Std 1003.1-2001 are present, however, + pthread_kill and pthread_sigmask are defined in and not + as they should be. Once we are compiled with glibc, + this should be eaiser. + +* Test cases. Can never have enough. + +* Ports + Port to other kernels (e.g. Linux and FreeBSD) and test on other + platforms. + +* Implementation details +** pthread_atfork + This cannot be implemented without either changing glibc to export + some hooks (c.f. libc/sysdeps/mach/hurd/fork.c) or by providing a + custom fork implementation that wraps the origial using dlopen et + al. + +** Scheduling and priorities + + We do not support scheduling right now in any way what so ever. + + This affects: + pthread_attr_getinheritsched + pthread_attr_setinheritsched + pthread_attr_getschedparam + pthread_attr_setschedparam + pthread_attr_getschedpolicy + pthread_attr_setschedpolicy + pthread_attr_getscope + pthread_attr_setscope + + pthread_mutexattr_getprioceiling + pthread_mutexattr_setprioceiling + pthread_mutexattr_getprotocol + pthread_mutexattr_setprotocol + pthread_mutex_getprioceiling + pthread_mutex_setprioceiling + + pthread_setschedprio + pthread_getschedparam + pthread_setschedparam + +** Alternate stacks + + Supporting alternate stacks (via pthread_attr_getstackaddr, + pthread_attr_setstackaddr, pthread_attr_getstack, + pthread_attr_setstack, pthread_attr_getstacksize and + pthread_attr_setstacksize) is no problem as long as they are of the + correct size and have the correct alignment. This is due to + limitations in the Hurd TSD implementation + (c.f. ). + +** Cancelation +*** Cancelation points + The only cancelation points are pthread_join, pthread_cond_wait, + pthead_cond_timedwait and pthread_testcancel. Need to explore if + the hurd_sigstate->cancel_hook (c.f. ) provides the + desired semantics. If not, must either wrap the some functions + using dlsym or wait until integration with glibc. +*** Async cancelation + We inject a new IP into the cancelled (running) thread and then + run the cancelation handlers + (c.f. sysdeps/mach/hurd/pt-docancel.c). The handlers need to have + access to the stack as they may use local variables. I think that + this method may leave the frame pointer in a corrupted state if + the thread was in, for instance, the middle of a function call. + The robustness needs to be confirmed. + +** Process Shared Attribute + + Currently, there is no real support for the process shared + attribute. spinlocks work because we just use a test and set loop, + however, barriers, conditions mutexes and rwlocks, however, signal + wakeups via ports of which the names are process local. + + We could have some process local data that is hashed to via the + address of the data structure. Then the first thread that blocks + per process would spin on the shared memory area and all others + would then block as normal. When the resource became available, + the first thread would signal the other local threads as necessary. + Alternatively, there could be some server, however, this opens a + new question: what can we use as an authentication agent. + +** Locking algorithm + + When a thread blocks, it puts itself on a queue and then waits for + a message on a thread local port. The thread which eventually does + the wakeup sends a message to the waiter thereby waking it up. If + the wakeup is a broadcast wakeup (e.g. pthread_cond_broadcast, + pthread_barrier_wait and pthread_rdlock_unlock), the thread must + send O(N) messages where N is the number of waiting threads. If + all the threads instead received on a lock local (rather than + thread local) port then the thread which eventually does the wake + need just do one operation, mach_port_destroy and all of the + waiting threads would wakeup and get MACH_RCV_PORT_DIED back from + mach_msg. Note that the trade off is that the port must be + recreated. This needs to be benchmarked. + + A possible problem with this is scheduling priorities. There may + be a preference for certain threads to wakeup before others + (especially if we are not doing a broadcast, for instance, + pthread_mutex_unlock and pthread_cond_signal). If we take this + approach, the kernel chooses which threads are awakened. If we + find that the kernel makes the wrong choices, we can still overcome + this by merging the two algorithms: have a list of ports sorted in + priority order and the waker does a mach_port_destroy on each as + appropriate. + +** Barriers + + Barriers can be very slow and the contention can be very high. The + above algorithm is very appealing, however, this may be augmented + with an initial number of spins and yields. It is expected that + all of the threads reach the barrier within close succession, thus + queuing a message may be more expensive. This needs to be + benchmarked. + +** Clocks +*** pthread_condattr_setclock allows a process to specify a clock for + use with pthread_cond_timedwaits. What is the correct default for + this, right now, we use CLOCK_REALTIME, however, we are really + using the system clock which, if I understand correctly, is + completely different. +*** Could we even use other clocks? mach_msg uses a relative time against + the system clock. +*** pthread_getcpuclockid just returns CLOCK_THREAD_CPUTIME_ID if defined. + Is this the correct behavior? + +** Timed Blocking +*** pthread_cond_timedwait, pthead_mutex_timedlock, pthread_rwlock_timedrdlock + and pthread_rwlock_timedwrlock all take absolute times. We need + to convert them to relative times for mach_msg. Is there a way + around this? How will clock skew affect us? + +** weak aliases + Use them consistently and correctly and start by reading + http://sources.redhat.com/ml/libc-alpha/2002-08/msg00278.html. + +* L4 Specific Issues +** Stack +*** Size + The stack size is defined to be a single page in + sysdeps/l4/hurd/pt-sysdep.h. Once we are able to setup regions, + this can be expanded to two megs as suggested by the Mach version. + Until then, however, we need to allocate too much physical memory. +*** Deallocation + __thread_stack_dealloc currently does not deallocate the stack. + For a proper implementation, we need a working memory manager. + +** Scheduling +*** yield + [L4] We cannot use yield for spin locks as L4 only yields to threads of + priority which are greater than or equal to the yielding thread. + If there are threads of lower priority, they are not considered; + the yielding thread is just placed back on the processor. This + introduces priority inversion quite quickly. L4 will not add a + priority suppression function call. As such, we need to do + an ipc with a small time out and then use exponential back off to + do the actual waiting. This sucks. + +** Stub code + [L4] We include in pt-start.c, however, we need a library + so we do not have to play with the corba stuff. + +** Root server and Task server +*** Getting the tids. + pt-start.c has a wonderfully evil hack that will never work well. + +** Paging + We set the pager to the root server. Evil. Fix this in pt-start.c. diff --git a/libpthread/headers.m4 b/libpthread/headers.m4 new file mode 100644 index 00000000..5a58b9bf --- /dev/null +++ b/libpthread/headers.m4 @@ -0,0 +1,45 @@ +# headers.m4 - Autoconf snippets to install links for header files. +# Copyright 2003, 2008 Free Software Foundation, Inc. +# Written by Marcus Brinkmann . +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +AC_CONFIG_LINKS([ + sysroot/include/pthread.h:libpthread/include/pthread.h + sysroot/include/pthread/pthread.h:libpthread/include/pthread/pthread.h + sysroot/include/pthread/pthreadtypes.h:libpthread/include/pthread/pthreadtypes.h + sysroot/include/bits/memory.h:libpthread/sysdeps/${arch}/bits/memory.h + sysroot/include/bits/spin-lock.h:libpthread/sysdeps/${arch}/bits/spin-lock.h + sysroot/include/bits/spin-lock-inline.h:libpthread/sysdeps/${arch}/bits/spin-lock-inline.h + sysroot/include/bits/pthreadtypes.h:libpthread/sysdeps/generic/bits/pthreadtypes.h + sysroot/include/bits/barrier-attr.h:libpthread/sysdeps/generic/bits/barrier-attr.h + sysroot/include/bits/barrier.h:libpthread/sysdeps/generic/bits/barrier.h + sysroot/include/bits/cancelation.h:libpthread/sysdeps/generic/bits/cancelation.h + sysroot/include/bits/condition-attr.h:libpthread/sysdeps/generic/bits/condition-attr.h + sysroot/include/bits/condition.h:libpthread/sysdeps/generic/bits/condition.h + sysroot/include/bits/mutex-attr.h:libpthread/sysdeps/generic/bits/mutex-attr.h + sysroot/include/bits/mutex.h:libpthread/sysdeps/generic/bits/mutex.h + sysroot/include/bits/once.h:libpthread/sysdeps/generic/bits/once.h + sysroot/include/bits/pthread.h:libpthread/sysdeps/generic/bits/pthread.h + sysroot/include/bits/rwlock-attr.h:libpthread/sysdeps/generic/bits/rwlock-attr.h + sysroot/include/bits/rwlock.h:libpthread/sysdeps/generic/bits/rwlock.h + sysroot/include/bits/thread-attr.h:libpthread/sysdeps/generic/bits/thread-attr.h + sysroot/include/bits/thread-barrier.h:libpthread/sysdeps/generic/bits/thread-barrier.h + sysroot/include/bits/thread-specific.h:libpthread/sysdeps/generic/bits/thread-specific.h + sysroot/include/bits/pthread-np.h:libpthread/sysdeps/l4/hurd/bits/pthread-np.h + sysroot/include/semaphore.h:libpthread/include/semaphore.h + sysroot/include/bits/semaphore.h:libpthread/sysdeps/generic/bits/semaphore.h + sysroot/include/signal.h:libpthread/signal/signal.h +]) + +AC_CONFIG_COMMANDS_POST([ + mkdir -p sysroot/lib libpthread && + ln -sf ../../libpthread/libpthread.a sysroot/lib/ && + touch libpthread/libpthread.a +]) diff --git a/libpthread/include/libc-symbols.h b/libpthread/include/libc-symbols.h new file mode 100644 index 00000000..54dd6e26 --- /dev/null +++ b/libpthread/include/libc-symbols.h @@ -0,0 +1,395 @@ +/* Support macros for making weak and strong aliases for symbols, + and for using symbol sets and linker warnings with GNU ld. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2008 + 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. */ + +#ifndef _LIBC_SYMBOLS_H +#define _LIBC_SYMBOLS_H 1 + +/* This file's macros are included implicitly in the compilation of every + file in the C library by -imacros. + + We include config.h which is generated by configure. + It should define for us the following symbols: + + * HAVE_ASM_SET_DIRECTIVE if we have `.set B, A' instead of `A = B'. + * ASM_GLOBAL_DIRECTIVE with `.globl' or `.global'. + * HAVE_GNU_LD if using GNU ld, with support for weak symbols in a.out, + and for symbol set and warning messages extensions in a.out and ELF. + * HAVE_ELF if using ELF, which supports weak symbols using `.weak'. + * HAVE_ASM_WEAK_DIRECTIVE if we have weak symbols using `.weak'. + * HAVE_ASM_WEAKEXT_DIRECTIVE if we have weak symbols using `.weakext'. + + */ + +/* This is defined for the compilation of all C library code. features.h + tests this to avoid inclusion of stubs.h while compiling the library, + before stubs.h has been generated. Some library code that is shared + with other packages also tests this symbol to see if it is being + compiled as part of the C library. We must define this before including + config.h, because it makes some definitions conditional on whether libc + itself is being compiled, or just some generator program. */ +// #define _LIBC 1 + +/* Enable declarations of GNU extensions, since we are compiling them. */ +#define _GNU_SOURCE 1 +/* And we also need the data for the reentrant functions. */ +#define _REENTRANT 1 + +// #include +#define HAVE_ASM_WEAK_DIRECTIVE +#define HAVE_WEAK_SYMBOLS +#define HAVE_ASM_SET_DIRECTIVE +#define HAVE_BUILTIN_EXPECT +#define HAVE_GNU_LD +#define HAVE_ELF +#define HAVE_SECTION_QUOTES +#define HAVE_VISIBILITY_ATTRIBUTE +#define HAVE_ASM_PREVIOUS_DIRECTIVE +// #define SHARED + +/* The symbols in all the user (non-_) macros are C symbols. + HAVE_GNU_LD without HAVE_ELF implies a.out. */ + +#if defined HAVE_ASM_WEAK_DIRECTIVE || defined HAVE_ASM_WEAKEXT_DIRECTIVE +# define HAVE_WEAK_SYMBOLS +#endif + +#ifndef __SYMBOL_PREFIX +# ifdef NO_UNDERSCORES +# define __SYMBOL_PREFIX +# else +# define __SYMBOL_PREFIX "_" +# endif +#endif + +#ifndef C_SYMBOL_NAME +# ifdef NO_UNDERSCORES +# define C_SYMBOL_NAME(name) name +# else +# define C_SYMBOL_NAME(name) _##name +# endif +#endif + +#ifndef ASM_LINE_SEP +# define ASM_LINE_SEP ; +#endif + +#ifndef C_SYMBOL_DOT_NAME +# define C_SYMBOL_DOT_NAME(name) .##name +#endif + +#ifndef __ASSEMBLER__ +/* GCC understands weak symbols and aliases; use its interface where + possible, instead of embedded assembly language. */ + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +/* This comes between the return type and function name in + a function definition to make that definition weak. */ +# define weak_function __attribute__ ((weak)) +# define weak_const_function __attribute__ ((weak, __const__)) + +# ifdef HAVE_WEAK_SYMBOLS + +/* Define ALIASNAME as a weak alias for NAME. + If weak aliases are not available, this defines a strong alias. */ +# define weak_alias(name, aliasname) _weak_alias (name, aliasname) +# define _weak_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); + +/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */ +# define weak_extern(symbol) _weak_extern (symbol) +# ifdef HAVE_ASM_WEAKEXT_DIRECTIVE +# define _weak_extern(symbol) asm (".weakext " __SYMBOL_PREFIX #symbol); +# else +# define _weak_extern(symbol) asm (".weak " __SYMBOL_PREFIX #symbol); +# endif + +# else + +# define weak_alias(name, aliasname) strong_alias(name, aliasname) +# define weak_extern(symbol) /* Nothing. */ + +# endif + +#else /* __ASSEMBLER__ */ + +# ifdef HAVE_ASM_SET_DIRECTIVE +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) +# else +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original) +# else +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# endif +# endif + +# ifdef HAVE_WEAK_SYMBOLS +# ifdef HAVE_ASM_WEAKEXT_DIRECTIVE +# define weak_alias(original, alias) \ + .weakext C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original) +# define weak_extern(symbol) \ + .weakext C_SYMBOL_NAME (symbol) + +# else /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original) +# else +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# endif + +# define weak_extern(symbol) \ + .weak C_SYMBOL_NAME (symbol) + +# endif /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# else /* ! HAVE_WEAK_SYMBOLS */ + +# define weak_alias(original, alias) strong_alias(original, alias) +# define weak_extern(symbol) /* Nothing */ +# endif /* ! HAVE_WEAK_SYMBOLS */ + +#endif /* __ASSEMBLER__ */ + +/* On some platforms we can make internal function calls (i.e., calls of + functions not exported) a bit faster by using a different calling + convention. */ +#ifndef internal_function +# define internal_function /* empty */ +#endif + +/* Prepare for the case that `__builtin_expect' is not available. */ +#ifndef HAVE_BUILTIN_EXPECT +# define __builtin_expect(expr, val) (expr) +#endif + +/* Determine the return address. */ +#define RETURN_ADDRESS(nr) \ + __builtin_extract_return_addr (__builtin_return_address (nr)) + +/* When a reference to SYMBOL is encountered, the linker will emit a + warning message MSG. */ +#ifdef HAVE_GNU_LD +# ifdef HAVE_ELF + +/* We want the .gnu.warning.SYMBOL section to be unallocated. */ +# ifdef HAVE_ASM_PREVIOUS_DIRECTIVE +# define __make_section_unallocated(section_string) \ + asm (".section " section_string "\n\t.previous"); +# elif defined HAVE_ASM_POPSECTION_DIRECTIVE +# define __make_section_unallocated(section_string) \ + asm (".pushsection " section_string "\n\t.popsection"); +# else +# define __make_section_unallocated(section_string) +# endif + +/* Tacking on "\n\t#" to the section name makes gcc put it's bogus + section attributes on what looks like a comment to the assembler. */ +# ifdef HAVE_SECTION_QUOTES +# define link_warning(symbol, msg) \ + __make_section_unallocated (".gnu.warning." #symbol) \ + static const char __evoke_link_warning_##symbol[] \ + __attribute__ ((unused, section (".gnu.warning." #symbol "\"\n\t#\""))) \ + = msg; +# else +# define link_warning(symbol, msg) \ + __make_section_unallocated (".gnu.warning." #symbol) \ + static const char __evoke_link_warning_##symbol[] \ + __attribute__ ((unused, section (".gnu.warning." #symbol "\n\t#"))) = msg; +# endif +# else /* Not ELF: a.out */ +# ifdef HAVE_XCOFF +/* XCOFF does not support .stabs. + The native aix linker will remove the .stab and .stabstr sections + The gnu linker will have a fatal error if there is a relocation for + symbol in the .stab section. Silently disable this macro. */ +# define link_warning(symbol, msg) +# else +# define link_warning(symbol, msg) \ + asm (".stabs \"" msg "\",30,0,0,0\n\t" \ + ".stabs \"" __SYMBOL_PREFIX #symbol "\",1,0,0,0\n"); +# endif /* XCOFF */ +# endif +#else +/* We will never be heard; they will all die horribly. */ +# define link_warning(symbol, msg) +#endif + +/* A canned warning for sysdeps/stub functions. */ +#define stub_warning(name) \ + link_warning (name, \ + "warning: " #name " is not implemented and will always fail") + +/* + +*/ + +#ifdef HAVE_GNU_LD + +/* Symbol set support macros. */ + +# ifdef HAVE_ELF + +/* Make SYMBOL, which is in the text segment, an element of SET. */ +# define text_set_element(set, symbol) _elf_set_element(set, symbol) +/* Make SYMBOL, which is in the data segment, an element of SET. */ +# define data_set_element(set, symbol) _elf_set_element(set, symbol) +/* Make SYMBOL, which is in the bss segment, an element of SET. */ +# define bss_set_element(set, symbol) _elf_set_element(set, symbol) + +/* These are all done the same way in ELF. + There is a new section created for each set. */ +# ifdef SHARED +/* When building a shared library, make the set section writable, + because it will need to be relocated at run time anyway. */ +# define _elf_set_element(set, symbol) \ + static const void *__elf_set_##set##_element_##symbol##__ \ + __attribute__ ((unused, section (#set))) = &(symbol) +# else +# define _elf_set_element(set, symbol) \ + static const void *const __elf_set_##set##_element_##symbol##__ \ + __attribute__ ((unused, section (#set))) = &(symbol) +# endif + +/* Define SET as a symbol set. This may be required (it is in a.out) to + be able to use the set's contents. */ +# define symbol_set_define(set) symbol_set_declare(set) + +/* Declare SET for use in this module, if defined in another module. */ +# define symbol_set_declare(set) \ + extern void *const __start_##set __attribute__ ((__weak__)); \ + extern void *const __stop_##set __attribute__ ((__weak__)); \ + weak_extern (__start_##set) weak_extern (__stop_##set) + +/* Return a pointer (void *const *) to the first element of SET. */ +# define symbol_set_first_element(set) (&__start_##set) + +/* Return true iff PTR (a void *const *) has been incremented + past the last element in SET. */ +# define symbol_set_end_p(set, ptr) ((ptr) >= &__stop_##set) + +# else /* Not ELF: a.out. */ + +# ifdef HAVE_XCOFF +/* XCOFF does not support .stabs. + The native aix linker will remove the .stab and .stabstr sections + The gnu linker will have a fatal error if there is a relocation for + symbol in the .stab section. Silently disable these macros. */ +# define text_set_element(set, symbol) +# define data_set_element(set, symbol) +# define bss_set_element(set, symbol) +# else +# define text_set_element(set, symbol) \ + asm (".stabs \"" __SYMBOL_PREFIX #set "\",23,0,0," __SYMBOL_PREFIX #symbol) +# define data_set_element(set, symbol) \ + asm (".stabs \"" __SYMBOL_PREFIX #set "\",25,0,0," __SYMBOL_PREFIX #symbol) +# define bss_set_element(set, symbol) ?error Must use initialized data. +# endif /* XCOFF */ +# define symbol_set_define(set) void *const (set)[1]; +# define symbol_set_declare(set) extern void *const (set)[1]; + +# define symbol_set_first_element(set) &(set)[1] +# define symbol_set_end_p(set, ptr) (*(ptr) == 0) + +# endif /* ELF. */ +#else +/* We cannot do anything in generial. */ +# define text_set_element(set, symbol) asm ("") +# define data_set_element(set, symbol) asm ("") +# define bss_set_element(set, symbol) asm ("") +# define symbol_set_define(set) void *const (set)[1]; +# define symbol_set_declare(set) extern void *const (set)[1]; + +# define symbol_set_first_element(set) &(set)[1] +# define symbol_set_end_p(set, ptr) (*(ptr) == 0) +#endif /* Have GNU ld. */ + +#if DO_VERSIONING +# define symbol_version(real, name, version) \ + _symbol_version(real, name, version) +# define default_symbol_version(real, name, version) \ + _default_symbol_version(real, name, version) +# ifdef __ASSEMBLER__ +# define _symbol_version(real, name, version) \ + .symver real, name##@##version +# define _default_symbol_version(real, name, version) \ + .symver real, name##@##@##version +# else +# define _symbol_version(real, name, version) \ + __asm__ (".symver " #real "," #name "@" #version) +# define _default_symbol_version(real, name, version) \ + __asm__ (".symver " #real "," #name "@@" #version) +# endif +#else +# define symbol_version(real, name, version) +# define default_symbol_version(real, name, version) \ + strong_alias(real, name) +#endif + +#if defined HAVE_VISIBILITY_ATTRIBUTE && defined SHARED +# define attribute_hidden __attribute__ ((visibility ("hidden"))) +#else +# define attribute_hidden +#endif + +/* Handling on non-exported internal names. We have to do this only + for shared code. */ +#ifdef SHARED +# define INTUSE(name) name##_internal +# define INTDEF(name) strong_alias (name, name##_internal) +# define INTVARDEF(name) \ + _INTVARDEF (name, name##_internal) +# if defined HAVE_VISIBILITY_ATTRIBUTE +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name), \ + visibility ("hidden"))); +# else +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +# endif +# define INTDEF2(name, newname) strong_alias (name, newname##_internal) +# define INTVARDEF2(name, newname) _INTVARDEF (name, newname##_internal) +#else +# define INTUSE(name) name +# define INTDEF(name) +# define INTVARDEF(name) +# define INTDEF2(name, newname) +# define INTVARDEF2(name, newname) +#endif + +#endif /* libc-symbols.h */ diff --git a/libpthread/include/pthread.h b/libpthread/include/pthread.h new file mode 100644 index 00000000..1d4d3c7b --- /dev/null +++ b/libpthread/include/pthread.h @@ -0,0 +1,7 @@ +#ifndef _PTHREAD_H +#include + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +#endif diff --git a/libpthread/include/pthread/pthread.h b/libpthread/include/pthread/pthread.h new file mode 100644 index 00000000..dedb09d4 --- /dev/null +++ b/libpthread/include/pthread/pthread.h @@ -0,0 +1,744 @@ +/* Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008, 2009 + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * POSIX Threads Extension: ??? + */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include + +#include +#ifndef __extern_inline +/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. */ +# if !defined __cplusplus || __GNUC_PREREQ (4,3) +# if defined __GNUC_STDC_INLINE__ || defined __cplusplus +# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) +# if __GNUC_PREREQ (4,3) +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__, __artificial__)) +# else +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__)) +# endif +# else +# define __extern_inline extern __inline +# define __extern_always_inline extern __always_inline +# endif +# endif +#endif + +#include + +__BEGIN_DECLS + +#include + +#include + +/* Possible values for the process shared attribute. */ +#define PTHREAD_PROCESS_PRIVATE __PTHREAD_PROCESS_PRIVATE +#define PTHREAD_PROCESS_SHARED __PTHREAD_PROCESS_SHARED + + +/* Thread attributes. */ + +/* Possible values for the inheritsched attribute. */ +#define PTHREAD_EXPLICIT_SCHED __PTHREAD_EXPLICIT_SCHED +#define PTHREAD_INHERIT_SCHED __PTHREAD_INHERIT_SCHED + +/* Possible values for the `contentionscope' attribute. */ +#define PTHREAD_SCOPE_SYSTEM __PTHREAD_SCOPE_SYSTEM +#define PTHREAD_SCOPE_PROCESS __PTHREAD_SCOPE_PROCESS + +/* Possible values for the `detachstate' attribute. */ +#define PTHREAD_CREATE_JOINABLE __PTHREAD_CREATE_JOINABLE +#define PTHREAD_CREATE_DETACHED __PTHREAD_CREATE_DETACHED + +#include + +/* Initialize the thread attribute object in *ATTR to the default + values. */ +extern int pthread_attr_init (pthread_attr_t *attr); + +/* Destroy the thread attribute object in *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *attr); + + +/* Return the value of the inheritsched attribute in *ATTR in + *INHERITSCHED. */ +extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict attr, + int *__restrict inheritsched); + +/* Set the value of the inheritsched attribute in *ATTR to + INHERITSCHED. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *attr, + int inheritsched); + + +/* Return the value of the schedparam attribute in *ATTR in *PARAM. */ +extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict attr, + struct sched_param *__restrict param); + +/* Set the value of the schedparam attribute in *ATTR to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict attr, + const struct sched_param *__restrict param); + + +/* Return the value of the schedpolicy attribute in *ATTR to *POLICY. */ +extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict attr, + int *__restrict policy); + +/* Set the value of the schedpolicy attribute in *ATTR to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *attr, + int policy); + + +/* Return the value of the contentionscope attribute in *ATTR in + *CONTENTIONSCOPE. */ +extern int pthread_attr_getscope (const pthread_attr_t *__restrict attr, + int *__restrict contentionscope); + +/* Set the value of the contentionscope attribute in *ATTR to + CONTENTIONSCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *attr, + int contentionscope); + + +/* Return the value of the stackaddr attribute in *ATTR in + *STACKADDR. */ +extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict attr, + void **__restrict stackaddr); + +/* Set the value of the stackaddr attribute in *ATTR to STACKADDR. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr); + + +#ifdef __USE_XOPEN2K +/* Return the value of the stackaddr and stacksize attributes in *ATTR + in *STACKADDR and *STACKSIZE respectively. */ +extern int pthread_attr_getstack (const pthread_attr_t *__restrict attr, + void **__restrict stackaddr, + size_t *__restrict stacksize); + +/* Set the value of the stackaddr and stacksize attributes in *ATTR to + STACKADDR and STACKSIZE respectively. */ +extern int pthread_attr_setstack (pthread_attr_t *attr, + void *stackaddr, + size_t stacksize); +#endif + + +/* Return the value of the detachstate attribute in *ATTR in + *DETACHSTATE. */ +extern int pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); + +/* Set the value of the detachstate attribute in *ATTR to + DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); + + +/* Return the value of the guardsize attribute in *ATTR in + *GUARDSIZE. */ +extern int pthread_attr_getguardsize (const pthread_attr_t *__restrict attr, + size_t *__restrict guardsize); + +/* Set the value of the guardsize attribute in *ATTR to GUARDSIZE. */ +extern int pthread_attr_setguardsize (pthread_attr_t *attr, + size_t guardsize); + + +/* Return the value of the stacksize attribute in *ATTR in + *STACKSIZE. */ +extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict attr, + size_t *__restrict stacksize); + +/* Set the value of the stacksize attribute in *ATTR to STACKSIZE. */ +extern int pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize); + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread THREAD. It shall be called on an uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr); +#endif + + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine)(void *), + void *__restrict __arg); + +/* Terminate the current thread and make STATUS available to any + thread that might join us. */ +extern void pthread_exit (void *__status) __attribute__ ((noreturn)); + +/* Make calling thread wait for termination of thread THREAD. Return + the exit status of the thread in *STATUS. */ +extern int pthread_join (pthread_t __threadp, void **__status); + +/* Indicate that the storage for THREAD can be reclaimed when it + terminates. */ +extern int pthread_detach (pthread_t __threadp); + +/* Compare thread IDs T1 and T2. Return nonzero if they are equal, 0 + if they are not. */ +extern int pthread_equal (pthread_t __t1, pthread_t __t2); + +# ifdef __USE_EXTERN_INLINES + +__extern_inline int +pthread_equal (pthread_t __t1, pthread_t __t2) +{ + return __pthread_equal (__t1, __t2); +} + +# endif /* Use extern inlines. */ + + +/* Return the thread ID of the calling thread. */ +extern pthread_t pthread_self (void); + + +/* Mutex attributes. */ + +#define PTHREAD_PRIO_NONE_NP __PTHREAD_PRIO_NONE +#define PTHREAD_PRIO_INHERIT_NP __PTHREAD_PRIO_INHERIT +#define PTHREAD_PRIO_PROTECT_NP __PTHREAD_PRIO_PROTECT +#ifdef __USE_UNIX98 +#define PTHREAD_PRIO_NONE PTHREAD_PRIO_NONE_NP +#define PTHREAD_PRIO_INHERIT PTHREAD_PRIO_INHERIT_NP +#define PTHREAD_PRIO_PROTECT PTHREAD_PRIO_PROTECT_NP +#endif + +#define PTHREAD_MUTEX_TIMED_NP __PTHREAD_MUTEX_TIMED +#define PTHREAD_MUTEX_ERRORCHECK_NP __PTHREAD_MUTEX_ERRORCHECK +#define PTHREAD_MUTEX_RECURSIVE_NP __PTHREAD_MUTEX_RECURSIVE +#ifdef __USE_UNIX98 +#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_TIMED_NP +#define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU +/* For compatibility. */ +#define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_TIMED_NP +#endif + +#include + +/* Initialize the mutex attribute object in *ATTR to the default + values. */ +extern int pthread_mutexattr_init(pthread_mutexattr_t *attr); + +/* Destroy the mutex attribute structure in *ATTR. */ +extern int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); + + +#ifdef __USE_UNIX98 +/* Return the value of the prioceiling attribute in *ATTR in + *PRIOCEILING. */ +extern int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict attr, + int *__restrict prioceiling); + +/* Set the value of the prioceiling attribute in *ATTR to + PRIOCEILING. */ +extern int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, + int prioceiling); + + +/* Return the value of the protocol attribute in *ATTR in + *PROTOCOL. */ +extern int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict attr, + int *__restrict protocol); + +/* Set the value of the protocol attribute in *ATTR to PROTOCOL. */ +extern int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, + int protocol); +#endif + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared attribute in *ATTR to + PSHARED. */ +extern int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, + int pshared); + + +#ifdef __USE_UNIX98 +/* Return the value of the type attribute in *ATTR in *TYPE. */ +extern int pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict attr, + int *__restrict type); + +/* Set the value of the type attribute in *ATTR to TYPE. */ +extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, + int type); +#endif + + +/* Mutexes. */ + +#include + +#define PTHREAD_MUTEX_INITIALIZER __PTHREAD_MUTEX_INITIALIZER +/* Static initializer for recursive mutexes. */ + +#ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + __PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#endif + +/* Create a mutex with attributes given by ATTR and store it in + *__MUTEX. */ +extern int pthread_mutex_init (struct __pthread_mutex *__restrict __mutex, + const pthread_mutexattr_t *__restrict attr); + +/* Destroy the mutex __MUTEX. */ +extern int pthread_mutex_destroy (struct __pthread_mutex *__mutex); + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex); + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex); + +#ifdef __USE_XOPEN2K +/* Try to lock MUTEX, block until *ABSTIME if it is already held. */ +extern int pthread_mutex_timedlock (struct __pthread_mutex *__restrict mutex, + const struct timespec *__restrict abstime); +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex); + +/* Transfer ownership of the mutex MUTEX to the thread TID. The + caller must own the lock. */ +extern int __pthread_mutex_transfer_np (struct __pthread_mutex *mutex, + pthread_t tid); + + +#ifdef __USE_UNIX98 +/* Return the priority ceiling of mutex *MUTEX in *PRIOCEILING. */ +extern int pthread_mutex_getprioceiling (const pthread_mutex_t *__restrict mutex, + int *__restrict prioceiling); + +/* After acquiring the mutex *MUTEX, set its priority ceiling to PRIO + and return the old priority ceiling in *OLDPRIO. Before returning, + release the mutex. */ +extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict mutex, + int prio, int *__restrict oldprio); +#endif + + + +/* Condition attributes. */ + +#include + +/* Initialize the condition attribute in *ATTR to the default + values. */ +extern int pthread_condattr_init (pthread_condattr_t *attr); + +/* Destroy the condition attribute structure in *ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *attr); + + +#ifdef __USE_XOPEN2K +/* Return the value of the clock attribute in *ATTR in *CLOCK_ID. */ +extern int pthread_condattr_getclock (const pthread_condattr_t *__restrict attr, + clockid_t *__restrict clock_id); + +/* Set the value of the clock attribute in *ATTR to CLOCK_ID. */ +extern int pthread_condattr_setclock (pthread_condattr_t *attr, + clockid_t clock_id); +#endif + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_condattr_getpshared (const pthread_condattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared attribute in *ATTR to + PSHARED. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *attr, + int pshared); + + +/* Condition variables. */ + +#include + +#define PTHREAD_COND_INITIALIZER __PTHREAD_COND_INITIALIZER + +extern int pthread_cond_init (pthread_cond_t *__restrict cond, + const pthread_condattr_t *__restrict attr); + +extern int pthread_cond_destroy (pthread_cond_t *cond); + +/* Unblock at least one of the threads that are blocked on condition + variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond); + +/* Unblock all threads that are blocked on condition variable COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond); + +/* Block on condition variable COND. MUTEX should be held by the + calling thread. On success, MUTEX will be held by the calling + thread. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Block on condition variable COND. MUTEX should be held by the + calling thread. On success, MUTEX will be held by the calling + thread. If the time specified by ABSTIME passes, ETIMEDOUT is + returned, and MUTEX will nevertheless be held. */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict __abstime); + + +/* Spin locks. */ + +#ifdef __USE_XOPEN2K + +# include + +#define PTHREAD_SPINLOCK_INITIALIZER __PTHREAD_SPIN_LOCK_INITIALIZER + +/* Destroy the spin lock object LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock); + +/* Initialize the spin lock object LOCK. PSHARED determines whether + the spin lock can be operated upon by multiple processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared); + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock); + +/* Lock the spin lock object LOCK. Fail if the lock is held by + another thread. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock); + +/* Unlock the spin lock object LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock); + +# ifdef __USE_EXTERN_INLINES + +# include + +__extern_inline int +pthread_spin_destroy (pthread_spinlock_t *__lock) +{ + return __pthread_spin_destroy (__lock); +} + +__extern_inline int +pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) +{ + return __pthread_spin_init (__lock, __pshared); +} + +__extern_inline int +pthread_spin_lock (pthread_spinlock_t *__lock) +{ + return __pthread_spin_lock (__lock); +} + +__extern_inline int +pthread_spin_trylock (pthread_spinlock_t *__lock) +{ + return __pthread_spin_trylock (__lock); +} + +__extern_inline int +pthread_spin_unlock (pthread_spinlock_t *__lock) +{ + return __pthread_spin_unlock (__lock); +} + +# endif /* Use extern inlines. */ + +#endif /* XPG6. */ + + +/* rwlock attributes. */ + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K + +#include + +/* Initialize rwlock attribute object in *ATTR to the default + values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *attr); + +/* Destroy the rwlock attribute object in *ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr); + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared atrribute in *ATTR to + PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, + int pshared); + + +/* rwlocks. */ + +#include + +#define PTHREAD_RWLOCK_INITIALIZER __PTHREAD_RWLOCK_INITIALIZER +/* Create a rwlock object with attributes given by ATTR and strore the + result in *RWLOCK. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict rwlock, + const pthread_rwlockattr_t *__restrict attr); + +/* Destroy the rwlock *RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *rwlock); + +/* Acquire the rwlock *RWLOCK for reading. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock); + +/* Acquire the rwlock *RWLOCK for reading. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock); + +# ifdef __USE_XOPEN2K +/* Acquire the rwlock *RWLOCK for reading blocking until *ABSTIME if + it is already held. */ +extern int pthread_rwlock_timedrdlock (struct __pthread_rwlock *__restrict rwlock, + const struct timespec *__restrict abstime); +# endif + +/* Acquire the rwlock *RWLOCK for writing. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock); + +/* Try to acquire the rwlock *RWLOCK for writing. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock); + +# ifdef __USE_XOPEN2K +/* Acquire the rwlock *RWLOCK for writing blocking until *ABSTIME if + it is already held. */ +extern int pthread_rwlock_timedwrlock (struct __pthread_rwlock *__restrict rwlock, + const struct timespec *__restrict abstime); +# endif + +/* Release the lock held by the current thread on *RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *rwlock); + +#endif /* __USE_UNIX98 || __USE_XOPEN2K */ + + + +/* Cancelation. */ + +/* Register a cleanup handler. */ +extern void pthread_cleanup_push (void (*routine) (void *), void *arg); + +/* Unregister a cleanup handler. */ +extern void pthread_cleanup_pop (int execute); + +#include + +#define pthread_cleanup_push(rt, rtarg) __pthread_cleanup_push(rt, rtarg) +#define pthread_cleanup_pop(execute) __pthread_cleanup_pop(execute) + +#define PTHREAD_CANCEL_DISABLE 0 +#define PTHREAD_CANCEL_ENABLE 1 + +/* Return the calling thread's cancelation state in *OLDSTATE and set + its state to STATE. */ +extern int pthread_setcancelstate (int state, int *oldstate); + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +/* Return the calling thread's cancelation type in *OLDTYPE and set + its type to TYPE. */ +extern int pthread_setcanceltype (int type, int *oldtype); + +/* Value returned by pthread_join if the target thread was + canceled. */ +#define PTHREAD_CANCELED ((void *) -1) + +/* Cancel THEAD. */ +extern int pthread_cancel (pthread_t thread); + +/* Add an explicit cancelation point. */ +extern void pthread_testcancel (void); + + +/* Barriers attributes. */ + +#ifdef __USE_XOPEN2K + +#include + +/* Initialize barrier attribute object in *ATTR to the default + values. */ +extern int pthread_barrierattr_init (pthread_barrierattr_t *attr); + +/* Destroy the barrier attribute object in *ATTR. */ +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *attr); + + +/* Return the value of the process shared attribute in *ATTR in + *PSHARED. */ +extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t *__restrict attr, + int *__restrict pshared); + +/* Set the value of the process shared atrribute in *ATTR to + PSHARED. */ +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, + int pshared); + + +/* Barriers. */ + +#include + +/* Returned by pthread_barrier_wait to exactly one thread each time a + barrier is passed. */ +#define PTHREAD_BARRIER_SERIAL_THREAD -1 + +/* Initialize barrier BARRIER. */ +extern int pthread_barrier_init (pthread_barrier_t *__restrict barrier, + const pthread_barrierattr_t *__restrict attr, + unsigned count); + +/* Destroy barrier BARRIER. */ +extern int pthread_barrier_destroy (pthread_barrier_t *barrier); + +/* Wait on barrier BARRIER. */ +extern int pthread_barrier_wait (pthread_barrier_t *barrier); + +#endif /* __USE_XOPEN2K */ + + + +/* Thread specific data. */ + +#include + +/* Create a thread specific data key in KEY visible to all threads. + On thread destruction, DESTRUCTOR shall be called with the thread + specific data associate with KEY if it is not NULL. */ +extern int pthread_key_create (pthread_key_t *key, + void (*destructor) (void *)); + +/* Delete the thread specific data key KEY. The associated destructor + function is not called. */ +extern int pthread_key_delete (pthread_key_t key); + +/* Return the caller thread's thread specific value of KEY. */ +extern void *pthread_getspecific (pthread_key_t key); + +/* Set the caller thread's thread specific value of KEY to VALUE. */ +extern int pthread_setspecific (pthread_key_t key, const void *value); + + +/* Dynamic package initialization. */ + +#include + +#define PTHREAD_ONCE_INIT __PTHREAD_ONCE_INIT + +/* Call INIT_ROUTINE if this function has never been called with + *ONCE_CONTROL, otherwise do nothing. */ +extern int pthread_once (pthread_once_t *once_control, + void (*init_routine) (void)); + + +/* Concurrency. */ + +#ifdef __USE_UNIX98 +/* Set the desired concurrency level to NEW_LEVEL. */ +extern int pthread_setconcurrency (int new_level); + +/* Get the current concurrency level. */ +extern int pthread_getconcurrency (void); +#endif + + +/* Forking. */ + +/* Register the function PREPARE to be run before the process forks, + the function PARENT to be run after a fork in the parent and the + function CHILD to be run in the child after the fork. If no + handling is desired then any of PREPARE, PARENT and CHILD may be + NULL. The prepare handles will be called in the reverse order + which they were registered and the parent and child handlers in the + order in which they were registered. */ +extern int pthread_atfork (void (*prepare) (void), void (*parent) (void), + void (*child) (void)); + + +/* Signals (should be in ). */ + +/* Send signal SIGNO to thread THREAD. */ +extern int pthread_kill (pthread_t thread, int signo); + + +/* Time. */ + +#ifdef __USE_XOPEN2K +/* Return the thread cpu clock. */ +extern int pthread_getcpuclockid (pthread_t thread, clockid_t *clock); +#endif + + +/* Scheduling. */ + +/* Return thread THREAD's scheduling paramters. */ +extern int pthread_getschedparam (pthread_t thread, int *__restrict policy, + struct sched_param *__restrict param); + +/* Set thread THREAD's scheduling paramters. */ +extern int pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param); + +/* Set thread THREAD's scheduling priority. */ +extern int pthread_setschedprio (pthread_t thread, int prio); + + +/* Kernel-specific interfaces. */ + +#include + + +__END_DECLS + +#endif /* pthread.h */ diff --git a/libpthread/include/pthread/pthreadtypes.h b/libpthread/include/pthread/pthreadtypes.h new file mode 100644 index 00000000..471e08ed --- /dev/null +++ b/libpthread/include/pthread/pthreadtypes.h @@ -0,0 +1,136 @@ +/* Copyright (C) 2000, 2002, 2005, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * POSIX Threads Extension: ??? + */ + +#ifndef _PTHREADTYPES_H +#define _PTHREADTYPES_H 1 + +#include + +#define __need_clockid_t +#include + +/* If we are in a mode where clockid_t is not automatically defined + and another header has already included then defining + __need_clockid_t was not enough. */ +#ifndef __clockid_t_defined +# define __clockid_t_defined 1 +# include +/* Clock ID used in clock and timer functions. */ +typedef __clockid_t clockid_t; +#endif + +__BEGIN_DECLS + +#include +typedef __pthread_t pthread_t; + +/* Possible values for the process shared attribute. */ +enum __pthread_process_shared + { + __PTHREAD_PROCESS_PRIVATE = 0, + __PTHREAD_PROCESS_SHARED + }; + +/* Possible values for the inheritsched attribute. */ +enum __pthread_inheritsched + { + __PTHREAD_EXPLICIT_SCHED = 0, + __PTHREAD_INHERIT_SCHED + }; + +/* Possible values for the `contentionscope' attribute. */ +enum __pthread_contentionscope + { + __PTHREAD_SCOPE_SYSTEM = 0, + __PTHREAD_SCOPE_PROCESS + }; + +/* Possible values for the `detachstate' attribute. */ +enum __pthread_detachstate + { + __PTHREAD_CREATE_JOINABLE = 0, + __PTHREAD_CREATE_DETACHED + }; + +#include +typedef struct __pthread_attr pthread_attr_t; + +enum __pthread_mutex_protocol + { + __PTHREAD_PRIO_NONE= 0, + __PTHREAD_PRIO_INHERIT, + __PTHREAD_PRIO_PROTECT + }; + +enum __pthread_mutex_type + { + __PTHREAD_MUTEX_TIMED, + __PTHREAD_MUTEX_ERRORCHECK, + __PTHREAD_MUTEX_RECURSIVE + }; + +#include +typedef struct __pthread_mutexattr pthread_mutexattr_t; + +#include +typedef struct __pthread_mutex pthread_mutex_t; + +#include +typedef struct __pthread_condattr pthread_condattr_t; + +#include +typedef struct __pthread_cond pthread_cond_t; + +#ifdef __USE_XOPEN2K +# include +typedef __pthread_spinlock_t pthread_spinlock_t; +#endif /* XPG6. */ + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K + +#include +typedef struct __pthread_rwlockattr pthread_rwlockattr_t; + +#include +typedef struct __pthread_rwlock pthread_rwlock_t; + +#endif /* __USE_UNIX98 || __USE_XOPEN2K */ + +#ifdef __USE_XOPEN2K + +#include +typedef struct __pthread_barrierattr pthread_barrierattr_t; + +#include +typedef struct __pthread_barrier pthread_barrier_t; + +#endif /* __USE_XOPEN2K */ + +#include +typedef __pthread_key pthread_key_t; + +#include +typedef struct __pthread_once pthread_once_t; + +__END_DECLS + +#endif /* pthreadtypes.h */ diff --git a/libpthread/include/semaphore.h b/libpthread/include/semaphore.h new file mode 100644 index 00000000..657e796e --- /dev/null +++ b/libpthread/include/semaphore.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2005, 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include + +__BEGIN_DECLS + +#include + +#define SEM_FAILED ((void *) 0) + +typedef struct __semaphore sem_t; + +/* Initialize semaphore *SEM with value VALUE. */ +extern int sem_init (sem_t *sem, int pshared, unsigned value); + +/* Destroy semaphore *SEM created with sem_init. */ +extern int sem_destroy (sem_t *sem); + +/* Store the value of semaphore *SEM in *VALUE. */ +extern int sem_getvalue (sem_t *__restrict sem, int *__restrict value); + +/* Perform a down operation on semaphore *SEM. */ +extern int sem_wait (sem_t *sem); + +/* Perform a down operation on semaphore *SEM if it can be done so + without blocking. */ +extern int sem_trywait (sem_t *sem); + +#ifdef __USE_XOPEN2K +/* Perform a down operation on semaphore *SEM but don't wait longer + than TIMEOUT. */ +extern int sem_timedwait (sem_t *__restrict sem, + const struct timespec *__restrict timeout); +#endif + +/* Perform an up operation on semaphore *SEM. */ +extern int sem_post (sem_t *sem); + +/* Open a named semaphore. */ +extern sem_t *sem_open (const char *name, int open_flags, ...); + +/* Close a semaphore returned by sem_open. */ +extern int sem_close (sem_t *sem); + +/* Unlink a named semaphore. */ +extern int sem_unlink (const char *name); + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/libpthread/include/set-hooks.h b/libpthread/include/set-hooks.h new file mode 100644 index 00000000..9ed71b32 --- /dev/null +++ b/libpthread/include/set-hooks.h @@ -0,0 +1,72 @@ +/* Macros for using symbol sets for running lists of functions. + Copyright (C) 1994, 1995, 1997, 2000 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. */ + +#ifndef _SET_HOOKS_H +#define _SET_HOOKS_H 1 + +#define __need_size_t +#include +// #include +#define __unbounded + +#ifdef symbol_set_define +/* Define a hook variable called NAME. Functions put on this hook take + arguments described by PROTO. Use `text_set_element (NAME, FUNCTION)' + from gnu-stabs.h to add a function to the hook. */ + +# define DEFINE_HOOK(NAME, PROTO) \ + typedef void __##NAME##_hook_function_t PROTO; \ + symbol_set_define (NAME) + +# define DECLARE_HOOK(NAME, PROTO) \ + typedef void __##NAME##_hook_function_t PROTO;\ + symbol_set_declare (NAME) + +/* Run all the functions hooked on the set called NAME. + Each function is called like this: `function ARGS'. */ + +# define RUN_HOOK(NAME, ARGS) \ +do { \ + void *const *__unbounded ptr; \ + for (ptr = symbol_set_first_element (NAME); \ + ! symbol_set_end_p (NAME, ptr); ++ptr) \ + (*(__##NAME##_hook_function_t *) *ptr) ARGS; \ +} while (0) + +/* Define a hook variable with NAME and PROTO, and a function called RUNNER + which calls each function on the hook in turn, with ARGS. */ + +# define DEFINE_HOOK_RUNNER(name, runner, proto, args) \ +DEFINE_HOOK (name, proto); \ +extern void runner proto; void runner proto { RUN_HOOK (name, args); } + +#else + +/* The system does not provide necessary support for this. */ +# define DEFINE_HOOK(NAME, PROTO) + +# define DECLARE_HOOK(NAME, PROTO) + +# define RUN_HOOK(NAME, ARGS) + +# define DEFINE_HOOK_RUNNER(name, runner, proto, args) + +#endif + +#endif /* set-hooks.h */ diff --git a/libpthread/libpthread.a b/libpthread/libpthread.a new file mode 100644 index 00000000..d0e689e9 --- /dev/null +++ b/libpthread/libpthread.a @@ -0,0 +1,20 @@ +/* pthread initializer is weak in glibc. It must be included if glibc + is to start threading. */ +EXTERN(_cthread_init_routine) + +/* Weak references in glibc that must be filled if glibc is to be + thread safe. */ +EXTERN(cthread_detach) +EXTERN(cthread_fork) +EXTERN(cthread_keycreate) +EXTERN(cthread_getspecific) +EXTERN(__libc_getspecific) +EXTERN(cthread_setspecific) +EXTERN(__mutex_lock_solid) +EXTERN(__mutex_unlock_solid) +/* For libio stream locking. */ +EXTERN(_cthreads_flockfile) +EXTERN(_cthreads_funlockfile) +EXTERN(_cthreads_ftrylockfile) + +GROUP(-lpthread2 -lihash) diff --git a/libpthread/libpthread_pic.a b/libpthread/libpthread_pic.a new file mode 100644 index 00000000..5673b4e7 --- /dev/null +++ b/libpthread/libpthread_pic.a @@ -0,0 +1,20 @@ +/* pthread initializer is weak in glibc. It must be included if glibc + is to start threading. */ +EXTERN(_cthread_init_routine) + +/* Weak references in glibc that must be filled if glibc is to be + thread safe. */ +EXTERN(cthread_detach) +EXTERN(cthread_fork) +EXTERN(cthread_keycreate) +EXTERN(cthread_getspecific) +EXTERN(__libc_getspecific) +EXTERN(cthread_setspecific) +EXTERN(__mutex_lock_solid) +EXTERN(__mutex_unlock_solid) +/* For libio stream locking. */ +EXTERN(_cthreads_flockfile) +EXTERN(_cthreads_funlockfile) +EXTERN(_cthreads_ftrylockfile) + +GROUP(-lpthread2_pic -lihash_pic) diff --git a/libpthread/lockfile.c b/libpthread/lockfile.c new file mode 100644 index 00000000..040cbfb4 --- /dev/null +++ b/libpthread/lockfile.c @@ -0,0 +1,65 @@ +/* lockfile - Handle locking and unlocking of streams. Hurd cthreads version. + Copyright (C) 2000,01,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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include /* Must come before ! */ +#include + +#ifdef _STDIO_USES_IOSTREAM + +void +_cthreads_flockfile (_IO_FILE *fp) +{ + _IO_lock_lock (*fp->_lock); +} + +void +_cthreads_funlockfile (_IO_FILE *fp) +{ + _IO_lock_unlock (*fp->_lock); +} + +int +_cthreads_ftrylockfile (_IO_FILE *fp) +{ + return __libc_lock_trylock_recursive (*fp->_lock); +} + +# undef _IO_flockfile +# undef _IO_funlockfile +# undef _IO_ftrylockfile +# undef flockfile +# undef funlockfile +# undef ftrylockfile + +void _IO_flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void _IO_funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int _IO_ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +void flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +#endif /* _STDIO_USES_IOSTREAM */ diff --git a/libpthread/not-in-libc.h b/libpthread/not-in-libc.h new file mode 100644 index 00000000..516d4d13 --- /dev/null +++ b/libpthread/not-in-libc.h @@ -0,0 +1,11 @@ +#define __mach_port_insert_right mach_port_insert_right +#define __mach_port_allocate mach_port_allocate +#define __mig_init mig_init +#define __thread_create thread_create +#define __thread_get_state thread_get_state +#define __thread_resume thread_resume +#define __thread_set_state thread_set_state +#define __thread_terminate thread_terminate +#define __vm_allocate vm_allocate +#define __vm_deallocate vm_deallocate +#define __sched_yield sched_yield diff --git a/libpthread/pthread/Versions b/libpthread/pthread/Versions new file mode 100644 index 00000000..e4b4e8bf --- /dev/null +++ b/libpthread/pthread/Versions @@ -0,0 +1,15 @@ +libc { + GLIBC_2.2 { + # XXX + __vm_deallocate; __mach_port_insert_right; __mach_reply_port; + __mig_init; __vm_allocate; + + # functions used in inline functions or macros + __pthread_spin_destroy; __pthread_spin_init; __pthread_spin_lock; + _pthread_spin_lock; __pthread_spin_trylock; __pthread_spin_unlock; + + # p* + pthread_spin_destroy; pthread_spin_init; pthread_spin_lock; + pthread_spin_trylock; pthread_spin_unlock; + } +} diff --git a/libpthread/pthread/cthreads-compat.c b/libpthread/pthread/cthreads-compat.c new file mode 100644 index 00000000..e0536ef2 --- /dev/null +++ b/libpthread/pthread/cthreads-compat.c @@ -0,0 +1,104 @@ +/* Compatibility routines for cthreads. + Copyright (C) 2000, 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +typedef void *cthread_t; +typedef void *(*cthread_fn_t) (void *arg); +typedef int cthread_key_t; + +#define CTHREAD_KEY_INVALID (cthread_key_t) -1 + +void +cthread_detach (cthread_t thread) +{ + int err; + + err = pthread_detach ((pthread_t) thread); + assert_perror (err); +} + +cthread_t +cthread_fork (cthread_fn_t func, void *arg) +{ + pthread_t thread; + int err; + + err = pthread_create (&thread, NULL, func, arg); + assert_perror (err); + + return (cthread_t) thread; +} + +int +cthread_keycreate (cthread_key_t *key) +{ + error_t err; + + err = pthread_key_create (key, 0); + if (err) + { + errno = err; + *key = CTHREAD_KEY_INVALID; + err = -1; + } + + return err; +} + +int +cthread_getspecific (cthread_key_t key, void **val) +{ + *val = pthread_getspecific (key); + return 0; +} + +void * +__libc_getspecific (cthread_key_t key) +{ + return pthread_getspecific (key); +} + +int +cthread_setspecific (cthread_key_t key, void *val) +{ + error_t err; + + err = pthread_setspecific (key, (const void *) val); + if (err) + { + errno = err; + err = -1; + } + + return err; +} + +void +__mutex_lock_solid (void *lock) +{ + __pthread_mutex_lock (lock); +} + +void +__mutex_unlock_solid (void *lock) +{ + __pthread_mutex_unlock (lock); +} diff --git a/libpthread/pthread/pt-alloc.c b/libpthread/pthread/pt-alloc.c new file mode 100644 index 00000000..6af2da92 --- /dev/null +++ b/libpthread/pthread/pt-alloc.c @@ -0,0 +1,215 @@ +/* Allocate a new thread structure. + Copyright (C) 2000, 2002, 2005, 2007, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#include + +/* This braindamage is necessary because the standard says that some + of the threads functions "shall fail" if "No thread could be found + corresponding to that specified by the given thread ID." */ + +/* Thread ID lookup table. */ +struct __pthread **__pthread_threads; + +/* The size of the thread ID lookup table. */ +int __pthread_max_threads; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +int __pthread_num_threads; + +/* A lock for the table, and the other variables above. */ +pthread_rwlock_t __pthread_threads_lock; + +/* List of thread structures corresponding to free thread IDs. */ +struct __pthread *__pthread_free_threads; +pthread_mutex_t __pthread_free_threads_lock; + +static inline error_t +initialize_pthread (struct __pthread *new, int recycling) +{ + error_t err; + + err = __pthread_init_specific (new); + if (err) + return err; + + new->cancel_state = PTHREAD_CANCEL_ENABLE; + new->cancel_type = PTHREAD_CANCEL_DEFERRED; + new->cancel_pending = 0; + + if (recycling) + /* Since we are recycling PTHREAD, we can assume certains things + about PTHREAD's current state and save some cycles by not + rewriting the memory. */ + return 0; + + new->stack = 0; + + new->state_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + new->state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER; + + new->cancelation_handlers = 0; + + new->next = 0; + new->prevp = 0; + + return 0; +} + + +/* Allocate a new thread structure and its pthread thread ID (but not + a kernel thread). */ +int +__pthread_alloc (struct __pthread **pthread) +{ + error_t err; + + struct __pthread *new; + struct __pthread **threads; + struct __pthread **old_threads; + int max_threads; + int new_max_threads; + + pthread_mutex_lock (&__pthread_free_threads_lock); + for (new = __pthread_free_threads; new; new = new->next) + { + /* There is no need to take NEW->STATE_LOCK: if NEW is on this + list, then it is protected by __PTHREAD_FREE_THREADS_LOCK + except in __pthread_dealloc where after it is added to the + list (with the lock held), it drops the lock and then sets + NEW->STATE and immediately stops using NEW. */ + if (new->state == PTHREAD_TERMINATED) + { + __pthread_dequeue (new); + break; + } + } + pthread_mutex_unlock (&__pthread_free_threads_lock); + + if (new) + { + /* The thread may still be running. Make sure it is stopped. + If this is the case, then the thread is either at the end of + __pthread_dealloc or in __pthread_thread_halt. In both + cases, we are interrupt it. */ + __pthread_thread_halt (new); + + err = initialize_pthread (new, 1); + if (! err) + *pthread = new; + return err; + } + + /* Allocate a new thread structure. */ + new = malloc (sizeof (struct __pthread)); + if (new == NULL) + return ENOMEM; + + err = initialize_pthread (new, 0); + if (err) + { + free (new); + return err; + } + + retry: + pthread_rwlock_wrlock (&__pthread_threads_lock); + + if (__pthread_num_threads < __pthread_max_threads) + { + /* We have a free slot. Use the slot number plus one as the + thread ID for the new thread. */ + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + *pthread = new; + return 0; + } +#ifdef PTHREAD_THREADS_MAX + else if (__pthread_num_threads >= PTHREAD_THREADS_MAX) + { + /* We have reached the limit on the number of threads per process. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (new); + return EAGAIN; + } +#endif + + /* We are going to enlarge the threads table. Save its current + size. We're going to release the lock before doing the necessary + memory allocation, since that's a potentially blocking operation. */ + max_threads = __pthread_max_threads; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Allocate a new lookup table that's twice as large. */ + new_max_threads + = max_threads > 0 ? max_threads * 2 : _POSIX_THREAD_THREADS_MAX; + threads = malloc (new_max_threads * sizeof (struct __pthread *)); + if (threads == NULL) + { + free (new); + return ENOMEM; + } + + pthread_rwlock_wrlock (&__pthread_threads_lock); + + /* Check if nobody else has already enlarged the table. */ + if (max_threads != __pthread_max_threads) + { + /* Yep, they did. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Free the newly allocated table and try again to allocate a slot. */ + free (threads); + goto retry; + } + + /* Copy over the contents of the old table. */ + memcpy (threads, __pthread_threads, + __pthread_max_threads * sizeof (struct __pthread *)); + + /* Save the location of the old table. We want to deallocate its + storage after we released the lock. */ + old_threads = __pthread_threads; + + /* Replace the table with the new one. */ + __pthread_max_threads = new_max_threads; + __pthread_threads = threads; + + /* And allocate ourselves one of the newly created slots. */ + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (old_threads); + + *pthread = new; + return 0; +} diff --git a/libpthread/pthread/pt-cancel.c b/libpthread/pthread/pt-cancel.c new file mode 100644 index 00000000..d19c557d --- /dev/null +++ b/libpthread/pthread/pt-cancel.c @@ -0,0 +1,40 @@ +/* Cancel a thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_cancel (pthread_t t) +{ + int err = 0; + struct __pthread *p; + + p = __pthread_getid (t); + if (! p) + return ESRCH; + + p->cancel_pending = 1; + if (p->cancel_state == PTHREAD_CANCEL_ENABLE + && p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS) + err = __pthread_do_cancel (p); + + return err; +} diff --git a/libpthread/pthread/pt-cleanup.c b/libpthread/pthread/pt-cleanup.c new file mode 100644 index 00000000..58865aa4 --- /dev/null +++ b/libpthread/pthread/pt-cleanup.c @@ -0,0 +1,28 @@ +/* Add a cancelation handler to the stack. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +struct __pthread_cancelation_handler ** +__pthread_get_cleanup_stack (void) +{ + return &_pthread_self ()->cancelation_handlers; +} diff --git a/libpthread/pthread/pt-create.c b/libpthread/pthread/pt-create.c new file mode 100644 index 00000000..8f62b78e --- /dev/null +++ b/libpthread/pthread/pt-create.c @@ -0,0 +1,206 @@ +/* Thread creation. + Copyright (C) 2000, 2002, 2005, 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +#include + +#ifdef HAVE_USELOCALE +# include +#endif + +/* The total number of pthreads currently active. This is defined + here since it would be really stupid to have a threads-using + program that doesn't call `pthread_create'. */ +__atomic_t __pthread_total; + + +/* The entry-point for new threads. */ +static void +entry_point (void *(*start_routine)(void *), void *arg) +{ +#ifdef HAVE_USELOCALE + /* A fresh thread needs to be bound to the global locale. */ + uselocale (LC_GLOBAL_LOCALE); +#endif + + __pthread_startup (); + + pthread_exit (start_routine (arg)); +} + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. */ +int +pthread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + + err = __pthread_create_internal (&pthread, attr, start_routine, arg); + if (! err) + *thread = pthread->thread; + + return err; +} + +/* Internal version of pthread_create. See comment in + pt-internal.h. */ +int +__pthread_create_internal (struct __pthread **thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + const struct __pthread_attr *setup; + sigset_t sigset; + + /* Allocate a new thread structure. */ + err = __pthread_alloc (&pthread); + if (err) + goto failed; + + /* Use the default attributes if ATTR is NULL. */ + setup = attr ? attr : &__pthread_default_attr; + + /* Initialize the thread state. */ + pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED + ? PTHREAD_DETACHED : PTHREAD_JOINABLE); + + /* If the user supplied a stack, it is not our responsibility to + setup a stack guard. */ + if (setup->stackaddr) + pthread->guardsize = 0; + else + pthread->guardsize = (setup->guardsize <= setup->stacksize + ? setup->guardsize : setup->stacksize); + + /* Find a stack. There are several scenarios: if a detached thread + kills itself, it has no way to deallocate its stack, thus it + leaves PTHREAD->stack set to true. We try to reuse it here, + however, if the user supplied a stack, we cannot use the old one. + Right now, we simply deallocate it. */ + if (pthread->stack) + { + if (setup->stackaddr != __pthread_default_attr.stackaddr) + { + __pthread_stack_dealloc (pthread->stackaddr, + pthread->stacksize); + pthread->stackaddr = setup->stackaddr; + pthread->stacksize = setup->stacksize; + } + } + else + { + err = __pthread_stack_alloc (&pthread->stackaddr, + setup->stacksize); + if (err) + goto failed_stack_alloc; + + pthread->stacksize = setup->stacksize; + pthread->stack = 1; + } + + /* Allocate the kernel thread and other required resources. */ + err = __pthread_thread_alloc (pthread); + if (err) + goto failed_thread_alloc; + + /* And initialize the rest of the machine context. This may include + additional machine- and system-specific initializations that + prove convenient. */ + err = __pthread_setup (pthread, entry_point, start_routine, arg); + if (err) + goto failed_setup; + + /* Initialize the system-specific signal state for the new + thread. */ + err = __pthread_sigstate_init (pthread); + if (err) + goto failed_sigstate; + + /* Set the new thread's signal mask and set the pending signals to + empty. POSIX says: "The signal mask shall be inherited from the + creating thread. The set of signals pending for the new thread + shall be empty." If the currnet thread is not a pthread then we + just inherit the process' sigmask. */ + if (__pthread_num_threads == 1) + err = sigprocmask (0, 0, &sigset); + else + err = __pthread_sigstate (_pthread_self (), 0, 0, &sigset, 0); + assert_perror (err); + + err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 1); + assert_perror (err); + + /* Increase the total number of threads. We do this before actually + starting the new thread, since the new thread might immediately + call `pthread_exit' which decreases the number of threads and + calls `exit' if the number of threads reaches zero. Increasing + the number of threads from within the new thread isn't an option + since this thread might return and call `pthread_exit' before the + new thread runs. */ + __atomic_inc (&__pthread_total); + + /* Store a pointer to this thread in the thread ID lookup table. We + could use __thread_setid, however, we only lock for reading as no + other thread should be using this entry (we also assume that the + store is atomic). */ + pthread_rwlock_rdlock (&__pthread_threads_lock); + __pthread_threads[pthread->thread - 1] = pthread; + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* At this point it is possible to guess our pthread ID. We have to + make sure that all functions taking a pthread_t argument can + handle the fact that this thread isn't really running yet. */ + + /* Schedule the new thread. */ + err = __pthread_thread_start (pthread); + if (err) + goto failed_starting; + + /* At this point the new thread is up and running. */ + + *thread = pthread; + + return 0; + + failed_starting: + __pthread_setid (pthread->thread, NULL); + __atomic_dec (&__pthread_total); + failed_sigstate: + __pthread_sigstate_destroy (pthread); + failed_setup: + __pthread_thread_dealloc (pthread); + __pthread_thread_halt (pthread); + failed_thread_alloc: + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + failed_stack_alloc: + __pthread_dealloc (pthread); + failed: + return err; +} diff --git a/libpthread/pthread/pt-dealloc.c b/libpthread/pthread/pt-dealloc.c new file mode 100644 index 00000000..92fe1fda --- /dev/null +++ b/libpthread/pthread/pt-dealloc.c @@ -0,0 +1,64 @@ +/* Deallocate a thread structure. + Copyright (C) 2000, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* List of thread structures corresponding to free thread IDs. */ +extern struct __pthread *__pthread_free_threads; +extern pthread_mutex_t __pthread_free_threads_lock; + + +/* Deallocate the thread structure for PTHREAD. */ +void +__pthread_dealloc (struct __pthread *pthread) +{ + assert (pthread->state != PTHREAD_TERMINATED); + + /* Withdraw this thread from the thread ID lookup table. */ + __pthread_setid (pthread->thread, NULL); + + /* Mark the thread as terminated. We broadcast the condition + here to prevent pthread_join from waiting for this thread to + exit where it was never really started. Such a call to + pthread_join is completely bogus, but unfortunately allowed + by the standards. */ + __pthread_mutex_lock (&pthread->state_lock); + if (pthread->state != PTHREAD_EXITED) + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + + /* We do not actually deallocate the thread structure, but add it to + a list of re-usable thread structures. */ + pthread_mutex_lock (&__pthread_free_threads_lock); + __pthread_enqueue (&__pthread_free_threads, pthread); + pthread_mutex_unlock (&__pthread_free_threads_lock); + + /* Setting PTHREAD->STATE to PTHREAD_TERMINATED makes this TCB + available for reuse. After that point, we can no longer assume + that PTHREAD is valid. + + Note that it is safe to not lock this update to PTHREAD->STATE: + the only way that it can now be accessed is in __pthread_alloc, + which reads this variable. */ + pthread->state = PTHREAD_TERMINATED; +} diff --git a/libpthread/pthread/pt-detach.c b/libpthread/pthread/pt-detach.c new file mode 100644 index 00000000..1e42c452 --- /dev/null +++ b/libpthread/pthread/pt-detach.c @@ -0,0 +1,92 @@ +/* Detach a thread. + Copyright (C) 2000, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Indicate that the storage for THREAD can be reclaimed when it + terminates. */ +int +pthread_detach (pthread_t thread) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + + switch (pthread->state) + { + case PTHREAD_JOINABLE: + /* THREAD still running. Mark it as detached such that its + resources can be reclaimed as soon as the thread exits. */ + pthread->state = PTHREAD_DETACHED; + + /* Broadcast the condition. This will make threads that are + waiting to join THREAD continue with hopefully disastrous + consequences instead of blocking indefinitely. */ + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + break; + + case PTHREAD_EXITED: + /* THREAD has already exited. Make sure that nobody can + reference it anymore, and mark it as terminated. */ + + __pthread_mutex_unlock (&pthread->state_lock); + + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_thread_dealloc (pthread); + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not detach non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/libpthread/pthread/pt-exit.c b/libpthread/pthread/pt-exit.c new file mode 100644 index 00000000..5fe0ba86 --- /dev/null +++ b/libpthread/pthread/pt-exit.c @@ -0,0 +1,118 @@ +/* Thread termination. + Copyright (C) 2000, 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +#include + + +/* Terminate the current thread and make STATUS available to any + thread that might join it. */ +void +pthread_exit (void *status) +{ + struct __pthread *self = _pthread_self (); + struct __pthread_cancelation_handler **handlers; + int oldstate; + int need_dealloc; + + /* Run any cancelation handlers. According to POSIX, the + cancellation cleanup handlers should be called with cancellation + disabled. */ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); + + for (handlers = __pthread_get_cleanup_stack (); + *handlers; + *handlers = (*handlers)->next) + (*handlers)->handler ((*handlers)->arg); + + pthread_setcancelstate (oldstate, &oldstate); + + /* Destory any thread specific data. */ + __pthread_destroy_specific (self); + + /* Destroy any signal state. */ + __pthread_sigstate_destroy (self); + + /* Decrease the number of threads. We use an atomic operation to + make sure that only the last thread calls `exit'. */ + if (__atomic_dec_and_test (&__pthread_total)) + /* We are the last thread. */ + exit (0); + + /* Note that after this point the process can be terminated at any + point if another thread calls `pthread_exit' and happens to be + the last thread. */ + + __pthread_mutex_lock (&self->state_lock); + + if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) + status = PTHREAD_CANCELED; + + switch (self->state) + { + default: + assert (! "Consistency error: unexpected self->state"); + abort (); + break; + + case PTHREAD_DETACHED: + /* Make sure that nobody can reference this thread anymore, and + mark it as terminated. Our thread ID will immediately become + available for re-use. For obvious reasons, we cannot + deallocate our own stack. However, it will eventually be + reused when this thread structure is recycled. */ + __pthread_mutex_unlock (&self->state_lock); + + __pthread_dealloc (self); + + break; + + case PTHREAD_JOINABLE: + /* We need to stay around for a while since another thread + might want to join us. */ + self->state = PTHREAD_EXITED; + + /* We need to remember the exit status. A thread joining us + might ask for it. */ + self->status = status; + + /* Broadcast the condition. This will wake up threads that are + waiting to join us. */ + pthread_cond_broadcast (&self->state_cond); + __pthread_mutex_unlock (&self->state_lock); + + break; + } + + /* Note that after this point the resources used by this thread can + be freed at any moment if another thread joins or detaches us. + This means that before freeing any resources, such a thread + should make sure that this thread is really halted. */ + + __pthread_thread_halt (self); + + /* NOTREACHED */ + abort (); +} diff --git a/libpthread/pthread/pt-getattr.c b/libpthread/pthread/pt-getattr.c new file mode 100644 index 00000000..24599c6e --- /dev/null +++ b/libpthread/pthread/pt-getattr.c @@ -0,0 +1,49 @@ +/* Thread attributes retrieval. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread THREAD. It shall be called on an uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +int +pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) +{ + struct __pthread *pthread; + + pthread = __pthread_getid(thread); + if (pthread == NULL) + return ESRCH; + + /* Some attributes (schedparam, inheritsched, contentionscope and schedpolicy) + are not supported yet, so fill them with our default values. */ + *attr = __pthread_default_attr; + + attr->stackaddr = pthread->stackaddr; + attr->stacksize = pthread->stacksize; + attr->guardsize = pthread->guardsize; + attr->detachstate = (pthread->state == PTHREAD_DETACHED + ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + + return 0; +} diff --git a/libpthread/pthread/pt-initialize.c b/libpthread/pthread/pt-initialize.c new file mode 100644 index 00000000..cf32b8b5 --- /dev/null +++ b/libpthread/pthread/pt-initialize.c @@ -0,0 +1,33 @@ +/* Initialize pthreads library. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +DEFINE_HOOK (__pthread_init, (void)); + +/* Initialize the pthreads library. */ +void +__pthread_initialize (void) +{ + RUN_HOOK (__pthread_init, ()); +} diff --git a/libpthread/pthread/pt-internal.h b/libpthread/pthread/pt-internal.h new file mode 100644 index 00000000..cb441d09 --- /dev/null +++ b/libpthread/pthread/pt-internal.h @@ -0,0 +1,290 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000, 2005, 2006, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_INTERNAL_H +#define _PT_INTERNAL_H 1 + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +/* Thread state. */ +enum pthread_state +{ + /* The thread is running and joinable. */ + PTHREAD_JOINABLE = 0, + /* The thread is running and detached. */ + PTHREAD_DETACHED, + /* A joinable thread exited and its return code is available. */ + PTHREAD_EXITED, + /* The thread structure is unallocated and available for reuse. */ + PTHREAD_TERMINATED +}; + +#ifndef PTHREAD_KEY_MEMBERS +# define PTHREAD_KEY_MEMBERS +#endif + +#ifndef PTHREAD_SYSDEP_MEMBERS +# define PTHREAD_SYSDEP_MEMBERS +#endif + +/* This structure describes a POSIX thread. */ +struct __pthread +{ + /* Thread ID. */ + pthread_t thread; + + /* Cancellation. */ + int cancel_state; + int cancel_type; + int cancel_pending; + struct __pthread_cancelation_handler *cancelation_handlers; + + /* Thread stack. */ + void *stackaddr; + size_t stacksize; + size_t guardsize; /* Included in STACKSIZE (i.e. total + stack memory is STACKSIZE, not + STACKSIZE + GUARDSIZE). */ + int stack; /* Nonzero if the stack was allocated. */ + + /* Exit status. */ + void *status; + + /* Thread state. */ + enum pthread_state state; + pthread_mutex_t state_lock; /* Locks the state. */ + pthread_cond_t state_cond; /* Signalled when the state changes. */ + + /* Thread context. */ + struct pthread_mcontext mcontext; + + PTHREAD_KEY_MEMBERS + + PTHREAD_SYSDEP_MEMBERS + + struct __pthread *next, **prevp; +}; + +/* Enqueue an element THREAD on the queue *HEAD. */ +static inline void +__pthread_enqueue (struct __pthread **head, struct __pthread *thread) +{ + assert (thread->prevp == 0); + + thread->next = *head; + thread->prevp = head; + if (*head) + (*head)->prevp = &thread->next; + *head = thread; +} + +/* Dequeue the element THREAD from the queue it is connected to. */ +static inline void +__pthread_dequeue (struct __pthread *thread) +{ + assert (thread); + + if (thread->next) + thread->next->prevp = thread->prevp; + *thread->prevp = thread->next; + thread->prevp = 0; +} + +/* Iterate over QUEUE storing each element in ELEMENT. */ +#define __pthread_queue_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + 1); \ + ) + +/* Iterate over QUEUE dequeuing each element, storing it in + ELEMENT. */ +#define __pthread_dequeuing_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + ((element)->prevp = 0), \ + 1); \ + ) + +/* The total number of threads currently active. */ +extern __atomic_t __pthread_total; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +extern int __pthread_num_threads; + +/* Concurrency hint. */ +extern int __pthread_concurrency; + +/* Array of __pthread structures and its lock. Indexed by the pthread + id minus one. (Why not just use the pthread id? Because some + brain-dead users of the pthread interface incorrectly assume that 0 + is an invalid pthread id.) */ +extern struct __pthread **__pthread_threads; +extern pthread_rwlock_t __pthread_threads_lock; + +#define __pthread_getid(thread) \ + ({ struct __pthread *__t; \ + pthread_rwlock_rdlock (&__pthread_threads_lock); \ + __t = __pthread_threads[thread - 1]; \ + pthread_rwlock_unlock (&__pthread_threads_lock); \ + __t; }) + +#define __pthread_setid(thread, pthread) \ + pthread_rwlock_wrlock (&__pthread_threads_lock); \ + __pthread_threads[thread - 1] = pthread; \ + pthread_rwlock_unlock (&__pthread_threads_lock); + +/* Similar to pthread_self, but returns the thread descriptor instead + of the thread ID. */ +#ifndef _pthread_self +extern struct __pthread *_pthread_self (void); +#endif + + +/* Initialize the pthreads library. */ +extern void __pthread_initialize (void); + +/* Internal version of pthread_create. Rather than return the new + tid, we return the whole __pthread structure in *PTHREAD. */ +extern int __pthread_create_internal (struct __pthread **__restrict pthread, + const pthread_attr_t *__restrict attr, + void *(*start_routine)(void *), + void *__restrict arg); + +/* Allocate a new thread structure and a pthread thread ID (but not a + kernel thread or a stack). */ +extern int __pthread_alloc (struct __pthread **thread); + +/* Deallocate the thread structure. This is the dual of + __pthread_alloc (N.B. it does not call __pthread_stack_alloc nor + __pthread_thread_halt). */ +extern void __pthread_dealloc (struct __pthread *thread); + + +/* Allocate a stack of size STACKSIZE. The stack base shall be + returned in *STACKADDR. */ +extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize); + +/* Deallocate the stack STACKADDR of size STACKSIZE. */ +extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize); + + +/* Setup thread THREAD's context. */ +extern int __pthread_setup (struct __pthread *__restrict thread, + void (*entry_point)(void *(*)(void *), + void *), + void *(*start_routine)(void *), + void *__restrict arg); + + +/* Allocate a kernel thread (and any miscellaneous system dependent + resources) for THREAD; it must not be placed on the run queue. */ +extern int __pthread_thread_alloc (struct __pthread *thread); + +/* Deallocate any kernel resources associated with THREAD. The thread + must not be running (that is, if __pthread_thread_start was called, + __pthread_thread_halt must first be called). This function will + never be called by a thread on itself. In the case that a thread + exits, its thread structure will be cached and cleaned up + later. */ +extern void __pthread_thread_dealloc (struct __pthread *thread); + +/* Start THREAD making it eligible to run. */ +extern int __pthread_thread_start (struct __pthread *thread); + +/* Stop the kernel thread associated with THREAD. This function may + be called by two threads in parallel. In particular, by the thread + itself and another thread trying to join it. This function must be + implemented such that this is safe. */ +extern void __pthread_thread_halt (struct __pthread *thread); + + +/* Called by a thread just before it calls the provided start + routine. */ +extern void __pthread_startup (void); + +/* Block THREAD. */ +extern void __pthread_block (struct __pthread *thread); + +/* Block THREAD until *ABSTIME is reached. */ +extern error_t __pthread_timedblock (struct __pthread *__restrict thread, + const struct timespec *__restrict abstime); + +/* Wakeup THREAD. */ +extern void __pthread_wakeup (struct __pthread *thread); + + +/* Perform a cancelation. */ +extern int __pthread_do_cancel (struct __pthread *thread); + + +/* Initialize the thread specific data structures. THREAD must be the + calling thread. */ +extern error_t __pthread_init_specific (struct __pthread *thread); + +/* Call the destructors on all of the thread specific data in THREAD. + THREAD must be the calling thread. */ +extern void __pthread_destroy_specific (struct __pthread *thread); + + +/* Initialize newly create thread *THREAD's signal state data + structures. */ +extern error_t __pthread_sigstate_init (struct __pthread *thread); + +/* Destroy the signal state data structures associcated with thread + *THREAD. */ +extern void __pthread_sigstate_destroy (struct __pthread *thread); + +/* Modify thread *THREAD's signal state. */ +extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how, + const sigset_t *__restrict set, + sigset_t *__restrict oset, + int clear_pending); + + +/* Default thread attributes. */ +extern const struct __pthread_attr __pthread_default_attr; + +/* Default barrier attributes. */ +extern const struct __pthread_barrierattr __pthread_default_barrierattr; + +/* Default mutex attributes. */ +extern const struct __pthread_mutexattr __pthread_default_mutexattr; + +/* Default rdlock attributes. */ +const struct __pthread_rwlockattr __pthread_default_rwlockattr; + +/* Default condition attributes. */ +const struct __pthread_condattr __pthread_default_condattr; + +#endif /* pt-internal.h */ diff --git a/libpthread/pthread/pt-join.c b/libpthread/pthread/pt-join.c new file mode 100644 index 00000000..153058b5 --- /dev/null +++ b/libpthread/pthread/pt-join.c @@ -0,0 +1,88 @@ +/* Wait for thread termination. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Make calling thread wait for termination of thread THREAD. Return + the exit status of the thread in *STATUS. */ +int +pthread_join (pthread_t thread, void **status) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock, + &pthread->state_lock); + + while (pthread->state == PTHREAD_JOINABLE) + pthread_cond_wait (&pthread->state_cond, &pthread->state_lock); + + pthread_cleanup_pop (0); + + switch (pthread->state) + { + case PTHREAD_EXITED: + __pthread_mutex_unlock (&pthread->state_lock); + + /* THREAD has already exited. Salvage its exit status. */ + if (status) + *status = pthread->status; + + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_thread_dealloc (pthread); + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not join non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/libpthread/pthread/pt-self.c b/libpthread/pthread/pt-self.c new file mode 100644 index 00000000..49768643 --- /dev/null +++ b/libpthread/pthread/pt-self.c @@ -0,0 +1,32 @@ +/* Get calling thread's ID. + Copyright (C) 2000, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Return the thread ID of the calling thread. */ +pthread_t +pthread_self (void) +{ + struct __pthread *self = _pthread_self (); + assert (self); + + return self->thread; +} diff --git a/libpthread/pthread/pt-setcancelstate.c b/libpthread/pthread/pt-setcancelstate.c new file mode 100644 index 00000000..ded58922 --- /dev/null +++ b/libpthread/pthread/pt-setcancelstate.c @@ -0,0 +1,42 @@ +/* Set the cancel state for the calling thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_setcancelstate (int state, int *oldstate) +{ + struct __pthread *p = _pthread_self (); + + switch (state) + { + default: + return EINVAL; + case PTHREAD_CANCEL_ENABLE: + case PTHREAD_CANCEL_DISABLE: + break; + } + + *oldstate = p->cancel_state; + p->cancel_state = state; + + return 0; +} diff --git a/libpthread/pthread/pt-setcanceltype.c b/libpthread/pthread/pt-setcanceltype.c new file mode 100644 index 00000000..9511c991 --- /dev/null +++ b/libpthread/pthread/pt-setcanceltype.c @@ -0,0 +1,42 @@ +/* Set the cancel type for the calling thread. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_setcanceltype (int type, int *oldtype) +{ + struct __pthread *p = _pthread_self (); + + switch (type) + { + default: + return EINVAL; + case PTHREAD_CANCEL_DEFERRED: + case PTHREAD_CANCEL_ASYNCHRONOUS: + break; + } + + *oldtype = p->cancel_type; + p->cancel_type = type; + + return 0; +} diff --git a/libpthread/pthread/pt-sigmask.c b/libpthread/pthread/pt-sigmask.c new file mode 100644 index 00000000..1b53873e --- /dev/null +++ b/libpthread/pthread/pt-sigmask.c @@ -0,0 +1,33 @@ +/* Get or set a thread's signal mask. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_sigmask (int how, const sigset_t *set, + sigset_t *oset) +{ + struct __pthread *self = _pthread_self (); + + /* Do not clear SELF's pending signals. */ + return __pthread_sigstate (self, how, set, oset, 0); +} diff --git a/libpthread/pthread/pt-spin-inlines.c b/libpthread/pthread/pt-spin-inlines.c new file mode 100644 index 00000000..cfb21dd3 --- /dev/null +++ b/libpthread/pthread/pt-spin-inlines.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* declares some extern inline functions. These + functions are declared additionally here for use when inlining is + not possible. */ + +#define _FORCE_INLINES +#define __PT_SPIN_INLINE /* empty */ + +#include + +/* Weak aliases for the spin lock functions. Note that + pthread_spin_lock is left out deliberately. We already provide an + implementation for it in pt-spin.c. */ +weak_alias (__pthread_spin_destroy, pthread_spin_destroy); +weak_alias (__pthread_spin_init, pthread_spin_init); +weak_alias (__pthread_spin_trylock, pthread_spin_trylock); +weak_alias (__pthread_spin_unlock, pthread_spin_unlock); diff --git a/libpthread/pthread/pt-testcancel.c b/libpthread/pthread/pt-testcancel.c new file mode 100644 index 00000000..01f1ac9c --- /dev/null +++ b/libpthread/pthread/pt-testcancel.c @@ -0,0 +1,31 @@ +/* Add an explicit cancelation point. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +void +pthread_testcancel (void) +{ + struct __pthread *p = _pthread_self (); + + if (p->cancel_state == PTHREAD_CANCEL_ENABLE && p->cancel_pending) + pthread_exit (PTHREAD_CANCELED); +} diff --git a/libpthread/signal/README b/libpthread/signal/README new file mode 100644 index 00000000..5487e2e3 --- /dev/null +++ b/libpthread/signal/README @@ -0,0 +1,4 @@ +This directory provides a signal implementation, which is appropriate +for operating systems where signals are managed at user-level. It is +up to the run-time to catch the signals and forward them to the +implementation via, e.g., the pthread_kill_info_np call. diff --git a/libpthread/signal/TODO b/libpthread/signal/TODO new file mode 100644 index 00000000..1148abb3 --- /dev/null +++ b/libpthread/signal/TODO @@ -0,0 +1,29 @@ +Unimplemented Functionality +--------------------------- + +We don't support interruptible functions. That is, if a signal is +delivered when a thread is in e.g. the write system call, then the +write function should be interrupted and return EINTR when the signal +handler is finished. To realize this behavior, we could have a thread +local interruptible flag and a setjmp buffer. A function that is +interruptible would fill the jump buffer and set the interruptible +flag. If a signal comes in and the interruptible flag is set, rather +than resuming the thread, we longjmp to the buffer. + +If a signal action has set the SA_SIGINFO, the third argument must be +a pointer to a ucontext describing the thread's interrupted state; +this implementation passes NULL. This isn't as bad as it sounds as +the the ucontext family of functions are marked obsolete in SUSv3 with +the advisory that any use of them should be replaced by the use of +pthread functionality (cf. makecontext rationale). + +stop and continue signals are not implemented (as we need to stop all +threads, this requires being in bed with libpthread). + +Implementation is not yet cancellation-safe. + +There are not even stubs for sighold, sigingore, sigpause, sigrelse, +however, according to posix: "Use of any of these functions is +unspecified in a multi-threaded process." + +Implement sigtimedwait, sigqueue. \ No newline at end of file diff --git a/libpthread/signal/kill.c b/libpthread/signal/kill.c new file mode 100644 index 00000000..27c9c32a --- /dev/null +++ b/libpthread/signal/kill.c @@ -0,0 +1,70 @@ +/* kill.c - Generic kill implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +kill (pid_t pid, int signo) +{ + if (pid != getpid ()) + { + errno = EOPNOTSUPP; + return -1; + } + + /* "Signals generated for the process shall be delivered to exactly + one of those threads within the process which is in a call to a + sigwait() function selecting that signal or has not blocked + delivery of the signal. If there are no threads in a call to a + sigwait() function selecting that signal, and if all threads + within the process block delivery of the signal, the signal shall + remaing pending on the process" (2.4.1). */ + + /* First, see if there is a waiter, which is interested in this + signal. */ + pthread_mutex_lock (&sig_lock); + + struct sigwaiter *waiter; + for (waiter = sigwaiters; waiter; waiter = waiter->next) + if ((waiter->signals & sigmask (signo))) + /* Got a winner. */ + { + sigdelset (&process_pending, signo); + + pthread_mutex_lock (&waiter->ss->lock); + sigdelset (&waiter->ss->pending, signo); + + memset (&waiter->info, 0, sizeof (waiter->info)); + waiter->info.si_signo = signo; + + sigwaiter_unblock (waiter); + + return 0; + } + + pthread_mutex_unlock (&sig_lock); + + /* XXX: We just generate the signal for the current thread. If the + current thread has blocked the signal, the correct thing to do is + to iterate over all the other threads and find on that hasn't + blocked it. */ + return pthread_kill (pthread_self (), signo); +} + diff --git a/libpthread/signal/pt-kill-siginfo-np.c b/libpthread/signal/pt-kill-siginfo-np.c new file mode 100644 index 00000000..9bdf6cc4 --- /dev/null +++ b/libpthread/signal/pt-kill-siginfo-np.c @@ -0,0 +1,88 @@ +/* pthread-kill-siginfo-np.c - Generic pthread_kill_siginfo_np implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "pt-internal.h" +#include "sig-internal.h" + +int +pthread_kill_siginfo_np (pthread_t tid, siginfo_t si) +{ + int sig = si.si_signo; + + if (sig < 0 || sig >= NSIG) + return EINVAL; + + if (sig == 0) + return 0; + + struct signal_state *ss = &__pthread_getid (tid)->ss; + + pthread_mutex_lock (&sig_lock); + pthread_mutex_lock (&ss->lock); + + if (ss->sigwaiter && (ss->sigwaiter->signals & sigmask (si.si_signo))) + /* The thread is in a call to sigwait. */ + { + ss->sigwaiter->info = si; + sigwaiter_unblock (ss->sigwaiter); + return 0; + } + + pthread_mutex_unlock (&sig_lock); + + if (ss->actions[sig - 1].sa_handler == (void *) SIG_IGN + || (ss->actions[sig - 1].sa_handler == (void *) SIG_DFL + && default_action (sig) == sig_ignore)) + /* It is unclear (to me) what is supposed to happen when a signal + is generated for a thread, which is blocking that signal and + ignoring it. POSIX does say that when the action associated + with a pending, blocked signal is set to SIG_IGN, the pending + signal is to be cleared. Thus, it makes sense that any signal + set to ignore is discarded at generation. */ + { + pthread_mutex_unlock (&ss->lock); + return 0; + } + + + if ((sigmask (sig) & ss->blocked)) + /* The signal is blocked. Mark it pending. */ + { + ss->pending |= sigmask (sig); + pthread_mutex_unlock (&ss->lock); + return 0; + } + + if (pthread_self () == tid + && (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) + || (ss->stack.ss_flags & SS_DISABLE) + || (ss->stack.ss_flags & SS_ONSTACK))) + /* We are sending a signal to ourself and we don't use an + alternate stack. */ + signal_dispatch (ss, &si); + else + signal_dispatch_lowlevel (ss, tid, si); + + /* Don't unlock ss: signal_dispatch and signal_dispatch_lowlevel + assume ownership of the lock. */ + + return 0; +} + diff --git a/libpthread/signal/sig-internal.c b/libpthread/signal/sig-internal.c new file mode 100644 index 00000000..f73f38b4 --- /dev/null +++ b/libpthread/signal/sig-internal.c @@ -0,0 +1,26 @@ +/* sig-internal.c - Signal state functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +pthread_mutex_t sig_lock = PTHREAD_MUTEX_INITIALIZER; + +sigset_t process_pending; +siginfo_t process_pending_info[NSIG]; diff --git a/libpthread/signal/sig-internal.h b/libpthread/signal/sig-internal.h new file mode 100644 index 00000000..6c86c796 --- /dev/null +++ b/libpthread/signal/sig-internal.h @@ -0,0 +1,177 @@ +/* sig-internal.h - Internal signal handling interface. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#ifndef SIG_INTERNAL_H +#define SIG_INTERNAL_H + +#include + +#include + +#define sigmask(sig) (1ULL << (sig - 1)) +#define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \ + sigmask (SIGSTOP) | sigmask (SIGTSTP)) + +/* General lock. Protects PROCESS_PENDING, PROCESS_PENDING_INFO, + SIGWAITERS. */ +extern pthread_mutex_t sig_lock; + +/* "Signals generated for the process shall be delivered to exactly + one of those threads within the process which is in a call to a + sigwait() function selecting that signal or has not blocked + delivery of the signal. If there are no threads in a call to a + sigwait() function selecting that signal, and if all threads within + the process block delivery of the signal, the signal shall remaing + pending on the process" (2.4.1). + + This variable is protected by SIG_LOCK. */ +extern sigset_t process_pending; +extern siginfo_t process_pending_info[NSIG]; + +struct sigwaiter; + +/* The per-thread signal state. */ +struct signal_state +{ + /* Protects the following fields. STACK.SA_FLAGS may be accessed + using atomic operations. */ + pthread_mutex_t lock; + + /* Pending signals. */ + sigset_t pending; + + /* Blocked signals (i.e., the signal mask). */ + sigset_t blocked; + + stack_t stack; + struct sigaction actions[NSIG]; + siginfo_t info[NSIG]; + + /* If the thread is blocked in a call to sigwait. */ + struct sigwaiter *sigwaiter; +}; + +#define PTHREAD_SIGNAL_MEMBERS struct signal_state ss; + +/* Arranges for thread TID to call signal_dispatch. Must not be + called if TID is the caller and an alternate stack is not required. + In this case, the caller should call signal_dispatch directly. */ +extern void signal_dispatch_lowlevel (struct signal_state *ss, + pthread_t tid, siginfo_t si); + +/* This is the signal handler entry point. A thread is forced into + this state when it receives a signal. We need to save the thread's + state and then invoke the high-level signal dispatcher. SS->LOCK + is locked by the caller. */ +extern void signal_dispatch (struct signal_state *ss, siginfo_t *si); + +#ifndef SIGNAL_DISPATCH_ENTRY +#define SIGNAL_DISPATCH_ENTRY +#endif + +#ifndef SIGNAL_DISPATCH_EXIT +#define SIGNAL_DISPATCH_EXIT +#endif + +/* When a thread calls sigwait and a requested signal is not pending, + it allocates the following structure, fills it in, adds it to + sigwaiters and sleeps. */ +struct sigwaiter +{ + struct sigwaiter *next; + struct sigwaiter *prev; + + /* Thread's signal state. */ + struct signal_state *ss; + + /* Signals this thread is waiting for. */ + sigset_t signals; + + /* The selected signal is returned here. The waiter also + futex_waits on this info.si_signo. */ + siginfo_t info; +}; + +/* This variable is protected by SIG_LOCK. */ +extern struct sigwaiter *sigwaiters; + +/* Block the caller waiting for a signal in set SET. SIG_LOCK and + SS->LOCK must be held and will be unlocked by this function before + blocking. */ +extern siginfo_t sigwaiter_block (struct signal_state *ss, + const sigset_t *restrict set); + +/* Unblock the waiter WAITER. SIG_LOCK and WAITER->SS->LOCK must be + held. Both will be dropped on return. */ +extern void sigwaiter_unblock (struct sigwaiter *waiter); + +enum sig_action { sig_core, sig_terminate, sig_ignore, sig_cont, sig_stop }; + +static inline enum sig_action +default_action (int signo) +{ + switch (signo) + { + case SIGABRT: + case SIGBUS: + case SIGFPE: + case SIGILL: + case SIGQUIT: + case SIGSEGV: + case SIGSTKFLT: + case SIGSYS: + case SIGTRAP: + case SIGXCPU: + case SIGXFSZ: + return sig_core; + + case SIGALRM: + case SIGHUP: + case SIGINT: + case SIGIO: /* Perhaps ignore? */ + case SIGKILL: + case SIGPIPE: + case SIGPROF: + case SIGTERM: + case SIGUSR1: + case SIGUSR2: + case SIGVTALRM: + return sig_terminate; + + case SIGCHLD: + case SIGPWR: + case SIGURG: + case SIGWINCH: + return sig_ignore; + + case SIGCONT: + return sig_cont; + + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + return sig_stop; + } + + panic ("Unknown signal number: %d", signo); +} + +#endif diff --git a/libpthread/signal/sigaction.c b/libpthread/signal/sigaction.c new file mode 100644 index 00000000..0126c99d --- /dev/null +++ b/libpthread/signal/sigaction.c @@ -0,0 +1,72 @@ +/* sigaction.c - Generic sigaction implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" +#include "pt-internal.h" + +int +sigaction (int sig, const struct sigaction *restrict sa, + struct sigaction *restrict osa) +{ + if (sig <= 0 || sig >= NSIG) + { + errno = EINVAL; + return -1; + } + + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if (osa) + *osa = ss->actions[sig - 1]; + + if (sa) + { + ss->actions[sig - 1] = *sa; + + /* "The SIGKILL and SIGSTOP signals shall not be added to the + signal mask using this mechanism; this restriction shall be + enforced by the system without causing an error to be + indicated" (sigaction). */ + sigdelset (&ss->blocked, SIGKILL); + sigdelset (&ss->blocked, SIGSTOP); + + /* A "signal shall remain pending on the process until it is + unblocked, it is accepted when ..., or the action associated + with it is set to ignore the signal" (2.4.1). + + "Setting a signal action to SIG_DFL for a signal that is + pending, and whose default action is to ignore the signal, + ..., shall cause the pending signal to be discarded, whether + or not it is blocked" (2.4.3). */ + if (sa->sa_handler == SIG_IGN + || (sa->sa_handler == SIG_DFL && default_action (sig) == sig_ignore)) + { + sigdelset (&ss->pending, sig); + sigdelset (&process_pending, sig); + } + } + + pthread_mutex_unlock (&ss->lock); + + return 0; +} + diff --git a/libpthread/signal/sigaltstack.c b/libpthread/signal/sigaltstack.c new file mode 100644 index 00000000..8334811a --- /dev/null +++ b/libpthread/signal/sigaltstack.c @@ -0,0 +1,69 @@ +/* sigaltstack.c - Generic sigaltstack implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" +#include "pt-internal.h" + +int +sigaltstack (const stack_t *restrict stack, stack_t *restrict old) +{ + int err = 0; + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if (old) + *old = ss->stack; + + if (stack) + { + if (stack->ss_size < MINSIGSTKSZ) + { + err = ENOMEM; + goto out; + } + + if ((stack->ss_flags & ~(SS_DISABLE))) + /* Flags contains a value other than SS_DISABLE. */ + { + err = EINVAL; + goto out; + } + + if ((ss->stack.ss_flags & SS_ONSTACK)) + /* Stack in use. */ + { + err = EPERM; + goto out; + } + + ss->stack = *stack; + } + + out: + pthread_mutex_unlock (&ss->lock); + + if (err) + { + errno = err; + return -1; + } + return 0; +} diff --git a/libpthread/signal/signal-dispatch.c b/libpthread/signal/signal-dispatch.c new file mode 100644 index 00000000..40440b70 --- /dev/null +++ b/libpthread/signal/signal-dispatch.c @@ -0,0 +1,117 @@ +/* signal-dispatch.c - Signal dispatcher. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +/* This is the signal handler entry point. A thread is forced into + this state when it receives a signal. We need to save the thread's + state and then invoke the high-level signal dispatcher. SS->LOCK + is locked by the caller. */ +void +signal_dispatch (struct signal_state *ss, siginfo_t *si) +{ + SIGNAL_DISPATCH_ENTRY; + + int signo = si->si_signo; + + assert (signo > 0 && signo < NSIG); + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + do + { + if ((sigmask (signo) & STOPSIGS)) + /* Stop signals clear a pending SIGCONT even if they + are handled or ignored (but not if preempted). */ + { + sigdelset (&ss->pending, SIGCONT); + sigdelset (&process_pending, SIGCONT); + } + else if ((signo == SIGCONT)) + /* Even if handled or ignored (but not preempted), SIGCONT + clears stop signals and resumes the process. */ + { + ss->pending &= ~STOPSIGS; + process_pending &= ~STOPSIGS; + } + + void (*handler)(int, siginfo_t *, void *) + = ss->actions[signo - 1].sa_sigaction; + + /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot + be automatically reset when delivered; the system silently + enforces this restriction (sigaction). */ + if (ss->actions[signo - 1].sa_flags & SA_RESETHAND + && signo != SIGILL && signo != SIGTRAP) + ss->actions[signo - 1].sa_handler = SIG_DFL; + + sigset_t orig_blocked = ss->blocked; + /* Block requested signals while running the handler. */ + ss->blocked |= ss->actions[signo - 1].sa_mask; + + /* Block SIGNO unless we're asked not to. */ + if (! (ss->actions[signo - 1].sa_flags & (SA_RESETHAND | SA_NODEFER))) + sigaddset (&ss->blocked, signo); + + sigdelset (&ss->pending, signo); + pthread_mutex_unlock (&ss->lock); + + pthread_mutex_lock (&sig_lock); + sigdelset (&process_pending, signo); + pthread_mutex_unlock (&sig_lock); + + if (handler == (void *) SIG_DFL) + { + enum sig_action action = default_action (signo); + + if (action == sig_terminate || action == sig_core) + _exit (128 + signo); + + if (action == sig_stop) + /* XXX: Implement me. */ + panic ("Stopping process unimplemented."); + + if (action == sig_cont) + /* XXX: Implement me. */; + panic ("Continuing process unimplemented."); + } + else if (handler == (void *) SIG_IGN) + ; + else + handler (signo, si, NULL); + + pthread_mutex_lock (&ss->lock); + + /* "When a thread's signal mask is changed in a signal-catching + function that is installed by sigaction(), the restoration of + the signal mask on return from the signal-catching function + overrides that change (see sigaction())" (sigprocmask). */ + ss->blocked = orig_blocked; + + sigset_t pending = ~ss->blocked & ss->pending; + if (! pending) + pending = ~ss->blocked & process_pending; + signo = l4_lsb64 (pending); + } + while (signo); + + pthread_mutex_unlock (&ss->lock); + + SIGNAL_DISPATCH_EXIT; +} diff --git a/libpthread/signal/signal.h b/libpthread/signal/signal.h new file mode 100644 index 00000000..a33d995c --- /dev/null +++ b/libpthread/signal/signal.h @@ -0,0 +1,275 @@ +/* signal.h - Signal handling interface. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#ifndef _SIGNAL_H +#define _SIGNAL_H 1 + +#include +#include + +typedef volatile int sig_atomic_t; + +typedef uint64_t sigset_t; + +int sigaddset (sigset_t *, int); +int sigdelset (sigset_t *, int); +int sigemptyset (sigset_t *); +int sigfillset (sigset_t *); +int sigismember (const sigset_t *, int); + +/* These values are consistent with Linux. */ +#define SIGRTMIN 34 +#define SIGRTMAX 64 + +enum + { + SIGHUP = 1, +#define SIGHUP SIGHUP + SIGINT, +#define SIGINT SIGINT + SIGQUIT, +#define SIGQUIT SIGQUIT + SIGILL, +#define SIGILL SIGILL + SIGTRAP, +#define SIGTRAP SIGTRAP + SIGABRT, +#define SIGABRT SIGABRT + SIGBUS, +#define SIGBUS SIGBUS + SIGFPE, +#define SIGFPE SIGFPE + SIGKILL, +#define SIGKILL SIGKILL + SIGUSR1, +#define SIGUSR1 SIGUSR1 + SIGSEGV, +#define SIGSEGV SIGSEGV + SIGUSR2, +#define SIGUSR2 SIGUSR2 + SIGPIPE, +#define SIGPIPE SIGPIPE + SIGALRM, +#define SIGALRM SIGALRM + SIGTERM, +#define SIGTERM SIGTERM + SIGSTKFLT, +#define SIGSTKFLT SIGSTKFLT + SIGCHLD, +#define SIGCHLD SIGCHLD + SIGCONT, +#define SIGCONT SIGCONT + SIGSTOP, +#define SIGSTOP SIGSTOP + SIGTSTP, +#define SIGTSTP SIGTSTP + SIGTTIN, +#define SIGTTIN SIGTTIN + SIGTTOU, +#define SIGTTOU SIGTTOU + SIGURG, +#define SIGURG SIGURG + SIGXCPU, +#define SIGXCPU SIGXCPU + SIGXFSZ, +#define SIGXFSZ SIGXFSZ + SIGVTALRM, +#define SIGVTALRM SIGVTALRM + SIGPROF, +#define SIGPROF SIGPROF + SIGWINCH, +#define SIGWINCH SIGWINCH + SIGIO, +#define SIGIO SIGIO + SIGPWR, +#define SIGPWR SIGPWR + SIGSYS, +#define SIGSYS SIGSYS + NSIG + }; + +/* The resulting set is the union of the current set and the signal + set pointed to by the argument set. */ +#define SIG_BLOCK 1 +/* The resulting set is the intersection of the current set and the + complement of the signal set pointed to by the argument set. */ +#define SIG_UNBLOCK 2 +/* The resulting set is the signal set pointed to by the argument + set. */ +#define SIG_SETMASK 3 + +int pthread_sigmask (int how, const sigset_t *mask, sigset_t *old); +int sigprocmask (int how, const sigset_t *restrict mask, + sigset_t *restrict old); + +/* Return set of pending signals. */ +int sigpending(sigset_t *set); + +union sigval +{ + int sival_int; + void *sival_ptr; +}; + +#define SIG_DFL ((void (*)(int)) (0)) +#define SIG_ERR ((void (*)(int)) (-1)) +#define SIG_IGN ((void (*)(int)) (1)) + +/* Causes signal delivery to occur on an alternate stack. */ +#define SA_ONSTACK (1 << 0) +/* Do not generate SIGCHLD when children stop or stopped children + continue. */ +#define SA_NOCLDSTOP (1 << 1) +/* Causes signal dispositions to be set to SIG_DFL on entry to signal + handlers. */ +#define SA_RESETHAND (1 << 2) +/* Causes certain functions to become restartable. */ +#define SA_RESTART (1 << 3) +/* Causes extra information to be passed to signal handlers at the + time of receipt of a signal. */ +#define SA_SIGINFO (1 << 4) +/* Causes implementations not to create zombie processes on child + death. */ +#define SA_NOCLDWAIT (1 << 5) +/* Causes signal not to be automatically blocked on entry to + signal handler. */ +#define SA_NODEFER (1 << 6) + +typedef struct +{ + int si_signo; + int si_code; + int si_errno; + pid_t si_pid; + uid_t si_uid; + void *si_addr; + int si_status; + long si_band; + union sigval si_value; +} siginfo_t; + +struct sigaction +{ + union + { + /* Pointer to a signal-catching function or one of the macros + SIG_IGN or SIG_DFL. */ + void (*sa_handler)(int); + + /* Pointer to a signal-catching function. */ + void (*sa_sigaction)(int, siginfo_t *, void *); + }; + + /* Set of signals to be blocked during execution of the signal + handling function. */ + sigset_t sa_mask; + + /* Special flags. */ + int sa_flags; +}; + +int sigaction (int signo, const struct sigaction *restrict newaction, + struct sigaction *restrict oldaction); + +void (*signal (int signo, void (*handler)(int)))(int); +void (*bsd_signal (int signo, void (*handler)(int)))(int); + +/* Process is executing on an alternate signal stack. */ +#define SS_ONSTACK (1 << 0) +/* Alternate signal stack is disabled. */ +#define SS_DISABLE (1 << 1) + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ PAGESIZE +/* Default size in bytes for the alternate signal stack. */ +#define SIGSTKSZ (16 * PAGESIZE) + +typedef struct +{ + void *ss_sp; + size_t ss_size; + int ss_flags; +} stack_t; + +int sigaltstack(const stack_t *restrict stack, stack_t *restrict old); + +#include + +/* Send SIGNO to the process PID. */ +int kill(pid_t pid, int signo); + +/* Send SIGNO to the process group PG. */ +int killpg(pid_t pg, int signo); + +/* Send SIGNO to thread TID. */ +int pthread_kill(pthread_t tid, int signo); + +/* Send a signal to thread TID using SIGINFO. */ +int pthread_kill_siginfo_np (pthread_t tid, siginfo_t siginfo); + +/* Send SIGNO to the calling thread. */ +int raise(int signo); + +typedef struct sigevent +{ + /* Notification type. */ + int sigev_notify; + + /* Signal number. */ + int sigev_signo; + + /* Signal value. */ + union sigval sigev_value; + + /* Notification function. */ + void (*sigev_notify_function) (union sigval); + + /* Notification attributes. */ + pthread_attr_t *sigev_notify_attributes; +} sigevent_t; + +enum + { + SIGEV_NONE = 0, +#define SIGEV_NONE SIGEV_NONE + SIGEV_SIGNAL, +#define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_THREAD +#define SIGEV_THREAD SIGEV_THREAD + }; + +#define SIG_HOLD + +int sighold (int); +int sigignore (int); +int siginterrupt (int, int); +int sigpause (int); +int sigqueue (pid_t, int, const union sigval); +int sigrelse (int); +void (*sigset (int, void (*)(int)))(int); +int sigsuspend (const sigset_t *); + +/* Wait for a signal. */ +int sigwait (const sigset_t *restrict set, int *restrict signo); +int sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info); +int sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, + const struct timespec *restrict timespec); + +#endif diff --git a/libpthread/signal/sigpending.c b/libpthread/signal/sigpending.c new file mode 100644 index 00000000..609b55d6 --- /dev/null +++ b/libpthread/signal/sigpending.c @@ -0,0 +1,38 @@ +/* sigpending.c - Generic sigpending implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +int +sigpending (sigset_t *set) +{ + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + /* There is no need to lock SIG_LOCK for process_pending since we + just read it, which is atomic. */ + *set = (ss->pending | process_pending) & ss->blocked; + + pthread_mutex_unlock (&ss->lock); + + return 0; +} diff --git a/libpthread/signal/sigsuspend.c b/libpthread/signal/sigsuspend.c new file mode 100644 index 00000000..73cf12a1 --- /dev/null +++ b/libpthread/signal/sigsuspend.c @@ -0,0 +1,29 @@ +/* sigsuspend.c - Generic sigsuspend implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigsuspend (const sigset_t *set) +{ + /* XXX: Implement me. */ + errno = EOPNOTSUPP; + return -1; +} diff --git a/libpthread/signal/sigtimedwait.c b/libpthread/signal/sigtimedwait.c new file mode 100644 index 00000000..52cd0176 --- /dev/null +++ b/libpthread/signal/sigtimedwait.c @@ -0,0 +1,30 @@ +/* sigtimedwait.c - Generic sigtimedwait implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, + const struct timespec *restrict timeout) +{ + errno = EOPNOTSUPP; + return -1; +} + diff --git a/libpthread/signal/sigwaiter.c b/libpthread/signal/sigwaiter.c new file mode 100644 index 00000000..8d041ac1 --- /dev/null +++ b/libpthread/signal/sigwaiter.c @@ -0,0 +1,91 @@ +/* sigwaiter.c - Signal handling functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +#include + +struct sigwaiter *sigwaiters; + +siginfo_t +sigwaiter_block (struct signal_state *ss, const sigset_t *restrict set) +{ + assert (pthread_mutex_trylock (&sig_lock) == EBUSY); + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + assert (! ss->sigwaiter); + + struct sigwaiter waiter; + + waiter.next = sigwaiters; + if (waiter.next) + { + assert (! waiter.next->prev); + waiter.next->prev = &waiter; + } + waiter.prev = 0; + sigwaiters = &waiter; + + waiter.ss = ss; + waiter.info.si_signo = 0; + waiter.signals = *set; + + ss->sigwaiter = &waiter; + + pthread_mutex_unlock (&ss->lock); + pthread_mutex_unlock (&sig_lock); + + futex_wait (&waiter.info.si_signo, 0); + +#ifndef NDEBUG + pthread_mutex_lock (&ss->lock); + ss->sigwaiter = 0; + pthread_mutex_unlock (&ss->lock); +#endif + + assert (waiter.info.si_signo); + return waiter.info; +} + +void +sigwaiter_unblock (struct sigwaiter *waiter) +{ + assert (pthread_mutex_trylock (&sig_lock) == EBUSY); + assert (pthread_mutex_trylock (&waiter->ss->lock) == EBUSY); + + struct sigwaiter *prev = waiter->prev; + struct sigwaiter *next = waiter->next; + + if (next) + next->prev = prev; + + if (prev) + prev->next = next; + else + sigwaiters = next; + + sigdelset (&process_pending, waiter->info.si_signo); + sigdelset (&waiter->ss->pending, waiter->info.si_signo); + + pthread_mutex_unlock (&waiter->ss->lock); + pthread_mutex_unlock (&sig_lock); + + futex_wake (&waiter->info.si_signo, 1); +} diff --git a/libpthread/signal/sigwaitinfo.c b/libpthread/signal/sigwaitinfo.c new file mode 100644 index 00000000..1b47079e --- /dev/null +++ b/libpthread/signal/sigwaitinfo.c @@ -0,0 +1,74 @@ +/* sigwaitinfo.c - Generic sigwaitinfo implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +int +sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info) +{ + pthread_mutex_lock (&sig_lock); + + struct signal_state *ss = &_pthread_self ()->ss; + + pthread_mutex_lock (&ss->lock); + + if ((process_pending & *set) || (ss->pending & *set)) + /* There is at least one signal pending. */ + { + bool local = true; + sigset_t extant = process_pending & *set; + if (! extant) + { + local = false; + extant = ss->pending & *set; + } + + assert (extant); + + int signo = l4_msb64 (extant); + + if (info) + { + if (local) + *info = ss->info[signo - 1]; + else + *info = process_pending_info[signo - 1]; + info->si_signo = signo; + } + + sigdelset (&process_pending, signo); + sigdelset (&ss->pending, signo); + + pthread_mutex_unlock (&ss->lock); + pthread_mutex_unlock (&sig_lock); + return 0; + } + + siginfo_t i = sigwaiter_block (ss, set); + assert (i.si_signo); + assert ((sigmask (i.si_signo) & *set)); + + if (info) + *info = i; + + return 0; +} + diff --git a/libpthread/sysdeps/generic/bits/barrier-attr.h b/libpthread/sysdeps/generic/bits/barrier-attr.h new file mode 100644 index 00000000..a9900b71 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/barrier-attr.h @@ -0,0 +1,32 @@ +/* Thread barrier attribute type. Generic version. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_BARRIER_ATTR_H +#define _BITS_BARRIER_ATTR_H 1 + +enum __pthread_process_shared; + +/* This structure describes the attributes of a POSIX thread barrier. + Note that not all of them are supported on all systems. */ +struct __pthread_barrierattr +{ + enum __pthread_process_shared pshared; +}; + +#endif /* bits/barrier-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/barrier.h b/libpthread/sysdeps/generic/bits/barrier.h new file mode 100644 index 00000000..5e559312 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/barrier.h @@ -0,0 +1,39 @@ +/* Thread barrier attribute type. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_BARRIER_H +#define _BITS_BARRIER_H 1 + +#include + +/* This structure describes the attributes of a POSIX barrier. */ +struct __pthread_barrier +{ + __pthread_spinlock_t lock; + struct __pthread *queue; /* List of waiters. */ + unsigned pending; /* Number of that still need to wait on + barrier. */ + unsigned count; /* Number of threads that must wait before + barrier is passed. */ + struct __pthread_barrierattr *attr; + void *data; +}; + + +#endif /* bits/barrier.h */ diff --git a/libpthread/sysdeps/generic/bits/cancelation.h b/libpthread/sysdeps/generic/bits/cancelation.h new file mode 100644 index 00000000..f446d595 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/cancelation.h @@ -0,0 +1,54 @@ +/* Cancelation. Generic version. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_CANCELATION_H +#define _BITS_CANCELATION_H 1 + +#include + +struct __pthread_cancelation_handler +{ + void (*handler)(void *); + void *arg; + struct __pthread_cancelation_handler *next; +}; + +/* Returns the thread local location of the cleanup handler stack. */ +struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); + +#define __pthread_cleanup_push(rt, rtarg) \ + { \ + struct __pthread_cancelation_handler **__handlers \ + = __pthread_get_cleanup_stack (); \ + struct __pthread_cancelation_handler __handler = \ + { \ + handler: (rt), \ + arg: (rtarg), \ + next: *__handlers \ + }; \ + *__handlers = &__handler; + +#define __pthread_cleanup_pop(execute) \ + if (execute) \ + __handler.handler (__handler.arg); \ + assert (*__handlers == &__handler); \ + *__handlers = __handler.next; \ + } + +#endif /* _BITS_CANCELATION_H */ diff --git a/libpthread/sysdeps/generic/bits/condition-attr.h b/libpthread/sysdeps/generic/bits/condition-attr.h new file mode 100644 index 00000000..a1311286 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/condition-attr.h @@ -0,0 +1,34 @@ +/* Condition attribute type. Generic version. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_CONDITION_ATTR_H +#define _BITS_CONDITION_ATTR_H 1 + +#include + +enum __pthread_process_shared; + +/* User visible part of a condition attribute variable. */ +struct __pthread_condattr + { + enum __pthread_process_shared pshared; + clockid_t clock; + }; + +#endif /* bits/condition.h */ diff --git a/libpthread/sysdeps/generic/bits/condition.h b/libpthread/sysdeps/generic/bits/condition.h new file mode 100644 index 00000000..bf13adab --- /dev/null +++ b/libpthread/sysdeps/generic/bits/condition.h @@ -0,0 +1,39 @@ +/* Condition type. Generic version. + Copyright (C) 2000, 2005, 2009 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_CONDITION_H +#define _BITS_CONDITION_H 1 + +#include + +/* User visible part of a condition variable. */ +struct __pthread_cond + { + __pthread_spinlock_t __lock; + struct __pthread *__queue; + struct __pthread_condattr *__attr; + struct __pthread_condimpl *__impl; + void *__data; + }; + +/* Initializer for a condition variable. */ +#define __PTHREAD_COND_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL } + +#endif /* bits/condition.h */ diff --git a/libpthread/sysdeps/generic/bits/mutex-attr.h b/libpthread/sysdeps/generic/bits/mutex-attr.h new file mode 100644 index 00000000..9161cdab --- /dev/null +++ b/libpthread/sysdeps/generic/bits/mutex-attr.h @@ -0,0 +1,40 @@ +/* Mutex attribute type. Generic version. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MUTEX_ATTR_H +#define _BITS_MUTEX_ATTR_H 1 + +enum __pthread_mutex_protocol; +enum __pthread_process_shared; +enum __pthread_mutex_type; + +/* This structure describes the attributes of a POSIX mutex + attribute. */ +struct __pthread_mutexattr +{ + int prioceiling; + enum __pthread_mutex_protocol protocol; + enum __pthread_process_shared pshared; + enum __pthread_mutex_type mutex_type; +}; + +/* Attributes for a recursive mutex. */ +extern const struct __pthread_mutexattr __pthread_recursive_mutexattr; + +#endif /* bits/mutex-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/mutex.h b/libpthread/sysdeps/generic/bits/mutex.h new file mode 100644 index 00000000..86068cf5 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/mutex.h @@ -0,0 +1,67 @@ +/* Mutex type. Generic version. + + Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008, 2009 + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MUTEX_H + +#ifndef __need_pthread_mutex +# define _BITS_MUTEX_H 1 +#endif + +#ifndef __pthread_mutex_defined +# if defined __need_pthread_mutex || defined _BITS_MUTEX_H +# undef __need_pthread_mutex +# define __pthread_mutex_defined + +# include +# include + +/* User visible part of a mutex. */ +struct __pthread_mutex + { + __pthread_spinlock_t __held; + __pthread_spinlock_t __lock; + /* In cthreads, mutex_init does not initialized thre third + pointer, as such, we cannot rely on its value for anything. */ + char *cthreadscompat1; + struct __pthread *__queue; + struct __pthread_mutexattr *attr; + void *data; + /* Up to this point, we are completely compatible with cthreads + and what libc expects. */ + void *owner; + unsigned locks; + /* If NULL then the default attributes apply. */ + }; + +/* Initializer for a mutex. N.B. this also happens to be compatible + with the cthread mutex initializer. */ +# define __PTHREAD_MUTEX_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } + +# define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ + (struct __pthread_mutexattr *) &__pthread_recursive_mutexattr, 0, 0, 0 } + +# endif +#endif /* Not __pthread_mutex_defined. */ + +#endif /* bits/mutex.h */ diff --git a/libpthread/sysdeps/generic/bits/once.h b/libpthread/sysdeps/generic/bits/once.h new file mode 100644 index 00000000..f4985d6f --- /dev/null +++ b/libpthread/sysdeps/generic/bits/once.h @@ -0,0 +1,34 @@ +/* Dynamic package initialization data structures. Generic version. + Copyright (C) 2002, 2009 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_ONCE_H +#define _BITS_ONCE_H 1 + +#include + +struct __pthread_once +{ + int run; + __pthread_spinlock_t lock; +}; + +#define __PTHREAD_ONCE_INIT \ + { 0, __PTHREAD_SPIN_LOCK_INITIALIZER } + +#endif /* bits/once.h */ diff --git a/libpthread/sysdeps/generic/bits/pthread-np.h b/libpthread/sysdeps/generic/bits/pthread-np.h new file mode 100644 index 00000000..d5ddbb05 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/pthread-np.h @@ -0,0 +1,27 @@ +/* Non-portable functions. Generic version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/generic/bits/pthread.h b/libpthread/sysdeps/generic/bits/pthread.h new file mode 100644 index 00000000..80e6b096 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/pthread.h @@ -0,0 +1,38 @@ +/* Pthread data structures. Generic version. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_PTHREAD_H +#define _BITS_PTHREAD_H 1 + +typedef int __pthread_t; + +/* Return true if __T1 and __T2 both name the same thread. Otherwise, + false. */ +extern int +__pthread_equal (__pthread_t __t1, __pthread_t __t2); + +#ifdef __USE_EXTERN_INLINES +__extern_inline int +__pthread_equal (__pthread_t __t1, __pthread_t __t2) +{ + return __t1 == __t2; +} +#endif + +#endif /* bits/pthread.h */ diff --git a/libpthread/sysdeps/generic/bits/pthreadtypes.h b/libpthread/sysdeps/generic/bits/pthreadtypes.h new file mode 100644 index 00000000..e5cbfd2a --- /dev/null +++ b/libpthread/sysdeps/generic/bits/pthreadtypes.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/sysdeps/generic/bits/rwlock-attr.h b/libpthread/sysdeps/generic/bits/rwlock-attr.h new file mode 100644 index 00000000..dba99f1d --- /dev/null +++ b/libpthread/sysdeps/generic/bits/rwlock-attr.h @@ -0,0 +1,32 @@ +/* Thread rwlock attribute type. Generic version. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_RWLOCK_ATTR_H +#define _BITS_RWLOCK_ATTR_H 1 + +enum __pthread_process_shared; + +/* This structure describes the attributes of a POSIX thread rwlock. + Note that not all of them are supported on all systems. */ +struct __pthread_rwlockattr +{ + enum __pthread_process_shared pshared; +}; + +#endif /* bits/rwlock-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/rwlock.h b/libpthread/sysdeps/generic/bits/rwlock.h new file mode 100644 index 00000000..af6b1c86 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/rwlock.h @@ -0,0 +1,46 @@ +/* rwlock type. Generic version. + Copyright (C) 2002, 2005, 2006, 2007, 2009 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_RWLOCK_H +#define _BITS_RWLOCK_H + +#include + +/* User visible part of a rwlock. If __held is not held and readers + is 0, then the lock is unlocked. If __held is held and readers is + 0, then the lock is held by a writer. If __held is held and + readers is greater than 0, then the lock is held by READERS + readers. */ +struct __pthread_rwlock + { + __pthread_spinlock_t __held; + __pthread_spinlock_t __lock; + int readers; + struct __pthread *readerqueue; + struct __pthread *writerqueue; + struct __pthread_rwlockattr *__attr; + void *__data; + }; + +/* Initializer for a rwlock. */ +#define __PTHREAD_RWLOCK_INITIALIZER \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } + + +#endif /* bits/rwlock.h */ diff --git a/libpthread/sysdeps/generic/bits/semaphore.h b/libpthread/sysdeps/generic/bits/semaphore.h new file mode 100644 index 00000000..5e987c15 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/semaphore.h @@ -0,0 +1,43 @@ +/* Semaphore type. Generic version. + Copyright (C) 2005, 2009 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_SEMAPHORE_H +#define _BITS_SEMAPHORE_H 1 + +#ifndef _SEMAPHORE_H +#error Never include directly. +#endif + +#include + +/* User visible part of a semaphore. */ +struct __semaphore + { + __pthread_spinlock_t __lock; + struct __pthread *__queue; + int __pshared; + int __value; + void *__data; + }; + +/* Initializer for a semaphore. */ +#define __SEMAPHORE_INITIALIZER(pshared, value) \ + { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, (pshared), (value), NULL } + +#endif /* bits/mutex.h */ diff --git a/libpthread/sysdeps/generic/bits/thread-attr.h b/libpthread/sysdeps/generic/bits/thread-attr.h new file mode 100644 index 00000000..c3a93fde --- /dev/null +++ b/libpthread/sysdeps/generic/bits/thread-attr.h @@ -0,0 +1,43 @@ +/* Thread attribute type. Generic version. + Copyright (C) 2000, 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_THREAD_ATTR_H +#define _BITS_THREAD_ATTR_H 1 + +#include + +enum __pthread_detachstate; +enum __pthread_inheritsched; +enum __pthread_contentionscope; + +/* This structure describes the attributes of a POSIX thread. Note + that not all of them are supported on all systems. */ +struct __pthread_attr +{ + struct sched_param schedparam; + void *stackaddr; + size_t stacksize; + size_t guardsize; + enum __pthread_detachstate detachstate; + enum __pthread_inheritsched inheritsched; + enum __pthread_contentionscope contentionscope; + int schedpolicy; +}; + +#endif /* bits/thread-attr.h */ diff --git a/libpthread/sysdeps/generic/bits/thread-specific.h b/libpthread/sysdeps/generic/bits/thread-specific.h new file mode 100644 index 00000000..b42d99e7 --- /dev/null +++ b/libpthread/sysdeps/generic/bits/thread-specific.h @@ -0,0 +1,25 @@ +/* Thread specific data. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_THREAD_SPECIFIC_H +#define _BITS_THREAD_SPECIFIC_H 1 + +typedef int __pthread_key; + +#endif /* bits/thread-specific.h */ diff --git a/libpthread/sysdeps/generic/killpg.c b/libpthread/sysdeps/generic/killpg.c new file mode 100644 index 00000000..7f7ed87d --- /dev/null +++ b/libpthread/sysdeps/generic/killpg.c @@ -0,0 +1,27 @@ +/* killpg.c - Generic killpg implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +killpg (pid_t pid, int sig) +{ + return kill (-pid, sig); +} diff --git a/libpthread/sysdeps/generic/pt-atfork.c b/libpthread/sysdeps/generic/pt-atfork.c new file mode 100644 index 00000000..32e1e78c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-atfork.c @@ -0,0 +1,29 @@ +/* Register fork handlers. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_atfork (void (*prepare) (void), + void (*parent) (void), + void (*child) (void)) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-attr-destroy.c b/libpthread/sysdeps/generic/pt-attr-destroy.c new file mode 100644 index 00000000..c4b9aa54 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_attr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_destroy (pthread_attr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getdetachstate.c b/libpthread/sysdeps/generic/pt-attr-getdetachstate.c new file mode 100644 index 00000000..be406f1d --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getdetachstate.c @@ -0,0 +1,29 @@ +/* pthread_attr_getdetachstate. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate) +{ + *detachstate = attr->detachstate; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getguardsize.c b/libpthread/sysdeps/generic/pt-attr-getguardsize.c new file mode 100644 index 00000000..c1d9f13e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getguardsize.c @@ -0,0 +1,29 @@ +/* pthread_attr_getguardsize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getguardsize (const pthread_attr_t *attr, + size_t *guardsize) +{ + *guardsize = attr->guardsize; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getinheritsched.c b/libpthread/sysdeps/generic/pt-attr-getinheritsched.c new file mode 100644 index 00000000..cca4e3d7 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getinheritsched.c @@ -0,0 +1,29 @@ +/* pthread_attr_getinheritsched. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inheritsched) +{ + *inheritsched = attr->inheritsched; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getschedparam.c b/libpthread/sysdeps/generic/pt-attr-getschedparam.c new file mode 100644 index 00000000..25afebd0 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getschedparam.c @@ -0,0 +1,31 @@ +/* pthread_attr_getschedparam. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param) +{ + *param = attr->schedparam; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getschedpolicy.c b/libpthread/sysdeps/generic/pt-attr-getschedpolicy.c new file mode 100644 index 00000000..4349a238 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getschedpolicy.c @@ -0,0 +1,29 @@ +/* pthread_attr_getschedpolicy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy) +{ + *policy = attr->schedpolicy; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getscope.c b/libpthread/sysdeps/generic/pt-attr-getscope.c new file mode 100644 index 00000000..97198fa5 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getscope.c @@ -0,0 +1,29 @@ +/* pthread_attr_getscope. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getscope (const pthread_attr_t *attr, + int *contentionscope) +{ + *contentionscope = attr->contentionscope; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getstack.c b/libpthread/sysdeps/generic/pt-attr-getstack.c new file mode 100644 index 00000000..7beb79f0 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getstack.c @@ -0,0 +1,31 @@ +/* pthread_attr_getstack. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getstack (const pthread_attr_t *attr, + void **stackaddr, + size_t *stacksize) +{ + pthread_attr_getstackaddr (attr, stackaddr); + pthread_attr_getstacksize (attr, stacksize); + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getstackaddr.c b/libpthread/sysdeps/generic/pt-attr-getstackaddr.c new file mode 100644 index 00000000..d43eeff7 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getstackaddr.c @@ -0,0 +1,29 @@ +/* pthread_attr_getstackaddr. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getstackaddr (const pthread_attr_t *attr, + void **stackaddr) +{ + *stackaddr = attr->stackaddr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-getstacksize.c b/libpthread/sysdeps/generic/pt-attr-getstacksize.c new file mode 100644 index 00000000..c1bc6617 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-getstacksize.c @@ -0,0 +1,29 @@ +/* pthread_attr_getstacksize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_getstacksize (const pthread_attr_t *attr, + size_t *stacksize) +{ + *stacksize = attr->stacksize; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-init.c b/libpthread/sysdeps/generic/pt-attr-init.c new file mode 100644 index 00000000..6a930e30 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-init.c @@ -0,0 +1,28 @@ +/* pthread_attr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_init (pthread_attr_t *attr) +{ + *attr = __pthread_default_attr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setdetachstate.c b/libpthread/sysdeps/generic/pt-attr-setdetachstate.c new file mode 100644 index 00000000..688ba5d6 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setdetachstate.c @@ -0,0 +1,38 @@ +/* pthread_attr_setdetachstate. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate) +{ + switch (detachstate) + { + case PTHREAD_CREATE_DETACHED: + case PTHREAD_CREATE_JOINABLE: + attr->detachstate = detachstate; + break; + default: + return EINVAL; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setguardsize.c b/libpthread/sysdeps/generic/pt-attr-setguardsize.c new file mode 100644 index 00000000..b2ba0f0f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setguardsize.c @@ -0,0 +1,29 @@ +/* pthread_attr_setguardsize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setguardsize (pthread_attr_t *attr, + size_t guardsize) +{ + attr->guardsize = guardsize; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setinheritsched.c b/libpthread/sysdeps/generic/pt-attr-setinheritsched.c new file mode 100644 index 00000000..e9012c58 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setinheritsched.c @@ -0,0 +1,38 @@ +/* pthread_attr_setinheritsched. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setinheritsched (pthread_attr_t *attr, + int inheritsched) +{ + switch (inheritsched) + { + case PTHREAD_INHERIT_SCHED: + case PTHREAD_EXPLICIT_SCHED: + attr->inheritsched = inheritsched; + break; + default: + return EINVAL; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setschedparam.c b/libpthread/sysdeps/generic/pt-attr-setschedparam.c new file mode 100644 index 00000000..18a575ec --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setschedparam.c @@ -0,0 +1,38 @@ +/* pthread_attr_getschedparam. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param) +{ + if (memcmp (param, &__pthread_default_attr.schedparam, + sizeof *param) == 0) + { + attr->schedparam = *param; + return 0; + } + + return ENOTSUP; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setschedpolicy.c b/libpthread/sysdeps/generic/pt-attr-setschedpolicy.c new file mode 100644 index 00000000..e481d04c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setschedpolicy.c @@ -0,0 +1,42 @@ +/* pthread_attr_getschedpolicy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setschedpolicy (pthread_attr_t *attr, + int policy) +{ + switch (policy) + { + case SCHED_OTHER: + attr->schedpolicy = policy; + break; + + case SCHED_FIFO: + case SCHED_RR: + return ENOTSUP; + + default: + return EINVAL; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setscope.c b/libpthread/sysdeps/generic/pt-attr-setscope.c new file mode 100644 index 00000000..c74a4f67 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setscope.c @@ -0,0 +1,41 @@ +/* pthread_attr_setscope. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setscope (pthread_attr_t *attr, + int contentionscope) +{ + if (contentionscope == __pthread_default_attr.contentionscope) + { + attr->contentionscope = contentionscope; + return 0; + } + + switch (contentionscope) + { + case PTHREAD_SCOPE_PROCESS: + case PTHREAD_SCOPE_SYSTEM: + return ENOTSUP; + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-attr-setstack.c b/libpthread/sysdeps/generic/pt-attr-setstack.c new file mode 100644 index 00000000..360d27a3 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setstack.c @@ -0,0 +1,51 @@ +/* pthread_attr_setstack. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_attr_setstack (pthread_attr_t *attr, + void *stackaddr, + size_t stacksize) +{ + int err; + size_t s; + + /* pthread_attr_setstack should always succeed, thus we set the size + first as it is more discriminating. */ + pthread_attr_getstacksize (attr, &s); + + err = pthread_attr_setstacksize (attr, stacksize); + if (err) + return err; + + err = pthread_attr_setstackaddr (attr, stackaddr); + if (err) + { + int e = pthread_attr_setstacksize (attr, s); + assert_perror (e); + + return err; + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setstackaddr.c b/libpthread/sysdeps/generic/pt-attr-setstackaddr.c new file mode 100644 index 00000000..431f2d0c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setstackaddr.c @@ -0,0 +1,29 @@ +/* pthread_attr_setstackaddr. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr) +{ + attr->stackaddr = stackaddr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-attr-setstacksize.c b/libpthread/sysdeps/generic/pt-attr-setstacksize.c new file mode 100644 index 00000000..d0e51022 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr-setstacksize.c @@ -0,0 +1,41 @@ +/* pthread_attr_setstacksize. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + if (stacksize == __pthread_default_attr.stacksize) + { + attr->stacksize = stacksize; + + /* The guard size cannot be larger than the stack itself, as + such, if the new stack size is smaller than the guard size, + we squash the guard size. */ + if (attr->guardsize > attr->stacksize) + attr->guardsize = attr->stacksize; + + return 0; + } + + return ENOTSUP; +} diff --git a/libpthread/sysdeps/generic/pt-attr.c b/libpthread/sysdeps/generic/pt-attr.c new file mode 100644 index 00000000..769f292a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-attr.c @@ -0,0 +1,41 @@ +/* Default attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +const struct __pthread_attr __pthread_default_attr = +{ + schedparam: { sched_priority: 0 }, + stacksize: PTHREAD_STACK_DEFAULT, + stackaddr: NULL, +#ifdef PAGESIZE + guardsize: PAGESIZE, +#else + guardsize: 0, +#endif /* PAGESIZE */ + detachstate: PTHREAD_CREATE_JOINABLE, + inheritsched: PTHREAD_EXPLICIT_SCHED, + contentionscope: PTHREAD_SCOPE_SYSTEM, + schedpolicy: SCHED_OTHER +}; diff --git a/libpthread/sysdeps/generic/pt-barrier-destroy.c b/libpthread/sysdeps/generic/pt-barrier-destroy.c new file mode 100644 index 00000000..01b938b4 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier-destroy.c @@ -0,0 +1,27 @@ +/* pthread_barrier_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrier_destroy (pthread_barrier_t *barrier) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrier-init.c b/libpthread/sysdeps/generic/pt-barrier-init.c new file mode 100644 index 00000000..c42b3bb6 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier-init.c @@ -0,0 +1,53 @@ +/* pthread_barrier_init. Generic version. + Copyright (C) 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +pthread_barrier_init (pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned count) +{ + if (count == 0) + return EINVAL; + + memset (barrier, 0, sizeof *barrier); + + barrier->lock = PTHREAD_SPINLOCK_INITIALIZER; + barrier->pending = count; + barrier->count = count; + + if (! attr + || memcmp (attr, &__pthread_default_barrierattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + barrier->attr = malloc (sizeof *attr); + if (! barrier->attr) + return ENOMEM; + + *barrier->attr = *attr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrier-wait.c b/libpthread/sysdeps/generic/pt-barrier-wait.c new file mode 100644 index 00000000..f1de250a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier-wait.c @@ -0,0 +1,61 @@ +/* pthread_barrier_wait. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_barrier_wait (pthread_barrier_t *barrier) +{ + __pthread_spin_lock (&barrier->lock); + if (-- barrier->pending == 0) + { + barrier->pending = barrier->count; + + if (barrier->count > 1) + { + struct __pthread *wakeup; + + wakeup = barrier->queue; + barrier->queue = NULL; + __pthread_spin_unlock (&barrier->lock); + + /* We can safely walk the list of waiting threads without + holding the lock since it is decoupled from the barrier + variable now. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + } + + return PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + struct __pthread *self = _pthread_self (); + + /* Add ourselves to the list of waiters. */ + __pthread_enqueue (&barrier->queue, self); + __pthread_spin_unlock (&barrier->lock); + + __pthread_block (self); + return 0; + } +} diff --git a/libpthread/sysdeps/generic/pt-barrier.c b/libpthread/sysdeps/generic/pt-barrier.c new file mode 100644 index 00000000..d772719f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrier.c @@ -0,0 +1,26 @@ +/* Default barrier attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +const struct __pthread_barrierattr __pthread_default_barrierattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE +}; diff --git a/libpthread/sysdeps/generic/pt-barrierattr-destroy.c b/libpthread/sysdeps/generic/pt-barrierattr-destroy.c new file mode 100644 index 00000000..eb396347 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_barrierattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_destroy (pthread_barrierattr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrierattr-getpshared.c b/libpthread/sysdeps/generic/pt-barrierattr-getpshared.c new file mode 100644 index 00000000..ed2cdd24 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_barrierattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_getpshared (const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrierattr-init.c b/libpthread/sysdeps/generic/pt-barrierattr-init.c new file mode 100644 index 00000000..45f16cc8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-init.c @@ -0,0 +1,28 @@ +/* pthread_barrierattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_init (pthread_barrierattr_t *attr) +{ + *attr = __pthread_default_barrierattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-barrierattr-setpshared.c b/libpthread/sysdeps/generic/pt-barrierattr-setpshared.c new file mode 100644 index 00000000..84ef2df8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-barrierattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_barrierattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-cond-brdcast.c b/libpthread/sysdeps/generic/pt-cond-brdcast.c new file mode 100644 index 00000000..3f55e33e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-brdcast.c @@ -0,0 +1,42 @@ +/* Broadcast a condition. Generic version. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Unblock all threads that are blocked on condition variable COND. */ +int +pthread_cond_broadcast (pthread_cond_t *cond) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&cond->__lock); + + wakeup = cond->__queue; + cond->__queue = NULL; + __pthread_spin_unlock (&cond->__lock); + + /* We can safely walk the list of waiting threads without holding + the lock since it is now decoupled from the condition. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-cond-destroy.c b/libpthread/sysdeps/generic/pt-cond-destroy.c new file mode 100644 index 00000000..eba47784 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-destroy.c @@ -0,0 +1,27 @@ +/* pthread_cond_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_cond_destroy (pthread_cond_t *cond) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-cond-init.c b/libpthread/sysdeps/generic/pt-cond-init.c new file mode 100644 index 00000000..b9e9fb7a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-init.c @@ -0,0 +1,45 @@ +/* pthread_cond_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *attr) +{ + *cond = (pthread_cond_t) __PTHREAD_COND_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_condattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + cond->__attr = malloc (sizeof *attr); + if (! cond->__attr) + return ENOMEM; + + *cond->__attr = *attr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-cond-signal.c b/libpthread/sysdeps/generic/pt-cond-signal.c new file mode 100644 index 00000000..c5e1bc1d --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-signal.c @@ -0,0 +1,54 @@ +/* Signal a condition. Generic version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +static int +cond_signal (struct __pthread_cond *cond, int *unblocked) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&cond->__lock); + wakeup = cond->__queue; + if (wakeup) + __pthread_dequeue (wakeup); + __pthread_spin_unlock (&cond->__lock); + + if (wakeup) + { + /* We found a thread waiting for the condition to be signalled. + Wake it up! */ + __pthread_wakeup (wakeup); + *unblocked = 1; + } + + return 0; +} + +/* Unblock at least one of the threads that are blocked on condition + variable COND. */ +int +pthread_cond_signal (pthread_cond_t *cond) +{ + int unblocked = 0; + + return cond_signal (cond, &unblocked); +} diff --git a/libpthread/sysdeps/generic/pt-cond-timedwait.c b/libpthread/sysdeps/generic/pt-cond-timedwait.c new file mode 100644 index 00000000..c10bdb30 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-timedwait.c @@ -0,0 +1,106 @@ +/* Wait on a condition. Generic version. + Copyright (C) 2000, 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + +int +pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + return __pthread_cond_timedwait_internal (cond, mutex, abstime); +} + +/* Block on condition variable COND until ABSTIME. As a GNU + extension, if ABSTIME is NULL, then wait forever. MUTEX should be + held by the calling thread. On return, MUTEX will be held by the + calling thread. */ +int +__pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + error_t err; + int canceltype; + + void cleanup (void *arg) + { + struct __pthread *self = _pthread_self (); + + __pthread_spin_lock (&cond->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&cond->__lock); + + pthread_setcanceltype (canceltype, &canceltype); + __pthread_mutex_lock (mutex); + } + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + struct __pthread *self = _pthread_self (); + + /* Add ourselves to the list of waiters. */ + __pthread_spin_lock (&cond->__lock); + __pthread_enqueue (&cond->__queue, self); + __pthread_spin_unlock (&cond->__lock); + + __pthread_mutex_unlock (mutex); + + /* Enter async cancelation mode. If cancelation is disabled, then + this does not change anything which is exactly what we want. */ + pthread_cleanup_push (cleanup, 0); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &canceltype); + + if (abstime) + { + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&mutex->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&mutex->__lock); + } + } + else + { + err = 0; + __pthread_block (self); + } + + pthread_cleanup_pop (1); + + return err; +} diff --git a/libpthread/sysdeps/generic/pt-cond-wait.c b/libpthread/sysdeps/generic/pt-cond-wait.c new file mode 100644 index 00000000..a03476df --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond-wait.c @@ -0,0 +1,37 @@ +/* Wait on a condition. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Implemented in pt-cond-timedwait.c. */ +extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); + + +/* Block on condition variable COND. MUTEX should be held by the + calling thread. On return, MUTEX will be held by the calling + thread. */ +int +pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + return __pthread_cond_timedwait_internal (cond, mutex, 0); +} diff --git a/libpthread/sysdeps/generic/pt-cond.c b/libpthread/sysdeps/generic/pt-cond.c new file mode 100644 index 00000000..033e767f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-cond.c @@ -0,0 +1,29 @@ +/* Default condition attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +const struct __pthread_condattr __pthread_default_condattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE, + clock: CLOCK_REALTIME +}; diff --git a/libpthread/sysdeps/generic/pt-condattr-destroy.c b/libpthread/sysdeps/generic/pt-condattr-destroy.c new file mode 100644 index 00000000..c8fd71b9 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_condattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_destroy (pthread_condattr_t *cond) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-getclock.c b/libpthread/sysdeps/generic/pt-condattr-getclock.c new file mode 100644 index 00000000..5b9f8893 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-getclock.c @@ -0,0 +1,31 @@ +/* pthread_condattr_getclock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_condattr_getclock (const pthread_condattr_t *attr, + clockid_t *clock) +{ + *clock = attr->clock; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-getpshared.c b/libpthread/sysdeps/generic/pt-condattr-getpshared.c new file mode 100644 index 00000000..c072a507 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_condattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_getpshared (const pthread_condattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-init.c b/libpthread/sysdeps/generic/pt-condattr-init.c new file mode 100644 index 00000000..cf9e1989 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-init.c @@ -0,0 +1,28 @@ +/* pthread_condattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_init (pthread_condattr_t *attr) +{ + *attr = __pthread_default_condattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-setclock.c b/libpthread/sysdeps/generic/pt-condattr-setclock.c new file mode 100644 index 00000000..984c17e2 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-setclock.c @@ -0,0 +1,33 @@ +/* pthread_condattr_setclock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock) +{ + if (__pthread_default_condattr.clock == clock) + { + attr->clock = clock; + return 0; + } + + return EINVAL; +} diff --git a/libpthread/sysdeps/generic/pt-condattr-setpshared.c b/libpthread/sysdeps/generic/pt-condattr-setpshared.c new file mode 100644 index 00000000..b9f0af83 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-condattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_condattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_condattr_setpshared (pthread_condattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-destroy-specific.c b/libpthread/sysdeps/generic/pt-destroy-specific.c new file mode 100644 index 00000000..b627f872 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-destroy-specific.c @@ -0,0 +1,28 @@ +/* __pthread_destory_specific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +void +__pthread_destory_specifc (struct __pthread *thread) +{ + /* Not support, thus there cannot be any. */ + return; +} diff --git a/libpthread/sysdeps/generic/pt-equal.c b/libpthread/sysdeps/generic/pt-equal.c new file mode 100644 index 00000000..8fbc519c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-equal.c @@ -0,0 +1,29 @@ +/* Default attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* Return true if __T1 and __T2 both name the same thread. Otherwise, + false. */ +int +pthread_equal (pthread_t __t1, pthread_t __t2) +{ + return __t1 == __t2; +} diff --git a/libpthread/sysdeps/generic/pt-getconcurrency.c b/libpthread/sysdeps/generic/pt-getconcurrency.c new file mode 100644 index 00000000..b55c8eef --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getconcurrency.c @@ -0,0 +1,27 @@ +/* Get the current level of desired concurrency. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_getconcurrency (void) +{ + return __pthread_concurrency; +} diff --git a/libpthread/sysdeps/generic/pt-getcpuclockid.c b/libpthread/sysdeps/generic/pt-getcpuclockid.c new file mode 100644 index 00000000..81f6aabd --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getcpuclockid.c @@ -0,0 +1,34 @@ +/* Return a thread's cpu clockid. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_getcpuclockid (pthread_t thread, clockid_t *clock) +{ +#ifdef CLOCK_THREAD_CPUTIME_ID + *clock = CLOCK_THREAD_CPUTIME_ID; + return 0; +#else + return ENOSYS; +#endif +} diff --git a/libpthread/sysdeps/generic/pt-getschedparam.c b/libpthread/sysdeps/generic/pt-getschedparam.c new file mode 100644 index 00000000..c128d02e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getschedparam.c @@ -0,0 +1,28 @@ +/* Get the scheduling parameters for a thread. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-getspecific.c b/libpthread/sysdeps/generic/pt-getspecific.c new file mode 100644 index 00000000..2a7c4a9e --- /dev/null +++ b/libpthread/sysdeps/generic/pt-getspecific.c @@ -0,0 +1,27 @@ +/* pthread_getspecific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_getspecific (pthread_key_t key) +{ + return EINVAL; +} diff --git a/libpthread/sysdeps/generic/pt-init-specific.c b/libpthread/sysdeps/generic/pt-init-specific.c new file mode 100644 index 00000000..00744fb6 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-init-specific.c @@ -0,0 +1,27 @@ +/* __pthread_init_specific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +error_t +__pthread_init_specific (struct __pthread *thread) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-key-create.c b/libpthread/sysdeps/generic/pt-key-create.c new file mode 100644 index 00000000..7ef4b991 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-key-create.c @@ -0,0 +1,27 @@ +/* pthread_key_create. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-key-delete.c b/libpthread/sysdeps/generic/pt-key-delete.c new file mode 100644 index 00000000..6c86f8e2 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-key-delete.c @@ -0,0 +1,27 @@ +/* pthread_key_delete. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_key_delete (pthread_key_t key) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-key.h b/libpthread/sysdeps/generic/pt-key.h new file mode 100644 index 00000000..544eb20f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-key.h @@ -0,0 +1,22 @@ +/* pthread_key internal declatations. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#define PTHREAD_KEY_MEMBERS diff --git a/libpthread/sysdeps/generic/pt-kill.c b/libpthread/sysdeps/generic/pt-kill.c new file mode 100644 index 00000000..0dfac344 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-kill.c @@ -0,0 +1,32 @@ +/* pthread-kill.c - Generic pthread-kill implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +pthread_kill (pthread_t tid, int signo) +{ + siginfo_t si; + memset (&si, 0, sizeof (si)); + si.si_signo = signo; + + return pthread_kill_siginfo_np (tid, si); +} + diff --git a/libpthread/sysdeps/generic/pt-mutex-destroy.c b/libpthread/sysdeps/generic/pt-mutex-destroy.c new file mode 100644 index 00000000..b0ca00f7 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-destroy.c @@ -0,0 +1,38 @@ +/* Destroy a mutex. Generic version. + Copyright (C) 2000, 2002, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +_pthread_mutex_destroy (pthread_mutex_t *mutex) +{ + if (mutex->attr == &__pthread_recursive_mutexattr) + /* Static attributes. */ + ; + else + free (mutex->attr); + + return 0; +} + +strong_alias (_pthread_mutex_destroy, pthread_mutex_destroy); diff --git a/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c b/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c new file mode 100644 index 00000000..eb51639b --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-getprioceiling.c @@ -0,0 +1,28 @@ +/* Get a mutex' priority ceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, + int *prioceiling) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutex-init.c b/libpthread/sysdeps/generic/pt-mutex-init.c new file mode 100644 index 00000000..a818fe3a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-init.c @@ -0,0 +1,53 @@ +/* Initialize a mutex. Generic version. + Copyright (C) 2000, 2002, 2005, 2006, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +int +_pthread_mutex_init (pthread_mutex_t *mutex, + const pthread_mutexattr_t *attr) +{ + *mutex = (pthread_mutex_t) __PTHREAD_MUTEX_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_mutexattr, sizeof (*attr) == 0)) + /* The default attributes. */ + return 0; + + if (attr == &__pthread_recursive_mutexattr) + /* Non-default but known attributes. */ + { + mutex->attr = attr; + return 0; + } + + mutex->attr = malloc (sizeof *attr); + if (! mutex->attr) + return ENOMEM; + + *mutex->attr = *attr; + return 0; +} + +strong_alias (_pthread_mutex_init, pthread_mutex_init); diff --git a/libpthread/sysdeps/generic/pt-mutex-lock.c b/libpthread/sysdeps/generic/pt-mutex-lock.c new file mode 100644 index 00000000..528e593f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-lock.c @@ -0,0 +1,37 @@ +/* Lock a mutex. Generic version. + Copyright (C) 2000, 2002, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Implemented in pt-mutex-timedlock.c. */ +extern int __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, + const struct timespec *abstime); + +/* Lock MUTEX, block if we can't get it. */ +int +__pthread_mutex_lock (struct __pthread_mutex *mutex) +{ + return __pthread_mutex_timedlock_internal (mutex, 0); +} + +strong_alias (__pthread_mutex_lock, _pthread_mutex_lock); +strong_alias (__pthread_mutex_lock, pthread_mutex_lock); diff --git a/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c b/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c new file mode 100644 index 00000000..9fa8e50d --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-setprioceiling.c @@ -0,0 +1,28 @@ +/* Set a mutex' priority ceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prio, + int *oldprio) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutex-timedlock.c b/libpthread/sysdeps/generic/pt-mutex-timedlock.c new file mode 100644 index 00000000..ee432192 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-timedlock.c @@ -0,0 +1,181 @@ +/* Lock a mutex with a timeout. Generic version. + Copyright (C) 2000, 2002, 2005, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Try to lock MUTEX, block until *ABSTIME if it is already held. As + a GNU extension, if TIMESPEC is NULL then wait forever. */ +int +__pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&mutex->__lock); + if (__pthread_spin_trylock (&mutex->__held) == 0) + /* Successfully acquired the lock. */ + { +#ifdef ALWAYS_TRACK_MUTEX_OWNER +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif +#endif + + if (mutex->attr) + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = _pthread_self (); + break; + + default: + LOSE; + } + + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + /* The lock is busy. */ + + self = _pthread_self (); + assert (self); + + if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) + assert (mutex->owner != self); +#endif + } + else + { + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_ERRORCHECK: + if (mutex->owner == self) + { + __pthread_spin_unlock (&mutex->__lock); + return EDEADLK; + } + break; + + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner == self) + { + mutex->locks ++; + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + break; + + default: + LOSE; + } + } + +#if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) +#endif + assert (mutex->owner); + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + /* Add ourselves to the queue. */ + __pthread_enqueue (&mutex->__queue, self); + __pthread_spin_unlock (&mutex->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&mutex->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&mutex->__lock); + + return err; + } + } + else + __pthread_block (self); + +#if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) +#endif + { + assert (mutex->owner == self); + } + + if (mutex->attr) + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + assert (mutex->locks == 0); + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = self; + break; + + default: + LOSE; + } + + return 0; +} + +int +pthread_mutex_timedlock (struct __pthread_mutex *mutex, + const struct timespec *abstime) +{ + return __pthread_mutex_timedlock_internal (mutex, abstime); +} diff --git a/libpthread/sysdeps/generic/pt-mutex-transfer-np.c b/libpthread/sysdeps/generic/pt-mutex-transfer-np.c new file mode 100644 index 00000000..7796ac4f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-transfer-np.c @@ -0,0 +1,59 @@ +/* Transfer ownership of a mutex. Generic version. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +#include + +int +__pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) +{ + assert (mutex->owner == _pthread_self ()); + + struct __pthread *thread = __pthread_getid (tid); + if (! thread) + return ESRCH; + + if (thread == _pthread_self ()) + return 0; + + if (mutex->attr && mutex->attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) + { + + if (mutex->owner != _pthread_self ()) + return EPERM; + + mutex->owner = thread; + } + +#ifndef NDEBUG +# if !defined(ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) +# endif + { + mutex->owner = thread; + } +#endif + + return 0; +} + +strong_alias (__pthread_mutex_transfer_np, pthread_mutex_transfer_np) diff --git a/libpthread/sysdeps/generic/pt-mutex-trylock.c b/libpthread/sysdeps/generic/pt-mutex-trylock.c new file mode 100644 index 00000000..5264dc7b --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-trylock.c @@ -0,0 +1,104 @@ +/* Try to Lock a mutex. Generic version. + Copyright (C) 2002, 2005, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Lock MUTEX, return EBUSY if we can't get it. */ +int +__pthread_mutex_trylock (struct __pthread_mutex *mutex) +{ + int err; + struct __pthread *self; + + __pthread_spin_lock (&mutex->__lock); + if (__pthread_spin_trylock (&mutex->__held) == 0) + /* Acquired the lock. */ + { +#ifndef NDEBUG + self = _pthread_self (); + if (self) + /* The main thread may take a lock before the library is fully + initialized, in particular, before the main thread has a + TCB. */ + { + assert (! mutex->owner); + mutex->owner = _pthread_self (); + } +#endif + + if (mutex->attr) + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_RECURSIVE: + mutex->locks = 1; + case PTHREAD_MUTEX_ERRORCHECK: + mutex->owner = _pthread_self (); + break; + + default: + LOSE; + } + + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + err = EBUSY; + + if (mutex->attr) + { + self = _pthread_self (); + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_NORMAL: + break; + + case PTHREAD_MUTEX_ERRORCHECK: + /* We could check if MUTEX->OWNER is SELF, however, POSIX + does not permit pthread_mutex_trylock to return EDEADLK + instead of EBUSY, only pthread_mutex_lock. */ + break; + + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner == self) + { + mutex->locks ++; + err = 0; + } + break; + + default: + LOSE; + } + } + + __pthread_spin_unlock (&mutex->__lock); + + return err; +} + +strong_alias (__pthread_mutex_trylock, _pthread_mutex_trylock); +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock); diff --git a/libpthread/sysdeps/generic/pt-mutex-unlock.c b/libpthread/sysdeps/generic/pt-mutex-unlock.c new file mode 100644 index 00000000..7645fd4c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutex-unlock.c @@ -0,0 +1,102 @@ +/* Unlock a mutex. Generic version. + Copyright (C) 2000, 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +#define LOSE do { * (int *) 0 = 0; } while (1) + +/* Unlock MUTEX, rescheduling a waiting thread. */ +int +__pthread_mutex_unlock (pthread_mutex_t *mutex) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&mutex->__lock); + + if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) + { +#if defined(ALWAYS_TRACK_MUTEX_OWNER) +# ifndef NDEBUG + if (_pthread_self ()) + { + assert (mutex->owner); + assert (mutex->owner == _pthread_self ()); + mutex->owner = NULL; + } +# endif +#endif + } + else + switch (mutex->attr->mutex_type) + { + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_RECURSIVE: + if (mutex->owner != _pthread_self ()) + { + __pthread_spin_unlock (&mutex->__lock); + return EPERM; + } + + if (mutex->attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) + if (--mutex->locks > 0) + { + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + mutex->owner = 0; + break; + + default: + LOSE; + } + + + if (mutex->__queue == NULL) + { + __pthread_spin_unlock (&mutex->__held); + __pthread_spin_unlock (&mutex->__lock); + return 0; + } + + wakeup = mutex->__queue; + __pthread_dequeue (wakeup); + +#ifndef NDEBUG +# if !defined (ALWAYS_TRACK_MUTEX_OWNER) + if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) +# endif + { + mutex->owner = wakeup; + } +#endif + + /* We do not unlock MUTEX->held: we are transferring the ownership + to the thread that we are waking up. */ + + __pthread_spin_unlock (&mutex->__lock); + __pthread_wakeup (wakeup); + + return 0; +} + +strong_alias (__pthread_mutex_unlock, _pthread_mutex_unlock); +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock); diff --git a/libpthread/sysdeps/generic/pt-mutexattr-destroy.c b/libpthread/sysdeps/generic/pt-mutexattr-destroy.c new file mode 100644 index 00000000..fe7e95d2 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_mutexattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_destroy (pthread_mutexattr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c b/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c new file mode 100644 index 00000000..d03d7192 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-getprioceiling.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_getprioceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr, + int *prioceiling) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-getprotocol.c b/libpthread/sysdeps/generic/pt-mutexattr-getprotocol.c new file mode 100644 index 00000000..d75021a3 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-getprotocol.c @@ -0,0 +1,29 @@ +/* pthread_mutexattr_getprotocol. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr, + int *protocol) +{ + *protocol = attr->protocol; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-getpshared.c b/libpthread/sysdeps/generic/pt-mutexattr-getpshared.c new file mode 100644 index 00000000..0dad13b8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_mutexattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-gettype.c b/libpthread/sysdeps/generic/pt-mutexattr-gettype.c new file mode 100644 index 00000000..ff2caea4 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-gettype.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_gettype. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type) +{ + *type = attr->mutex_type; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-init.c b/libpthread/sysdeps/generic/pt-mutexattr-init.c new file mode 100644 index 00000000..2f23673c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-init.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_init (pthread_mutexattr_t *attr) +{ + *attr = __pthread_default_mutexattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c b/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c new file mode 100644 index 00000000..a9bbd327 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-setprioceiling.c @@ -0,0 +1,28 @@ +/* pthread_mutexattr_setprioceiling. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr, + int prioceiling) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-setprotocol.c b/libpthread/sysdeps/generic/pt-mutexattr-setprotocol.c new file mode 100644 index 00000000..9a0d1b1f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-setprotocol.c @@ -0,0 +1,42 @@ +/* pthread_mutexattr_setprotocol. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, + int protocol) +{ + if (protocol == __pthread_default_mutexattr.protocol) + { + attr->protocol = protocol; + return 0; + } + + switch (protocol) + { + case PTHREAD_PRIO_NONE: + case PTHREAD_PRIO_INHERIT: + case PTHREAD_PRIO_PROTECT: + return ENOTSUP; + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-setpshared.c b/libpthread/sysdeps/generic/pt-mutexattr-setpshared.c new file mode 100644 index 00000000..bcbc4d91 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_mutexattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr-settype.c b/libpthread/sysdeps/generic/pt-mutexattr-settype.c new file mode 100644 index 00000000..e7ae213a --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr-settype.c @@ -0,0 +1,37 @@ +/* pthread_mutexattr_settype. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type) +{ + switch (type) + { + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_RECURSIVE: + attr->mutex_type = type; + return 0; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-mutexattr.c b/libpthread/sysdeps/generic/pt-mutexattr.c new file mode 100644 index 00000000..d80a7d74 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-mutexattr.c @@ -0,0 +1,37 @@ +/* Default mutex attributes. Generic version. + Copyright (C) 2000, 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +const struct __pthread_mutexattr __pthread_default_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_DEFAULT +}; + +const struct __pthread_mutexattr __pthread_recursive_mutexattr = +{ + prioceiling: 0, + protocol: PTHREAD_PRIO_NONE, + pshared: PTHREAD_PROCESS_PRIVATE, + mutex_type: PTHREAD_MUTEX_RECURSIVE +}; diff --git a/libpthread/sysdeps/generic/pt-once.c b/libpthread/sysdeps/generic/pt-once.c new file mode 100644 index 00000000..5be5e484 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-once.c @@ -0,0 +1,43 @@ +/* pthread_once. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + if (once_control->run == 0) + { + __pthread_spin_lock (&once_control->lock); + + if (once_control->run == 0) + { + init_routine (); + __memory_barrier (); + once_control->run = 1; + } + + __pthread_spin_unlock (&once_control->lock); + } + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-attr.c b/libpthread/sysdeps/generic/pt-rwlock-attr.c new file mode 100644 index 00000000..1587feef --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-attr.c @@ -0,0 +1,26 @@ +/* Default rwlock attributes. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +const struct __pthread_rwlockattr __pthread_default_rwlockattr = +{ + pshared: PTHREAD_PROCESS_PRIVATE +}; diff --git a/libpthread/sysdeps/generic/pt-rwlock-destroy.c b/libpthread/sysdeps/generic/pt-rwlock-destroy.c new file mode 100644 index 00000000..045eebd8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-destroy.c @@ -0,0 +1,29 @@ +/* Destroy a rwlock. Generic version. + Copyright (C) 2002, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + return 0; +} + +strong_alias (_pthread_rwlock_destroy, pthread_rwlock_destroy); diff --git a/libpthread/sysdeps/generic/pt-rwlock-init.c b/libpthread/sysdeps/generic/pt-rwlock-init.c new file mode 100644 index 00000000..c9ff9b28 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-init.c @@ -0,0 +1,45 @@ +/* Initialize a rwlock. Generic version. + Copyright (C) 2002, 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +int +_pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + *rwlock = (pthread_rwlock_t) __PTHREAD_RWLOCK_INITIALIZER; + + if (! attr + || memcmp (attr, &__pthread_default_rwlockattr, sizeof (*attr) == 0)) + /* Use the default attributes. */ + return 0; + + /* Non-default attributes. */ + + rwlock->__attr = malloc (sizeof *attr); + if (! rwlock->__attr) + return ENOMEM; + + *rwlock->__attr = *attr; + return 0; +} + +strong_alias (_pthread_rwlock_init, pthread_rwlock_init); diff --git a/libpthread/sysdeps/generic/pt-rwlock-rdlock.c b/libpthread/sysdeps/generic/pt-rwlock-rdlock.c new file mode 100644 index 00000000..480cf489 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-rdlock.c @@ -0,0 +1,32 @@ +/* Acquire a rwlock for reading. Generic version. + Copyright (C) 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* Implemented in pt-rwlock-timedrdlock.c. */ +extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime); + +/* Acquire RWLOCK for reading, block if we can't get it. */ +int +pthread_rwlock_rdlock (struct __pthread_rwlock *rwlock) +{ + return __pthread_rwlock_timedrdlock_internal (rwlock, 0); +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c b/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c new file mode 100644 index 00000000..ba610fa5 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-timedrdlock.c @@ -0,0 +1,113 @@ +/* Acquire a rwlock for reading. Generic version. + Copyright (C) 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Acquire the rwlock *RWLOCK for reading blocking until *ABSTIME if + it is already held. As a GNU extension, if TIMESPEC is NULL then + wait forever. */ +int +__pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + rwlock->readers = 1; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + else + /* Lock is held, but is held by a reader? */ + if (rwlock->readers > 0) + /* Just add ourself to number of readers. */ + { + assert (rwlock->readerqueue == 0); + rwlock->readers ++; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + /* Better be blocked by a writer. */ + assert (rwlock->readers == 0); + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + self = _pthread_self (); + + /* Add ourself to the queue. */ + __pthread_enqueue (&rwlock->readerqueue, self); + __pthread_spin_unlock (&rwlock->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&rwlock->__lock); + if (self->prevp) + /* Disconnect ourself. */ + __pthread_dequeue (self); + __pthread_spin_unlock (&rwlock->__lock); + + return err; + } + } + else + __pthread_block (self); + + + /* The reader count has already been increment by whoever woke us + up. */ + + assert (rwlock->readers > 0); + + return 0; +} + +int +pthread_rwlock_timedrdlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedrdlock_internal (rwlock, abstime); +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c b/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c new file mode 100644 index 00000000..04eab51f --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-timedwrlock.c @@ -0,0 +1,95 @@ +/* Acquire a rwlock for writing. Generic version. + Copyright (C) 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Acquire RWLOCK for writing blocking until *ABSTIME if we cannot get + it. As a special GNU extension, if ABSTIME is NULL then the wait + shall not time out. */ +int +__pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + struct __pthread *self; + + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + self = _pthread_self (); + + /* Add ourselves to the queue. */ + __pthread_enqueue (&rwlock->writerqueue, self); + __pthread_spin_unlock (&rwlock->__lock); + + /* Block the thread. */ + if (abstime) + { + error_t err; + + err = __pthread_timedblock (self, abstime); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&rwlock->__lock); + if (self->prevp) + /* Disconnect ourself. */ + __pthread_dequeue (self); + __pthread_spin_unlock (&rwlock->__lock); + + return err; + } + } + else + __pthread_block (self); + + assert (rwlock->readers == 0); + + return 0; +} + +int +pthread_rwlock_timedwrlock (struct __pthread_rwlock *rwlock, + const struct timespec *abstime) +{ + return __pthread_rwlock_timedwrlock_internal (rwlock, abstime); +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c b/libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c new file mode 100644 index 00000000..2419efb1 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-tryrdlock.c @@ -0,0 +1,56 @@ +/* Try to acquire a rwlock for reading. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Try to acquire RWLOCK. */ +int +pthread_rwlock_tryrdlock (struct __pthread_rwlock *rwlock) +{ + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + rwlock->readers = 1; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + else + /* Lock is held, but is held by a reader? */ + if (rwlock->readers > 0) + { + assert (rwlock->readerqueue == 0); + rwlock->readers ++; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + __pthread_spin_unlock (&rwlock->__lock); + + return EBUSY; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-trywrlock.c b/libpthread/sysdeps/generic/pt-rwlock-trywrlock.c new file mode 100644 index 00000000..6b9c5b56 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-trywrlock.c @@ -0,0 +1,46 @@ +/* Try to acquire a rwlock for writing. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Try to acquire RWLOCK for writing. */ +int +pthread_rwlock_trywrlock (struct __pthread_rwlock *rwlock) +{ + __pthread_spin_lock (&rwlock->__lock); + if (__pthread_spin_trylock (&rwlock->__held) == 0) + /* Successfully acquired the lock. */ + { + assert (rwlock->readerqueue == 0); + assert (rwlock->writerqueue == 0); + assert (rwlock->readers == 0); + + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + /* The lock is busy. */ + + __pthread_spin_unlock (&rwlock->__lock); + + return EBUSY; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-unlock.c b/libpthread/sysdeps/generic/pt-rwlock-unlock.c new file mode 100644 index 00000000..fb23a0b9 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-unlock.c @@ -0,0 +1,90 @@ +/* Unlock a rwlock. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Unlock *RWLOCK, rescheduling a waiting writer thread or, if there + are no threads waiting for a write lock, rescheduling the reader + threads. */ +int +pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&rwlock->__lock); + + assert (__pthread_spin_trylock (&rwlock->__held) == EBUSY); + + if (rwlock->readers > 1) + /* There are other readers. */ + { + rwlock->readers --; + __pthread_spin_unlock (&rwlock->__lock); + return 0; + } + + if (rwlock->readers == 1) + /* Last reader. */ + rwlock->readers = 0; + + + /* Wake someone else up. Try the writer queue first, then the + reader queue if that is empty. */ + + if (rwlock->writerqueue) + { + wakeup = rwlock->writerqueue; + __pthread_dequeue (wakeup); + + /* We do not unlock RWLOCK->held: we are transferring the ownership + to the thread that we are waking up. */ + + __pthread_spin_unlock (&rwlock->__lock); + __pthread_wakeup (wakeup); + + return 0; + } + + if (rwlock->readerqueue) + { + __pthread_queue_iterate (rwlock->readerqueue, wakeup) + rwlock->readers ++; + + wakeup = rwlock->readerqueue; + rwlock->readerqueue = 0; + + __pthread_spin_unlock (&rwlock->__lock); + + /* We can safely walk the list of waiting threads without holding + the lock since it is now decoupled from the rwlock. */ + __pthread_dequeuing_iterate (wakeup, wakeup) + __pthread_wakeup (wakeup); + + return 0; + } + + + /* Noone is waiting. Just unlock it. */ + + __pthread_spin_unlock (&rwlock->__held); + __pthread_spin_unlock (&rwlock->__lock); + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlock-wrlock.c b/libpthread/sysdeps/generic/pt-rwlock-wrlock.c new file mode 100644 index 00000000..be85b906 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlock-wrlock.c @@ -0,0 +1,34 @@ +/* Acquire a rwlock for writing. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Implemented in pt-rwlock-timedwrlock.c. */ +extern int __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, + const struct timespec *abstime); + +/* Acquire RWLOCK for writing. */ +int +pthread_rwlock_wrlock (struct __pthread_rwlock *rwlock) +{ + return __pthread_rwlock_timedwrlock_internal (rwlock, 0); +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-destroy.c b/libpthread/sysdeps/generic/pt-rwlockattr-destroy.c new file mode 100644 index 00000000..eabfcbe8 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-destroy.c @@ -0,0 +1,27 @@ +/* pthread_rwlockattr_destroy. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-getpshared.c b/libpthread/sysdeps/generic/pt-rwlockattr-getpshared.c new file mode 100644 index 00000000..e8752c0c --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-getpshared.c @@ -0,0 +1,29 @@ +/* pthread_rwlockattr_getpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, + int *pshared) +{ + *pshared = attr->pshared; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-init.c b/libpthread/sysdeps/generic/pt-rwlockattr-init.c new file mode 100644 index 00000000..34da6bf0 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-init.c @@ -0,0 +1,28 @@ +/* pthread_rwlockattr_init. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + *attr = __pthread_default_rwlockattr; + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-rwlockattr-setpshared.c b/libpthread/sysdeps/generic/pt-rwlockattr-setpshared.c new file mode 100644 index 00000000..a861d034 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-rwlockattr-setpshared.c @@ -0,0 +1,39 @@ +/* pthread_rwlockattr_setpshared. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, + int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->pshared = pshared; + return 0; + + case PTHREAD_PROCESS_SHARED: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/libpthread/sysdeps/generic/pt-setconcurrency.c b/libpthread/sysdeps/generic/pt-setconcurrency.c new file mode 100644 index 00000000..cd55b1ba --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setconcurrency.c @@ -0,0 +1,34 @@ +/* Set the desired level of concurrency. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int __pthread_concurrency; + +int +pthread_setconcurrency (int new_level) +{ + if (new_level < 0) + return EINVAL; + + __pthread_concurrency = new_level; + + return 0; +} diff --git a/libpthread/sysdeps/generic/pt-setschedparam.c b/libpthread/sysdeps/generic/pt-setschedparam.c new file mode 100644 index 00000000..a70b0796 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setschedparam.c @@ -0,0 +1,28 @@ +/* Set the scheduling parameters for a thread. Generic version. + Copyright (C) 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-setschedprio.c b/libpthread/sysdeps/generic/pt-setschedprio.c new file mode 100644 index 00000000..60668eb1 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setschedprio.c @@ -0,0 +1,27 @@ +/* Set the scheduling priority of a thread. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_setschedprio (pthread_t thread, int prio) +{ + return ENOSYS; +} diff --git a/libpthread/sysdeps/generic/pt-setspecific.c b/libpthread/sysdeps/generic/pt-setspecific.c new file mode 100644 index 00000000..d520c5df --- /dev/null +++ b/libpthread/sysdeps/generic/pt-setspecific.c @@ -0,0 +1,27 @@ +/* pthread_setspecific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +pthread_setspecific (pthread_key_t key, const void *value) +{ + return EINVAL; +} diff --git a/libpthread/sysdeps/generic/pt-startup.c b/libpthread/sysdeps/generic/pt-startup.c new file mode 100644 index 00000000..c21a1819 --- /dev/null +++ b/libpthread/sysdeps/generic/pt-startup.c @@ -0,0 +1,25 @@ +/* Thread initialization. Generic version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +void +__pthread_startup (void) +{ +} diff --git a/libpthread/sysdeps/generic/raise.c b/libpthread/sysdeps/generic/raise.c new file mode 100644 index 00000000..410f557d --- /dev/null +++ b/libpthread/sysdeps/generic/raise.c @@ -0,0 +1,41 @@ +/* raise.c - Generic raise implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +raise (int signo) +{ + /* According to POSIX, if we implement threads (and we do), then + "the effect of the raise() function shall be equivalent to + calling: pthread_kill(pthread_self(), sig);" */ + +debug (0, ""); + int err = pthread_kill (pthread_self (), signo); +debug (0, ""); + if (err) + { + errno = err; + return -1; + } + + return 0; +} + diff --git a/libpthread/sysdeps/generic/sem-close.c b/libpthread/sysdeps/generic/sem-close.c new file mode 100644 index 00000000..9f48032f --- /dev/null +++ b/libpthread/sysdeps/generic/sem-close.c @@ -0,0 +1,32 @@ +/* Close a named semaphore. Generic version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_close (sem_t *sem) +{ + errno = EOPNOTSUPP; + return -1; +} + +strong_alias (__sem_close, sem_close); diff --git a/libpthread/sysdeps/generic/sem-destroy.c b/libpthread/sysdeps/generic/sem-destroy.c new file mode 100644 index 00000000..6486599c --- /dev/null +++ b/libpthread/sysdeps/generic/sem-destroy.c @@ -0,0 +1,38 @@ +/* Destroy a semaphore. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_destroy (sem_t *sem) +{ + if (sem->__queue) + /* There are threads waiting on *SEM. */ + { + errno = EBUSY; + return -1; + } + + return 0; +} + +strong_alias (__sem_destroy, sem_destroy); diff --git a/libpthread/sysdeps/generic/sem-getvalue.c b/libpthread/sysdeps/generic/sem-getvalue.c new file mode 100644 index 00000000..7762089b --- /dev/null +++ b/libpthread/sysdeps/generic/sem-getvalue.c @@ -0,0 +1,33 @@ +/* Get the value of a semaphore. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int +__sem_getvalue (sem_t *restrict sem, int *restrict value) +{ + __pthread_spin_lock (&sem->__lock); + *value = sem->__value; + __pthread_spin_unlock (&sem->__lock); + + return 0; +} + +strong_alias (__sem_getvalue, sem_getvalue); diff --git a/libpthread/sysdeps/generic/sem-init.c b/libpthread/sysdeps/generic/sem-init.c new file mode 100644 index 00000000..d2414f5d --- /dev/null +++ b/libpthread/sysdeps/generic/sem-init.c @@ -0,0 +1,46 @@ +/* Initialize a semaphore. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_init (sem_t *sem, int pshared, unsigned value) +{ + if (pshared != 0) + { + errno = EOPNOTSUPP; + return -1; + } + +#ifdef SEM_VALUE_MAX + if (value > SEM_VALUE_MAX) + { + errno = EINVAL; + return -1; + } +#endif + + *sem = (sem_t) __SEMAPHORE_INITIALIZER (pshared, value); + return 0; +} + +strong_alias (__sem_init, sem_init); diff --git a/libpthread/sysdeps/generic/sem-open.c b/libpthread/sysdeps/generic/sem-open.c new file mode 100644 index 00000000..bae87ed0 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-open.c @@ -0,0 +1,32 @@ +/* Open a named semaphore. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +sem_t * +__sem_open (const char *name, int open_flags, ...) +{ + errno = EOPNOTSUPP; + return SEM_FAILED; +} + +strong_alias (__sem_open, sem_open); diff --git a/libpthread/sysdeps/generic/sem-post.c b/libpthread/sysdeps/generic/sem-post.c new file mode 100644 index 00000000..6d438bf2 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-post.c @@ -0,0 +1,62 @@ +/* Post a semaphore. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_post (sem_t *sem) +{ + struct __pthread *wakeup; + + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Do a quick up. */ + { + assert (! sem->__queue); + sem->__value ++; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + if (! sem->__queue) + /* No one waiting. */ + { + sem->__value = 1; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + /* Wake someone up. */ + + /* First dequeue someone. */ + wakeup = sem->__queue; + __pthread_dequeue (wakeup); + + /* Then drop the lock and transfer control. */ + __pthread_spin_unlock (&sem->__lock); + + __pthread_wakeup (wakeup); + + return 0; +} + +strong_alias (__sem_post, sem_post); diff --git a/libpthread/sysdeps/generic/sem-timedwait.c b/libpthread/sysdeps/generic/sem-timedwait.c new file mode 100644 index 00000000..e34539a9 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-timedwait.c @@ -0,0 +1,91 @@ +/* Wait on a semaphore with a timeout. Generic version. + Copyright (C) 2005, 2006, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +__sem_timedwait_internal (sem_t *restrict sem, + const struct timespec *restrict timeout) +{ + struct __pthread *self; + + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Successful down. */ + { + sem->__value --; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + + if (timeout && (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000)) + { + errno = EINVAL; + return -1; + } + + /* Add ourselves to the queue. */ + self = _pthread_self (); + + __pthread_enqueue (&sem->__queue, self); + __pthread_spin_unlock (&sem->__lock); + + /* Block the thread. */ + if (timeout) + { + error_t err; + + err = __pthread_timedblock (self, timeout); + if (err) + /* We timed out. We may need to disconnect ourself from the + waiter queue. + + FIXME: What do we do if we get a wakeup message before we + disconnect ourself? It may remain until the next time we + block. */ + { + assert (err == ETIMEDOUT); + + __pthread_spin_lock (&sem->__lock); + if (self->prevp) + __pthread_dequeue (self); + __pthread_spin_unlock (&sem->__lock); + + errno = err; + return -1; + } + } + else + __pthread_block (self); + + return 0; +} + +int +__sem_timedwait (sem_t *restrict sem, + const struct timespec *restrict timeout) +{ + return __sem_timedwait_internal (sem, timeout); +} + +strong_alias (__sem_timedwait, sem_timedwait); diff --git a/libpthread/sysdeps/generic/sem-trywait.c b/libpthread/sysdeps/generic/sem-trywait.c new file mode 100644 index 00000000..437e2822 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-trywait.c @@ -0,0 +1,42 @@ +/* Lock a semaphore if it does not require blocking. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_trywait (sem_t *sem) +{ + __pthread_spin_lock (&sem->__lock); + if (sem->__value > 0) + /* Successful down. */ + { + sem->__value --; + __pthread_spin_unlock (&sem->__lock); + return 0; + } + __pthread_spin_unlock (&sem->__lock); + + errno = EAGAIN; + return -1; +} + +strong_alias (__sem_trywait, sem_trywait); diff --git a/libpthread/sysdeps/generic/sem-unlink.c b/libpthread/sysdeps/generic/sem-unlink.c new file mode 100644 index 00000000..570ed614 --- /dev/null +++ b/libpthread/sysdeps/generic/sem-unlink.c @@ -0,0 +1,32 @@ +/* Unlink a named semaphore. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +__sem_unlink (const char *name) +{ + errno = EOPNOTSUPP; + return -1; +} + +strong_alias (__sem_unlink, sem_unlink); diff --git a/libpthread/sysdeps/generic/sem-wait.c b/libpthread/sysdeps/generic/sem-wait.c new file mode 100644 index 00000000..8347480c --- /dev/null +++ b/libpthread/sysdeps/generic/sem-wait.c @@ -0,0 +1,32 @@ +/* Wait on a semaphore. Generic version. + Copyright (C) 2005, 2006 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +extern int __sem_timedwait_internal (sem_t *restrict sem, + const struct timespec *restrict timeout); + +int +__sem_wait (sem_t *sem) +{ + return __sem_timedwait_internal (sem, 0); +} + +strong_alias (__sem_wait, sem_wait); diff --git a/libpthread/sysdeps/generic/sigaddset.c b/libpthread/sysdeps/generic/sigaddset.c new file mode 100644 index 00000000..14edb71c --- /dev/null +++ b/libpthread/sysdeps/generic/sigaddset.c @@ -0,0 +1,35 @@ +/* sigaddset.c - Generic sigaddset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigaddset (sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + *sigset |= sigmask (signo); + return 0; +} + diff --git a/libpthread/sysdeps/generic/sigdelset.c b/libpthread/sysdeps/generic/sigdelset.c new file mode 100644 index 00000000..5456467f --- /dev/null +++ b/libpthread/sysdeps/generic/sigdelset.c @@ -0,0 +1,35 @@ +/* sigdelset.c - Generic sigdelset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigdelset (sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + *sigset &= ~sigmask (signo); + return 0; +} + diff --git a/libpthread/sysdeps/generic/sigemptyset.c b/libpthread/sysdeps/generic/sigemptyset.c new file mode 100644 index 00000000..690c15b6 --- /dev/null +++ b/libpthread/sysdeps/generic/sigemptyset.c @@ -0,0 +1,29 @@ +/* sigemptyset.c - Generic sigemptyset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include + +int +sigemptyset (sigset_t *sigset) +{ + *sigset = 0; + return 0; +} + diff --git a/libpthread/sysdeps/generic/sigfillset.c b/libpthread/sysdeps/generic/sigfillset.c new file mode 100644 index 00000000..f0ac0781 --- /dev/null +++ b/libpthread/sysdeps/generic/sigfillset.c @@ -0,0 +1,29 @@ +/* sigfillset.c - Generic sigfillset implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include + +int +sigfillset (sigset_t *sigset) +{ + *sigset = (1ULL << (NSIG - 1)) - 1; + return 0; +} + diff --git a/libpthread/sysdeps/generic/siginterrupt.c b/libpthread/sysdeps/generic/siginterrupt.c new file mode 100644 index 00000000..0899efbb --- /dev/null +++ b/libpthread/sysdeps/generic/siginterrupt.c @@ -0,0 +1,36 @@ +/* siginterrupt.c - Generic siginterrupt implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +siginterrupt (int sig, int flag) +{ + int ret; + struct sigaction act; + + sigaction (sig, NULL, &act); + if (flag) + act.sa_flags &= ~SA_RESTART; + else + act.sa_flags |= SA_RESTART; + ret = sigaction(sig, &act, NULL); + return ret; +} diff --git a/libpthread/sysdeps/generic/sigismember.c b/libpthread/sysdeps/generic/sigismember.c new file mode 100644 index 00000000..b3d65c97 --- /dev/null +++ b/libpthread/sysdeps/generic/sigismember.c @@ -0,0 +1,36 @@ +/* sigismember.c - Generic sigismember implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigismember (const sigset_t *sigset, int signo) +{ + if (signo <= 0 || signo >= NSIG) + { + errno = EINVAL; + return -1; + } + + if (*sigset & sigmask (signo)) + return 1; + else + return 0; +} diff --git a/libpthread/sysdeps/generic/signal.c b/libpthread/sysdeps/generic/signal.c new file mode 100644 index 00000000..7555d0a1 --- /dev/null +++ b/libpthread/sysdeps/generic/signal.c @@ -0,0 +1,44 @@ +/* signal.c - Generic signal implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +void (*signal (int sig, void (*handler)(int)))(int) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sa.sa_flags = SA_RESTART; + + if (sigemptyset (&sa.sa_mask) < 0 + || sigaddset (&sa.sa_mask, sig) < 0) + return SIG_ERR; + + struct sigaction osa; + if (sigaction (sig, &sa, &osa) < 0) + return SIG_ERR; + + return osa.sa_handler; +} + +void (*bsd_signal (int sig, void (*func)(int)))(int) +{ + return signal (sig, func); +} diff --git a/libpthread/sysdeps/generic/sigwait.c b/libpthread/sysdeps/generic/sigwait.c new file mode 100644 index 00000000..7d10bf8b --- /dev/null +++ b/libpthread/sysdeps/generic/sigwait.c @@ -0,0 +1,34 @@ +/* sigwait.c - Generic sigwait implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include "sig-internal.h" + +int +sigwait (const sigset_t *restrict set, int *restrict signo) +{ + siginfo_t info; + + if (sigwaitinfo (set, &info) < 0) + return -1; + + *signo = info.si_signo; + return 0; +} + diff --git a/libpthread/sysdeps/hurd/pt-destroy-specific.c b/libpthread/sysdeps/hurd/pt-destroy-specific.c new file mode 100644 index 00000000..23c7fbc0 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-destroy-specific.c @@ -0,0 +1,79 @@ +/* __pthread_destory_specific. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +void +__pthread_destroy_specific (struct __pthread *thread) +{ + error_t err; + int i; + int seen_one; + + /* Check if there is any thread specific data. */ + if (! thread->thread_specifics) + return; + + __pthread_key_lock_ready (); + + /* Iterate and call the destructors on any thread specific data. */ + for (;;) + { + seen_one = 0; + + __pthread_mutex_lock (&__pthread_key_lock); + + for (i = 0; i < __pthread_key_count; i ++) + { + void *value; + + if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID) + break; + + value = hurd_ihash_find (thread->thread_specifics, i); + if (value) + { + err = hurd_ihash_remove (thread->thread_specifics, i); + assert (err == 1); + + if (__pthread_key_destructors[i]) + { + seen_one = 1; + __pthread_key_destructors[i] (value); + } + } + } + + __pthread_mutex_unlock (&__pthread_key_lock); + + if (! seen_one) + break; + + /* This may take a very long time. Let those blocking on + pthread_key_create or pthread_key_delete make progress. */ + sched_yield (); + } + + hurd_ihash_free (thread->thread_specifics); + thread->thread_specifics = 0; +} diff --git a/libpthread/sysdeps/hurd/pt-getspecific.c b/libpthread/sysdeps/hurd/pt-getspecific.c new file mode 100644 index 00000000..30605984 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-getspecific.c @@ -0,0 +1,37 @@ +/* pthread_getspecific. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +void * +pthread_getspecific (pthread_key_t key) +{ + struct __pthread *self; + + assert (key < __pthread_key_count); + + self = _pthread_self (); + if (! self->thread_specifics) + return 0; + + return hurd_ihash_find (self->thread_specifics, key); +} diff --git a/libpthread/sysdeps/hurd/pt-init-specific.c b/libpthread/sysdeps/hurd/pt-init-specific.c new file mode 100644 index 00000000..c1bacbcb --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-init-specific.c @@ -0,0 +1,30 @@ +/* __pthread_init_specific. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +error_t +__pthread_init_specific (struct __pthread *thread) +{ + thread->thread_specifics = 0; + return 0; +} diff --git a/libpthread/sysdeps/hurd/pt-key-create.c b/libpthread/sysdeps/hurd/pt-key-create.c new file mode 100644 index 00000000..b3e01412 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-key-create.c @@ -0,0 +1,109 @@ +/* pthread_key_create. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +pthread_mutex_t __pthread_key_lock; + +void (**__pthread_key_destructors) (void *arg); +int __pthread_key_size; +int __pthread_key_count; +int __pthread_key_invalid_count; + +int +pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) +{ + /* Where to look for the next key slot. */ + static int index; + + __pthread_key_lock_ready (); + + __pthread_mutex_lock (&__pthread_key_lock); + + do_search: + /* Use the search hint and try to find a free slot. */ + for (; index < __pthread_key_count + && __pthread_key_destructors[index] != PTHREAD_KEY_INVALID; + index ++) + ; + + /* See if we actually found a free element. */ + if (index < __pthread_key_count) + { + assert (__pthread_key_destructors[index] == PTHREAD_KEY_INVALID); + assert (__pthread_key_invalid_count > 0); + + __pthread_key_invalid_count --; + __pthread_key_destructors[index] = destructor; + *key = index ++; + + __pthread_mutex_unlock (&__pthread_key_lock); + return 0; + } + + assert (index == __pthread_key_count); + + /* No space at the end. */ + if (__pthread_key_size == __pthread_key_count) + { + /* See if it is worth looking for a free element. */ + if (__pthread_key_invalid_count > 4 + && __pthread_key_invalid_count > __pthread_key_size / 8) + { + index = 0; + goto do_search; + } + + + /* Resize the array. */ + { + void *t; + int newsize; + + if (__pthread_key_size == 0) + newsize = 8; + else + newsize = __pthread_key_size * 2; + + t = realloc (__pthread_key_destructors, + newsize * sizeof (*__pthread_key_destructors)); + if (! t) + { + __pthread_mutex_unlock (&__pthread_key_lock); + return ENOMEM; + } + + __pthread_key_size = newsize; + __pthread_key_destructors = t; + } + } + + __pthread_key_destructors[index] = destructor; + *key = index; + + index ++; + __pthread_key_count ++; + + __pthread_mutex_unlock (&__pthread_key_lock); + return 0; +} diff --git a/libpthread/sysdeps/hurd/pt-key-delete.c b/libpthread/sysdeps/hurd/pt-key-delete.c new file mode 100644 index 00000000..2426bb11 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-key-delete.c @@ -0,0 +1,45 @@ +/* pthread_key_delete. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +int +pthread_key_delete (pthread_key_t key) +{ + error_t err = 0; + + __pthread_key_lock_ready (); + + __pthread_mutex_lock (&__pthread_key_lock); + + if (key < 0 || key >= __pthread_key_count + || __pthread_key_destructors[key] == PTHREAD_KEY_INVALID) + err = EINVAL; + else + { + __pthread_key_destructors[key] = PTHREAD_KEY_INVALID; + __pthread_key_invalid_count ++; + } + + __pthread_mutex_unlock (&__pthread_key_lock); + + return err; +} diff --git a/libpthread/sysdeps/hurd/pt-key.h b/libpthread/sysdeps/hurd/pt-key.h new file mode 100644 index 00000000..494e01d7 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-key.h @@ -0,0 +1,76 @@ +/* pthread_key internal declatations for the Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#define PTHREAD_KEY_MEMBERS \ + hurd_ihash_t thread_specifics; + +#define PTHREAD_KEY_INVALID (void *) (-1) + + +/* __PTHREAD_KEY_DESTRUCTORS is an array of destructors with + __PTHREAD_KEY_SIZE elements. If an element with index less than + __PTHREAD_KEY_COUNT is invalid, it shall contain the value + PTHREAD_KEY_INVALID which shall be distinct from NULL. + + Normally, we just add new keys to the end of the array and realloc + it as necessary. The pthread_key_create routine may decide to + rescan the array if __PTHREAD_KEY_FREE is large. */ +extern void (**__pthread_key_destructors) (void *arg); +extern int __pthread_key_size; +extern int __pthread_key_count; +/* Number of invalid elements in the array. Does not include elements + for which memory has been allocated but which have not yet been + used (i.e. those elements with indexes greater than + __PTHREAD_KEY_COUNT). */ +extern int __pthread_key_invalid_count; + +/* Protects the above variables. This must be a recursive lock: the + destructors may call pthread_key_delete. */ +extern pthread_mutex_t __pthread_key_lock; + +#include + +static inline void +__pthread_key_lock_ready (void) +{ + static pthread_once_t o = PTHREAD_ONCE_INIT; + + void do_init (void) + { + int err; + pthread_mutexattr_t attr; + + err = pthread_mutexattr_init (&attr); + assert_perror (err); + + err = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); + assert_perror (err); + + err = pthread_mutex_init (&__pthread_key_lock, &attr); + assert_perror (err); + + err = pthread_mutexattr_destroy (&attr); + assert_perror (err); + } + + pthread_once (&o, do_init); +} diff --git a/libpthread/sysdeps/hurd/pt-kill.c b/libpthread/sysdeps/hurd/pt-kill.c new file mode 100644 index 00000000..f970e065 --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-kill.c @@ -0,0 +1,49 @@ +/* pthread_kill. Hurd version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +int +pthread_kill (pthread_t thread, int sig) +{ + struct __pthread *pthread; + struct hurd_signal_detail detail; + struct hurd_sigstate *ss; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + ss = _hurd_thread_sigstate (pthread->kernel_thread); + assert (ss); + + detail.exc = 0; + detail.code = sig; + detail.error = 0; + + _hurd_raise_signal (ss, sig, &detail); + + return 0; +} diff --git a/libpthread/sysdeps/hurd/pt-setspecific.c b/libpthread/sysdeps/hurd/pt-setspecific.c new file mode 100644 index 00000000..89ca4d7f --- /dev/null +++ b/libpthread/sysdeps/hurd/pt-setspecific.c @@ -0,0 +1,43 @@ +/* pthread_setspecific. Generic version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +int +pthread_setspecific (pthread_key_t key, const void *value) +{ + error_t err; + struct __pthread *self = _pthread_self (); + + if (! self->thread_specifics) + { + err = hurd_ihash_create (&self->thread_specifics, HURD_IHASH_NO_LOCP); + if (err) + return ENOMEM; + } + + err = hurd_ihash_add (self->thread_specifics, key, (void *) value); + if (err) + return ENOMEM; + + return 0; +} diff --git a/libpthread/sysdeps/ia32/bits/atomic.h b/libpthread/sysdeps/ia32/bits/atomic.h new file mode 100644 index 00000000..0dfc1f60 --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/atomic.h @@ -0,0 +1,66 @@ +/* Atomic operations. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +typedef __volatile int __atomic_t; + +static inline void +__atomic_inc (__atomic_t *__var) +{ + __asm__ __volatile ("lock; incl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline void +__atomic_dec (__atomic_t *__var) +{ + __asm__ __volatile ("lock; decl %0" : "=m" (*__var) : "m" (*__var)); +} + +static inline int +__atomic_dec_and_test (__atomic_t *__var) +{ + unsigned char __ret; + + __asm__ __volatile ("lock; decl %0; sete %1" + : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); + return __ret != 0; +} + +/* We assume that an __atomicptr_t is only used for pointers to + word-aligned objects, and use the lowest bit for a simple lock. */ +typedef __volatile int * __atomicptr_t; + +/* Actually we don't implement that yet, and assume that we run on + something that has the i486 instruction set. */ +static inline int +__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, + void * __newval) +{ + char __ret; + int __dummy; + + __asm__ __volatile ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (__ret), "=m" (*__ptr), "=a" (__dummy) + : "r" (__newval), "m" (*__ptr), "a" (__oldval)); + return __ret; +} + +#endif diff --git a/libpthread/sysdeps/ia32/bits/memory.h b/libpthread/sysdeps/ia32/bits/memory.h new file mode 100644 index 00000000..932c4086 --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/memory.h @@ -0,0 +1,40 @@ +/* Memory barrier operations. i386 version. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MEMORY_H +#define _BITS_MEMORY_H 1 + +/* Prevent read and write reordering across this function. */ +static inline void +__memory_barrier (void) +{ + int i; + + /* Any lock'ed instruction will do. We just do a simple + increment. */ + __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i) : "memory"); +} + +/* Prevent read reordering across this function. */ +#define __memory_read_barrier __memory_barrier + +/* Prevent write reordering across this function. */ +#define __memory_write_barrier __memory_barrier + +#endif diff --git a/libpthread/sysdeps/ia32/bits/spin-lock-inline.h b/libpthread/sysdeps/ia32/bits/spin-lock-inline.h new file mode 100644 index 00000000..e5ed3def --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/spin-lock-inline.h @@ -0,0 +1,98 @@ +/* Machine-specific definitions for spin locks. i386 version. + Copyright (C) 2000, 2005, 2008, 2009 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_SPIN_LOCK_INLINE_H +#define _BITS_SPIN_LOCK_INLINE_H 1 + +#include +#include + +__BEGIN_DECLS + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE __extern_inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + int __locked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__locked), "=m" (*__lock) : "0" (1) : "memory"); + return __locked ? __EBUSY : 0; +} + +__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +__extern_inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + int __unlocked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0) : "memory"); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/ia32/bits/spin-lock.h b/libpthread/sysdeps/ia32/bits/spin-lock.h new file mode 100644 index 00000000..5ae81e18 --- /dev/null +++ b/libpthread/sysdeps/ia32/bits/spin-lock.h @@ -0,0 +1,39 @@ +/* Machine-specific definitions for spin locks. i386 version. + Copyright (C) 2000, 2005, 2008, 2009 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __volatile int __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +# define __PTHREAD_SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/ia32/machine-sp.h b/libpthread/sysdeps/ia32/machine-sp.h new file mode 100644 index 00000000..cef6ab72 --- /dev/null +++ b/libpthread/sysdeps/ia32/machine-sp.h @@ -0,0 +1,30 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994, 1997, 2001, 2006 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + register void *__sp__ asm("esp"); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/libpthread/sysdeps/ia32/pt-machdep.h b/libpthread/sysdeps/ia32/pt-machdep.h new file mode 100644 index 00000000..6d456367 --- /dev/null +++ b/libpthread/sysdeps/ia32/pt-machdep.h @@ -0,0 +1,29 @@ +/* Machine dependent pthreads internal defenitions. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */ diff --git a/libpthread/sysdeps/l4/bits/pthread-np.h b/libpthread/sysdeps/l4/bits/pthread-np.h new file mode 100644 index 00000000..6a02bdc0 --- /dev/null +++ b/libpthread/sysdeps/l4/bits/pthread-np.h @@ -0,0 +1,35 @@ +/* Non-portable functions. L4 version. + Copyright (C) 2003, 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include + +/* Add the thread TID to the internal kernel thread pool. */ +extern int pthread_pool_add_np (l4_thread_id_t tid); + +/* Get the first thread from the pool. */ +extern l4_thread_id_t pthread_pool_get_np (void); + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/l4/hurd/bits/pthread-np.h b/libpthread/sysdeps/l4/hurd/bits/pthread-np.h new file mode 100644 index 00000000..a90793df --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/bits/pthread-np.h @@ -0,0 +1,31 @@ +/* Non-portable functions. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include + +int pthread_setactivity_np (addr_t activity); + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c b/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c new file mode 100644 index 00000000..dbf5cd7e --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Nothing to do. */ diff --git a/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c new file mode 100644 index 00000000..579905c9 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c @@ -0,0 +1,117 @@ +/* Setup thread stack. Viengoos/i386 version. + Copyright (C) 2000, 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | Return address | + ----------------- <- %ebp + | Frame pointer | + ----------------- + + We do the following: setup the stack to return to the entry routine. + + +*/ + +/* The stack contains: + + arg + start_routine + 0 <- fake return address + C entry_point +*/ +extern uintptr_t _pthread_entry_point; +__asm__ ("\n\ + .globl _pthread_entry_point, __pthread_entry_point\n\ +_pthread_entry_point:\n\ +__pthread_entry_point:\n\ + pushl $0\n\ + popf\n\ +\n\ + xor %ebp, %ebp\n\ + ret\n"); + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg, + void (*entry_point)(void *(*)(void *), void *)) +{ + uintptr_t *top; + + /* Calculate top of the new stack. */ + top = (uintptr_t *) ((uintptr_t) thread->stackaddr + thread->stacksize); + + /* Align on 0x10 for MMX operations. */ + top = (uintptr_t) top & ~0xf; + + if (start_routine) + { + /* Set up call frame. */ + *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + *--top = (uintptr_t) start_routine; + *--top = 0; /* Fake return address. */ + *--top = (uintptr_t) entry_point; + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = (void *) &_pthread_entry_point; + thread->mcontext.sp = (void *) stack_setup (thread, start_routine, arg, + entry_point); + + if (__pthread_num_threads == 1) + return 0; + + assert (! ADDR_IS_VOID (thread->exception_area[0])); + + struct exception_page *exception_page = thread->exception_area_va; + + /* SP is set to the end of the exception area minus one word, which + is the location of the exception page. */ + exception_page->exception_handler_sp + = (uintptr_t) thread->exception_area_va + EXCEPTION_AREA_SIZE; + exception_page->exception_handler_sp -= sizeof (void *); + * (void **) exception_page->exception_handler_sp = thread->exception_area_va; + + exception_page->exception_handler_ip = (uintptr_t) &exception_handler_entry; + exception_page->exception_handler_end = (uintptr_t) &exception_handler_end; + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c new file mode 100644 index 00000000..37ef8215 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c @@ -0,0 +1,213 @@ +/* signal-dispatch-lowlevel.c - ia32 specific signal handling functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +#include +#include +#include +#include + +extern char _signal_dispatch_entry; +/* - 0(%esp) a pointer to the thread's struct signal_state. + - 4(%esp) a pointer to a siginfo_t. + - 8(%esp) is a pointer to the ss_flags field (or NULL). + - 12(%esp)+4 is the value of the sp when the thread was interrupted (intr_sp) + - 0(intr_sp) is the value of the ip when the thread was interrupted. + - 16(%esp) - 16 byte register save area +*/ +__asm__ ("\n\ + .globl _signal_dispatch_entry\n\ +_signal_dispatch_entry:\n\ + /* Save caller saved registers (16 bytes). */\n\ + mov %eax, 16(%esp)\n\ + mov %ecx, 16+4(%esp)\n\ + mov %edx, 16+8(%esp)\n\ + pushf\n\ + popl %eax\n\ + mov %eax, 16+12(%esp)\n\ +\n\ + /* Reset EFLAGS. */\n\ + cld\n\ + call signal_dispatch\n\ +\n\ + /* Get the original stack and begin restoration. */\n\ + mov 12(%esp), %edx\n\ +\n\ + /* Move the saved registers to the user stack. */\n\ + sub $16, %edx\n\ + /* eax. */\n\ + mov 16+0(%esp), %ecx\n\ + mov %ecx, 0(%edx)\n\ + /* ecx. */\n\ + mov 16+4(%esp), %ecx\n\ + mov %ecx, 4(%edx)\n\ + /* edx. */\n\ + mov 16+8(%esp), %ecx\n\ + mov %ecx, 8(%edx)\n\ + /* eflags. */\n\ + mov 16+12(%esp), %ecx\n\ + mov %ecx, 12(%edx)\n\ +\n\ + /* Get the pointer to the sigaltstack flags. */\n\ + mov 8(%esp), %ecx\n\ +\n\ + /* Restore the user stack. */\n\ + mov %edx, %esp\n\ +\n\ + /* Clear the SA_ONSTACK flag. */\n\ + and %ecx, %ecx\n\ + jz after_clear\n\ + lock; and $~1, 0(%ecx)\n\ +after_clear:\n\ +\n\ + /* Restore eflags, the scratch regs and the original sp and ip. */\n\ + popl %eax\n\ + popl %ecx\n\ + popl %edx\n\ + popf\n\ + ret\n"); + +extern char _signal_dispatch_entry_self; +/* - 0(%esp) is the return address (we ignore it) + - 4(%esp) is the sp to load + + Since we are returning to signal_dispatch_lowlevel's caller, we + also need to restore its frame pointer. */ +__asm__ ("\n\ + .globl _signal_dispatch_entry_self\n\ +_signal_dispatch_entry_self:\n\ + mov 0(%ebp), %ebp\n\ + mov 4(%esp), %esp\n\ + jmp _signal_dispatch_entry\n"); + +void +signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, + siginfo_t si) +{ + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + struct __pthread *thread = __pthread_getid (tid); + + bool self = tid == pthread_self (); + + uintptr_t intr_sp; + + if (self) + { + /* The return address is just before the first argument. */ + intr_sp = (uintptr_t) &ss - 4; + assert (* (void **) intr_sp == __builtin_return_address (0)); + } + else + { + struct hurd_thread_exregs_in in; + memset (&in, 0, sizeof (in)); + struct hurd_thread_exregs_out out; + + error_t err; + err = rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC + | HURD_EXREGS_GET_REGS, + in, &out); + if (err) + panic ("Failed to modify thread " ADDR_FMT, + ADDR_PRINTF (thread->object)); + + intr_sp = out.sp; + + /* Push the ip on the user stack. */ + intr_sp -= 4; + * (uintptr_t *) intr_sp = out.ip; + } + + bool altstack = false; + uintptr_t sp; + if (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) + || (ss->stack.ss_flags & SS_DISABLE) + || (ss->stack.ss_flags & SS_ONSTACK)) + { + assert (! self); + sp = intr_sp; + } + else + { + /* The stack grows down. */ + sp = (uintptr_t) ss->stack.ss_sp + ss->stack.ss_size; + + /* We know intimately that SS_ONSTACK is the least significant + bit. */ + assert (SS_ONSTACK == 1); + atomic_bit_set (&ss->stack.ss_flags, 0); + + altstack = true; + } + + /* Set up the call frame for a call to signal_dispatch_entry. */ + + /* Allocate a siginfo structure on the stack. */ + sp = sp - sizeof (siginfo_t); + siginfo_t *sip = (void *) sp; + /* Copy the user supplied values. */ + *sip = si; + + /* Add space for the 4 caller saved registers. */ + sp -= 4 * sizeof (uintptr_t); + + /* Save the interrupted sp. */ + sp -= 4; + * (uintptr_t *) sp = intr_sp; + + /* Address of the ss_flags. */ + sp -= 4; + if (altstack) + * (uintptr_t *) sp = (uintptr_t) &ss->stack.ss_flags; + else + * (uintptr_t *) sp = 0; + + /* Push the parameters to signal_dispatch. */ + + /* signal info structure. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) sip; + + /* The ss. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) ss; + + pthread_mutex_transfer_np (&ss->lock, tid); + + if (self) + ((void (*) (uintptr_t)) &_signal_dispatch_entry_self) ((uintptr_t) sp); + else + { + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; + + in.sp = sp; + in.ip = (uintptr_t) &_signal_dispatch_entry; + + rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, + in, &out); + } +} diff --git a/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c b/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c new file mode 100644 index 00000000..754d203e --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Nothing to do. */ diff --git a/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c b/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c new file mode 100644 index 00000000..d3cf4ec3 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c @@ -0,0 +1,93 @@ +/* Setup thread stack. Hurd/PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +/* Arguments is passed in registers on the PowerPC. But the + exchange registers syscall only allows us to set the PC and the + stack pointer so we put the entry point and start function on + the stack. */ +struct start_info +{ + void (*entry_point) (void *(*)(void *), void *); + void *(*start_routine) (void *); + void *arg; +}; + +void first_entry_1 (void); + +/* Stage 1 entry function. The start_info structure is inlined on the + stack. Put values into registers and call entry function. */ +asm (" ;\ +first_entry_1: ;\ + lwz 0, 0(1) ;\ + lwz 3, 4(1) ;\ + lwz 4, 8(1) ;\ + mtctr 0 ;\ + bctrl ;\ +"); + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + l4_word_t *top; + + /* Calculate top of the new stack. */ + top = (l4_word_t *) ((l4_word_t) thread->stackaddr + thread->stacksize); + + /* Initial stack frame. */ + top[-4] = 0; + top = top - 4; + + if (start_routine) + { + struct start_info *info = ((struct start_info *) top) - 1; + + info->entry_point = entry_point; + info->start_routine = start_routine; + info->arg = arg; + return (void *) info; + } + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = first_entry_1; + thread->mcontext.sp = stack_setup (thread, entry_point, + start_routine, arg); + + if (l4_same_threads (thread->threadid, l4_myself ())) + l4_set_user_defined_handle ((l4_word_t) thread); + else + l4_set_user_defined_handle_of (thread->threadid, + (l4_word_t) thread); + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-block.c b/libpthread/sysdeps/l4/hurd/pt-block.c new file mode 100644 index 00000000..2315b1c4 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-block.c @@ -0,0 +1,30 @@ +/* Block a thread. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + futex_wait (&thread->threadid, thread->threadid); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-kill.c b/libpthread/sysdeps/l4/hurd/pt-kill.c new file mode 100644 index 00000000..c72e82f4 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-kill.c @@ -0,0 +1,3 @@ +/* The generic version is good enough for us, however, the generic + Hurd on Mach version supplies a specialized version */ +#include "../generic/pt-kill.c" diff --git a/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c new file mode 100644 index 00000000..f2f07233 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c @@ -0,0 +1,39 @@ +/* Set a thread's activity activity. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +int +pthread_setactivity_np (addr_t activity) +{ + struct __pthread *self = _pthread_self (); + + struct hurd_thread_exregs_in in; + in.activity = activity; + + struct hurd_thread_exregs_out out; + int err = rm_thread_exregs (ADDR_VOID, self->object, + HURD_EXREGS_SET_ACTIVITY, + in, &out); + + return err; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c b/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c new file mode 100644 index 00000000..997a0369 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ + /* Nothing to do. */ +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c b/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c new file mode 100644 index 00000000..4c40fdb3 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c @@ -0,0 +1,44 @@ +/* Initialize the signal state. Hurd on L4 version. + Copyright (C) 2003, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + struct signal_state *ss = &thread->ss; + + memset (ss, 0, sizeof (*ss)); + + ss->stack.ss_flags = SS_DISABLE; + + int signo; + for (signo = 1; signo < NSIG; ++signo) + { + sigemptyset (&ss->actions[signo - 1].sa_mask); + ss->actions[signo - 1].sa_flags = SA_RESTART; + ss->actions[signo - 1].sa_handler = SIG_DFL; + ss->lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + } + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate.c b/libpthread/sysdeps/l4/hurd/pt-sigstate.c new file mode 100644 index 00000000..66dd08cf --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate.c @@ -0,0 +1,81 @@ +/* Set a thread's signal state. Hurd on L4 version. + Copyright (C) 2002, 2005, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending) +{ + struct signal_state *ss = &thread->ss; + pthread_mutex_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + { + /* Mask out SIGKILL and SIGSTOP. */ + sigset_t s = *set; + sigdelset (&s, SIGKILL); + sigdelset (&s, SIGSTOP); + + switch (how) + { + case SIG_BLOCK: + ss->blocked |= s; + break; + case SIG_UNBLOCK: + ss->blocked &= ~s; + break; + case SIG_SETMASK: + ss->blocked = s; + break; + default: + errno = EINVAL; + pthread_mutex_unlock (&ss->lock); + return -1; + } + } + + if (clear_pending) + sigemptyset (&ss->pending); + + /* A "signal shall remain pending until it is unblocked" (2.4.1). + + "If there are any pending unblocked signals after the call to + sigprocmask(), at least one of those signals shall be delivered + before the call to sigprocmask() returns." + (pthread_sigmask). */ + sigset_t extant = ~ss->blocked & ss->pending; + if (! extant) + extant = ~ss->blocked & process_pending; + + pthread_mutex_unlock (&ss->lock); + + if (extant) + raise (l4_lsb64 (extant)); + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-startup.c b/libpthread/sysdeps/l4/hurd/pt-startup.c new file mode 100644 index 00000000..b6461de7 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-startup.c @@ -0,0 +1,30 @@ +/* Thread initialization. Hurd/L4 version. + Copyright (C) 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +void +__pthread_startup (void) +{ + struct __pthread *pthread = _pthread_self (); + pthread->threadid = l4_myself (); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sysdep.c b/libpthread/sysdeps/l4/hurd/pt-sysdep.c new file mode 100644 index 00000000..c23364c7 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sysdep.c @@ -0,0 +1,61 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 2000, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +sched_yield (void) +{ + l4_yield (); + return 0; +} + +/* Forward. */ +static void init_routine (void (*) (void *), void *) + __attribute__ ((noreturn)); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +void (*_pthread_init_routine)(void (*) (void *), void *) = &init_routine; + +/* This function is called from the Hurd-specific startup code. It + should return a new stack pointer for the main thread. The caller + will switch to this new stack before doing anything serious. */ +static void +init_routine (void (*entry) (void *), void *arg) +{ + /* Initialize the library. */ + __pthread_initialize (); + + struct __pthread *thread; + int err; + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, + (void *(*)(void *)) entry, arg); + assert_perror (err); + + /* Switch stacks. */ + l4_start_sp_ip (l4_myself (), thread->mcontext.sp, + thread->mcontext.pc); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sysdep.h b/libpthread/sysdeps/l4/hurd/pt-sysdep.h new file mode 100644 index 00000000..08bcd143 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sysdep.h @@ -0,0 +1,61 @@ +/* Internal definitions for pthreads library. + Copyright (C) 2000, 2002, 2005, 2007, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include +#include +#include + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size: 2MB. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) + +#include + +#define EXCEPTION_AREA_SIZE EXCEPTION_STACK_SIZE +#define EXCEPTION_AREA_SIZE_LOG2 EXCEPTION_STACK_SIZE_LOG2 +/* The exception page is the first object. */ +#define EXCEPTION_PAGE 0 + +#define PTHREAD_SYSDEP_MEMBERS \ + addr_t object; \ + l4_thread_id_t threadid; \ + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; \ + void *exception_area_va; \ + l4_word_t my_errno; + +extern inline struct __pthread * +__attribute__((__always_inline__)) +_pthread_self (void) +{ + return (struct __pthread *) l4_user_defined_handle (); +} + +extern inline void +__attribute__((__always_inline__)) +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + munmap (stackaddr, stacksize); +} + +#endif /* pt-sysdep.h */ diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c new file mode 100644 index 00000000..ada7b3b8 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c @@ -0,0 +1,95 @@ +/* Allocate kernel thread. Viengoos version. + Copyright (C) 2007, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +extern struct hurd_startup_data *__hurd_startup_data; + +extern addr_t meta_data_activity; + +int +__pthread_thread_alloc (struct __pthread *thread) +{ + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + { + thread->object = __hurd_startup_data->thread; + thread->threadid = l4_myself (); + return 0; + } + else + { + addr_t exception_area = as_alloc (EXCEPTION_AREA_SIZE_LOG2, 1, true); + + thread->exception_area_va + = ADDR_TO_PTR (addr_extend (exception_area, + 0, EXCEPTION_AREA_SIZE_LOG2)); + + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + addr_t slot = addr_chop (PTR_TO_ADDR (thread->exception_area_va + + i * PAGESIZE), + PAGESIZE_LOG2); + as_ensure (slot); + + struct storage storage = storage_alloc (ADDR_VOID, cap_page, + STORAGE_LONG_LIVED, + OBJECT_POLICY_DEFAULT, + slot); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < i; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + + thread->exception_area[i] = storage.addr; + } + + struct storage storage; + storage = storage_alloc (meta_data_activity, cap_thread, + /* Threads are rarely shortly lived. */ + STORAGE_MEDIUM_LIVED, OBJECT_POLICY_DEFAULT, + ADDR_VOID); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < EXCEPTION_AREA_SIZE / PAGESIZE; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + + thread->object = storage.addr; + } + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-halt.c b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c new file mode 100644 index 00000000..98fefaab --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c @@ -0,0 +1,104 @@ +/* Deallocate the kernel thread resources. Viengoos version. + Copyright (C) 2007, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +#include +#include +#include +#include + +/* If we try to deallocate our self, we will end up causing a + deadlock. Thus, when a thread tries to free itself, we add it + here. The next thread to free a thread will free it. */ +ss_mutex_t saved_object_lock; +static addr_t saved_object; + +void +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +{ + /* We may deallocate THREAD. First save any data we need. */ + + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; + memcpy (exception_area, thread->exception_area, + sizeof (thread->exception_area)); + memset (thread->exception_area, 0, sizeof (thread->exception_area)); + + void *va = thread->exception_area_va; + + addr_t object = thread->object; + l4_thread_id_t tid = thread->threadid; + + if (need_dealloc) + __pthread_dealloc (thread); + + /* The THREAD data structure is no longer valid. */ + thread = NULL; + + /* Deallocate any saved object. */ + ss_mutex_lock (&saved_object_lock); + if (! ADDR_IS_VOID (saved_object)) + { + storage_free (saved_object, false); + saved_object = ADDR_VOID; + } + ss_mutex_unlock (&saved_object_lock); + + /* Free the exception area. */ + + /* Clean up the exception page. */ + exception_page_cleanup + (ADDR_TO_PTR (addr_extend (exception_area[EXCEPTION_PAGE], + 0, PAGESIZE_LOG2))); + + /* Free the storage. */ + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + assert (! ADDR_IS_VOID (exception_area[i])); + storage_free (exception_area[i], false); + } + + /* And the address space. */ + as_free (addr_chop (PTR_TO_ADDR (va), EXCEPTION_AREA_SIZE_LOG2), false); + + if (tid == l4_myself ()) + /* If we try to storage_free (storage.addr), we will freeze in the + middle. That's no good. We set SAVED_OBJECT to our thread + object and the next thread in will free us. */ + { + ss_mutex_lock (&saved_object_lock); + saved_object = object; + ss_mutex_unlock (&saved_object_lock); + } + else + storage_free (object, false); + + if (tid == l4_myself ()) + { + l4_send_timeout (l4_myself (), L4_NEVER); + panic ("Failed to stop thread %x.%x!", + l4_thread_no (l4_myself ()), l4_version (l4_myself ())); + } + else + thread_stop (object); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-start.c b/libpthread/sysdeps/l4/hurd/pt-thread-start.c new file mode 100644 index 00000000..9db399ce --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-start.c @@ -0,0 +1,70 @@ +/* Start thread. L4 version. + Copyright (C) 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#include + +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ + { + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); + l4_set_user_defined_handle ((l4_word_t) thread); + } + else + { + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; + + in.aspace = ADDR (0, 0); + in.aspace_cap_properties = CAP_PROPERTIES_VOID; + in.aspace_cap_properties_flags = CAP_COPY_COPY_SOURCE_GUARD; + + in.activity = ADDR_VOID; + + in.exception_page = addr_chop (PTR_TO_ADDR (thread->exception_area_va), + PAGESIZE_LOG2); + + in.sp = (l4_word_t) thread->mcontext.sp; + in.ip = (l4_word_t) thread->mcontext.pc; + + in.user_handle = (l4_word_t) thread; + err = rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_SET_ASPACE + | HURD_EXREGS_SET_ACTIVITY + | HURD_EXREGS_SET_EXCEPTION_PAGE + | HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_SET_USER_HANDLE + | HURD_EXREGS_START + | HURD_EXREGS_ABORT_IPC, + in, &out); + assert (err == 0); + } + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-wakeup.c b/libpthread/sysdeps/l4/hurd/pt-wakeup.c new file mode 100644 index 00000000..e568a6f9 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-wakeup.c @@ -0,0 +1,46 @@ +/* Wakeup a thread. Viengoos version. + Copyright (C) 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + /* We need to loop here as the blocked thread may not yet be + blocked! Here's what happens when a thread blocks: it registers + itself as blocked, drops the relevant lock and then actually + blocks (via __pthread_block). This means that after dropping the + lock and before blocking, it may be interrupted and another + thread may try to wake it. */ + long ret; + do + { + ret = futex_wake (&thread->threadid, INT_MAX); + assertx (ret <= 1, "tid: %x, ret: %d", thread->threadid, ret); + + if (ret == 0) + l4_thread_switch (thread->threadid); + } + while (ret == 0); +} diff --git a/libpthread/sysdeps/l4/hurd/sig-sysdep.h b/libpthread/sysdeps/l4/hurd/sig-sysdep.h new file mode 100644 index 00000000..33e13857 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/sig-sysdep.h @@ -0,0 +1,69 @@ +/* sig-sysdep.h - Hurd system specific header file. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +struct utcb +{ + l4_word_t saved_sender; + l4_word_t saved_receiver; + l4_word_t saved_timeout; + l4_word_t saved_error_code; + l4_word_t saved_flags; + l4_word_t saved_br0; + l4_msg_t saved_message; +}; + +static inline void +utcb_state_save (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + buffer->saved_sender = utcb[_L4_UTCB_SENDER]; + buffer->saved_receiver = utcb[_L4_UTCB_RECEIVER]; + buffer->saved_timeout = utcb[_L4_UTCB_TIMEOUT]; + buffer->saved_error_code = utcb[_L4_UTCB_ERROR_CODE]; + buffer->saved_flags = utcb[_L4_UTCB_FLAGS]; + buffer->saved_br0 = utcb[_L4_UTCB_BR0]; + memcpy (&buffer->saved_message, + utcb, L4_NUM_MRS * sizeof (l4_word_t)); +} + +static inline void +utcb_state_restore (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + utcb[_L4_UTCB_SENDER] = buffer->saved_sender; + utcb[_L4_UTCB_RECEIVER] = buffer->saved_receiver; + utcb[_L4_UTCB_TIMEOUT] = buffer->saved_timeout; + utcb[_L4_UTCB_ERROR_CODE] = buffer->saved_error_code; + utcb[_L4_UTCB_FLAGS] = buffer->saved_flags; + utcb[_L4_UTCB_BR0] = buffer->saved_br0; + memcpy (utcb, &buffer->saved_message, + L4_NUM_MRS * sizeof (l4_word_t)); +} + +#define SIGNAL_DISPATCH_ENTRY \ + struct utcb buffer; utcb_state_save (&buffer); + +#define SIGNAL_DISPATCH_EXIT \ + utcb_state_restore (&buffer); diff --git a/libpthread/sysdeps/l4/hurd/sigprocmask.c b/libpthread/sysdeps/l4/hurd/sigprocmask.c new file mode 100644 index 00000000..a38b3795 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/sigprocmask.c @@ -0,0 +1,41 @@ +/* sigprocmask.c - Generic sigprocmask implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield . + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + . */ + +#include +#include + +int +sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict old) +{ + struct __pthread *thread = _pthread_self (); + if (! thread) + /* Library is initializing. */ + { + assert (__pthread_num_threads == 1); + + /* We should get the default mask from the startup data structure. */ + if (old) + *old = 0; + + return 0; + } + + return pthread_sigmask (how, set, old); +} diff --git a/libpthread/sysdeps/l4/pt-block.c b/libpthread/sysdeps/l4/pt-block.c new file mode 100644 index 00000000..69e1d358 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-block.c @@ -0,0 +1,47 @@ +/* Block a thread. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +#include + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + debug (5, "%x.%x/%x blocking", + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + + l4_accept (L4_UNTYPED_WORDS_ACCEPTOR); + l4_msg_tag_t tag = l4_receive (l4_anythread); + if (l4_ipc_failed (tag)) + { + debug (1, "%x.%x failed to block: %d, offset: %x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + (l4_error_code () >> 1) & 0x7, + l4_error_code () >> 4); + assert (! l4_ipc_failed (tag)); + } + else + debug (5, "%x.%x unblocked", + l4_thread_no (thread->threadid), l4_version (thread->threadid)); +} diff --git a/libpthread/sysdeps/l4/pt-docancel.c b/libpthread/sysdeps/l4/pt-docancel.c new file mode 100644 index 00000000..a3965d0d --- /dev/null +++ b/libpthread/sysdeps/l4/pt-docancel.c @@ -0,0 +1,42 @@ +/* Cancel a thread. + Copyright (C) 2002, 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + assert (p->cancel_pending == 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + if (l4_is_thread_equal (l4_myself (), p->threadid)) + call_exit (); + else + l4_start_sp_ip (p->threadid, (l4_word_t) p->mcontext.sp, + (l4_word_t) call_exit); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-pool-np.c b/libpthread/sysdeps/l4/pt-pool-np.c new file mode 100644 index 00000000..e83022ba --- /dev/null +++ b/libpthread/sysdeps/l4/pt-pool-np.c @@ -0,0 +1,54 @@ +/* Thread pool for L4 threads. + Copyright (C) 2004, 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; + +_L4_thread_id_t pool_list = l4_nilthread; + +/* Add the thread TID to the pthread kernel thread pool. */ +int +pthread_pool_add_np (l4_thread_id_t tid) +{ + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + l4_set_user_defined_handle_of (tid, pool_list); + pool_list = tid; + __pthread_mutex_unlock (&pool_lock); + + return 0; +} + + +/* Get the first thread from the pool. */ +l4_thread_id_t +pthread_pool_get_np (void) +{ + _L4_thread_id_t tid; + + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + tid = pool_list; + if (tid != l4_nilthread) + pool_list = l4_user_defined_handle_of (tid); + __pthread_mutex_unlock (&pool_lock); + return tid; +} diff --git a/libpthread/sysdeps/l4/pt-spin.c b/libpthread/sysdeps/l4/pt-spin.c new file mode 100644 index 00000000..b6978b0c --- /dev/null +++ b/libpthread/sysdeps/l4/pt-spin.c @@ -0,0 +1,63 @@ +/* Spin locks. L4 version. + Copyright (C) 2000, 2004 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +/* The default for single processor machines; don't spin, it's + pointless. */ +#ifndef __PTHREAD_SPIN_COUNT +# define __PTHREAD_SPIN_COUNT 1 +#endif + +/* The number of times to spin while trying to lock a spin lock object + before yielding the processor. */ +int __pthread_spin_count = __PTHREAD_SPIN_COUNT; + + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + l4_time_t timeout; + int i; + + /* Start with a small timeout of 2 microseconds, then back off + exponentially. */ + timeout = l4_time_period (2); + + while (1) + { + for (i = 0; i < __pthread_spin_count; i++) + { + if (__pthread_spin_trylock (lock) == 0) + return 0; + } + l4_sleep (timeout); + + timeout = l4_time_mul2 (timeout); + if (timeout == L4_NEVER) + timeout = L4_TIME_PERIOD_MAX; + } +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/libpthread/sysdeps/l4/pt-stack-alloc.c b/libpthread/sysdeps/l4/pt-stack-alloc.c new file mode 100644 index 00000000..b7ec12b4 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-stack-alloc.c @@ -0,0 +1,43 @@ +/* Allocate a new stack. L4 Hurd version. + Copyright (C) 2000, 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +#include + +/* Allocate a new stack of size STACKSIZE. If successful, store the + address of the newly allocated stack in *STACKADDR and return 0. + Otherwise return an error code (EINVAL for an invalid stack size, + EAGAIN if the system lacked the necessary resources to allocate a + new stack). */ +int +__pthread_stack_alloc (void **stackaddr, size_t stacksize) +{ + void *buffer = mmap (0, stacksize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buffer == MAP_FAILED) + return EAGAIN; + + *stackaddr = buffer; + + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-thread-alloc.c b/libpthread/sysdeps/l4/pt-thread-alloc.c new file mode 100644 index 00000000..ec69afb5 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-alloc.c @@ -0,0 +1,43 @@ +/* Allocate kernel thread. L4 version. + Copyright (C) 2003, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +int +__pthread_thread_alloc (struct __pthread *thread) +{ + error_t err; + + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + thread->threadid = l4_myself (); + else + { + thread->threadid = pthread_pool_get_np (); + if (thread->threadid != l4_nilthread) + return 0; + + return EAGAIN; + } + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-thread-dealloc.c b/libpthread/sysdeps/l4/pt-thread-dealloc.c new file mode 100644 index 00000000..c09e4860 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-dealloc.c @@ -0,0 +1,32 @@ +/* Deallocate the kernel thread resources. L4 version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +void +__pthread_thread_dealloc (struct __pthread *thread) +{ +} diff --git a/libpthread/sysdeps/l4/pt-thread-halt.c b/libpthread/sysdeps/l4/pt-thread-halt.c new file mode 100644 index 00000000..aa2bf43d --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-halt.c @@ -0,0 +1,45 @@ +/* Deallocate the kernel thread resources. L4version. + Copyright (C) 2000, 2002, 2004 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +/* Deallocate the kernel thread resources associated with THREAD. */ +void +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +{ + l4_thread_id_t tid = thread->threadid; + + if (need_dealloc) + __pthread_dealloc (thread); + + /* There is potential race here: once if TID is the current thread, + then once we add TID to the pool, someone can reallocate it + before we call stop. However, to start the thread, the caller + atomically starts and sets the sp and ip, thus, if the stop has + not yet executed at that point, it won't. */ + + if (tid != l4_myself ()) + l4_stop (tid); + pthread_pool_add_np (tid); + if (tid == l4_myself ()) + l4_stop (tid); +} diff --git a/libpthread/sysdeps/l4/pt-thread-start.c b/libpthread/sysdeps/l4/pt-thread-start.c new file mode 100644 index 00000000..144c58bb --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-start.c @@ -0,0 +1,40 @@ +/* Start thread. L4 version. + Copyright (C) 2003, 2004, 2007 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ + { + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); + } + else + l4_start_sp_ip (thread->threadid, (l4_word_t) thread->mcontext.sp, + (l4_word_t) thread->mcontext.pc); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-timedblock.c b/libpthread/sysdeps/l4/pt-timedblock.c new file mode 100644 index 00000000..ce7972bd --- /dev/null +++ b/libpthread/sysdeps/l4/pt-timedblock.c @@ -0,0 +1,35 @@ +/* Block a thread with a timeout. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +/* Block THREAD. */ +error_t +__pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime) +{ +#warning Need gettimeofday to implement properly. + __pthread_block (thread); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-wakeup.c b/libpthread/sysdeps/l4/pt-wakeup.c new file mode 100644 index 00000000..de378465 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-wakeup.c @@ -0,0 +1,54 @@ +/* Wakeup a thread. L4 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +#include + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + debug (5, "%x.%x/%x waking %x.%x/%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), l4_myself (), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + + /* Signal the waiter. */ + l4_msg_t msg; + l4_msg_clear (msg); + l4_msg_set_untyped_words (msg, 0); + l4_msg_load (msg); + + l4_msg_tag_t tag = l4_send (thread->threadid); + if (l4_ipc_failed (tag)) + { + int err = l4_error_code (); + debug (1, "%x.%x failed to wake %x.%x: %s (%d)", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + l4_strerror (err), err); + } + else + debug (5, "%x.%x woke %x.%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid)); +} diff --git a/libpthread/sysdeps/mach/bits/spin-lock-inline.h b/libpthread/sysdeps/mach/bits/spin-lock-inline.h new file mode 100644 index 00000000..f9f7c299 --- /dev/null +++ b/libpthread/sysdeps/mach/bits/spin-lock-inline.h @@ -0,0 +1,90 @@ +/* Definitions of user-visible names for spin locks. + Copyright (C) 1994, 1997, 2002, 2008, 2009 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. */ + +#ifndef _BITS_SPIN_LOCK_INLINE_H +#define _BITS_SPIN_LOCK_INLINE_H 1 + +#include +#include +#include /* This does all the work. */ + +__BEGIN_DECLS + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE __extern_inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + return __spin_try_lock (__lock) ? 0 : __EBUSY; +} + +__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +__extern_inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + __spin_unlock (__lock); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/mach/bits/spin-lock.h b/libpthread/sysdeps/mach/bits/spin-lock.h new file mode 100644 index 00000000..537dac9d --- /dev/null +++ b/libpthread/sysdeps/mach/bits/spin-lock.h @@ -0,0 +1,38 @@ +/* Definitions of user-visible names for spin locks. + Copyright (C) 1994, 1997, 2002, 2008, 2009 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. */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include +#include /* This does all the work. */ + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __spin_lock_t __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +#ifndef __PTHREAD_SPIN_LOCK_INITIALIZER +#error __PTHREAD_SPIN_LOCK_INITIALIZER undefined: should be defined by . +#endif + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c b/libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c new file mode 100644 index 00000000..face46c5 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/ia32/pt-machdep.c @@ -0,0 +1,54 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include + +int +__thread_set_pcsp (thread_t thread, + int set_ip, void *ip, + int set_sp, void *sp) +{ + error_t err; + struct i386_thread_state state; + mach_msg_type_number_t state_count; + + state_count = i386_THREAD_STATE_COUNT; + + err = __thread_get_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, &state_count); + if (err) + return err; + + if (set_sp) + state.uesp = (unsigned int) sp; + if (set_ip) + state.eip = (unsigned int) ip; + + err = __thread_set_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, + i386_THREAD_STATE_COUNT); + if (err) + return err; + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/ia32/pt-setup.c b/libpthread/sysdeps/mach/hurd/ia32/pt-setup.c new file mode 100644 index 00000000..ba438d6a --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/ia32/pt-setup.c @@ -0,0 +1,105 @@ +/* Setup thread stack. Hurd/i386 version. + Copyright (C) 2000, 2002, 2005, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- + | | + | Fast TSD | + | | + ----------------- + + We need to reserve __hurd_threadvar_max `unsigned long int's' of + (fast) thread-specific data (TSD) for the Hurd. */ + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg) +{ + error_t err; + uintptr_t *bottom, *top; + + /* Calculate the top of the new stack. */ + bottom = thread->stackaddr; + top = (uintptr_t *) ((uintptr_t) bottom + thread->stacksize); + + /* Next, make room for the TSDs. */ + top -= __hurd_threadvar_max; + + /* Save the self pointer. */ + top[_HURD_THREADVAR_THREAD] = (uintptr_t) thread; + + if (start_routine) + { + /* And then the call frame. */ + top -= 2; + top = (uintptr_t) top & ~0xf; + top[1] = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + top[0] = (uintptr_t) start_routine; + *--top = 0; /* Fake return address. */ + } + + if (thread->guardsize) + { + err = __vm_protect (__mach_task_self (), (vm_address_t) bottom, + thread->guardsize, 0, 0); + assert_perror (err); + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + error_t err; + mach_port_t ktid; + + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + ktid = __mach_thread_self (); + if (thread->kernel_thread != ktid) + { + err = __thread_set_pcsp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp); + assert_perror (err); + } + __mach_port_deallocate (__mach_task_self (), ktid); + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-attr-setstackaddr.c b/libpthread/sysdeps/mach/hurd/pt-attr-setstackaddr.c new file mode 100644 index 00000000..1225ed5b --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-attr-setstackaddr.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstackaddr. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr) +{ + if ((long) stackaddr & (__pthread_stacksize - 1)) + return EINVAL; + + attr->stackaddr = stackaddr; + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-attr-setstacksize.c b/libpthread/sysdeps/mach/hurd/pt-attr-setstacksize.c new file mode 100644 index 00000000..6471c0a3 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-attr-setstacksize.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstacksize. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + if (stacksize != __pthread_stacksize) + return EINVAL; + + attr->stacksize = stacksize; + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-docancel.c b/libpthread/sysdeps/mach/hurd/pt-docancel.c new file mode 100644 index 00000000..b81a5c70 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-docancel.c @@ -0,0 +1,64 @@ +/* Cancel a thread. + Copyright (C) 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + mach_port_t ktid; + int me; + + assert (p->cancel_pending == 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + ktid = __mach_thread_self (); + me = p->kernel_thread == ktid; + __mach_port_deallocate (__mach_task_self (), ktid); + + if (me) + call_exit (); + else + { + error_t err; + + err = __thread_suspend (p->kernel_thread); + assert_perror (err); + + err = __thread_abort (p->kernel_thread); + assert_perror (err); + + err = __thread_set_pcsp (p->kernel_thread, + 1, (void *) call_exit, 0, 0); + assert_perror (err); + + err = __thread_resume (p->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c b/libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c new file mode 100644 index 00000000..8e56c5cf --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ + /* Nothing to do. */ +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c b/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c new file mode 100644 index 00000000..da5a9455 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sigstate-init.c @@ -0,0 +1,37 @@ +/* Initialize the signal state. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + void **location = + (void *) __hurd_threadvar_location_from_sp (_HURD_THREADVAR_SIGSTATE, + thread->stackaddr); + + /* The real initialization happens internally in glibc the first + time that _hurd_thead_sigstate is called. */ + *location = 0; + + return 0; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sigstate.c b/libpthread/sysdeps/mach/hurd/pt-sigstate.c new file mode 100644 index 00000000..68c79c5b --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sigstate.c @@ -0,0 +1,69 @@ +/* Set a thread's signal state. Hurd on Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending) +{ + error_t err = 0; + struct hurd_sigstate *ss; + + ss = _hurd_thread_sigstate (thread->kernel_thread); + assert (ss); + + __pthread_spin_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + switch (how) + { + case SIG_BLOCK: + ss->blocked |= *set; + break; + + case SIG_SETMASK: + ss->blocked = *set; + break; + + case SIG_UNBLOCK: + ss->blocked &= ~*set; + break; + + default: + err = EINVAL; + break; + } + + if (! err && clear_pending) + __sigemptyset (&ss->pending); + + __pthread_spin_unlock (&ss->lock); + + return err; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sysdep.c b/libpthread/sysdeps/mach/hurd/pt-sysdep.c new file mode 100644 index 00000000..5e070067 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sysdep.c @@ -0,0 +1,72 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 2000, 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include +#include + +#include + +#include + +/* Forward. */ +static void *init_routine (void); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +void *(*_cthread_init_routine)(void) = &init_routine; + +/* This function is called from the Hurd-specific startup code. It + should return a new stack pointer for the main thread. The caller + will switch to this new stack before doing anything serious. */ +static void * +init_routine (void) +{ + struct __pthread *thread; + int err; + + /* Initialize the library. */ + __pthread_initialize (); + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, 0, 0); + assert_perror (err); + + ((void **) (__hurd_threadvar_stack_offset))[_HURD_THREADVAR_THREAD] + = thread; + + /* Decrease the number of threads, to take into account that the + signal thread (which will be created by the glibc startup code + when we return from here) shouldn't be seen as a user thread. */ + __pthread_total--; + + /* Make MiG code thread aware. */ + __mig_init (thread->stackaddr); + + /* Make sure we can find the per-thread variables. */ + __hurd_threadvar_stack_mask = ~(__pthread_default_attr.stacksize - 1); + __hurd_threadvar_stack_offset + = (__pthread_default_attr.stacksize + - __hurd_threadvar_max * sizeof (uintptr_t)); + + return thread->mcontext.sp; +} diff --git a/libpthread/sysdeps/mach/hurd/pt-sysdep.h b/libpthread/sysdeps/mach/hurd/pt-sysdep.h new file mode 100644 index 00000000..f14a1366 --- /dev/null +++ b/libpthread/sysdeps/mach/hurd/pt-sysdep.h @@ -0,0 +1,70 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000, 2002, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include + +#include + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) + +#define PTHREAD_SYSDEP_MEMBERS \ + thread_t kernel_thread; \ + mach_msg_header_t wakeupmsg; \ + int have_kernel_resources; + +#define _HURD_THREADVAR_THREAD _HURD_THREADVAR_DYNAMIC_USER + +#define _pthread_self() \ + ({ \ + struct __pthread *thread; \ + \ + assert (__pthread_threads); \ + thread = *(struct __pthread **) \ + __hurd_threadvar_location (_HURD_THREADVAR_THREAD); \ + \ + assert (thread); \ + assert (({ mach_port_t ktid = __mach_thread_self (); \ + int ok = thread->kernel_thread == ktid; \ + __mach_port_deallocate (__mach_task_self (), ktid);\ + ok; })); \ + thread; \ + }) + +extern inline void +__attribute__((__always_inline__)) +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize); +} + +/* Change thread THREAD's program counter to PC if SET_PC is true and + its stack pointer to SP if SET_IP is true. */ +extern int __thread_set_pcsp (thread_t thread, + int set_pc, void *pc, + int set_sp, void *sp); + + +#endif /* pt-sysdep.h */ diff --git a/libpthread/sysdeps/mach/pt-block.c b/libpthread/sysdeps/mach/pt-block.c new file mode 100644 index 00000000..a947b27c --- /dev/null +++ b/libpthread/sysdeps/mach/pt-block.c @@ -0,0 +1,39 @@ +/* Block a thread. Mach version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +#include + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + mach_msg_header_t msg; + error_t err; + + err = __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg, + thread->wakeupmsg.msgh_remote_port, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} diff --git a/libpthread/sysdeps/mach/pt-spin.c b/libpthread/sysdeps/mach/pt-spin.c new file mode 100644 index 00000000..d9a2a32a --- /dev/null +++ b/libpthread/sysdeps/mach/pt-spin.c @@ -0,0 +1,36 @@ +/* Spin locks. Mach version. + Copyright (C) 2002, 2004 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* In glibc. */ +extern void __spin_lock_solid (__pthread_spinlock_t *lock); + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + __spin_lock_solid (lock); + return 0; +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); +weak_alias (_pthread_spin_lock, __pthread_spin_lock); diff --git a/libpthread/sysdeps/mach/pt-stack-alloc.c b/libpthread/sysdeps/mach/pt-stack-alloc.c new file mode 100644 index 00000000..0956fc7d --- /dev/null +++ b/libpthread/sysdeps/mach/pt-stack-alloc.c @@ -0,0 +1,74 @@ +/* Allocate a new stack. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include + +#include + +#define __pthread_stacksize __pthread_default_attr.stacksize + +/* The next address to use for stack allocation. */ +static vm_address_t next_stack_base = VM_MIN_ADDRESS; + + +/* Allocate a new stack of size STACKSIZE. If successful, store the + address of the newly allocated stack in *STACKADDR and return 0. + Otherwise return an error code (EINVAL for an invalid stack size, + EAGAIN if the system lacked the necessary resources to allocate a + new stack). */ +int +__pthread_stack_alloc (void **stackaddr, size_t stacksize) +{ + vm_offset_t base; + int i = 0; + + if (stacksize != __pthread_stacksize) + return EINVAL; + + get_stack: + i ++; + for (base = next_stack_base; + base < VM_MAX_ADDRESS + && __vm_allocate (__mach_task_self (), &base, + __pthread_stacksize, FALSE) != KERN_SUCCESS; + base += __pthread_stacksize) + ; + + if (base >= VM_MAX_ADDRESS) + { + if (i == 1) + { + next_stack_base = VM_MIN_ADDRESS; + goto get_stack; + } + else + return EAGAIN; + } + + if (base >= VM_MAX_ADDRESS) + return EAGAIN; + + next_stack_base = base + __pthread_stacksize; + + (*stackaddr) = (void *) base; + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-thread-alloc.c b/libpthread/sysdeps/mach/pt-thread-alloc.c new file mode 100644 index 00000000..3d7c0465 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-alloc.c @@ -0,0 +1,106 @@ +/* Start thread. Mach version. + Copyright (C) 2000, 2002, 2005, 2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +#include + +/* Prepare a wakeup message. */ +static error_t +create_wakeupmsg (struct __pthread *thread) +{ + kern_return_t err; + + /* Build wakeup message. */ + thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); + thread->wakeupmsg.msgh_size = 0; + + err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &thread->wakeupmsg.msgh_remote_port); + if (err) + return EAGAIN; + + thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL; + thread->wakeupmsg.msgh_seqno = 0; + thread->wakeupmsg.msgh_id = 0; + + err = __mach_port_insert_right (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port, + thread->wakeupmsg.msgh_remote_port, + MACH_MSG_TYPE_MAKE_SEND); + if (err) + { + __mach_port_destroy (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + return EAGAIN; + } + + return 0; +} + +/* Allocate any resouces for THREAD. The new kernel thread should not + be eligible to be scheduled. */ +int +__pthread_thread_alloc (struct __pthread *thread) +{ + if (thread->have_kernel_resources) + return 0; + + error_t err; + + err = create_wakeupmsg (thread); + if (err) + return err; + + /* If there are no pthreads in the system then the pthread library + is bootstrapping and the main thread must create initialize + itself. The thread itself is already running, it just has not + pthread context. We want to reuse what it already has (including + the kernel thread), however, we must determine which thread is + the main thread. + + We cannot test if __pthread_total is one as we later decrement + before creating the signal thread. Currently, we check if + __pthread_num_threads--the number of allocated thread + structures--is one. __pthread_alloc has already been called in + __pthread_create_internal for us. This predicate could be improved, + however, it is sufficient for now. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 0); + thread->kernel_thread = __mach_thread_self (); + /* We implicitly hold a reference drop the one that we just + acquired. */ + __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); + } + else + { + err = __thread_create (__mach_task_self (), &thread->kernel_thread); + if (err) + return EAGAIN; + } + + thread->have_kernel_resources = 1; + + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-thread-dealloc.c b/libpthread/sysdeps/mach/pt-thread-dealloc.c new file mode 100644 index 00000000..55d8c4d5 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-dealloc.c @@ -0,0 +1,41 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +void +__pthread_thread_dealloc (struct __pthread *thread) +{ + /* Why no assert? Easy. When Mach kills a task, it starts by + invalidating the task port and then terminating the threads one + by one. But while it is terminating them, they are still + eligible to be scheduled. Imagine we have two threads, one calls + exit, one calls pthread_exit. The second one may run this after + the mask port can been destroyed thus gratuitously triggering the + assert. */ + __mach_port_destroy (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); +} diff --git a/libpthread/sysdeps/mach/pt-thread-halt.c b/libpthread/sysdeps/mach/pt-thread-halt.c new file mode 100644 index 00000000..973cde1e --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-halt.c @@ -0,0 +1,37 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 2000, 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is + true, the function must call __pthread_dealloc on THREAD. + + NB: The thread executing this function may be the thread which is + being halted, thus the last action should be halting the thread + itself. */ +void +__pthread_thread_halt (struct __pthread *thread) +{ + error_t err = __thread_terminate (thread->kernel_thread); + assert_perror (err); +} diff --git a/libpthread/sysdeps/mach/pt-thread-start.c b/libpthread/sysdeps/mach/pt-thread-start.c new file mode 100644 index 00000000..11b017ff --- /dev/null +++ b/libpthread/sysdeps/mach/pt-thread-start.c @@ -0,0 +1,49 @@ +/* Start thread. Mach version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + { + /* The main thread is already running: do nothing. */ + assert (__pthread_total == 1); + assert (({ mach_port_t ktid = __mach_thread_self (); + int ok = thread->kernel_thread == ktid; + __mach_port_deallocate (__mach_task_self (), + thread->kernel_thread); + ok; })); + } + else + { + err = __thread_resume (thread->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-timedblock.c b/libpthread/sysdeps/mach/pt-timedblock.c new file mode 100644 index 00000000..6f547265 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-timedblock.c @@ -0,0 +1,68 @@ +/* Block a thread with a timeout. Mach version. + Copyright (C) 2000, 2002, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include +#include + +#include + +/* Block THREAD. */ +error_t +__pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime) +{ + error_t err; + mach_msg_header_t msg; + mach_msg_timeout_t timeout; + struct timeval now; + + /* We have an absolute time and now we have to convert it to a + relative time. Arg. */ + + err = gettimeofday(&now, NULL); + assert (! err); + + if (now.tv_sec > abstime->tv_sec + || (now.tv_sec == abstime->tv_sec + && now.tv_usec > ((abstime->tv_nsec + 999) / 1000))) + return ETIMEDOUT; + + timeout = (abstime->tv_sec - now.tv_sec) * 1000; + + if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec) + timeout += (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000; + else + /* Need to do a carry. */ + timeout -= (now.tv_usec + 999) / 1000 - + ((abstime->tv_nsec + 999999) / 1000000); + + err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, + sizeof msg, thread->wakeupmsg.msgh_remote_port, + timeout, MACH_PORT_NULL); + if (err == EMACH_RCV_TIMED_OUT) + return ETIMEDOUT; + + assert_perror (err); + return 0; +} diff --git a/libpthread/sysdeps/mach/pt-wakeup.c b/libpthread/sysdeps/mach/pt-wakeup.c new file mode 100644 index 00000000..4920d102 --- /dev/null +++ b/libpthread/sysdeps/mach/pt-wakeup.c @@ -0,0 +1,38 @@ +/* Wakeup a thread. Mach version. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +#include + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + error_t err; + + err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG, + sizeof (thread->wakeupmsg), 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} diff --git a/libpthread/sysdeps/posix/pt-spin.c b/libpthread/sysdeps/posix/pt-spin.c new file mode 100644 index 00000000..cb809c64 --- /dev/null +++ b/libpthread/sysdeps/posix/pt-spin.c @@ -0,0 +1,54 @@ +/* Spin locks. + Copyright (C) 2000, 2004, 2005 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* The default for single processor machines; don't spin, it's + pointless. */ +#ifndef __PTHREAD_SPIN_COUNT +# define __PTHREAD_SPIN_COUNT 1 +#endif + +/* The number of times to spin while trying to lock a spin lock object + before yielding the processor. */ +int __pthread_spin_count = __PTHREAD_SPIN_COUNT; + + +/* Lock the spin lock object LOCK. If the lock is held by another + thread spin until it becomes available. */ +int +_pthread_spin_lock (__pthread_spinlock_t *lock) +{ + int i; + + while (1) + { + for (i = 0; i < __pthread_spin_count; i++) + { + if (__pthread_spin_trylock (lock) == 0) + return 0; + } + + __sched_yield (); + } +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); +weak_alias (_pthread_spin_lock, __pthread_spin_lock); diff --git a/libpthread/sysdeps/powerpc/bits/machine-lock.h b/libpthread/sysdeps/powerpc/bits/machine-lock.h new file mode 100644 index 00000000..cba6b0a6 --- /dev/null +++ b/libpthread/sysdeps/powerpc/bits/machine-lock.h @@ -0,0 +1,78 @@ +/* Machine-specific definition for spin locks. PowerPC version. + Copyright (C) 1994,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. */ + +#ifndef _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile long int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0L + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + long int __locked; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (register __spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); + return !__rtn; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %0,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock) : "cr0"); + return __rtn; +} + + +#endif /* machine-lock.h */ diff --git a/libpthread/sysdeps/powerpc/bits/memory.h b/libpthread/sysdeps/powerpc/bits/memory.h new file mode 100644 index 00000000..96624c3e --- /dev/null +++ b/libpthread/sysdeps/powerpc/bits/memory.h @@ -0,0 +1,36 @@ +/* Memory barrier operations. PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_MEMORY_H +#define _BITS_MEMORY_H 1 + +/* Prevent read and write reordering across this function. */ +inline void +__memory_barrier (void) +{ + asm ("sync" ::: "memory"); +} + +/* Prevent read reordering across this function. */ +#define __memory_read_barrier __memory_barrier + +/* Prevent write reordering across this function. */ +#define __memory_write_barrier __memory_barrier + +#endif diff --git a/libpthread/sysdeps/powerpc/bits/spin-lock.h b/libpthread/sysdeps/powerpc/bits/spin-lock.h new file mode 100644 index 00000000..1dc25710 --- /dev/null +++ b/libpthread/sysdeps/powerpc/bits/spin-lock.h @@ -0,0 +1,108 @@ +/* Machine-specific definitions for spin locks. PowerPC version. + Copyright (C) 2003 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use or instead. + */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __volatile int __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) + +#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES + +# ifndef __EBUSY +# include +# define __EBUSY EBUSY +# endif + +# ifndef __PT_SPIN_INLINE +# define __PT_SPIN_INLINE extern __inline +# endif + +__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_destroy (__pthread_spinlock_t *__lock) +{ + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, + int __pshared); + +__PT_SPIN_INLINE int +__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) +{ + *__lock = __SPIN_LOCK_INITIALIZER; + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_trylock (__pthread_spinlock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); + return __rtn ? __EBUSY : 0; +} + +extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +extern inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__lock); + return 0; +} + +__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); + +__PT_SPIN_INLINE int +__pthread_spin_unlock (__pthread_spinlock_t *__lock) +{ + long int __locked; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/libpthread/sysdeps/powerpc/machine-sp.h b/libpthread/sysdeps/powerpc/machine-sp.h new file mode 100644 index 00000000..aa787c59 --- /dev/null +++ b/libpthread/sysdeps/powerpc/machine-sp.h @@ -0,0 +1,31 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994,97,2001 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + void *__sp__; \ + __asm__ ("mr %0, 1" : "=r" (__sp__)); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/libpthread/sysdeps/powerpc/pt-machdep.h b/libpthread/sysdeps/powerpc/pt-machdep.h new file mode 100644 index 00000000..6d456367 --- /dev/null +++ b/libpthread/sysdeps/powerpc/pt-machdep.h @@ -0,0 +1,29 @@ +/* Machine dependent pthreads internal defenitions. i386 version. + Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHDEP_H +#define _PT_MACHDEP_H 1 + +struct pthread_mcontext +{ + void *pc; + void *sp; +}; + +#endif /* pt-machdep.h */ diff --git a/libpthread/tests/.cvsignore b/libpthread/tests/.cvsignore new file mode 100644 index 00000000..70845e08 --- /dev/null +++ b/libpthread/tests/.cvsignore @@ -0,0 +1 @@ +Makefile.in diff --git a/libpthread/tests/Makefile b/libpthread/tests/Makefile new file mode 100644 index 00000000..9509c957 --- /dev/null +++ b/libpthread/tests/Makefile @@ -0,0 +1,29 @@ +CFLAGS=-Wall -g + +LDLIBS = -lpthread + +CHECK_SRC := test-1.c test-2.c test-3.c test-6.c test-7.c test-8.c \ + test-9.c test-10.c test-11.c test-12.c test-13.c test-14.c \ + test-15.c test-16.c + +CHECK_OBJS := $(addsuffix .o,$(basename $(notdir $(CHECK_SRC)))) +CHECK_PROGS := $(basename $(notdir $(CHECK_SRC))) \ + $(addsuffix -static, $(basename $(CHECK_SRC))) + +%-static: %.o + $(CC) -static $(CFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS) + +check: $(CHECK_OBJS) $(CHECK_PROGS) + for i in $(CHECK_PROGS); do \ + echo -n Running $$i...\ ; \ + if ./$$i 2>&1 > $$i.out; \ + then \ + echo Success.; \ + else \ + echo Failure.; \ + fi \ + done + +clean: + rm -f $(CHECK_OBJS) $(CHECK_PROGS) \ + $(addsuffix .out,$(basename $(notdir $(CHECK_PROGS)))) \ No newline at end of file diff --git a/libpthread/tests/test-1.c b/libpthread/tests/test-1.c new file mode 100644 index 00000000..318fd6e9 --- /dev/null +++ b/libpthread/tests/test-1.c @@ -0,0 +1,49 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#define THREADS 500 + +void * +foo (void *arg) +{ + pthread_mutex_t *mutex = arg; + pthread_mutex_lock (mutex); + pthread_mutex_unlock (mutex); + return mutex; +} + +int +main (int argc, char **argv) +{ + int i; + error_t err; + pthread_t tid[THREADS]; + pthread_mutex_t mutex[THREADS]; + + for (i = 0; i < THREADS; i ++) + { + pthread_mutex_init (&mutex[i], 0); + pthread_mutex_lock (&mutex[i]); + err = pthread_create (&tid[i], 0, foo, &mutex[i]); + if (err) + error (1, err, "pthread_create"); + sched_yield (); + } + + for (i = THREADS - 1; i >= 0; i --) + { + void *ret; + pthread_mutex_unlock (&mutex[i]); + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + assert (ret == &mutex[i]); + } + + return 0; +} diff --git a/libpthread/tests/test-10.c b/libpthread/tests/test-10.c new file mode 100644 index 00000000..bec05c14 --- /dev/null +++ b/libpthread/tests/test-10.c @@ -0,0 +1,46 @@ +/* Test error checking mutexes. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + error_t err; + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + + err = pthread_mutexattr_init (&mattr); + if (err) + error (1, err, "pthread_mutexattr_init"); + + err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_ERRORCHECK); + if (err) + error (1, err, "pthread_mutexattr_settype"); + + err = pthread_mutex_init (&mutex, &mattr); + if (err) + error (1, err, "pthread_mutex_init"); + + err = pthread_mutexattr_destroy (&mattr); + if (err) + error (1, err, "pthread_mutexattr_destroy"); + + err = pthread_mutex_lock (&mutex); + assert (err == 0); + + err = pthread_mutex_lock (&mutex); + assert (err == EDEADLK); + + err = pthread_mutex_unlock (&mutex); + assert (err == 0); + + err = pthread_mutex_unlock (&mutex); + assert (err == EPERM); + + return 0; +} diff --git a/libpthread/tests/test-11.c b/libpthread/tests/test-11.c new file mode 100644 index 00000000..de779a40 --- /dev/null +++ b/libpthread/tests/test-11.c @@ -0,0 +1,143 @@ +/* Test rwlocks. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 1 + +int a; +int b; + +/* Get a read lock and assert that a == b. */ +void * +test1 (void *arg) +{ + error_t err; + pthread_rwlock_t *lock = arg; + int i; + + for (i = 0; i < 200; i ++) + { + err = pthread_rwlock_rdlock (lock); + assert (err == 0); + + assert (a == b); + + sched_yield (); + + assert (a == b); + + err = pthread_rwlock_unlock (lock); + assert (err == 0); + } + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + pthread_rwlockattr_t attr; + pthread_rwlock_t lock; + int pshared; + + int i; + pthread_t tid[THREADS]; + void *ret; + + err = pthread_rwlockattr_init (&attr); + if (err) + error (1, err, "pthread_rwlockattr_init"); + + err = pthread_rwlockattr_getpshared (&attr, &pshared); + if (err) + error (1, err, "pthread_rwlockattr_getpshared"); + + /* Assert the default state as mandated by POSIX. */ + assert (pshared == PTHREAD_PROCESS_PRIVATE); + + err = pthread_rwlockattr_setpshared (&attr, pshared); + if (err) + error (1, err, "pthread_rwlockattr_setpshared"); + + err = pthread_rwlock_init (&lock, &attr); + if (err) + error (1, err, "pthread_rwlock_init"); + + err = pthread_rwlockattr_destroy (&attr); + if (err) + error (1, err, "pthread_rwlockattr_destroy"); + + /* Now test the lock. */ + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, test1, &lock); + if (err) + error (1, err, "pthread_create"); + } + + for (i = 0; i < 10; i ++) + { + sched_yield (); + + /* Get a write lock. */ + pthread_rwlock_wrlock (&lock); + /* Increment a and b giving other threads a chance to run in + between. */ + sched_yield (); + a ++; + sched_yield (); + b ++; + sched_yield (); + /* Unlock. */ + pthread_rwlock_unlock (&lock); + } + + for (i = 0; i < THREADS; i ++) + { + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + } + + /* Read lock it. */ + err = pthread_rwlock_tryrdlock (&lock); + assert (err == 0); + + /* Try to write lock it. It should fail with EBUSY. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == EBUSY); + + /* Drop the read lock. */ + err = pthread_rwlock_unlock (&lock); + assert (err == 0); + + /* Get a write lock. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == 0); + + /* Fail trying to acquire another write lock. */ + err = pthread_rwlock_trywrlock (&lock); + assert (err == EBUSY); + + /* Try to get a read lock which should also fail. */ + err = pthread_rwlock_tryrdlock (&lock); + assert (err == EBUSY); + + /* Unlock it. */ + err = pthread_rwlock_unlock (&lock); + assert (err == 0); + + + err = pthread_rwlock_destroy (&lock); + if (err) + error (1, err, "pthread_rwlock_destroy"); + + return 0; +} diff --git a/libpthread/tests/test-12.c b/libpthread/tests/test-12.c new file mode 100644 index 00000000..2b784908 --- /dev/null +++ b/libpthread/tests/test-12.c @@ -0,0 +1,29 @@ +/* Test concurrency level. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + int i; + int err; + + i = pthread_getconcurrency (); + assert (i == 0); + + err = pthread_setconcurrency (-1); + assert (err == EINVAL); + + err = pthread_setconcurrency (4); + assert (err == 0); + + i = pthread_getconcurrency (); + assert (i == 4); + + return 0; +} diff --git a/libpthread/tests/test-13.c b/libpthread/tests/test-13.c new file mode 100644 index 00000000..13b09051 --- /dev/null +++ b/libpthread/tests/test-13.c @@ -0,0 +1,66 @@ +/* Test condition attributes and pthread_cond_timedwait. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_condattr_t attr; + pthread_cond_t cond; + struct timespec ts; + pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + struct timeval before, after; + int diff; + + err = pthread_condattr_init (&attr); + if (err) + error (1, err, "pthread_condattr_init"); + + err = pthread_condattr_getpshared (&attr, &i); + if (err) + error (1, err, "pthread_condattr_getpshared"); + assert (i == PTHREAD_PROCESS_PRIVATE); + + err = pthread_condattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); + assert (err == 0); + + err = pthread_cond_init (&cond, &attr); + if (err) + error (1, err, "pthread_cond_init"); + + err = pthread_condattr_destroy (&attr); + if (err) + error (1, err, "pthread_condattr_destroy"); + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Starting wait @ %d\n", (int) before.tv_sec); + + pthread_mutex_lock (&m); + err = pthread_cond_timedwait (&cond, &m, &ts); + + gettimeofday (&after, 0); + + printf ("End wait @ %d (err = %d)\n", (int) after.tv_sec, err); + + assert (err == ETIMEDOUT); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_cond_timedwait waited %d us", diff); + + return 0; +} diff --git a/libpthread/tests/test-14.c b/libpthread/tests/test-14.c new file mode 100644 index 00000000..b1dbfa66 --- /dev/null +++ b/libpthread/tests/test-14.c @@ -0,0 +1,44 @@ +/* Test pthread_mutex_timedlock. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + error_t err; + struct timespec ts; + pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + struct timeval before, after; + int diff; + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Starting wait @ %d\n", (int) before.tv_sec); + + pthread_mutex_lock (&m); + /* A default mutex shall dead lock if locked twice. As such we do + not need spawn a second thread. */ + err = pthread_mutex_timedlock (&m, &ts); + assert (err == ETIMEDOUT); + + gettimeofday (&after, 0); + + printf ("End wait @ %d\n", (int) after.tv_sec); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); + + return 0; +} diff --git a/libpthread/tests/test-15.c b/libpthread/tests/test-15.c new file mode 100644 index 00000000..173f8b6b --- /dev/null +++ b/libpthread/tests/test-15.c @@ -0,0 +1,87 @@ +/* Test pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#define THREADS 10 + +pthread_rwlock_t rwlock; + +void * +test (void *arg) +{ + error_t err; + int foo = (int) arg; + struct timespec ts; + struct timeval before, after; + int diff; + + gettimeofday (&before, 0); + ts.tv_sec = before.tv_sec + 1; + ts.tv_nsec = before.tv_usec * 1000; + + printf ("Thread %d starting wait @ %d\n", pthread_self (), + (int) before.tv_sec); + + if (foo % 2 == 0) + err = pthread_rwlock_timedrdlock (&rwlock, &ts); + else + err = pthread_rwlock_timedwrlock (&rwlock, &ts); + + assert (err == ETIMEDOUT); + + gettimeofday (&after, 0); + + printf ("Thread %d ending wait @ %d\n", pthread_self (), + (int) after.tv_sec); + + diff = after.tv_sec * 1000000 + after.tv_usec + - before.tv_sec * 1000000 - before.tv_usec; + + if (diff < 900000 || diff > 1100000) + error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + err = pthread_rwlock_init (&rwlock, 0); + if (err) + error (1, err, "pthread_rwlock_init"); + + /* Lock it so all the threads will block. */ + err = pthread_rwlock_wrlock (&rwlock); + assert (err == 0); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, test, (void *) i); + if (err) + error (1, err, "pthread_create"); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + return 0; +} diff --git a/libpthread/tests/test-16.c b/libpthread/tests/test-16.c new file mode 100644 index 00000000..b6a52d01 --- /dev/null +++ b/libpthread/tests/test-16.c @@ -0,0 +1,71 @@ +/* Test pthread_kill.c. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +pthread_t testthread; + +int i; + +void * +test (void *arg) +{ + error_t err; + + printf ("test: %d\n", pthread_self ()); + + err = pthread_kill (pthread_self (), SIGINFO); + if (err) + error (1, err, "pthread_kill"); + + /* To avoid using condition variables in a signal handler. */ + while (i == 0) + sched_yield (); + + return 0; +} + +static void +handler (int sig, siginfo_t *info, void *context) +{ + assert (pthread_equal (pthread_self (), testthread)); + printf ("handler: %d\n", pthread_self ()); + i = 1; +} + +int +main (int argc, char **argv) +{ + error_t err; + struct sigaction sa; + void *ret; + + printf ("main: %d\n", pthread_self ()); + + sa.sa_handler = handler; + sa.sa_mask = 0; + sa.sa_flags = 0; + + err = sigaction (SIGINFO, &sa, 0); + if (err) + error (1, err, "sigaction"); + + err = pthread_create (&testthread, 0, test, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_join (testthread, &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + + return 0; +} diff --git a/libpthread/tests/test-2.c b/libpthread/tests/test-2.c new file mode 100644 index 00000000..701462e8 --- /dev/null +++ b/libpthread/tests/test-2.c @@ -0,0 +1,39 @@ +/* Test detachability. */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +void * +thread (void *arg) +{ + while (1) + sched_yield (); +} + +int +main (int argc, char **argv) +{ + int err; + pthread_t tid; + void *ret; + + err = pthread_create (&tid, 0, thread, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_detach (tid); + if (err) + error (1, err, "pthread_detach"); + + err = pthread_detach (tid); + assert (err == EINVAL); + + err = pthread_join (tid, &ret); + assert (err == EINVAL); + + return 0; +} diff --git a/libpthread/tests/test-3.c b/libpthread/tests/test-3.c new file mode 100644 index 00000000..7db2e43f --- /dev/null +++ b/libpthread/tests/test-3.c @@ -0,0 +1,55 @@ +/* Test the thread attribute get and set methods. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + error_t err; + pthread_attr_t attr; + + int i; + struct sched_param sp; + void *p; + size_t sz; + + err = pthread_attr_init (&attr); + assert_perror (err); + + err = pthread_attr_destroy (&attr); + assert_perror (err); + + err = pthread_attr_init (&attr); + assert_perror (err); + +#define TEST1(foo, rv, v) \ + err = pthread_attr_get##foo (&attr, rv); \ + assert_perror (err); \ + \ + err = pthread_attr_set##foo (&attr, v); \ + assert_perror (err); + +#define TEST(foo, rv, v) TEST1(foo, rv, v) + + TEST(inheritsched, &i, i); + TEST(schedparam, &sp, &sp); + TEST(schedpolicy, &i, i); + TEST(scope, &i, i); + TEST(stackaddr, &p, p); + TEST(detachstate, &i, i); + TEST(guardsize, &sz, sz); + TEST(stacksize, &sz, sz); + + err = pthread_attr_getstack (&attr, &p, &sz); + assert_perror (err); + + err = pthread_attr_setstack (&attr, p, sz); + assert_perror (err); + + return 0; +} diff --git a/libpthread/tests/test-4.c b/libpthread/tests/test-4.c new file mode 100644 index 00000000..de9c8fe4 --- /dev/null +++ b/libpthread/tests/test-4.c @@ -0,0 +1,86 @@ +/* Test the stack guard. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +size_t stacksize; + +void * +thr (void *arg) +{ + int i; + char *foo; + + foo = alloca (3 * stacksize / 4); + for (i = 0; i < sizeof foo; i ++) + foo[i] = -1; + + return (void *) 1; +} + +int +main (int argc, char *argv[]) +{ + error_t err; + pid_t child; + + child = fork (); + switch (child) + { + case -1: + error (1, errno, "fork"); + break; + + case 0: + { + pthread_attr_t attr; + pthread_t tid; + void *ret; + + err = pthread_attr_init (&attr); + assert_perror (err); + + err = pthread_attr_getstacksize (&attr, &stacksize); + assert_perror (err); + + err = pthread_attr_setguardsize (&attr, stacksize / 2); + if (err == ENOTSUP) + { + printf ("Stack guard attribute not supported.\n"); + return 1; + } + assert_perror (err); + + err = pthread_create (&tid, &attr, thr, 0); + assert_perror (err); + + err = pthread_attr_destroy (&attr); + assert_perror (err); + + err = pthread_join (tid, &ret); + /* Should never be successful. */ + printf ("Thread did not segfault!?!\n"); + assert_perror (err); + return 0; + } + + default: + { + pid_t pid; + int status; + + pid = waitpid (child, &status, 0); + printf ("pid = %d; child = %d; status = %d\n", pid, child, status); + assert (pid == child); + assert (status != 0); + } + } + + return 0; +} diff --git a/libpthread/tests/test-5.c b/libpthread/tests/test-5.c new file mode 100644 index 00000000..0f5000b2 --- /dev/null +++ b/libpthread/tests/test-5.c @@ -0,0 +1,75 @@ +/* Test signals. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +void * +thr (void *arg) +{ + * (int *)0 = 0; + return 0; +} + +int foobar; + +int +main (int argc, char *argv[]) +{ + error_t err; + pid_t child; + + struct rlimit limit; + + limit.rlim_cur = 0; + limit.rlim_max = 0; + + err = setrlimit (RLIMIT_CORE, &limit); + if (err) + error (1, err, "setrlimit"); + + child = fork (); + switch (child) + { + case -1: + error (1, errno, "fork"); + break; + + case 0: + { + pthread_t tid; + void *ret; + + err = pthread_create (&tid, 0, thr, 0); + if (err) + error (1, err, "pthread_create"); + + err = pthread_join (tid, &ret); + assert_perror (err); + + /* Should have never returned. Our parent expects us to fail + thus we succeed and indicate the error. */ + return 0; + } + + default: + { + pid_t pid; + int status; + + pid = waitpid (child, &status, 0); + printf ("pid = %d; child = %d; status = %d\n", pid, child, status); + assert (pid == child); + assert (status != 0); + } + } + + return 0; +} diff --git a/libpthread/tests/test-6.c b/libpthread/tests/test-6.c new file mode 100644 index 00000000..98aa8ba7 --- /dev/null +++ b/libpthread/tests/test-6.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 500 +#define WAITS 3 + +void * +dowait (void *arg) +{ + pthread_barrier_t *barrier = arg; + int ret; + + ret = pthread_barrier_wait (barrier); + printf ("%d ", pthread_self ()); + return (void *) ret; +} + +int +main (int argc, char **argv) +{ + pthread_barrierattr_t attr; + pthread_barrier_t barrier; + + int i, j; + error_t err; + pthread_t tid[THREADS]; + + int havesyncs; + + err = pthread_barrierattr_init (&attr); + if (err) + error (1, err, "pthread_barrierattr_init"); + + err = pthread_barrierattr_getpshared (&attr, &i); + if (err) + error (1, err, "pthread_barrierattr_getpshared"); + assert (i == PTHREAD_PROCESS_PRIVATE || i == PTHREAD_PROCESS_SHARED); + + err = pthread_barrierattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); + if (err) + error (1, err, "pthread_barrierattr_setpshared"); + + err = pthread_barrier_init (&barrier, &attr, THREADS + 1); + if (err) + error (1, err, "pthread_barrier_init"); + + for (j = 0; j < WAITS; j ++) + { + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, dowait, &barrier); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + printf ("Manager will now call pthread_barrier_wait.\n"); + + havesyncs + = pthread_barrier_wait (&barrier) == PTHREAD_BARRIER_SERIAL_THREAD + ? 1 : 0; + + for (i = THREADS - 1; i >= 0; i --) + { + void *ret; + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + switch ((int) ret) + { + case 0: + break; + + case PTHREAD_BARRIER_SERIAL_THREAD: + havesyncs ++; + break; + + default: + assert (! "Unknown value returned from pthread_barrier_wait."); + break; + } + } + + printf ("\n"); + + assert (havesyncs == 1); + } + + return 0; +} diff --git a/libpthread/tests/test-7.c b/libpthread/tests/test-7.c new file mode 100644 index 00000000..bd97acfa --- /dev/null +++ b/libpthread/tests/test-7.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 10 +#define KEYS 400 + +pthread_key_t key[KEYS]; + +void * +thr (void *arg) +{ + error_t err; + int i; + + for (i = 0; i < KEYS; i ++) + { + printf ("pthread_getspecific(%d).\n", key[i]); + assert (pthread_getspecific (key[i]) == NULL); + printf ("pthread_setspecific(%d, %d).\n", key[i], pthread_self ()); + err = pthread_setspecific (key[i], (void *) pthread_self ()); + printf ("pthread_setspecific(%d, %d) => %d.\n", key[i], pthread_self (), err); + assert_perror (err); + } + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + void des (void *val) + { + assert ((pthread_t) val == pthread_self ()); + } + + for (i = 0; i < KEYS; i ++) + err = pthread_key_create (&key[i], des); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, 0); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + return 0; +} diff --git a/libpthread/tests/test-8.c b/libpthread/tests/test-8.c new file mode 100644 index 00000000..85a7f8f6 --- /dev/null +++ b/libpthread/tests/test-8.c @@ -0,0 +1,60 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 10 + +pthread_once_t inc_var_once = PTHREAD_ONCE_INIT; +int var; + +void +inc_var (void) +{ + var ++; +} + +void * +thr (void *arg) +{ + int i; + + for (i = 0; i < 500; i ++) + pthread_once (&inc_var_once, inc_var); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, 0); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + assert (thr (0) == 0); + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + assert (var == 1); + + return 0; +} diff --git a/libpthread/tests/test-9.c b/libpthread/tests/test-9.c new file mode 100644 index 00000000..82051570 --- /dev/null +++ b/libpthread/tests/test-9.c @@ -0,0 +1,88 @@ +/* Test recursive mutexes. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +#define THREADS 10 + +int foo; + +void * +thr (void *arg) +{ + int i; + + pthread_mutex_lock (arg); + + foo = pthread_self (); + + for (i = 0; i < 500; i ++) + pthread_mutex_lock (arg); + for (i = 0; i < 500; i ++) + pthread_mutex_unlock (arg); + + assert (foo == pthread_self ()); + + pthread_mutex_unlock (arg); + + return 0; +} + +int +main (int argc, char **argv) +{ + error_t err; + int i; + pthread_t tid[THREADS]; + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + + err = pthread_mutexattr_init (&mattr); + if (err) + error (1, err, "pthread_mutexattr_init"); + + err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_RECURSIVE); + if (err) + error (1, err, "pthread_mutexattr_settype"); + + err = pthread_mutex_init (&mutex, &mattr); + if (err) + error (1, err, "pthread_mutex_init"); + + err = pthread_mutexattr_destroy (&mattr); + if (err) + error (1, err, "pthread_mutexattr_destroy"); + + pthread_mutex_lock (&mutex); + pthread_mutex_lock (&mutex); + pthread_mutex_unlock (&mutex); + pthread_mutex_unlock (&mutex); + + for (i = 0; i < THREADS; i ++) + { + err = pthread_create (&tid[i], 0, thr, &mutex); + if (err) + error (1, err, "pthread_create (%d)", i); + } + + for (i = 0; i < THREADS; i ++) + { + void *ret; + + err = pthread_join (tid[i], &ret); + if (err) + error (1, err, "pthread_join"); + + assert (ret == 0); + } + + err = pthread_mutex_destroy (&mutex); + if (err) + error (1, err, "pthread_mutex_destroy"); + + return 0; +} diff --git a/libpthread_pic.a b/libpthread_pic.a deleted file mode 100644 index 5673b4e7..00000000 --- a/libpthread_pic.a +++ /dev/null @@ -1,20 +0,0 @@ -/* pthread initializer is weak in glibc. It must be included if glibc - is to start threading. */ -EXTERN(_cthread_init_routine) - -/* Weak references in glibc that must be filled if glibc is to be - thread safe. */ -EXTERN(cthread_detach) -EXTERN(cthread_fork) -EXTERN(cthread_keycreate) -EXTERN(cthread_getspecific) -EXTERN(__libc_getspecific) -EXTERN(cthread_setspecific) -EXTERN(__mutex_lock_solid) -EXTERN(__mutex_unlock_solid) -/* For libio stream locking. */ -EXTERN(_cthreads_flockfile) -EXTERN(_cthreads_funlockfile) -EXTERN(_cthreads_ftrylockfile) - -GROUP(-lpthread2_pic -lihash_pic) diff --git a/lockfile.c b/lockfile.c deleted file mode 100644 index 040cbfb4..00000000 --- a/lockfile.c +++ /dev/null @@ -1,65 +0,0 @@ -/* lockfile - Handle locking and unlocking of streams. Hurd cthreads version. - Copyright (C) 2000,01,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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include /* Must come before ! */ -#include - -#ifdef _STDIO_USES_IOSTREAM - -void -_cthreads_flockfile (_IO_FILE *fp) -{ - _IO_lock_lock (*fp->_lock); -} - -void -_cthreads_funlockfile (_IO_FILE *fp) -{ - _IO_lock_unlock (*fp->_lock); -} - -int -_cthreads_ftrylockfile (_IO_FILE *fp) -{ - return __libc_lock_trylock_recursive (*fp->_lock); -} - -# undef _IO_flockfile -# undef _IO_funlockfile -# undef _IO_ftrylockfile -# undef flockfile -# undef funlockfile -# undef ftrylockfile - -void _IO_flockfile (_IO_FILE *) - __attribute__ ((alias ("_cthreads_flockfile"))); -void _IO_funlockfile (_IO_FILE *) - __attribute__ ((alias ("_cthreads_funlockfile"))); -int _IO_ftrylockfile (_IO_FILE *) - __attribute__ ((alias ("_cthreads_ftrylockfile"))); - -void flockfile (_IO_FILE *) - __attribute__ ((alias ("_cthreads_flockfile"))); -void funlockfile (_IO_FILE *) - __attribute__ ((alias ("_cthreads_funlockfile"))); -int ftrylockfile (_IO_FILE *) - __attribute__ ((alias ("_cthreads_ftrylockfile"))); - -#endif /* _STDIO_USES_IOSTREAM */ diff --git a/not-in-libc.h b/not-in-libc.h deleted file mode 100644 index 516d4d13..00000000 --- a/not-in-libc.h +++ /dev/null @@ -1,11 +0,0 @@ -#define __mach_port_insert_right mach_port_insert_right -#define __mach_port_allocate mach_port_allocate -#define __mig_init mig_init -#define __thread_create thread_create -#define __thread_get_state thread_get_state -#define __thread_resume thread_resume -#define __thread_set_state thread_set_state -#define __thread_terminate thread_terminate -#define __vm_allocate vm_allocate -#define __vm_deallocate vm_deallocate -#define __sched_yield sched_yield diff --git a/pthread/Versions b/pthread/Versions deleted file mode 100644 index e4b4e8bf..00000000 --- a/pthread/Versions +++ /dev/null @@ -1,15 +0,0 @@ -libc { - GLIBC_2.2 { - # XXX - __vm_deallocate; __mach_port_insert_right; __mach_reply_port; - __mig_init; __vm_allocate; - - # functions used in inline functions or macros - __pthread_spin_destroy; __pthread_spin_init; __pthread_spin_lock; - _pthread_spin_lock; __pthread_spin_trylock; __pthread_spin_unlock; - - # p* - pthread_spin_destroy; pthread_spin_init; pthread_spin_lock; - pthread_spin_trylock; pthread_spin_unlock; - } -} diff --git a/pthread/cthreads-compat.c b/pthread/cthreads-compat.c deleted file mode 100644 index e0536ef2..00000000 --- a/pthread/cthreads-compat.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Compatibility routines for cthreads. - Copyright (C) 2000, 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -typedef void *cthread_t; -typedef void *(*cthread_fn_t) (void *arg); -typedef int cthread_key_t; - -#define CTHREAD_KEY_INVALID (cthread_key_t) -1 - -void -cthread_detach (cthread_t thread) -{ - int err; - - err = pthread_detach ((pthread_t) thread); - assert_perror (err); -} - -cthread_t -cthread_fork (cthread_fn_t func, void *arg) -{ - pthread_t thread; - int err; - - err = pthread_create (&thread, NULL, func, arg); - assert_perror (err); - - return (cthread_t) thread; -} - -int -cthread_keycreate (cthread_key_t *key) -{ - error_t err; - - err = pthread_key_create (key, 0); - if (err) - { - errno = err; - *key = CTHREAD_KEY_INVALID; - err = -1; - } - - return err; -} - -int -cthread_getspecific (cthread_key_t key, void **val) -{ - *val = pthread_getspecific (key); - return 0; -} - -void * -__libc_getspecific (cthread_key_t key) -{ - return pthread_getspecific (key); -} - -int -cthread_setspecific (cthread_key_t key, void *val) -{ - error_t err; - - err = pthread_setspecific (key, (const void *) val); - if (err) - { - errno = err; - err = -1; - } - - return err; -} - -void -__mutex_lock_solid (void *lock) -{ - __pthread_mutex_lock (lock); -} - -void -__mutex_unlock_solid (void *lock) -{ - __pthread_mutex_unlock (lock); -} diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c deleted file mode 100644 index 6af2da92..00000000 --- a/pthread/pt-alloc.c +++ /dev/null @@ -1,215 +0,0 @@ -/* Allocate a new thread structure. - Copyright (C) 2000, 2002, 2005, 2007, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include -#include - -#include - -/* This braindamage is necessary because the standard says that some - of the threads functions "shall fail" if "No thread could be found - corresponding to that specified by the given thread ID." */ - -/* Thread ID lookup table. */ -struct __pthread **__pthread_threads; - -/* The size of the thread ID lookup table. */ -int __pthread_max_threads; - -/* The total number of thread IDs currently in use, or on the list of - available thread IDs. */ -int __pthread_num_threads; - -/* A lock for the table, and the other variables above. */ -pthread_rwlock_t __pthread_threads_lock; - -/* List of thread structures corresponding to free thread IDs. */ -struct __pthread *__pthread_free_threads; -pthread_mutex_t __pthread_free_threads_lock; - -static inline error_t -initialize_pthread (struct __pthread *new, int recycling) -{ - error_t err; - - err = __pthread_init_specific (new); - if (err) - return err; - - new->cancel_state = PTHREAD_CANCEL_ENABLE; - new->cancel_type = PTHREAD_CANCEL_DEFERRED; - new->cancel_pending = 0; - - if (recycling) - /* Since we are recycling PTHREAD, we can assume certains things - about PTHREAD's current state and save some cycles by not - rewriting the memory. */ - return 0; - - new->stack = 0; - - new->state_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; - new->state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER; - - new->cancelation_handlers = 0; - - new->next = 0; - new->prevp = 0; - - return 0; -} - - -/* Allocate a new thread structure and its pthread thread ID (but not - a kernel thread). */ -int -__pthread_alloc (struct __pthread **pthread) -{ - error_t err; - - struct __pthread *new; - struct __pthread **threads; - struct __pthread **old_threads; - int max_threads; - int new_max_threads; - - pthread_mutex_lock (&__pthread_free_threads_lock); - for (new = __pthread_free_threads; new; new = new->next) - { - /* There is no need to take NEW->STATE_LOCK: if NEW is on this - list, then it is protected by __PTHREAD_FREE_THREADS_LOCK - except in __pthread_dealloc where after it is added to the - list (with the lock held), it drops the lock and then sets - NEW->STATE and immediately stops using NEW. */ - if (new->state == PTHREAD_TERMINATED) - { - __pthread_dequeue (new); - break; - } - } - pthread_mutex_unlock (&__pthread_free_threads_lock); - - if (new) - { - /* The thread may still be running. Make sure it is stopped. - If this is the case, then the thread is either at the end of - __pthread_dealloc or in __pthread_thread_halt. In both - cases, we are interrupt it. */ - __pthread_thread_halt (new); - - err = initialize_pthread (new, 1); - if (! err) - *pthread = new; - return err; - } - - /* Allocate a new thread structure. */ - new = malloc (sizeof (struct __pthread)); - if (new == NULL) - return ENOMEM; - - err = initialize_pthread (new, 0); - if (err) - { - free (new); - return err; - } - - retry: - pthread_rwlock_wrlock (&__pthread_threads_lock); - - if (__pthread_num_threads < __pthread_max_threads) - { - /* We have a free slot. Use the slot number plus one as the - thread ID for the new thread. */ - new->thread = 1 + __pthread_num_threads++; - __pthread_threads[new->thread - 1] = NULL; - - pthread_rwlock_unlock (&__pthread_threads_lock); - - *pthread = new; - return 0; - } -#ifdef PTHREAD_THREADS_MAX - else if (__pthread_num_threads >= PTHREAD_THREADS_MAX) - { - /* We have reached the limit on the number of threads per process. */ - pthread_rwlock_unlock (&__pthread_threads_lock); - - free (new); - return EAGAIN; - } -#endif - - /* We are going to enlarge the threads table. Save its current - size. We're going to release the lock before doing the necessary - memory allocation, since that's a potentially blocking operation. */ - max_threads = __pthread_max_threads; - - pthread_rwlock_unlock (&__pthread_threads_lock); - - /* Allocate a new lookup table that's twice as large. */ - new_max_threads - = max_threads > 0 ? max_threads * 2 : _POSIX_THREAD_THREADS_MAX; - threads = malloc (new_max_threads * sizeof (struct __pthread *)); - if (threads == NULL) - { - free (new); - return ENOMEM; - } - - pthread_rwlock_wrlock (&__pthread_threads_lock); - - /* Check if nobody else has already enlarged the table. */ - if (max_threads != __pthread_max_threads) - { - /* Yep, they did. */ - pthread_rwlock_unlock (&__pthread_threads_lock); - - /* Free the newly allocated table and try again to allocate a slot. */ - free (threads); - goto retry; - } - - /* Copy over the contents of the old table. */ - memcpy (threads, __pthread_threads, - __pthread_max_threads * sizeof (struct __pthread *)); - - /* Save the location of the old table. We want to deallocate its - storage after we released the lock. */ - old_threads = __pthread_threads; - - /* Replace the table with the new one. */ - __pthread_max_threads = new_max_threads; - __pthread_threads = threads; - - /* And allocate ourselves one of the newly created slots. */ - new->thread = 1 + __pthread_num_threads++; - __pthread_threads[new->thread - 1] = NULL; - - pthread_rwlock_unlock (&__pthread_threads_lock); - - free (old_threads); - - *pthread = new; - return 0; -} diff --git a/pthread/pt-cancel.c b/pthread/pt-cancel.c deleted file mode 100644 index d19c557d..00000000 --- a/pthread/pt-cancel.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Cancel a thread. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -int -pthread_cancel (pthread_t t) -{ - int err = 0; - struct __pthread *p; - - p = __pthread_getid (t); - if (! p) - return ESRCH; - - p->cancel_pending = 1; - if (p->cancel_state == PTHREAD_CANCEL_ENABLE - && p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS) - err = __pthread_do_cancel (p); - - return err; -} diff --git a/pthread/pt-cleanup.c b/pthread/pt-cleanup.c deleted file mode 100644 index 58865aa4..00000000 --- a/pthread/pt-cleanup.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Add a cancelation handler to the stack. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -struct __pthread_cancelation_handler ** -__pthread_get_cleanup_stack (void) -{ - return &_pthread_self ()->cancelation_handlers; -} diff --git a/pthread/pt-create.c b/pthread/pt-create.c deleted file mode 100644 index 8f62b78e..00000000 --- a/pthread/pt-create.c +++ /dev/null @@ -1,206 +0,0 @@ -/* Thread creation. - Copyright (C) 2000, 2002, 2005, 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -#include - -#ifdef HAVE_USELOCALE -# include -#endif - -/* The total number of pthreads currently active. This is defined - here since it would be really stupid to have a threads-using - program that doesn't call `pthread_create'. */ -__atomic_t __pthread_total; - - -/* The entry-point for new threads. */ -static void -entry_point (void *(*start_routine)(void *), void *arg) -{ -#ifdef HAVE_USELOCALE - /* A fresh thread needs to be bound to the global locale. */ - uselocale (LC_GLOBAL_LOCALE); -#endif - - __pthread_startup (); - - pthread_exit (start_routine (arg)); -} - -/* Create a thread with attributes given by ATTR, executing - START_ROUTINE with argument ARG. */ -int -pthread_create (pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg) -{ - int err; - struct __pthread *pthread; - - err = __pthread_create_internal (&pthread, attr, start_routine, arg); - if (! err) - *thread = pthread->thread; - - return err; -} - -/* Internal version of pthread_create. See comment in - pt-internal.h. */ -int -__pthread_create_internal (struct __pthread **thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg) -{ - int err; - struct __pthread *pthread; - const struct __pthread_attr *setup; - sigset_t sigset; - - /* Allocate a new thread structure. */ - err = __pthread_alloc (&pthread); - if (err) - goto failed; - - /* Use the default attributes if ATTR is NULL. */ - setup = attr ? attr : &__pthread_default_attr; - - /* Initialize the thread state. */ - pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED - ? PTHREAD_DETACHED : PTHREAD_JOINABLE); - - /* If the user supplied a stack, it is not our responsibility to - setup a stack guard. */ - if (setup->stackaddr) - pthread->guardsize = 0; - else - pthread->guardsize = (setup->guardsize <= setup->stacksize - ? setup->guardsize : setup->stacksize); - - /* Find a stack. There are several scenarios: if a detached thread - kills itself, it has no way to deallocate its stack, thus it - leaves PTHREAD->stack set to true. We try to reuse it here, - however, if the user supplied a stack, we cannot use the old one. - Right now, we simply deallocate it. */ - if (pthread->stack) - { - if (setup->stackaddr != __pthread_default_attr.stackaddr) - { - __pthread_stack_dealloc (pthread->stackaddr, - pthread->stacksize); - pthread->stackaddr = setup->stackaddr; - pthread->stacksize = setup->stacksize; - } - } - else - { - err = __pthread_stack_alloc (&pthread->stackaddr, - setup->stacksize); - if (err) - goto failed_stack_alloc; - - pthread->stacksize = setup->stacksize; - pthread->stack = 1; - } - - /* Allocate the kernel thread and other required resources. */ - err = __pthread_thread_alloc (pthread); - if (err) - goto failed_thread_alloc; - - /* And initialize the rest of the machine context. This may include - additional machine- and system-specific initializations that - prove convenient. */ - err = __pthread_setup (pthread, entry_point, start_routine, arg); - if (err) - goto failed_setup; - - /* Initialize the system-specific signal state for the new - thread. */ - err = __pthread_sigstate_init (pthread); - if (err) - goto failed_sigstate; - - /* Set the new thread's signal mask and set the pending signals to - empty. POSIX says: "The signal mask shall be inherited from the - creating thread. The set of signals pending for the new thread - shall be empty." If the currnet thread is not a pthread then we - just inherit the process' sigmask. */ - if (__pthread_num_threads == 1) - err = sigprocmask (0, 0, &sigset); - else - err = __pthread_sigstate (_pthread_self (), 0, 0, &sigset, 0); - assert_perror (err); - - err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 1); - assert_perror (err); - - /* Increase the total number of threads. We do this before actually - starting the new thread, since the new thread might immediately - call `pthread_exit' which decreases the number of threads and - calls `exit' if the number of threads reaches zero. Increasing - the number of threads from within the new thread isn't an option - since this thread might return and call `pthread_exit' before the - new thread runs. */ - __atomic_inc (&__pthread_total); - - /* Store a pointer to this thread in the thread ID lookup table. We - could use __thread_setid, however, we only lock for reading as no - other thread should be using this entry (we also assume that the - store is atomic). */ - pthread_rwlock_rdlock (&__pthread_threads_lock); - __pthread_threads[pthread->thread - 1] = pthread; - pthread_rwlock_unlock (&__pthread_threads_lock); - - /* At this point it is possible to guess our pthread ID. We have to - make sure that all functions taking a pthread_t argument can - handle the fact that this thread isn't really running yet. */ - - /* Schedule the new thread. */ - err = __pthread_thread_start (pthread); - if (err) - goto failed_starting; - - /* At this point the new thread is up and running. */ - - *thread = pthread; - - return 0; - - failed_starting: - __pthread_setid (pthread->thread, NULL); - __atomic_dec (&__pthread_total); - failed_sigstate: - __pthread_sigstate_destroy (pthread); - failed_setup: - __pthread_thread_dealloc (pthread); - __pthread_thread_halt (pthread); - failed_thread_alloc: - __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); - pthread->stack = 0; - failed_stack_alloc: - __pthread_dealloc (pthread); - failed: - return err; -} diff --git a/pthread/pt-dealloc.c b/pthread/pt-dealloc.c deleted file mode 100644 index 92fe1fda..00000000 --- a/pthread/pt-dealloc.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Deallocate a thread structure. - Copyright (C) 2000, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* List of thread structures corresponding to free thread IDs. */ -extern struct __pthread *__pthread_free_threads; -extern pthread_mutex_t __pthread_free_threads_lock; - - -/* Deallocate the thread structure for PTHREAD. */ -void -__pthread_dealloc (struct __pthread *pthread) -{ - assert (pthread->state != PTHREAD_TERMINATED); - - /* Withdraw this thread from the thread ID lookup table. */ - __pthread_setid (pthread->thread, NULL); - - /* Mark the thread as terminated. We broadcast the condition - here to prevent pthread_join from waiting for this thread to - exit where it was never really started. Such a call to - pthread_join is completely bogus, but unfortunately allowed - by the standards. */ - __pthread_mutex_lock (&pthread->state_lock); - if (pthread->state != PTHREAD_EXITED) - pthread_cond_broadcast (&pthread->state_cond); - __pthread_mutex_unlock (&pthread->state_lock); - - /* We do not actually deallocate the thread structure, but add it to - a list of re-usable thread structures. */ - pthread_mutex_lock (&__pthread_free_threads_lock); - __pthread_enqueue (&__pthread_free_threads, pthread); - pthread_mutex_unlock (&__pthread_free_threads_lock); - - /* Setting PTHREAD->STATE to PTHREAD_TERMINATED makes this TCB - available for reuse. After that point, we can no longer assume - that PTHREAD is valid. - - Note that it is safe to not lock this update to PTHREAD->STATE: - the only way that it can now be accessed is in __pthread_alloc, - which reads this variable. */ - pthread->state = PTHREAD_TERMINATED; -} diff --git a/pthread/pt-detach.c b/pthread/pt-detach.c deleted file mode 100644 index 1e42c452..00000000 --- a/pthread/pt-detach.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Detach a thread. - Copyright (C) 2000, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Indicate that the storage for THREAD can be reclaimed when it - terminates. */ -int -pthread_detach (pthread_t thread) -{ - struct __pthread *pthread; - int err = 0; - - /* Lookup the thread structure for THREAD. */ - pthread = __pthread_getid (thread); - if (pthread == NULL) - return ESRCH; - - __pthread_mutex_lock (&pthread->state_lock); - - switch (pthread->state) - { - case PTHREAD_JOINABLE: - /* THREAD still running. Mark it as detached such that its - resources can be reclaimed as soon as the thread exits. */ - pthread->state = PTHREAD_DETACHED; - - /* Broadcast the condition. This will make threads that are - waiting to join THREAD continue with hopefully disastrous - consequences instead of blocking indefinitely. */ - pthread_cond_broadcast (&pthread->state_cond); - __pthread_mutex_unlock (&pthread->state_lock); - break; - - case PTHREAD_EXITED: - /* THREAD has already exited. Make sure that nobody can - reference it anymore, and mark it as terminated. */ - - __pthread_mutex_unlock (&pthread->state_lock); - - /* Make sure the thread is not running before we remove its - stack. (The only possibility is that it is in a call to - __pthread_thread_halt itself, but that is enough to cause a - sigsegv.) */ - __pthread_thread_halt (pthread); - - /* Destroy the stack, the kernel resources and the control - block. */ - assert (pthread->stack); - __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); - pthread->stack = 0; - - __pthread_thread_dealloc (pthread); - - __pthread_dealloc (pthread); - break; - - case PTHREAD_TERMINATED: - /* Pretend THREAD wasn't there in the first place. */ - __pthread_mutex_unlock (&pthread->state_lock); - err = ESRCH; - break; - - default: - /* Thou shalt not detach non-joinable threads! */ - __pthread_mutex_unlock (&pthread->state_lock); - err = EINVAL; - break; - } - - return err; -} diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c deleted file mode 100644 index 5fe0ba86..00000000 --- a/pthread/pt-exit.c +++ /dev/null @@ -1,118 +0,0 @@ -/* Thread termination. - Copyright (C) 2000, 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -#include - - -/* Terminate the current thread and make STATUS available to any - thread that might join it. */ -void -pthread_exit (void *status) -{ - struct __pthread *self = _pthread_self (); - struct __pthread_cancelation_handler **handlers; - int oldstate; - int need_dealloc; - - /* Run any cancelation handlers. According to POSIX, the - cancellation cleanup handlers should be called with cancellation - disabled. */ - pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); - - for (handlers = __pthread_get_cleanup_stack (); - *handlers; - *handlers = (*handlers)->next) - (*handlers)->handler ((*handlers)->arg); - - pthread_setcancelstate (oldstate, &oldstate); - - /* Destory any thread specific data. */ - __pthread_destroy_specific (self); - - /* Destroy any signal state. */ - __pthread_sigstate_destroy (self); - - /* Decrease the number of threads. We use an atomic operation to - make sure that only the last thread calls `exit'. */ - if (__atomic_dec_and_test (&__pthread_total)) - /* We are the last thread. */ - exit (0); - - /* Note that after this point the process can be terminated at any - point if another thread calls `pthread_exit' and happens to be - the last thread. */ - - __pthread_mutex_lock (&self->state_lock); - - if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) - status = PTHREAD_CANCELED; - - switch (self->state) - { - default: - assert (! "Consistency error: unexpected self->state"); - abort (); - break; - - case PTHREAD_DETACHED: - /* Make sure that nobody can reference this thread anymore, and - mark it as terminated. Our thread ID will immediately become - available for re-use. For obvious reasons, we cannot - deallocate our own stack. However, it will eventually be - reused when this thread structure is recycled. */ - __pthread_mutex_unlock (&self->state_lock); - - __pthread_dealloc (self); - - break; - - case PTHREAD_JOINABLE: - /* We need to stay around for a while since another thread - might want to join us. */ - self->state = PTHREAD_EXITED; - - /* We need to remember the exit status. A thread joining us - might ask for it. */ - self->status = status; - - /* Broadcast the condition. This will wake up threads that are - waiting to join us. */ - pthread_cond_broadcast (&self->state_cond); - __pthread_mutex_unlock (&self->state_lock); - - break; - } - - /* Note that after this point the resources used by this thread can - be freed at any moment if another thread joins or detaches us. - This means that before freeing any resources, such a thread - should make sure that this thread is really halted. */ - - __pthread_thread_halt (self); - - /* NOTREACHED */ - abort (); -} diff --git a/pthread/pt-getattr.c b/pthread/pt-getattr.c deleted file mode 100644 index 24599c6e..00000000 --- a/pthread/pt-getattr.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Thread attributes retrieval. - Copyright (C) 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Initialize thread attribute *ATTR with attributes corresponding to the - already running thread THREAD. It shall be called on an uninitialized ATTR - and destroyed with pthread_attr_destroy when no longer needed. */ -int -pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) -{ - struct __pthread *pthread; - - pthread = __pthread_getid(thread); - if (pthread == NULL) - return ESRCH; - - /* Some attributes (schedparam, inheritsched, contentionscope and schedpolicy) - are not supported yet, so fill them with our default values. */ - *attr = __pthread_default_attr; - - attr->stackaddr = pthread->stackaddr; - attr->stacksize = pthread->stacksize; - attr->guardsize = pthread->guardsize; - attr->detachstate = (pthread->state == PTHREAD_DETACHED - ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); - - return 0; -} diff --git a/pthread/pt-initialize.c b/pthread/pt-initialize.c deleted file mode 100644 index cf32b8b5..00000000 --- a/pthread/pt-initialize.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Initialize pthreads library. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include -#include - -DEFINE_HOOK (__pthread_init, (void)); - -/* Initialize the pthreads library. */ -void -__pthread_initialize (void) -{ - RUN_HOOK (__pthread_init, ()); -} diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h deleted file mode 100644 index cb441d09..00000000 --- a/pthread/pt-internal.h +++ /dev/null @@ -1,290 +0,0 @@ -/* Internal defenitions for pthreads library. - Copyright (C) 2000, 2005, 2006, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _PT_INTERNAL_H -#define _PT_INTERNAL_H 1 - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -/* Thread state. */ -enum pthread_state -{ - /* The thread is running and joinable. */ - PTHREAD_JOINABLE = 0, - /* The thread is running and detached. */ - PTHREAD_DETACHED, - /* A joinable thread exited and its return code is available. */ - PTHREAD_EXITED, - /* The thread structure is unallocated and available for reuse. */ - PTHREAD_TERMINATED -}; - -#ifndef PTHREAD_KEY_MEMBERS -# define PTHREAD_KEY_MEMBERS -#endif - -#ifndef PTHREAD_SYSDEP_MEMBERS -# define PTHREAD_SYSDEP_MEMBERS -#endif - -/* This structure describes a POSIX thread. */ -struct __pthread -{ - /* Thread ID. */ - pthread_t thread; - - /* Cancellation. */ - int cancel_state; - int cancel_type; - int cancel_pending; - struct __pthread_cancelation_handler *cancelation_handlers; - - /* Thread stack. */ - void *stackaddr; - size_t stacksize; - size_t guardsize; /* Included in STACKSIZE (i.e. total - stack memory is STACKSIZE, not - STACKSIZE + GUARDSIZE). */ - int stack; /* Nonzero if the stack was allocated. */ - - /* Exit status. */ - void *status; - - /* Thread state. */ - enum pthread_state state; - pthread_mutex_t state_lock; /* Locks the state. */ - pthread_cond_t state_cond; /* Signalled when the state changes. */ - - /* Thread context. */ - struct pthread_mcontext mcontext; - - PTHREAD_KEY_MEMBERS - - PTHREAD_SYSDEP_MEMBERS - - struct __pthread *next, **prevp; -}; - -/* Enqueue an element THREAD on the queue *HEAD. */ -static inline void -__pthread_enqueue (struct __pthread **head, struct __pthread *thread) -{ - assert (thread->prevp == 0); - - thread->next = *head; - thread->prevp = head; - if (*head) - (*head)->prevp = &thread->next; - *head = thread; -} - -/* Dequeue the element THREAD from the queue it is connected to. */ -static inline void -__pthread_dequeue (struct __pthread *thread) -{ - assert (thread); - - if (thread->next) - thread->next->prevp = thread->prevp; - *thread->prevp = thread->next; - thread->prevp = 0; -} - -/* Iterate over QUEUE storing each element in ELEMENT. */ -#define __pthread_queue_iterate(queue, element) \ - for (struct __pthread *__pdi_next = (queue); \ - ((element) = __pdi_next) \ - && ((__pdi_next = __pdi_next->next), \ - 1); \ - ) - -/* Iterate over QUEUE dequeuing each element, storing it in - ELEMENT. */ -#define __pthread_dequeuing_iterate(queue, element) \ - for (struct __pthread *__pdi_next = (queue); \ - ((element) = __pdi_next) \ - && ((__pdi_next = __pdi_next->next), \ - ((element)->prevp = 0), \ - 1); \ - ) - -/* The total number of threads currently active. */ -extern __atomic_t __pthread_total; - -/* The total number of thread IDs currently in use, or on the list of - available thread IDs. */ -extern int __pthread_num_threads; - -/* Concurrency hint. */ -extern int __pthread_concurrency; - -/* Array of __pthread structures and its lock. Indexed by the pthread - id minus one. (Why not just use the pthread id? Because some - brain-dead users of the pthread interface incorrectly assume that 0 - is an invalid pthread id.) */ -extern struct __pthread **__pthread_threads; -extern pthread_rwlock_t __pthread_threads_lock; - -#define __pthread_getid(thread) \ - ({ struct __pthread *__t; \ - pthread_rwlock_rdlock (&__pthread_threads_lock); \ - __t = __pthread_threads[thread - 1]; \ - pthread_rwlock_unlock (&__pthread_threads_lock); \ - __t; }) - -#define __pthread_setid(thread, pthread) \ - pthread_rwlock_wrlock (&__pthread_threads_lock); \ - __pthread_threads[thread - 1] = pthread; \ - pthread_rwlock_unlock (&__pthread_threads_lock); - -/* Similar to pthread_self, but returns the thread descriptor instead - of the thread ID. */ -#ifndef _pthread_self -extern struct __pthread *_pthread_self (void); -#endif - - -/* Initialize the pthreads library. */ -extern void __pthread_initialize (void); - -/* Internal version of pthread_create. Rather than return the new - tid, we return the whole __pthread structure in *PTHREAD. */ -extern int __pthread_create_internal (struct __pthread **__restrict pthread, - const pthread_attr_t *__restrict attr, - void *(*start_routine)(void *), - void *__restrict arg); - -/* Allocate a new thread structure and a pthread thread ID (but not a - kernel thread or a stack). */ -extern int __pthread_alloc (struct __pthread **thread); - -/* Deallocate the thread structure. This is the dual of - __pthread_alloc (N.B. it does not call __pthread_stack_alloc nor - __pthread_thread_halt). */ -extern void __pthread_dealloc (struct __pthread *thread); - - -/* Allocate a stack of size STACKSIZE. The stack base shall be - returned in *STACKADDR. */ -extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize); - -/* Deallocate the stack STACKADDR of size STACKSIZE. */ -extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize); - - -/* Setup thread THREAD's context. */ -extern int __pthread_setup (struct __pthread *__restrict thread, - void (*entry_point)(void *(*)(void *), - void *), - void *(*start_routine)(void *), - void *__restrict arg); - - -/* Allocate a kernel thread (and any miscellaneous system dependent - resources) for THREAD; it must not be placed on the run queue. */ -extern int __pthread_thread_alloc (struct __pthread *thread); - -/* Deallocate any kernel resources associated with THREAD. The thread - must not be running (that is, if __pthread_thread_start was called, - __pthread_thread_halt must first be called). This function will - never be called by a thread on itself. In the case that a thread - exits, its thread structure will be cached and cleaned up - later. */ -extern void __pthread_thread_dealloc (struct __pthread *thread); - -/* Start THREAD making it eligible to run. */ -extern int __pthread_thread_start (struct __pthread *thread); - -/* Stop the kernel thread associated with THREAD. This function may - be called by two threads in parallel. In particular, by the thread - itself and another thread trying to join it. This function must be - implemented such that this is safe. */ -extern void __pthread_thread_halt (struct __pthread *thread); - - -/* Called by a thread just before it calls the provided start - routine. */ -extern void __pthread_startup (void); - -/* Block THREAD. */ -extern void __pthread_block (struct __pthread *thread); - -/* Block THREAD until *ABSTIME is reached. */ -extern error_t __pthread_timedblock (struct __pthread *__restrict thread, - const struct timespec *__restrict abstime); - -/* Wakeup THREAD. */ -extern void __pthread_wakeup (struct __pthread *thread); - - -/* Perform a cancelation. */ -extern int __pthread_do_cancel (struct __pthread *thread); - - -/* Initialize the thread specific data structures. THREAD must be the - calling thread. */ -extern error_t __pthread_init_specific (struct __pthread *thread); - -/* Call the destructors on all of the thread specific data in THREAD. - THREAD must be the calling thread. */ -extern void __pthread_destroy_specific (struct __pthread *thread); - - -/* Initialize newly create thread *THREAD's signal state data - structures. */ -extern error_t __pthread_sigstate_init (struct __pthread *thread); - -/* Destroy the signal state data structures associcated with thread - *THREAD. */ -extern void __pthread_sigstate_destroy (struct __pthread *thread); - -/* Modify thread *THREAD's signal state. */ -extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how, - const sigset_t *__restrict set, - sigset_t *__restrict oset, - int clear_pending); - - -/* Default thread attributes. */ -extern const struct __pthread_attr __pthread_default_attr; - -/* Default barrier attributes. */ -extern const struct __pthread_barrierattr __pthread_default_barrierattr; - -/* Default mutex attributes. */ -extern const struct __pthread_mutexattr __pthread_default_mutexattr; - -/* Default rdlock attributes. */ -const struct __pthread_rwlockattr __pthread_default_rwlockattr; - -/* Default condition attributes. */ -const struct __pthread_condattr __pthread_default_condattr; - -#endif /* pt-internal.h */ diff --git a/pthread/pt-join.c b/pthread/pt-join.c deleted file mode 100644 index 153058b5..00000000 --- a/pthread/pt-join.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Wait for thread termination. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Make calling thread wait for termination of thread THREAD. Return - the exit status of the thread in *STATUS. */ -int -pthread_join (pthread_t thread, void **status) -{ - struct __pthread *pthread; - int err = 0; - - /* Lookup the thread structure for THREAD. */ - pthread = __pthread_getid (thread); - if (pthread == NULL) - return ESRCH; - - __pthread_mutex_lock (&pthread->state_lock); - pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock, - &pthread->state_lock); - - while (pthread->state == PTHREAD_JOINABLE) - pthread_cond_wait (&pthread->state_cond, &pthread->state_lock); - - pthread_cleanup_pop (0); - - switch (pthread->state) - { - case PTHREAD_EXITED: - __pthread_mutex_unlock (&pthread->state_lock); - - /* THREAD has already exited. Salvage its exit status. */ - if (status) - *status = pthread->status; - - /* Make sure the thread is not running before we remove its - stack. (The only possibility is that it is in a call to - __pthread_thread_halt itself, but that is enough to cause a - sigsegv.) */ - __pthread_thread_halt (pthread); - - /* Destroy the stack, the kernel resources and the control - block. */ - assert (pthread->stack); - __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); - pthread->stack = 0; - - __pthread_thread_dealloc (pthread); - - __pthread_dealloc (pthread); - break; - - case PTHREAD_TERMINATED: - /* Pretend THREAD wasn't there in the first place. */ - __pthread_mutex_unlock (&pthread->state_lock); - err = ESRCH; - break; - - default: - /* Thou shalt not join non-joinable threads! */ - __pthread_mutex_unlock (&pthread->state_lock); - err = EINVAL; - break; - } - - return err; -} diff --git a/pthread/pt-self.c b/pthread/pt-self.c deleted file mode 100644 index 49768643..00000000 --- a/pthread/pt-self.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Get calling thread's ID. - Copyright (C) 2000, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* Return the thread ID of the calling thread. */ -pthread_t -pthread_self (void) -{ - struct __pthread *self = _pthread_self (); - assert (self); - - return self->thread; -} diff --git a/pthread/pt-setcancelstate.c b/pthread/pt-setcancelstate.c deleted file mode 100644 index ded58922..00000000 --- a/pthread/pt-setcancelstate.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Set the cancel state for the calling thread. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -int -pthread_setcancelstate (int state, int *oldstate) -{ - struct __pthread *p = _pthread_self (); - - switch (state) - { - default: - return EINVAL; - case PTHREAD_CANCEL_ENABLE: - case PTHREAD_CANCEL_DISABLE: - break; - } - - *oldstate = p->cancel_state; - p->cancel_state = state; - - return 0; -} diff --git a/pthread/pt-setcanceltype.c b/pthread/pt-setcanceltype.c deleted file mode 100644 index 9511c991..00000000 --- a/pthread/pt-setcanceltype.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Set the cancel type for the calling thread. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -int -pthread_setcanceltype (int type, int *oldtype) -{ - struct __pthread *p = _pthread_self (); - - switch (type) - { - default: - return EINVAL; - case PTHREAD_CANCEL_DEFERRED: - case PTHREAD_CANCEL_ASYNCHRONOUS: - break; - } - - *oldtype = p->cancel_type; - p->cancel_type = type; - - return 0; -} diff --git a/pthread/pt-sigmask.c b/pthread/pt-sigmask.c deleted file mode 100644 index 1b53873e..00000000 --- a/pthread/pt-sigmask.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Get or set a thread's signal mask. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_sigmask (int how, const sigset_t *set, - sigset_t *oset) -{ - struct __pthread *self = _pthread_self (); - - /* Do not clear SELF's pending signals. */ - return __pthread_sigstate (self, how, set, oset, 0); -} diff --git a/pthread/pt-spin-inlines.c b/pthread/pt-spin-inlines.c deleted file mode 100644 index cfb21dd3..00000000 --- a/pthread/pt-spin-inlines.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* declares some extern inline functions. These - functions are declared additionally here for use when inlining is - not possible. */ - -#define _FORCE_INLINES -#define __PT_SPIN_INLINE /* empty */ - -#include - -/* Weak aliases for the spin lock functions. Note that - pthread_spin_lock is left out deliberately. We already provide an - implementation for it in pt-spin.c. */ -weak_alias (__pthread_spin_destroy, pthread_spin_destroy); -weak_alias (__pthread_spin_init, pthread_spin_init); -weak_alias (__pthread_spin_trylock, pthread_spin_trylock); -weak_alias (__pthread_spin_unlock, pthread_spin_unlock); diff --git a/pthread/pt-testcancel.c b/pthread/pt-testcancel.c deleted file mode 100644 index 01f1ac9c..00000000 --- a/pthread/pt-testcancel.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Add an explicit cancelation point. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -void -pthread_testcancel (void) -{ - struct __pthread *p = _pthread_self (); - - if (p->cancel_state == PTHREAD_CANCEL_ENABLE && p->cancel_pending) - pthread_exit (PTHREAD_CANCELED); -} diff --git a/signal/README b/signal/README deleted file mode 100644 index 5487e2e3..00000000 --- a/signal/README +++ /dev/null @@ -1,4 +0,0 @@ -This directory provides a signal implementation, which is appropriate -for operating systems where signals are managed at user-level. It is -up to the run-time to catch the signals and forward them to the -implementation via, e.g., the pthread_kill_info_np call. diff --git a/signal/TODO b/signal/TODO deleted file mode 100644 index 1148abb3..00000000 --- a/signal/TODO +++ /dev/null @@ -1,29 +0,0 @@ -Unimplemented Functionality ---------------------------- - -We don't support interruptible functions. That is, if a signal is -delivered when a thread is in e.g. the write system call, then the -write function should be interrupted and return EINTR when the signal -handler is finished. To realize this behavior, we could have a thread -local interruptible flag and a setjmp buffer. A function that is -interruptible would fill the jump buffer and set the interruptible -flag. If a signal comes in and the interruptible flag is set, rather -than resuming the thread, we longjmp to the buffer. - -If a signal action has set the SA_SIGINFO, the third argument must be -a pointer to a ucontext describing the thread's interrupted state; -this implementation passes NULL. This isn't as bad as it sounds as -the the ucontext family of functions are marked obsolete in SUSv3 with -the advisory that any use of them should be replaced by the use of -pthread functionality (cf. makecontext rationale). - -stop and continue signals are not implemented (as we need to stop all -threads, this requires being in bed with libpthread). - -Implementation is not yet cancellation-safe. - -There are not even stubs for sighold, sigingore, sigpause, sigrelse, -however, according to posix: "Use of any of these functions is -unspecified in a multi-threaded process." - -Implement sigtimedwait, sigqueue. \ No newline at end of file diff --git a/signal/kill.c b/signal/kill.c deleted file mode 100644 index 27c9c32a..00000000 --- a/signal/kill.c +++ /dev/null @@ -1,70 +0,0 @@ -/* kill.c - Generic kill implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -kill (pid_t pid, int signo) -{ - if (pid != getpid ()) - { - errno = EOPNOTSUPP; - return -1; - } - - /* "Signals generated for the process shall be delivered to exactly - one of those threads within the process which is in a call to a - sigwait() function selecting that signal or has not blocked - delivery of the signal. If there are no threads in a call to a - sigwait() function selecting that signal, and if all threads - within the process block delivery of the signal, the signal shall - remaing pending on the process" (2.4.1). */ - - /* First, see if there is a waiter, which is interested in this - signal. */ - pthread_mutex_lock (&sig_lock); - - struct sigwaiter *waiter; - for (waiter = sigwaiters; waiter; waiter = waiter->next) - if ((waiter->signals & sigmask (signo))) - /* Got a winner. */ - { - sigdelset (&process_pending, signo); - - pthread_mutex_lock (&waiter->ss->lock); - sigdelset (&waiter->ss->pending, signo); - - memset (&waiter->info, 0, sizeof (waiter->info)); - waiter->info.si_signo = signo; - - sigwaiter_unblock (waiter); - - return 0; - } - - pthread_mutex_unlock (&sig_lock); - - /* XXX: We just generate the signal for the current thread. If the - current thread has blocked the signal, the correct thing to do is - to iterate over all the other threads and find on that hasn't - blocked it. */ - return pthread_kill (pthread_self (), signo); -} - diff --git a/signal/pt-kill-siginfo-np.c b/signal/pt-kill-siginfo-np.c deleted file mode 100644 index 9bdf6cc4..00000000 --- a/signal/pt-kill-siginfo-np.c +++ /dev/null @@ -1,88 +0,0 @@ -/* pthread-kill-siginfo-np.c - Generic pthread_kill_siginfo_np implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "pt-internal.h" -#include "sig-internal.h" - -int -pthread_kill_siginfo_np (pthread_t tid, siginfo_t si) -{ - int sig = si.si_signo; - - if (sig < 0 || sig >= NSIG) - return EINVAL; - - if (sig == 0) - return 0; - - struct signal_state *ss = &__pthread_getid (tid)->ss; - - pthread_mutex_lock (&sig_lock); - pthread_mutex_lock (&ss->lock); - - if (ss->sigwaiter && (ss->sigwaiter->signals & sigmask (si.si_signo))) - /* The thread is in a call to sigwait. */ - { - ss->sigwaiter->info = si; - sigwaiter_unblock (ss->sigwaiter); - return 0; - } - - pthread_mutex_unlock (&sig_lock); - - if (ss->actions[sig - 1].sa_handler == (void *) SIG_IGN - || (ss->actions[sig - 1].sa_handler == (void *) SIG_DFL - && default_action (sig) == sig_ignore)) - /* It is unclear (to me) what is supposed to happen when a signal - is generated for a thread, which is blocking that signal and - ignoring it. POSIX does say that when the action associated - with a pending, blocked signal is set to SIG_IGN, the pending - signal is to be cleared. Thus, it makes sense that any signal - set to ignore is discarded at generation. */ - { - pthread_mutex_unlock (&ss->lock); - return 0; - } - - - if ((sigmask (sig) & ss->blocked)) - /* The signal is blocked. Mark it pending. */ - { - ss->pending |= sigmask (sig); - pthread_mutex_unlock (&ss->lock); - return 0; - } - - if (pthread_self () == tid - && (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) - || (ss->stack.ss_flags & SS_DISABLE) - || (ss->stack.ss_flags & SS_ONSTACK))) - /* We are sending a signal to ourself and we don't use an - alternate stack. */ - signal_dispatch (ss, &si); - else - signal_dispatch_lowlevel (ss, tid, si); - - /* Don't unlock ss: signal_dispatch and signal_dispatch_lowlevel - assume ownership of the lock. */ - - return 0; -} - diff --git a/signal/sig-internal.c b/signal/sig-internal.c deleted file mode 100644 index f73f38b4..00000000 --- a/signal/sig-internal.c +++ /dev/null @@ -1,26 +0,0 @@ -/* sig-internal.c - Signal state functions. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -pthread_mutex_t sig_lock = PTHREAD_MUTEX_INITIALIZER; - -sigset_t process_pending; -siginfo_t process_pending_info[NSIG]; diff --git a/signal/sig-internal.h b/signal/sig-internal.h deleted file mode 100644 index 6c86c796..00000000 --- a/signal/sig-internal.h +++ /dev/null @@ -1,177 +0,0 @@ -/* sig-internal.h - Internal signal handling interface. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#ifndef SIG_INTERNAL_H -#define SIG_INTERNAL_H - -#include - -#include - -#define sigmask(sig) (1ULL << (sig - 1)) -#define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \ - sigmask (SIGSTOP) | sigmask (SIGTSTP)) - -/* General lock. Protects PROCESS_PENDING, PROCESS_PENDING_INFO, - SIGWAITERS. */ -extern pthread_mutex_t sig_lock; - -/* "Signals generated for the process shall be delivered to exactly - one of those threads within the process which is in a call to a - sigwait() function selecting that signal or has not blocked - delivery of the signal. If there are no threads in a call to a - sigwait() function selecting that signal, and if all threads within - the process block delivery of the signal, the signal shall remaing - pending on the process" (2.4.1). - - This variable is protected by SIG_LOCK. */ -extern sigset_t process_pending; -extern siginfo_t process_pending_info[NSIG]; - -struct sigwaiter; - -/* The per-thread signal state. */ -struct signal_state -{ - /* Protects the following fields. STACK.SA_FLAGS may be accessed - using atomic operations. */ - pthread_mutex_t lock; - - /* Pending signals. */ - sigset_t pending; - - /* Blocked signals (i.e., the signal mask). */ - sigset_t blocked; - - stack_t stack; - struct sigaction actions[NSIG]; - siginfo_t info[NSIG]; - - /* If the thread is blocked in a call to sigwait. */ - struct sigwaiter *sigwaiter; -}; - -#define PTHREAD_SIGNAL_MEMBERS struct signal_state ss; - -/* Arranges for thread TID to call signal_dispatch. Must not be - called if TID is the caller and an alternate stack is not required. - In this case, the caller should call signal_dispatch directly. */ -extern void signal_dispatch_lowlevel (struct signal_state *ss, - pthread_t tid, siginfo_t si); - -/* This is the signal handler entry point. A thread is forced into - this state when it receives a signal. We need to save the thread's - state and then invoke the high-level signal dispatcher. SS->LOCK - is locked by the caller. */ -extern void signal_dispatch (struct signal_state *ss, siginfo_t *si); - -#ifndef SIGNAL_DISPATCH_ENTRY -#define SIGNAL_DISPATCH_ENTRY -#endif - -#ifndef SIGNAL_DISPATCH_EXIT -#define SIGNAL_DISPATCH_EXIT -#endif - -/* When a thread calls sigwait and a requested signal is not pending, - it allocates the following structure, fills it in, adds it to - sigwaiters and sleeps. */ -struct sigwaiter -{ - struct sigwaiter *next; - struct sigwaiter *prev; - - /* Thread's signal state. */ - struct signal_state *ss; - - /* Signals this thread is waiting for. */ - sigset_t signals; - - /* The selected signal is returned here. The waiter also - futex_waits on this info.si_signo. */ - siginfo_t info; -}; - -/* This variable is protected by SIG_LOCK. */ -extern struct sigwaiter *sigwaiters; - -/* Block the caller waiting for a signal in set SET. SIG_LOCK and - SS->LOCK must be held and will be unlocked by this function before - blocking. */ -extern siginfo_t sigwaiter_block (struct signal_state *ss, - const sigset_t *restrict set); - -/* Unblock the waiter WAITER. SIG_LOCK and WAITER->SS->LOCK must be - held. Both will be dropped on return. */ -extern void sigwaiter_unblock (struct sigwaiter *waiter); - -enum sig_action { sig_core, sig_terminate, sig_ignore, sig_cont, sig_stop }; - -static inline enum sig_action -default_action (int signo) -{ - switch (signo) - { - case SIGABRT: - case SIGBUS: - case SIGFPE: - case SIGILL: - case SIGQUIT: - case SIGSEGV: - case SIGSTKFLT: - case SIGSYS: - case SIGTRAP: - case SIGXCPU: - case SIGXFSZ: - return sig_core; - - case SIGALRM: - case SIGHUP: - case SIGINT: - case SIGIO: /* Perhaps ignore? */ - case SIGKILL: - case SIGPIPE: - case SIGPROF: - case SIGTERM: - case SIGUSR1: - case SIGUSR2: - case SIGVTALRM: - return sig_terminate; - - case SIGCHLD: - case SIGPWR: - case SIGURG: - case SIGWINCH: - return sig_ignore; - - case SIGCONT: - return sig_cont; - - case SIGSTOP: - case SIGTSTP: - case SIGTTIN: - case SIGTTOU: - return sig_stop; - } - - panic ("Unknown signal number: %d", signo); -} - -#endif diff --git a/signal/sigaction.c b/signal/sigaction.c deleted file mode 100644 index 0126c99d..00000000 --- a/signal/sigaction.c +++ /dev/null @@ -1,72 +0,0 @@ -/* sigaction.c - Generic sigaction implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" -#include "pt-internal.h" - -int -sigaction (int sig, const struct sigaction *restrict sa, - struct sigaction *restrict osa) -{ - if (sig <= 0 || sig >= NSIG) - { - errno = EINVAL; - return -1; - } - - struct signal_state *ss = &_pthread_self ()->ss; - - pthread_mutex_lock (&ss->lock); - - if (osa) - *osa = ss->actions[sig - 1]; - - if (sa) - { - ss->actions[sig - 1] = *sa; - - /* "The SIGKILL and SIGSTOP signals shall not be added to the - signal mask using this mechanism; this restriction shall be - enforced by the system without causing an error to be - indicated" (sigaction). */ - sigdelset (&ss->blocked, SIGKILL); - sigdelset (&ss->blocked, SIGSTOP); - - /* A "signal shall remain pending on the process until it is - unblocked, it is accepted when ..., or the action associated - with it is set to ignore the signal" (2.4.1). - - "Setting a signal action to SIG_DFL for a signal that is - pending, and whose default action is to ignore the signal, - ..., shall cause the pending signal to be discarded, whether - or not it is blocked" (2.4.3). */ - if (sa->sa_handler == SIG_IGN - || (sa->sa_handler == SIG_DFL && default_action (sig) == sig_ignore)) - { - sigdelset (&ss->pending, sig); - sigdelset (&process_pending, sig); - } - } - - pthread_mutex_unlock (&ss->lock); - - return 0; -} - diff --git a/signal/sigaltstack.c b/signal/sigaltstack.c deleted file mode 100644 index 8334811a..00000000 --- a/signal/sigaltstack.c +++ /dev/null @@ -1,69 +0,0 @@ -/* sigaltstack.c - Generic sigaltstack implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" -#include "pt-internal.h" - -int -sigaltstack (const stack_t *restrict stack, stack_t *restrict old) -{ - int err = 0; - struct signal_state *ss = &_pthread_self ()->ss; - - pthread_mutex_lock (&ss->lock); - - if (old) - *old = ss->stack; - - if (stack) - { - if (stack->ss_size < MINSIGSTKSZ) - { - err = ENOMEM; - goto out; - } - - if ((stack->ss_flags & ~(SS_DISABLE))) - /* Flags contains a value other than SS_DISABLE. */ - { - err = EINVAL; - goto out; - } - - if ((ss->stack.ss_flags & SS_ONSTACK)) - /* Stack in use. */ - { - err = EPERM; - goto out; - } - - ss->stack = *stack; - } - - out: - pthread_mutex_unlock (&ss->lock); - - if (err) - { - errno = err; - return -1; - } - return 0; -} diff --git a/signal/signal-dispatch.c b/signal/signal-dispatch.c deleted file mode 100644 index 40440b70..00000000 --- a/signal/signal-dispatch.c +++ /dev/null @@ -1,117 +0,0 @@ -/* signal-dispatch.c - Signal dispatcher. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -/* This is the signal handler entry point. A thread is forced into - this state when it receives a signal. We need to save the thread's - state and then invoke the high-level signal dispatcher. SS->LOCK - is locked by the caller. */ -void -signal_dispatch (struct signal_state *ss, siginfo_t *si) -{ - SIGNAL_DISPATCH_ENTRY; - - int signo = si->si_signo; - - assert (signo > 0 && signo < NSIG); - assert (pthread_mutex_trylock (&ss->lock) == EBUSY); - - do - { - if ((sigmask (signo) & STOPSIGS)) - /* Stop signals clear a pending SIGCONT even if they - are handled or ignored (but not if preempted). */ - { - sigdelset (&ss->pending, SIGCONT); - sigdelset (&process_pending, SIGCONT); - } - else if ((signo == SIGCONT)) - /* Even if handled or ignored (but not preempted), SIGCONT - clears stop signals and resumes the process. */ - { - ss->pending &= ~STOPSIGS; - process_pending &= ~STOPSIGS; - } - - void (*handler)(int, siginfo_t *, void *) - = ss->actions[signo - 1].sa_sigaction; - - /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot - be automatically reset when delivered; the system silently - enforces this restriction (sigaction). */ - if (ss->actions[signo - 1].sa_flags & SA_RESETHAND - && signo != SIGILL && signo != SIGTRAP) - ss->actions[signo - 1].sa_handler = SIG_DFL; - - sigset_t orig_blocked = ss->blocked; - /* Block requested signals while running the handler. */ - ss->blocked |= ss->actions[signo - 1].sa_mask; - - /* Block SIGNO unless we're asked not to. */ - if (! (ss->actions[signo - 1].sa_flags & (SA_RESETHAND | SA_NODEFER))) - sigaddset (&ss->blocked, signo); - - sigdelset (&ss->pending, signo); - pthread_mutex_unlock (&ss->lock); - - pthread_mutex_lock (&sig_lock); - sigdelset (&process_pending, signo); - pthread_mutex_unlock (&sig_lock); - - if (handler == (void *) SIG_DFL) - { - enum sig_action action = default_action (signo); - - if (action == sig_terminate || action == sig_core) - _exit (128 + signo); - - if (action == sig_stop) - /* XXX: Implement me. */ - panic ("Stopping process unimplemented."); - - if (action == sig_cont) - /* XXX: Implement me. */; - panic ("Continuing process unimplemented."); - } - else if (handler == (void *) SIG_IGN) - ; - else - handler (signo, si, NULL); - - pthread_mutex_lock (&ss->lock); - - /* "When a thread's signal mask is changed in a signal-catching - function that is installed by sigaction(), the restoration of - the signal mask on return from the signal-catching function - overrides that change (see sigaction())" (sigprocmask). */ - ss->blocked = orig_blocked; - - sigset_t pending = ~ss->blocked & ss->pending; - if (! pending) - pending = ~ss->blocked & process_pending; - signo = l4_lsb64 (pending); - } - while (signo); - - pthread_mutex_unlock (&ss->lock); - - SIGNAL_DISPATCH_EXIT; -} diff --git a/signal/signal.h b/signal/signal.h deleted file mode 100644 index a33d995c..00000000 --- a/signal/signal.h +++ /dev/null @@ -1,275 +0,0 @@ -/* signal.h - Signal handling interface. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#ifndef _SIGNAL_H -#define _SIGNAL_H 1 - -#include -#include - -typedef volatile int sig_atomic_t; - -typedef uint64_t sigset_t; - -int sigaddset (sigset_t *, int); -int sigdelset (sigset_t *, int); -int sigemptyset (sigset_t *); -int sigfillset (sigset_t *); -int sigismember (const sigset_t *, int); - -/* These values are consistent with Linux. */ -#define SIGRTMIN 34 -#define SIGRTMAX 64 - -enum - { - SIGHUP = 1, -#define SIGHUP SIGHUP - SIGINT, -#define SIGINT SIGINT - SIGQUIT, -#define SIGQUIT SIGQUIT - SIGILL, -#define SIGILL SIGILL - SIGTRAP, -#define SIGTRAP SIGTRAP - SIGABRT, -#define SIGABRT SIGABRT - SIGBUS, -#define SIGBUS SIGBUS - SIGFPE, -#define SIGFPE SIGFPE - SIGKILL, -#define SIGKILL SIGKILL - SIGUSR1, -#define SIGUSR1 SIGUSR1 - SIGSEGV, -#define SIGSEGV SIGSEGV - SIGUSR2, -#define SIGUSR2 SIGUSR2 - SIGPIPE, -#define SIGPIPE SIGPIPE - SIGALRM, -#define SIGALRM SIGALRM - SIGTERM, -#define SIGTERM SIGTERM - SIGSTKFLT, -#define SIGSTKFLT SIGSTKFLT - SIGCHLD, -#define SIGCHLD SIGCHLD - SIGCONT, -#define SIGCONT SIGCONT - SIGSTOP, -#define SIGSTOP SIGSTOP - SIGTSTP, -#define SIGTSTP SIGTSTP - SIGTTIN, -#define SIGTTIN SIGTTIN - SIGTTOU, -#define SIGTTOU SIGTTOU - SIGURG, -#define SIGURG SIGURG - SIGXCPU, -#define SIGXCPU SIGXCPU - SIGXFSZ, -#define SIGXFSZ SIGXFSZ - SIGVTALRM, -#define SIGVTALRM SIGVTALRM - SIGPROF, -#define SIGPROF SIGPROF - SIGWINCH, -#define SIGWINCH SIGWINCH - SIGIO, -#define SIGIO SIGIO - SIGPWR, -#define SIGPWR SIGPWR - SIGSYS, -#define SIGSYS SIGSYS - NSIG - }; - -/* The resulting set is the union of the current set and the signal - set pointed to by the argument set. */ -#define SIG_BLOCK 1 -/* The resulting set is the intersection of the current set and the - complement of the signal set pointed to by the argument set. */ -#define SIG_UNBLOCK 2 -/* The resulting set is the signal set pointed to by the argument - set. */ -#define SIG_SETMASK 3 - -int pthread_sigmask (int how, const sigset_t *mask, sigset_t *old); -int sigprocmask (int how, const sigset_t *restrict mask, - sigset_t *restrict old); - -/* Return set of pending signals. */ -int sigpending(sigset_t *set); - -union sigval -{ - int sival_int; - void *sival_ptr; -}; - -#define SIG_DFL ((void (*)(int)) (0)) -#define SIG_ERR ((void (*)(int)) (-1)) -#define SIG_IGN ((void (*)(int)) (1)) - -/* Causes signal delivery to occur on an alternate stack. */ -#define SA_ONSTACK (1 << 0) -/* Do not generate SIGCHLD when children stop or stopped children - continue. */ -#define SA_NOCLDSTOP (1 << 1) -/* Causes signal dispositions to be set to SIG_DFL on entry to signal - handlers. */ -#define SA_RESETHAND (1 << 2) -/* Causes certain functions to become restartable. */ -#define SA_RESTART (1 << 3) -/* Causes extra information to be passed to signal handlers at the - time of receipt of a signal. */ -#define SA_SIGINFO (1 << 4) -/* Causes implementations not to create zombie processes on child - death. */ -#define SA_NOCLDWAIT (1 << 5) -/* Causes signal not to be automatically blocked on entry to - signal handler. */ -#define SA_NODEFER (1 << 6) - -typedef struct -{ - int si_signo; - int si_code; - int si_errno; - pid_t si_pid; - uid_t si_uid; - void *si_addr; - int si_status; - long si_band; - union sigval si_value; -} siginfo_t; - -struct sigaction -{ - union - { - /* Pointer to a signal-catching function or one of the macros - SIG_IGN or SIG_DFL. */ - void (*sa_handler)(int); - - /* Pointer to a signal-catching function. */ - void (*sa_sigaction)(int, siginfo_t *, void *); - }; - - /* Set of signals to be blocked during execution of the signal - handling function. */ - sigset_t sa_mask; - - /* Special flags. */ - int sa_flags; -}; - -int sigaction (int signo, const struct sigaction *restrict newaction, - struct sigaction *restrict oldaction); - -void (*signal (int signo, void (*handler)(int)))(int); -void (*bsd_signal (int signo, void (*handler)(int)))(int); - -/* Process is executing on an alternate signal stack. */ -#define SS_ONSTACK (1 << 0) -/* Alternate signal stack is disabled. */ -#define SS_DISABLE (1 << 1) - -/* Minimum stack size for a signal handler. */ -#define MINSIGSTKSZ PAGESIZE -/* Default size in bytes for the alternate signal stack. */ -#define SIGSTKSZ (16 * PAGESIZE) - -typedef struct -{ - void *ss_sp; - size_t ss_size; - int ss_flags; -} stack_t; - -int sigaltstack(const stack_t *restrict stack, stack_t *restrict old); - -#include - -/* Send SIGNO to the process PID. */ -int kill(pid_t pid, int signo); - -/* Send SIGNO to the process group PG. */ -int killpg(pid_t pg, int signo); - -/* Send SIGNO to thread TID. */ -int pthread_kill(pthread_t tid, int signo); - -/* Send a signal to thread TID using SIGINFO. */ -int pthread_kill_siginfo_np (pthread_t tid, siginfo_t siginfo); - -/* Send SIGNO to the calling thread. */ -int raise(int signo); - -typedef struct sigevent -{ - /* Notification type. */ - int sigev_notify; - - /* Signal number. */ - int sigev_signo; - - /* Signal value. */ - union sigval sigev_value; - - /* Notification function. */ - void (*sigev_notify_function) (union sigval); - - /* Notification attributes. */ - pthread_attr_t *sigev_notify_attributes; -} sigevent_t; - -enum - { - SIGEV_NONE = 0, -#define SIGEV_NONE SIGEV_NONE - SIGEV_SIGNAL, -#define SIGEV_SIGNAL SIGEV_SIGNAL - SIGEV_THREAD -#define SIGEV_THREAD SIGEV_THREAD - }; - -#define SIG_HOLD - -int sighold (int); -int sigignore (int); -int siginterrupt (int, int); -int sigpause (int); -int sigqueue (pid_t, int, const union sigval); -int sigrelse (int); -void (*sigset (int, void (*)(int)))(int); -int sigsuspend (const sigset_t *); - -/* Wait for a signal. */ -int sigwait (const sigset_t *restrict set, int *restrict signo); -int sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info); -int sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, - const struct timespec *restrict timespec); - -#endif diff --git a/signal/sigpending.c b/signal/sigpending.c deleted file mode 100644 index 609b55d6..00000000 --- a/signal/sigpending.c +++ /dev/null @@ -1,38 +0,0 @@ -/* sigpending.c - Generic sigpending implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include -#include - -int -sigpending (sigset_t *set) -{ - struct signal_state *ss = &_pthread_self ()->ss; - - pthread_mutex_lock (&ss->lock); - - /* There is no need to lock SIG_LOCK for process_pending since we - just read it, which is atomic. */ - *set = (ss->pending | process_pending) & ss->blocked; - - pthread_mutex_unlock (&ss->lock); - - return 0; -} diff --git a/signal/sigsuspend.c b/signal/sigsuspend.c deleted file mode 100644 index 73cf12a1..00000000 --- a/signal/sigsuspend.c +++ /dev/null @@ -1,29 +0,0 @@ -/* sigsuspend.c - Generic sigsuspend implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -sigsuspend (const sigset_t *set) -{ - /* XXX: Implement me. */ - errno = EOPNOTSUPP; - return -1; -} diff --git a/signal/sigtimedwait.c b/signal/sigtimedwait.c deleted file mode 100644 index 52cd0176..00000000 --- a/signal/sigtimedwait.c +++ /dev/null @@ -1,30 +0,0 @@ -/* sigtimedwait.c - Generic sigtimedwait implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -sigtimedwait (const sigset_t *restrict set, siginfo_t *restrict info, - const struct timespec *restrict timeout) -{ - errno = EOPNOTSUPP; - return -1; -} - diff --git a/signal/sigwaiter.c b/signal/sigwaiter.c deleted file mode 100644 index 8d041ac1..00000000 --- a/signal/sigwaiter.c +++ /dev/null @@ -1,91 +0,0 @@ -/* sigwaiter.c - Signal handling functions. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -#include - -struct sigwaiter *sigwaiters; - -siginfo_t -sigwaiter_block (struct signal_state *ss, const sigset_t *restrict set) -{ - assert (pthread_mutex_trylock (&sig_lock) == EBUSY); - assert (pthread_mutex_trylock (&ss->lock) == EBUSY); - - assert (! ss->sigwaiter); - - struct sigwaiter waiter; - - waiter.next = sigwaiters; - if (waiter.next) - { - assert (! waiter.next->prev); - waiter.next->prev = &waiter; - } - waiter.prev = 0; - sigwaiters = &waiter; - - waiter.ss = ss; - waiter.info.si_signo = 0; - waiter.signals = *set; - - ss->sigwaiter = &waiter; - - pthread_mutex_unlock (&ss->lock); - pthread_mutex_unlock (&sig_lock); - - futex_wait (&waiter.info.si_signo, 0); - -#ifndef NDEBUG - pthread_mutex_lock (&ss->lock); - ss->sigwaiter = 0; - pthread_mutex_unlock (&ss->lock); -#endif - - assert (waiter.info.si_signo); - return waiter.info; -} - -void -sigwaiter_unblock (struct sigwaiter *waiter) -{ - assert (pthread_mutex_trylock (&sig_lock) == EBUSY); - assert (pthread_mutex_trylock (&waiter->ss->lock) == EBUSY); - - struct sigwaiter *prev = waiter->prev; - struct sigwaiter *next = waiter->next; - - if (next) - next->prev = prev; - - if (prev) - prev->next = next; - else - sigwaiters = next; - - sigdelset (&process_pending, waiter->info.si_signo); - sigdelset (&waiter->ss->pending, waiter->info.si_signo); - - pthread_mutex_unlock (&waiter->ss->lock); - pthread_mutex_unlock (&sig_lock); - - futex_wake (&waiter->info.si_signo, 1); -} diff --git a/signal/sigwaitinfo.c b/signal/sigwaitinfo.c deleted file mode 100644 index 1b47079e..00000000 --- a/signal/sigwaitinfo.c +++ /dev/null @@ -1,74 +0,0 @@ -/* sigwaitinfo.c - Generic sigwaitinfo implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include -#include - -int -sigwaitinfo (const sigset_t *restrict set, siginfo_t *restrict info) -{ - pthread_mutex_lock (&sig_lock); - - struct signal_state *ss = &_pthread_self ()->ss; - - pthread_mutex_lock (&ss->lock); - - if ((process_pending & *set) || (ss->pending & *set)) - /* There is at least one signal pending. */ - { - bool local = true; - sigset_t extant = process_pending & *set; - if (! extant) - { - local = false; - extant = ss->pending & *set; - } - - assert (extant); - - int signo = l4_msb64 (extant); - - if (info) - { - if (local) - *info = ss->info[signo - 1]; - else - *info = process_pending_info[signo - 1]; - info->si_signo = signo; - } - - sigdelset (&process_pending, signo); - sigdelset (&ss->pending, signo); - - pthread_mutex_unlock (&ss->lock); - pthread_mutex_unlock (&sig_lock); - return 0; - } - - siginfo_t i = sigwaiter_block (ss, set); - assert (i.si_signo); - assert ((sigmask (i.si_signo) & *set)); - - if (info) - *info = i; - - return 0; -} - diff --git a/sysdeps/generic/bits/barrier-attr.h b/sysdeps/generic/bits/barrier-attr.h deleted file mode 100644 index a9900b71..00000000 --- a/sysdeps/generic/bits/barrier-attr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Thread barrier attribute type. Generic version. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_BARRIER_ATTR_H -#define _BITS_BARRIER_ATTR_H 1 - -enum __pthread_process_shared; - -/* This structure describes the attributes of a POSIX thread barrier. - Note that not all of them are supported on all systems. */ -struct __pthread_barrierattr -{ - enum __pthread_process_shared pshared; -}; - -#endif /* bits/barrier-attr.h */ diff --git a/sysdeps/generic/bits/barrier.h b/sysdeps/generic/bits/barrier.h deleted file mode 100644 index 5e559312..00000000 --- a/sysdeps/generic/bits/barrier.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Thread barrier attribute type. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_BARRIER_H -#define _BITS_BARRIER_H 1 - -#include - -/* This structure describes the attributes of a POSIX barrier. */ -struct __pthread_barrier -{ - __pthread_spinlock_t lock; - struct __pthread *queue; /* List of waiters. */ - unsigned pending; /* Number of that still need to wait on - barrier. */ - unsigned count; /* Number of threads that must wait before - barrier is passed. */ - struct __pthread_barrierattr *attr; - void *data; -}; - - -#endif /* bits/barrier.h */ diff --git a/sysdeps/generic/bits/cancelation.h b/sysdeps/generic/bits/cancelation.h deleted file mode 100644 index f446d595..00000000 --- a/sysdeps/generic/bits/cancelation.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Cancelation. Generic version. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_CANCELATION_H -#define _BITS_CANCELATION_H 1 - -#include - -struct __pthread_cancelation_handler -{ - void (*handler)(void *); - void *arg; - struct __pthread_cancelation_handler *next; -}; - -/* Returns the thread local location of the cleanup handler stack. */ -struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); - -#define __pthread_cleanup_push(rt, rtarg) \ - { \ - struct __pthread_cancelation_handler **__handlers \ - = __pthread_get_cleanup_stack (); \ - struct __pthread_cancelation_handler __handler = \ - { \ - handler: (rt), \ - arg: (rtarg), \ - next: *__handlers \ - }; \ - *__handlers = &__handler; - -#define __pthread_cleanup_pop(execute) \ - if (execute) \ - __handler.handler (__handler.arg); \ - assert (*__handlers == &__handler); \ - *__handlers = __handler.next; \ - } - -#endif /* _BITS_CANCELATION_H */ diff --git a/sysdeps/generic/bits/condition-attr.h b/sysdeps/generic/bits/condition-attr.h deleted file mode 100644 index a1311286..00000000 --- a/sysdeps/generic/bits/condition-attr.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Condition attribute type. Generic version. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_CONDITION_ATTR_H -#define _BITS_CONDITION_ATTR_H 1 - -#include - -enum __pthread_process_shared; - -/* User visible part of a condition attribute variable. */ -struct __pthread_condattr - { - enum __pthread_process_shared pshared; - clockid_t clock; - }; - -#endif /* bits/condition.h */ diff --git a/sysdeps/generic/bits/condition.h b/sysdeps/generic/bits/condition.h deleted file mode 100644 index bf13adab..00000000 --- a/sysdeps/generic/bits/condition.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Condition type. Generic version. - Copyright (C) 2000, 2005, 2009 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_CONDITION_H -#define _BITS_CONDITION_H 1 - -#include - -/* User visible part of a condition variable. */ -struct __pthread_cond - { - __pthread_spinlock_t __lock; - struct __pthread *__queue; - struct __pthread_condattr *__attr; - struct __pthread_condimpl *__impl; - void *__data; - }; - -/* Initializer for a condition variable. */ -#define __PTHREAD_COND_INITIALIZER \ - { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, NULL, NULL, NULL } - -#endif /* bits/condition.h */ diff --git a/sysdeps/generic/bits/mutex-attr.h b/sysdeps/generic/bits/mutex-attr.h deleted file mode 100644 index 9161cdab..00000000 --- a/sysdeps/generic/bits/mutex-attr.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Mutex attribute type. Generic version. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_MUTEX_ATTR_H -#define _BITS_MUTEX_ATTR_H 1 - -enum __pthread_mutex_protocol; -enum __pthread_process_shared; -enum __pthread_mutex_type; - -/* This structure describes the attributes of a POSIX mutex - attribute. */ -struct __pthread_mutexattr -{ - int prioceiling; - enum __pthread_mutex_protocol protocol; - enum __pthread_process_shared pshared; - enum __pthread_mutex_type mutex_type; -}; - -/* Attributes for a recursive mutex. */ -extern const struct __pthread_mutexattr __pthread_recursive_mutexattr; - -#endif /* bits/mutex-attr.h */ diff --git a/sysdeps/generic/bits/mutex.h b/sysdeps/generic/bits/mutex.h deleted file mode 100644 index 86068cf5..00000000 --- a/sysdeps/generic/bits/mutex.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Mutex type. Generic version. - - Copyright (C) 2000, 2002, 2005, 2006, 2007, 2008, 2009 - 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_MUTEX_H - -#ifndef __need_pthread_mutex -# define _BITS_MUTEX_H 1 -#endif - -#ifndef __pthread_mutex_defined -# if defined __need_pthread_mutex || defined _BITS_MUTEX_H -# undef __need_pthread_mutex -# define __pthread_mutex_defined - -# include -# include - -/* User visible part of a mutex. */ -struct __pthread_mutex - { - __pthread_spinlock_t __held; - __pthread_spinlock_t __lock; - /* In cthreads, mutex_init does not initialized thre third - pointer, as such, we cannot rely on its value for anything. */ - char *cthreadscompat1; - struct __pthread *__queue; - struct __pthread_mutexattr *attr; - void *data; - /* Up to this point, we are completely compatible with cthreads - and what libc expects. */ - void *owner; - unsigned locks; - /* If NULL then the default attributes apply. */ - }; - -/* Initializer for a mutex. N.B. this also happens to be compatible - with the cthread mutex initializer. */ -# define __PTHREAD_MUTEX_INITIALIZER \ - { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0, 0 } - -# define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ - { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, \ - (struct __pthread_mutexattr *) &__pthread_recursive_mutexattr, 0, 0, 0 } - -# endif -#endif /* Not __pthread_mutex_defined. */ - -#endif /* bits/mutex.h */ diff --git a/sysdeps/generic/bits/once.h b/sysdeps/generic/bits/once.h deleted file mode 100644 index f4985d6f..00000000 --- a/sysdeps/generic/bits/once.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Dynamic package initialization data structures. Generic version. - Copyright (C) 2002, 2009 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_ONCE_H -#define _BITS_ONCE_H 1 - -#include - -struct __pthread_once -{ - int run; - __pthread_spinlock_t lock; -}; - -#define __PTHREAD_ONCE_INIT \ - { 0, __PTHREAD_SPIN_LOCK_INITIALIZER } - -#endif /* bits/once.h */ diff --git a/sysdeps/generic/bits/pthread-np.h b/sysdeps/generic/bits/pthread-np.h deleted file mode 100644 index d5ddbb05..00000000 --- a/sysdeps/generic/bits/pthread-np.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Non-portable functions. Generic version. - Copyright (C) 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * Never include this file directly; use or instead. - */ - -#ifndef _BITS_PTHREAD_NP_H -#define _BITS_PTHREAD_NP_H 1 - -#endif /* bits/pthread-np.h */ diff --git a/sysdeps/generic/bits/pthread.h b/sysdeps/generic/bits/pthread.h deleted file mode 100644 index 80e6b096..00000000 --- a/sysdeps/generic/bits/pthread.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Pthread data structures. Generic version. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_PTHREAD_H -#define _BITS_PTHREAD_H 1 - -typedef int __pthread_t; - -/* Return true if __T1 and __T2 both name the same thread. Otherwise, - false. */ -extern int -__pthread_equal (__pthread_t __t1, __pthread_t __t2); - -#ifdef __USE_EXTERN_INLINES -__extern_inline int -__pthread_equal (__pthread_t __t1, __pthread_t __t2) -{ - return __t1 == __t2; -} -#endif - -#endif /* bits/pthread.h */ diff --git a/sysdeps/generic/bits/pthreadtypes.h b/sysdeps/generic/bits/pthreadtypes.h deleted file mode 100644 index e5cbfd2a..00000000 --- a/sysdeps/generic/bits/pthreadtypes.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#if !defined _BITS_TYPES_H && !defined _PTHREAD_H -# error "Never include directly; use instead." -#endif - -#ifndef _BITS_PTHREADTYPES_H -#define _BITS_PTHREADTYPES_H 1 - -#include - -#endif /* bits/pthreadtypes.h */ diff --git a/sysdeps/generic/bits/rwlock-attr.h b/sysdeps/generic/bits/rwlock-attr.h deleted file mode 100644 index dba99f1d..00000000 --- a/sysdeps/generic/bits/rwlock-attr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Thread rwlock attribute type. Generic version. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_RWLOCK_ATTR_H -#define _BITS_RWLOCK_ATTR_H 1 - -enum __pthread_process_shared; - -/* This structure describes the attributes of a POSIX thread rwlock. - Note that not all of them are supported on all systems. */ -struct __pthread_rwlockattr -{ - enum __pthread_process_shared pshared; -}; - -#endif /* bits/rwlock-attr.h */ diff --git a/sysdeps/generic/bits/rwlock.h b/sysdeps/generic/bits/rwlock.h deleted file mode 100644 index af6b1c86..00000000 --- a/sysdeps/generic/bits/rwlock.h +++ /dev/null @@ -1,46 +0,0 @@ -/* rwlock type. Generic version. - Copyright (C) 2002, 2005, 2006, 2007, 2009 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_RWLOCK_H -#define _BITS_RWLOCK_H - -#include - -/* User visible part of a rwlock. If __held is not held and readers - is 0, then the lock is unlocked. If __held is held and readers is - 0, then the lock is held by a writer. If __held is held and - readers is greater than 0, then the lock is held by READERS - readers. */ -struct __pthread_rwlock - { - __pthread_spinlock_t __held; - __pthread_spinlock_t __lock; - int readers; - struct __pthread *readerqueue; - struct __pthread *writerqueue; - struct __pthread_rwlockattr *__attr; - void *__data; - }; - -/* Initializer for a rwlock. */ -#define __PTHREAD_RWLOCK_INITIALIZER \ - { __PTHREAD_SPIN_LOCK_INITIALIZER, __PTHREAD_SPIN_LOCK_INITIALIZER, 0, 0, 0, 0, 0 } - - -#endif /* bits/rwlock.h */ diff --git a/sysdeps/generic/bits/semaphore.h b/sysdeps/generic/bits/semaphore.h deleted file mode 100644 index 5e987c15..00000000 --- a/sysdeps/generic/bits/semaphore.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Semaphore type. Generic version. - Copyright (C) 2005, 2009 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_SEMAPHORE_H -#define _BITS_SEMAPHORE_H 1 - -#ifndef _SEMAPHORE_H -#error Never include directly. -#endif - -#include - -/* User visible part of a semaphore. */ -struct __semaphore - { - __pthread_spinlock_t __lock; - struct __pthread *__queue; - int __pshared; - int __value; - void *__data; - }; - -/* Initializer for a semaphore. */ -#define __SEMAPHORE_INITIALIZER(pshared, value) \ - { __PTHREAD_SPIN_LOCK_INITIALIZER, NULL, (pshared), (value), NULL } - -#endif /* bits/mutex.h */ diff --git a/sysdeps/generic/bits/thread-attr.h b/sysdeps/generic/bits/thread-attr.h deleted file mode 100644 index c3a93fde..00000000 --- a/sysdeps/generic/bits/thread-attr.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Thread attribute type. Generic version. - Copyright (C) 2000, 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_THREAD_ATTR_H -#define _BITS_THREAD_ATTR_H 1 - -#include - -enum __pthread_detachstate; -enum __pthread_inheritsched; -enum __pthread_contentionscope; - -/* This structure describes the attributes of a POSIX thread. Note - that not all of them are supported on all systems. */ -struct __pthread_attr -{ - struct sched_param schedparam; - void *stackaddr; - size_t stacksize; - size_t guardsize; - enum __pthread_detachstate detachstate; - enum __pthread_inheritsched inheritsched; - enum __pthread_contentionscope contentionscope; - int schedpolicy; -}; - -#endif /* bits/thread-attr.h */ diff --git a/sysdeps/generic/bits/thread-specific.h b/sysdeps/generic/bits/thread-specific.h deleted file mode 100644 index b42d99e7..00000000 --- a/sysdeps/generic/bits/thread-specific.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Thread specific data. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_THREAD_SPECIFIC_H -#define _BITS_THREAD_SPECIFIC_H 1 - -typedef int __pthread_key; - -#endif /* bits/thread-specific.h */ diff --git a/sysdeps/generic/killpg.c b/sysdeps/generic/killpg.c deleted file mode 100644 index 7f7ed87d..00000000 --- a/sysdeps/generic/killpg.c +++ /dev/null @@ -1,27 +0,0 @@ -/* killpg.c - Generic killpg implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -killpg (pid_t pid, int sig) -{ - return kill (-pid, sig); -} diff --git a/sysdeps/generic/pt-atfork.c b/sysdeps/generic/pt-atfork.c deleted file mode 100644 index 32e1e78c..00000000 --- a/sysdeps/generic/pt-atfork.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Register fork handlers. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_atfork (void (*prepare) (void), - void (*parent) (void), - void (*child) (void)) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-attr-destroy.c b/sysdeps/generic/pt-attr-destroy.c deleted file mode 100644 index c4b9aa54..00000000 --- a/sysdeps/generic/pt-attr-destroy.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_attr_destroy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_destroy (pthread_attr_t *attr) -{ - return 0; -} diff --git a/sysdeps/generic/pt-attr-getdetachstate.c b/sysdeps/generic/pt-attr-getdetachstate.c deleted file mode 100644 index be406f1d..00000000 --- a/sysdeps/generic/pt-attr-getdetachstate.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_getdetachstate. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getdetachstate (const pthread_attr_t *attr, - int *detachstate) -{ - *detachstate = attr->detachstate; - return 0; -} diff --git a/sysdeps/generic/pt-attr-getguardsize.c b/sysdeps/generic/pt-attr-getguardsize.c deleted file mode 100644 index c1d9f13e..00000000 --- a/sysdeps/generic/pt-attr-getguardsize.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_getguardsize. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getguardsize (const pthread_attr_t *attr, - size_t *guardsize) -{ - *guardsize = attr->guardsize; - return 0; -} diff --git a/sysdeps/generic/pt-attr-getinheritsched.c b/sysdeps/generic/pt-attr-getinheritsched.c deleted file mode 100644 index cca4e3d7..00000000 --- a/sysdeps/generic/pt-attr-getinheritsched.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_getinheritsched. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getinheritsched (const pthread_attr_t *attr, - int *inheritsched) -{ - *inheritsched = attr->inheritsched; - return 0; -} diff --git a/sysdeps/generic/pt-attr-getschedparam.c b/sysdeps/generic/pt-attr-getschedparam.c deleted file mode 100644 index 25afebd0..00000000 --- a/sysdeps/generic/pt-attr-getschedparam.c +++ /dev/null @@ -1,31 +0,0 @@ -/* pthread_attr_getschedparam. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_attr_getschedparam (const pthread_attr_t *attr, - struct sched_param *param) -{ - *param = attr->schedparam; - return 0; -} diff --git a/sysdeps/generic/pt-attr-getschedpolicy.c b/sysdeps/generic/pt-attr-getschedpolicy.c deleted file mode 100644 index 4349a238..00000000 --- a/sysdeps/generic/pt-attr-getschedpolicy.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_getschedpolicy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getschedpolicy (const pthread_attr_t *attr, - int *policy) -{ - *policy = attr->schedpolicy; - return 0; -} diff --git a/sysdeps/generic/pt-attr-getscope.c b/sysdeps/generic/pt-attr-getscope.c deleted file mode 100644 index 97198fa5..00000000 --- a/sysdeps/generic/pt-attr-getscope.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_getscope. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getscope (const pthread_attr_t *attr, - int *contentionscope) -{ - *contentionscope = attr->contentionscope; - return 0; -} diff --git a/sysdeps/generic/pt-attr-getstack.c b/sysdeps/generic/pt-attr-getstack.c deleted file mode 100644 index 7beb79f0..00000000 --- a/sysdeps/generic/pt-attr-getstack.c +++ /dev/null @@ -1,31 +0,0 @@ -/* pthread_attr_getstack. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getstack (const pthread_attr_t *attr, - void **stackaddr, - size_t *stacksize) -{ - pthread_attr_getstackaddr (attr, stackaddr); - pthread_attr_getstacksize (attr, stacksize); - return 0; -} diff --git a/sysdeps/generic/pt-attr-getstackaddr.c b/sysdeps/generic/pt-attr-getstackaddr.c deleted file mode 100644 index d43eeff7..00000000 --- a/sysdeps/generic/pt-attr-getstackaddr.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_getstackaddr. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getstackaddr (const pthread_attr_t *attr, - void **stackaddr) -{ - *stackaddr = attr->stackaddr; - return 0; -} diff --git a/sysdeps/generic/pt-attr-getstacksize.c b/sysdeps/generic/pt-attr-getstacksize.c deleted file mode 100644 index c1bc6617..00000000 --- a/sysdeps/generic/pt-attr-getstacksize.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_getstacksize. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_getstacksize (const pthread_attr_t *attr, - size_t *stacksize) -{ - *stacksize = attr->stacksize; - return 0; -} diff --git a/sysdeps/generic/pt-attr-init.c b/sysdeps/generic/pt-attr-init.c deleted file mode 100644 index 6a930e30..00000000 --- a/sysdeps/generic/pt-attr-init.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_attr_init. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_init (pthread_attr_t *attr) -{ - *attr = __pthread_default_attr; - return 0; -} diff --git a/sysdeps/generic/pt-attr-setdetachstate.c b/sysdeps/generic/pt-attr-setdetachstate.c deleted file mode 100644 index 688ba5d6..00000000 --- a/sysdeps/generic/pt-attr-setdetachstate.c +++ /dev/null @@ -1,38 +0,0 @@ -/* pthread_attr_setdetachstate. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_setdetachstate (pthread_attr_t *attr, - int detachstate) -{ - switch (detachstate) - { - case PTHREAD_CREATE_DETACHED: - case PTHREAD_CREATE_JOINABLE: - attr->detachstate = detachstate; - break; - default: - return EINVAL; - } - - return 0; -} diff --git a/sysdeps/generic/pt-attr-setguardsize.c b/sysdeps/generic/pt-attr-setguardsize.c deleted file mode 100644 index b2ba0f0f..00000000 --- a/sysdeps/generic/pt-attr-setguardsize.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_setguardsize. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_setguardsize (pthread_attr_t *attr, - size_t guardsize) -{ - attr->guardsize = guardsize; - return 0; -} diff --git a/sysdeps/generic/pt-attr-setinheritsched.c b/sysdeps/generic/pt-attr-setinheritsched.c deleted file mode 100644 index e9012c58..00000000 --- a/sysdeps/generic/pt-attr-setinheritsched.c +++ /dev/null @@ -1,38 +0,0 @@ -/* pthread_attr_setinheritsched. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_setinheritsched (pthread_attr_t *attr, - int inheritsched) -{ - switch (inheritsched) - { - case PTHREAD_INHERIT_SCHED: - case PTHREAD_EXPLICIT_SCHED: - attr->inheritsched = inheritsched; - break; - default: - return EINVAL; - } - - return 0; -} diff --git a/sysdeps/generic/pt-attr-setschedparam.c b/sysdeps/generic/pt-attr-setschedparam.c deleted file mode 100644 index 18a575ec..00000000 --- a/sysdeps/generic/pt-attr-setschedparam.c +++ /dev/null @@ -1,38 +0,0 @@ -/* pthread_attr_getschedparam. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -pthread_attr_setschedparam (pthread_attr_t *attr, - const struct sched_param *param) -{ - if (memcmp (param, &__pthread_default_attr.schedparam, - sizeof *param) == 0) - { - attr->schedparam = *param; - return 0; - } - - return ENOTSUP; -} diff --git a/sysdeps/generic/pt-attr-setschedpolicy.c b/sysdeps/generic/pt-attr-setschedpolicy.c deleted file mode 100644 index e481d04c..00000000 --- a/sysdeps/generic/pt-attr-setschedpolicy.c +++ /dev/null @@ -1,42 +0,0 @@ -/* pthread_attr_getschedpolicy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_setschedpolicy (pthread_attr_t *attr, - int policy) -{ - switch (policy) - { - case SCHED_OTHER: - attr->schedpolicy = policy; - break; - - case SCHED_FIFO: - case SCHED_RR: - return ENOTSUP; - - default: - return EINVAL; - } - - return 0; -} diff --git a/sysdeps/generic/pt-attr-setscope.c b/sysdeps/generic/pt-attr-setscope.c deleted file mode 100644 index c74a4f67..00000000 --- a/sysdeps/generic/pt-attr-setscope.c +++ /dev/null @@ -1,41 +0,0 @@ -/* pthread_attr_setscope. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_setscope (pthread_attr_t *attr, - int contentionscope) -{ - if (contentionscope == __pthread_default_attr.contentionscope) - { - attr->contentionscope = contentionscope; - return 0; - } - - switch (contentionscope) - { - case PTHREAD_SCOPE_PROCESS: - case PTHREAD_SCOPE_SYSTEM: - return ENOTSUP; - default: - return EINVAL; - } -} diff --git a/sysdeps/generic/pt-attr-setstack.c b/sysdeps/generic/pt-attr-setstack.c deleted file mode 100644 index 360d27a3..00000000 --- a/sysdeps/generic/pt-attr-setstack.c +++ /dev/null @@ -1,51 +0,0 @@ -/* pthread_attr_setstack. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_attr_setstack (pthread_attr_t *attr, - void *stackaddr, - size_t stacksize) -{ - int err; - size_t s; - - /* pthread_attr_setstack should always succeed, thus we set the size - first as it is more discriminating. */ - pthread_attr_getstacksize (attr, &s); - - err = pthread_attr_setstacksize (attr, stacksize); - if (err) - return err; - - err = pthread_attr_setstackaddr (attr, stackaddr); - if (err) - { - int e = pthread_attr_setstacksize (attr, s); - assert_perror (e); - - return err; - } - - return 0; -} diff --git a/sysdeps/generic/pt-attr-setstackaddr.c b/sysdeps/generic/pt-attr-setstackaddr.c deleted file mode 100644 index 431f2d0c..00000000 --- a/sysdeps/generic/pt-attr-setstackaddr.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_attr_setstackaddr. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_setstackaddr (pthread_attr_t *attr, - void *stackaddr) -{ - attr->stackaddr = stackaddr; - return 0; -} diff --git a/sysdeps/generic/pt-attr-setstacksize.c b/sysdeps/generic/pt-attr-setstacksize.c deleted file mode 100644 index d0e51022..00000000 --- a/sysdeps/generic/pt-attr-setstacksize.c +++ /dev/null @@ -1,41 +0,0 @@ -/* pthread_attr_setstacksize. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_attr_setstacksize (pthread_attr_t *attr, - size_t stacksize) -{ - if (stacksize == __pthread_default_attr.stacksize) - { - attr->stacksize = stacksize; - - /* The guard size cannot be larger than the stack itself, as - such, if the new stack size is smaller than the guard size, - we squash the guard size. */ - if (attr->guardsize > attr->stacksize) - attr->guardsize = attr->stacksize; - - return 0; - } - - return ENOTSUP; -} diff --git a/sysdeps/generic/pt-attr.c b/sysdeps/generic/pt-attr.c deleted file mode 100644 index 769f292a..00000000 --- a/sysdeps/generic/pt-attr.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Default attributes. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -const struct __pthread_attr __pthread_default_attr = -{ - schedparam: { sched_priority: 0 }, - stacksize: PTHREAD_STACK_DEFAULT, - stackaddr: NULL, -#ifdef PAGESIZE - guardsize: PAGESIZE, -#else - guardsize: 0, -#endif /* PAGESIZE */ - detachstate: PTHREAD_CREATE_JOINABLE, - inheritsched: PTHREAD_EXPLICIT_SCHED, - contentionscope: PTHREAD_SCOPE_SYSTEM, - schedpolicy: SCHED_OTHER -}; diff --git a/sysdeps/generic/pt-barrier-destroy.c b/sysdeps/generic/pt-barrier-destroy.c deleted file mode 100644 index 01b938b4..00000000 --- a/sysdeps/generic/pt-barrier-destroy.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_barrier_destroy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_barrier_destroy (pthread_barrier_t *barrier) -{ - return 0; -} diff --git a/sysdeps/generic/pt-barrier-init.c b/sysdeps/generic/pt-barrier-init.c deleted file mode 100644 index c42b3bb6..00000000 --- a/sysdeps/generic/pt-barrier-init.c +++ /dev/null @@ -1,53 +0,0 @@ -/* pthread_barrier_init. Generic version. - Copyright (C) 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -pthread_barrier_init (pthread_barrier_t *barrier, - const pthread_barrierattr_t *attr, - unsigned count) -{ - if (count == 0) - return EINVAL; - - memset (barrier, 0, sizeof *barrier); - - barrier->lock = PTHREAD_SPINLOCK_INITIALIZER; - barrier->pending = count; - barrier->count = count; - - if (! attr - || memcmp (attr, &__pthread_default_barrierattr, sizeof (*attr) == 0)) - /* Use the default attributes. */ - return 0; - - /* Non-default attributes. */ - - barrier->attr = malloc (sizeof *attr); - if (! barrier->attr) - return ENOMEM; - - *barrier->attr = *attr; - return 0; -} diff --git a/sysdeps/generic/pt-barrier-wait.c b/sysdeps/generic/pt-barrier-wait.c deleted file mode 100644 index f1de250a..00000000 --- a/sysdeps/generic/pt-barrier-wait.c +++ /dev/null @@ -1,61 +0,0 @@ -/* pthread_barrier_wait. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_barrier_wait (pthread_barrier_t *barrier) -{ - __pthread_spin_lock (&barrier->lock); - if (-- barrier->pending == 0) - { - barrier->pending = barrier->count; - - if (barrier->count > 1) - { - struct __pthread *wakeup; - - wakeup = barrier->queue; - barrier->queue = NULL; - __pthread_spin_unlock (&barrier->lock); - - /* We can safely walk the list of waiting threads without - holding the lock since it is decoupled from the barrier - variable now. */ - __pthread_dequeuing_iterate (wakeup, wakeup) - __pthread_wakeup (wakeup); - } - - return PTHREAD_BARRIER_SERIAL_THREAD; - } - else - { - struct __pthread *self = _pthread_self (); - - /* Add ourselves to the list of waiters. */ - __pthread_enqueue (&barrier->queue, self); - __pthread_spin_unlock (&barrier->lock); - - __pthread_block (self); - return 0; - } -} diff --git a/sysdeps/generic/pt-barrier.c b/sysdeps/generic/pt-barrier.c deleted file mode 100644 index d772719f..00000000 --- a/sysdeps/generic/pt-barrier.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Default barrier attributes. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -const struct __pthread_barrierattr __pthread_default_barrierattr = -{ - pshared: PTHREAD_PROCESS_PRIVATE -}; diff --git a/sysdeps/generic/pt-barrierattr-destroy.c b/sysdeps/generic/pt-barrierattr-destroy.c deleted file mode 100644 index eb396347..00000000 --- a/sysdeps/generic/pt-barrierattr-destroy.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_barrierattr_destroy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_barrierattr_destroy (pthread_barrierattr_t *attr) -{ - return 0; -} diff --git a/sysdeps/generic/pt-barrierattr-getpshared.c b/sysdeps/generic/pt-barrierattr-getpshared.c deleted file mode 100644 index ed2cdd24..00000000 --- a/sysdeps/generic/pt-barrierattr-getpshared.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_barrierattr_getpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_barrierattr_getpshared (const pthread_barrierattr_t *attr, - int *pshared) -{ - *pshared = attr->pshared; - return 0; -} diff --git a/sysdeps/generic/pt-barrierattr-init.c b/sysdeps/generic/pt-barrierattr-init.c deleted file mode 100644 index 45f16cc8..00000000 --- a/sysdeps/generic/pt-barrierattr-init.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_barrierattr_init. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_barrierattr_init (pthread_barrierattr_t *attr) -{ - *attr = __pthread_default_barrierattr; - return 0; -} diff --git a/sysdeps/generic/pt-barrierattr-setpshared.c b/sysdeps/generic/pt-barrierattr-setpshared.c deleted file mode 100644 index 84ef2df8..00000000 --- a/sysdeps/generic/pt-barrierattr-setpshared.c +++ /dev/null @@ -1,39 +0,0 @@ -/* pthread_barrierattr_setpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, - int pshared) -{ - switch (pshared) - { - case PTHREAD_PROCESS_PRIVATE: - attr->pshared = pshared; - return 0; - - case PTHREAD_PROCESS_SHARED: - return ENOTSUP; - - default: - return EINVAL; - } -} diff --git a/sysdeps/generic/pt-cond-brdcast.c b/sysdeps/generic/pt-cond-brdcast.c deleted file mode 100644 index 3f55e33e..00000000 --- a/sysdeps/generic/pt-cond-brdcast.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Broadcast a condition. Generic version. - 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* Unblock all threads that are blocked on condition variable COND. */ -int -pthread_cond_broadcast (pthread_cond_t *cond) -{ - struct __pthread *wakeup; - - __pthread_spin_lock (&cond->__lock); - - wakeup = cond->__queue; - cond->__queue = NULL; - __pthread_spin_unlock (&cond->__lock); - - /* We can safely walk the list of waiting threads without holding - the lock since it is now decoupled from the condition. */ - __pthread_dequeuing_iterate (wakeup, wakeup) - __pthread_wakeup (wakeup); - - return 0; -} diff --git a/sysdeps/generic/pt-cond-destroy.c b/sysdeps/generic/pt-cond-destroy.c deleted file mode 100644 index eba47784..00000000 --- a/sysdeps/generic/pt-cond-destroy.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_cond_destroy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_cond_destroy (pthread_cond_t *cond) -{ - return 0; -} diff --git a/sysdeps/generic/pt-cond-init.c b/sysdeps/generic/pt-cond-init.c deleted file mode 100644 index b9e9fb7a..00000000 --- a/sysdeps/generic/pt-cond-init.c +++ /dev/null @@ -1,45 +0,0 @@ -/* pthread_cond_init. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -pthread_cond_init (pthread_cond_t *cond, - const pthread_condattr_t *attr) -{ - *cond = (pthread_cond_t) __PTHREAD_COND_INITIALIZER; - - if (! attr - || memcmp (attr, &__pthread_default_condattr, sizeof (*attr) == 0)) - /* Use the default attributes. */ - return 0; - - /* Non-default attributes. */ - - cond->__attr = malloc (sizeof *attr); - if (! cond->__attr) - return ENOMEM; - - *cond->__attr = *attr; - return 0; -} diff --git a/sysdeps/generic/pt-cond-signal.c b/sysdeps/generic/pt-cond-signal.c deleted file mode 100644 index c5e1bc1d..00000000 --- a/sysdeps/generic/pt-cond-signal.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Signal a condition. Generic version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -static int -cond_signal (struct __pthread_cond *cond, int *unblocked) -{ - struct __pthread *wakeup; - - __pthread_spin_lock (&cond->__lock); - wakeup = cond->__queue; - if (wakeup) - __pthread_dequeue (wakeup); - __pthread_spin_unlock (&cond->__lock); - - if (wakeup) - { - /* We found a thread waiting for the condition to be signalled. - Wake it up! */ - __pthread_wakeup (wakeup); - *unblocked = 1; - } - - return 0; -} - -/* Unblock at least one of the threads that are blocked on condition - variable COND. */ -int -pthread_cond_signal (pthread_cond_t *cond) -{ - int unblocked = 0; - - return cond_signal (cond, &unblocked); -} diff --git a/sysdeps/generic/pt-cond-timedwait.c b/sysdeps/generic/pt-cond-timedwait.c deleted file mode 100644 index c10bdb30..00000000 --- a/sysdeps/generic/pt-cond-timedwait.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Wait on a condition. Generic version. - Copyright (C) 2000, 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec *abstime); - -int -pthread_cond_timedwait (pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec *abstime) -{ - return __pthread_cond_timedwait_internal (cond, mutex, abstime); -} - -/* Block on condition variable COND until ABSTIME. As a GNU - extension, if ABSTIME is NULL, then wait forever. MUTEX should be - held by the calling thread. On return, MUTEX will be held by the - calling thread. */ -int -__pthread_cond_timedwait_internal (pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec *abstime) -{ - error_t err; - int canceltype; - - void cleanup (void *arg) - { - struct __pthread *self = _pthread_self (); - - __pthread_spin_lock (&cond->__lock); - if (self->prevp) - __pthread_dequeue (self); - __pthread_spin_unlock (&cond->__lock); - - pthread_setcanceltype (canceltype, &canceltype); - __pthread_mutex_lock (mutex); - } - - if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) - return EINVAL; - - struct __pthread *self = _pthread_self (); - - /* Add ourselves to the list of waiters. */ - __pthread_spin_lock (&cond->__lock); - __pthread_enqueue (&cond->__queue, self); - __pthread_spin_unlock (&cond->__lock); - - __pthread_mutex_unlock (mutex); - - /* Enter async cancelation mode. If cancelation is disabled, then - this does not change anything which is exactly what we want. */ - pthread_cleanup_push (cleanup, 0); - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &canceltype); - - if (abstime) - { - err = __pthread_timedblock (self, abstime); - if (err) - /* We timed out. We may need to disconnect ourself from the - waiter queue. - - FIXME: What do we do if we get a wakeup message before we - disconnect ourself? It may remain until the next time we - block. */ - { - assert (err == ETIMEDOUT); - - __pthread_spin_lock (&mutex->__lock); - if (self->prevp) - __pthread_dequeue (self); - __pthread_spin_unlock (&mutex->__lock); - } - } - else - { - err = 0; - __pthread_block (self); - } - - pthread_cleanup_pop (1); - - return err; -} diff --git a/sysdeps/generic/pt-cond-wait.c b/sysdeps/generic/pt-cond-wait.c deleted file mode 100644 index a03476df..00000000 --- a/sysdeps/generic/pt-cond-wait.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Wait on a condition. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* Implemented in pt-cond-timedwait.c. */ -extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec *abstime); - - -/* Block on condition variable COND. MUTEX should be held by the - calling thread. On return, MUTEX will be held by the calling - thread. */ -int -pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) -{ - return __pthread_cond_timedwait_internal (cond, mutex, 0); -} diff --git a/sysdeps/generic/pt-cond.c b/sysdeps/generic/pt-cond.c deleted file mode 100644 index 033e767f..00000000 --- a/sysdeps/generic/pt-cond.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Default condition attributes. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -const struct __pthread_condattr __pthread_default_condattr = -{ - pshared: PTHREAD_PROCESS_PRIVATE, - clock: CLOCK_REALTIME -}; diff --git a/sysdeps/generic/pt-condattr-destroy.c b/sysdeps/generic/pt-condattr-destroy.c deleted file mode 100644 index c8fd71b9..00000000 --- a/sysdeps/generic/pt-condattr-destroy.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_condattr_destroy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_condattr_destroy (pthread_condattr_t *cond) -{ - return 0; -} diff --git a/sysdeps/generic/pt-condattr-getclock.c b/sysdeps/generic/pt-condattr-getclock.c deleted file mode 100644 index 5b9f8893..00000000 --- a/sysdeps/generic/pt-condattr-getclock.c +++ /dev/null @@ -1,31 +0,0 @@ -/* pthread_condattr_getclock. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_condattr_getclock (const pthread_condattr_t *attr, - clockid_t *clock) -{ - *clock = attr->clock; - return 0; -} diff --git a/sysdeps/generic/pt-condattr-getpshared.c b/sysdeps/generic/pt-condattr-getpshared.c deleted file mode 100644 index c072a507..00000000 --- a/sysdeps/generic/pt-condattr-getpshared.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_condattr_getpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_condattr_getpshared (const pthread_condattr_t *attr, - int *pshared) -{ - *pshared = attr->pshared; - return 0; -} diff --git a/sysdeps/generic/pt-condattr-init.c b/sysdeps/generic/pt-condattr-init.c deleted file mode 100644 index cf9e1989..00000000 --- a/sysdeps/generic/pt-condattr-init.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_condattr_init. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_condattr_init (pthread_condattr_t *attr) -{ - *attr = __pthread_default_condattr; - return 0; -} diff --git a/sysdeps/generic/pt-condattr-setclock.c b/sysdeps/generic/pt-condattr-setclock.c deleted file mode 100644 index 984c17e2..00000000 --- a/sysdeps/generic/pt-condattr-setclock.c +++ /dev/null @@ -1,33 +0,0 @@ -/* pthread_condattr_setclock. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock) -{ - if (__pthread_default_condattr.clock == clock) - { - attr->clock = clock; - return 0; - } - - return EINVAL; -} diff --git a/sysdeps/generic/pt-condattr-setpshared.c b/sysdeps/generic/pt-condattr-setpshared.c deleted file mode 100644 index b9f0af83..00000000 --- a/sysdeps/generic/pt-condattr-setpshared.c +++ /dev/null @@ -1,39 +0,0 @@ -/* pthread_condattr_setpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_condattr_setpshared (pthread_condattr_t *attr, - int pshared) -{ - switch (pshared) - { - case PTHREAD_PROCESS_PRIVATE: - attr->pshared = pshared; - return 0; - - case PTHREAD_PROCESS_SHARED: - return ENOTSUP; - - default: - return EINVAL; - } -} diff --git a/sysdeps/generic/pt-destroy-specific.c b/sysdeps/generic/pt-destroy-specific.c deleted file mode 100644 index b627f872..00000000 --- a/sysdeps/generic/pt-destroy-specific.c +++ /dev/null @@ -1,28 +0,0 @@ -/* __pthread_destory_specific. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -void -__pthread_destory_specifc (struct __pthread *thread) -{ - /* Not support, thus there cannot be any. */ - return; -} diff --git a/sysdeps/generic/pt-equal.c b/sysdeps/generic/pt-equal.c deleted file mode 100644 index 8fbc519c..00000000 --- a/sysdeps/generic/pt-equal.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Default attributes. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -/* Return true if __T1 and __T2 both name the same thread. Otherwise, - false. */ -int -pthread_equal (pthread_t __t1, pthread_t __t2) -{ - return __t1 == __t2; -} diff --git a/sysdeps/generic/pt-getconcurrency.c b/sysdeps/generic/pt-getconcurrency.c deleted file mode 100644 index b55c8eef..00000000 --- a/sysdeps/generic/pt-getconcurrency.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Get the current level of desired concurrency. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_getconcurrency (void) -{ - return __pthread_concurrency; -} diff --git a/sysdeps/generic/pt-getcpuclockid.c b/sysdeps/generic/pt-getcpuclockid.c deleted file mode 100644 index 81f6aabd..00000000 --- a/sysdeps/generic/pt-getcpuclockid.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Return a thread's cpu clockid. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_getcpuclockid (pthread_t thread, clockid_t *clock) -{ -#ifdef CLOCK_THREAD_CPUTIME_ID - *clock = CLOCK_THREAD_CPUTIME_ID; - return 0; -#else - return ENOSYS; -#endif -} diff --git a/sysdeps/generic/pt-getschedparam.c b/sysdeps/generic/pt-getschedparam.c deleted file mode 100644 index c128d02e..00000000 --- a/sysdeps/generic/pt-getschedparam.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Get the scheduling parameters for a thread. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_getschedparam (pthread_t thread, int *policy, - struct sched_param *param) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-getspecific.c b/sysdeps/generic/pt-getspecific.c deleted file mode 100644 index 2a7c4a9e..00000000 --- a/sysdeps/generic/pt-getspecific.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_getspecific. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_getspecific (pthread_key_t key) -{ - return EINVAL; -} diff --git a/sysdeps/generic/pt-init-specific.c b/sysdeps/generic/pt-init-specific.c deleted file mode 100644 index 00744fb6..00000000 --- a/sysdeps/generic/pt-init-specific.c +++ /dev/null @@ -1,27 +0,0 @@ -/* __pthread_init_specific. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -error_t -__pthread_init_specific (struct __pthread *thread) -{ - return 0; -} diff --git a/sysdeps/generic/pt-key-create.c b/sysdeps/generic/pt-key-create.c deleted file mode 100644 index 7ef4b991..00000000 --- a/sysdeps/generic/pt-key-create.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_key_create. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-key-delete.c b/sysdeps/generic/pt-key-delete.c deleted file mode 100644 index 6c86f8e2..00000000 --- a/sysdeps/generic/pt-key-delete.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_key_delete. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_key_delete (pthread_key_t key) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-key.h b/sysdeps/generic/pt-key.h deleted file mode 100644 index 544eb20f..00000000 --- a/sysdeps/generic/pt-key.h +++ /dev/null @@ -1,22 +0,0 @@ -/* pthread_key internal declatations. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#define PTHREAD_KEY_MEMBERS diff --git a/sysdeps/generic/pt-kill.c b/sysdeps/generic/pt-kill.c deleted file mode 100644 index 0dfac344..00000000 --- a/sysdeps/generic/pt-kill.c +++ /dev/null @@ -1,32 +0,0 @@ -/* pthread-kill.c - Generic pthread-kill implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -pthread_kill (pthread_t tid, int signo) -{ - siginfo_t si; - memset (&si, 0, sizeof (si)); - si.si_signo = signo; - - return pthread_kill_siginfo_np (tid, si); -} - diff --git a/sysdeps/generic/pt-mutex-destroy.c b/sysdeps/generic/pt-mutex-destroy.c deleted file mode 100644 index b0ca00f7..00000000 --- a/sysdeps/generic/pt-mutex-destroy.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Destroy a mutex. Generic version. - Copyright (C) 2000, 2002, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -_pthread_mutex_destroy (pthread_mutex_t *mutex) -{ - if (mutex->attr == &__pthread_recursive_mutexattr) - /* Static attributes. */ - ; - else - free (mutex->attr); - - return 0; -} - -strong_alias (_pthread_mutex_destroy, pthread_mutex_destroy); diff --git a/sysdeps/generic/pt-mutex-getprioceiling.c b/sysdeps/generic/pt-mutex-getprioceiling.c deleted file mode 100644 index eb51639b..00000000 --- a/sysdeps/generic/pt-mutex-getprioceiling.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Get a mutex' priority ceiling. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, - int *prioceiling) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-mutex-init.c b/sysdeps/generic/pt-mutex-init.c deleted file mode 100644 index a818fe3a..00000000 --- a/sysdeps/generic/pt-mutex-init.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Initialize a mutex. Generic version. - Copyright (C) 2000, 2002, 2005, 2006, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -int -_pthread_mutex_init (pthread_mutex_t *mutex, - const pthread_mutexattr_t *attr) -{ - *mutex = (pthread_mutex_t) __PTHREAD_MUTEX_INITIALIZER; - - if (! attr - || memcmp (attr, &__pthread_default_mutexattr, sizeof (*attr) == 0)) - /* The default attributes. */ - return 0; - - if (attr == &__pthread_recursive_mutexattr) - /* Non-default but known attributes. */ - { - mutex->attr = attr; - return 0; - } - - mutex->attr = malloc (sizeof *attr); - if (! mutex->attr) - return ENOMEM; - - *mutex->attr = *attr; - return 0; -} - -strong_alias (_pthread_mutex_init, pthread_mutex_init); diff --git a/sysdeps/generic/pt-mutex-lock.c b/sysdeps/generic/pt-mutex-lock.c deleted file mode 100644 index 528e593f..00000000 --- a/sysdeps/generic/pt-mutex-lock.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Lock a mutex. Generic version. - Copyright (C) 2000, 2002, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -/* Implemented in pt-mutex-timedlock.c. */ -extern int __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, - const struct timespec *abstime); - -/* Lock MUTEX, block if we can't get it. */ -int -__pthread_mutex_lock (struct __pthread_mutex *mutex) -{ - return __pthread_mutex_timedlock_internal (mutex, 0); -} - -strong_alias (__pthread_mutex_lock, _pthread_mutex_lock); -strong_alias (__pthread_mutex_lock, pthread_mutex_lock); diff --git a/sysdeps/generic/pt-mutex-setprioceiling.c b/sysdeps/generic/pt-mutex-setprioceiling.c deleted file mode 100644 index 9fa8e50d..00000000 --- a/sysdeps/generic/pt-mutex-setprioceiling.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Set a mutex' priority ceiling. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prio, - int *oldprio) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c deleted file mode 100644 index ee432192..00000000 --- a/sysdeps/generic/pt-mutex-timedlock.c +++ /dev/null @@ -1,181 +0,0 @@ -/* Lock a mutex with a timeout. Generic version. - Copyright (C) 2000, 2002, 2005, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -#define LOSE do { * (int *) 0 = 0; } while (1) - -/* Try to lock MUTEX, block until *ABSTIME if it is already held. As - a GNU extension, if TIMESPEC is NULL then wait forever. */ -int -__pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex, - const struct timespec *abstime) -{ - struct __pthread *self; - - __pthread_spin_lock (&mutex->__lock); - if (__pthread_spin_trylock (&mutex->__held) == 0) - /* Successfully acquired the lock. */ - { -#ifdef ALWAYS_TRACK_MUTEX_OWNER -#ifndef NDEBUG - self = _pthread_self (); - if (self) - /* The main thread may take a lock before the library is fully - initialized, in particular, before the main thread has a - TCB. */ - { - assert (! mutex->owner); - mutex->owner = _pthread_self (); - } -#endif -#endif - - if (mutex->attr) - switch (mutex->attr->mutex_type) - { - case PTHREAD_MUTEX_NORMAL: - break; - - case PTHREAD_MUTEX_RECURSIVE: - mutex->locks = 1; - case PTHREAD_MUTEX_ERRORCHECK: - mutex->owner = _pthread_self (); - break; - - default: - LOSE; - } - - __pthread_spin_unlock (&mutex->__lock); - return 0; - } - - /* The lock is busy. */ - - self = _pthread_self (); - assert (self); - - if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) - { -#if defined(ALWAYS_TRACK_MUTEX_OWNER) - assert (mutex->owner != self); -#endif - } - else - { - switch (mutex->attr->mutex_type) - { - case PTHREAD_MUTEX_ERRORCHECK: - if (mutex->owner == self) - { - __pthread_spin_unlock (&mutex->__lock); - return EDEADLK; - } - break; - - case PTHREAD_MUTEX_RECURSIVE: - if (mutex->owner == self) - { - mutex->locks ++; - __pthread_spin_unlock (&mutex->__lock); - return 0; - } - break; - - default: - LOSE; - } - } - -#if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) -#endif - assert (mutex->owner); - - if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) - return EINVAL; - - /* Add ourselves to the queue. */ - __pthread_enqueue (&mutex->__queue, self); - __pthread_spin_unlock (&mutex->__lock); - - /* Block the thread. */ - if (abstime) - { - error_t err; - - err = __pthread_timedblock (self, abstime); - if (err) - /* We timed out. We may need to disconnect ourself from the - waiter queue. - - FIXME: What do we do if we get a wakeup message before we - disconnect ourself? It may remain until the next time we - block. */ - { - assert (err == ETIMEDOUT); - - __pthread_spin_lock (&mutex->__lock); - if (self->prevp) - __pthread_dequeue (self); - __pthread_spin_unlock (&mutex->__lock); - - return err; - } - } - else - __pthread_block (self); - -#if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) -#endif - { - assert (mutex->owner == self); - } - - if (mutex->attr) - switch (mutex->attr->mutex_type) - { - case PTHREAD_MUTEX_NORMAL: - break; - - case PTHREAD_MUTEX_RECURSIVE: - assert (mutex->locks == 0); - mutex->locks = 1; - case PTHREAD_MUTEX_ERRORCHECK: - mutex->owner = self; - break; - - default: - LOSE; - } - - return 0; -} - -int -pthread_mutex_timedlock (struct __pthread_mutex *mutex, - const struct timespec *abstime) -{ - return __pthread_mutex_timedlock_internal (mutex, abstime); -} diff --git a/sysdeps/generic/pt-mutex-transfer-np.c b/sysdeps/generic/pt-mutex-transfer-np.c deleted file mode 100644 index 7796ac4f..00000000 --- a/sysdeps/generic/pt-mutex-transfer-np.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Transfer ownership of a mutex. Generic version. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include -#include - -#include - -int -__pthread_mutex_transfer_np (struct __pthread_mutex *mutex, pthread_t tid) -{ - assert (mutex->owner == _pthread_self ()); - - struct __pthread *thread = __pthread_getid (tid); - if (! thread) - return ESRCH; - - if (thread == _pthread_self ()) - return 0; - - if (mutex->attr && mutex->attr->mutex_type == PTHREAD_MUTEX_ERRORCHECK) - { - - if (mutex->owner != _pthread_self ()) - return EPERM; - - mutex->owner = thread; - } - -#ifndef NDEBUG -# if !defined(ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) -# endif - { - mutex->owner = thread; - } -#endif - - return 0; -} - -strong_alias (__pthread_mutex_transfer_np, pthread_mutex_transfer_np) diff --git a/sysdeps/generic/pt-mutex-trylock.c b/sysdeps/generic/pt-mutex-trylock.c deleted file mode 100644 index 5264dc7b..00000000 --- a/sysdeps/generic/pt-mutex-trylock.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Try to Lock a mutex. Generic version. - Copyright (C) 2002, 2005, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -#define LOSE do { * (int *) 0 = 0; } while (1) - -/* Lock MUTEX, return EBUSY if we can't get it. */ -int -__pthread_mutex_trylock (struct __pthread_mutex *mutex) -{ - int err; - struct __pthread *self; - - __pthread_spin_lock (&mutex->__lock); - if (__pthread_spin_trylock (&mutex->__held) == 0) - /* Acquired the lock. */ - { -#ifndef NDEBUG - self = _pthread_self (); - if (self) - /* The main thread may take a lock before the library is fully - initialized, in particular, before the main thread has a - TCB. */ - { - assert (! mutex->owner); - mutex->owner = _pthread_self (); - } -#endif - - if (mutex->attr) - switch (mutex->attr->mutex_type) - { - case PTHREAD_MUTEX_NORMAL: - break; - - case PTHREAD_MUTEX_RECURSIVE: - mutex->locks = 1; - case PTHREAD_MUTEX_ERRORCHECK: - mutex->owner = _pthread_self (); - break; - - default: - LOSE; - } - - __pthread_spin_unlock (&mutex->__lock); - return 0; - } - - err = EBUSY; - - if (mutex->attr) - { - self = _pthread_self (); - switch (mutex->attr->mutex_type) - { - case PTHREAD_MUTEX_NORMAL: - break; - - case PTHREAD_MUTEX_ERRORCHECK: - /* We could check if MUTEX->OWNER is SELF, however, POSIX - does not permit pthread_mutex_trylock to return EDEADLK - instead of EBUSY, only pthread_mutex_lock. */ - break; - - case PTHREAD_MUTEX_RECURSIVE: - if (mutex->owner == self) - { - mutex->locks ++; - err = 0; - } - break; - - default: - LOSE; - } - } - - __pthread_spin_unlock (&mutex->__lock); - - return err; -} - -strong_alias (__pthread_mutex_trylock, _pthread_mutex_trylock); -strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock); diff --git a/sysdeps/generic/pt-mutex-unlock.c b/sysdeps/generic/pt-mutex-unlock.c deleted file mode 100644 index 7645fd4c..00000000 --- a/sysdeps/generic/pt-mutex-unlock.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Unlock a mutex. Generic version. - Copyright (C) 2000, 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -#define LOSE do { * (int *) 0 = 0; } while (1) - -/* Unlock MUTEX, rescheduling a waiting thread. */ -int -__pthread_mutex_unlock (pthread_mutex_t *mutex) -{ - struct __pthread *wakeup; - - __pthread_spin_lock (&mutex->__lock); - - if (! mutex->attr || mutex->attr->mutex_type == PTHREAD_MUTEX_NORMAL) - { -#if defined(ALWAYS_TRACK_MUTEX_OWNER) -# ifndef NDEBUG - if (_pthread_self ()) - { - assert (mutex->owner); - assert (mutex->owner == _pthread_self ()); - mutex->owner = NULL; - } -# endif -#endif - } - else - switch (mutex->attr->mutex_type) - { - case PTHREAD_MUTEX_ERRORCHECK: - case PTHREAD_MUTEX_RECURSIVE: - if (mutex->owner != _pthread_self ()) - { - __pthread_spin_unlock (&mutex->__lock); - return EPERM; - } - - if (mutex->attr->mutex_type == PTHREAD_MUTEX_RECURSIVE) - if (--mutex->locks > 0) - { - __pthread_spin_unlock (&mutex->__lock); - return 0; - } - - mutex->owner = 0; - break; - - default: - LOSE; - } - - - if (mutex->__queue == NULL) - { - __pthread_spin_unlock (&mutex->__held); - __pthread_spin_unlock (&mutex->__lock); - return 0; - } - - wakeup = mutex->__queue; - __pthread_dequeue (wakeup); - -#ifndef NDEBUG -# if !defined (ALWAYS_TRACK_MUTEX_OWNER) - if (mutex->attr && mutex->attr->mutex_type != PTHREAD_MUTEX_NORMAL) -# endif - { - mutex->owner = wakeup; - } -#endif - - /* We do not unlock MUTEX->held: we are transferring the ownership - to the thread that we are waking up. */ - - __pthread_spin_unlock (&mutex->__lock); - __pthread_wakeup (wakeup); - - return 0; -} - -strong_alias (__pthread_mutex_unlock, _pthread_mutex_unlock); -strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock); diff --git a/sysdeps/generic/pt-mutexattr-destroy.c b/sysdeps/generic/pt-mutexattr-destroy.c deleted file mode 100644 index fe7e95d2..00000000 --- a/sysdeps/generic/pt-mutexattr-destroy.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_mutexattr_destroy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_destroy (pthread_mutexattr_t *attr) -{ - return 0; -} diff --git a/sysdeps/generic/pt-mutexattr-getprioceiling.c b/sysdeps/generic/pt-mutexattr-getprioceiling.c deleted file mode 100644 index d03d7192..00000000 --- a/sysdeps/generic/pt-mutexattr-getprioceiling.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_mutexattr_getprioceiling. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr, - int *prioceiling) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-mutexattr-getprotocol.c b/sysdeps/generic/pt-mutexattr-getprotocol.c deleted file mode 100644 index d75021a3..00000000 --- a/sysdeps/generic/pt-mutexattr-getprotocol.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_mutexattr_getprotocol. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr, - int *protocol) -{ - *protocol = attr->protocol; - return 0; -} diff --git a/sysdeps/generic/pt-mutexattr-getpshared.c b/sysdeps/generic/pt-mutexattr-getpshared.c deleted file mode 100644 index 0dad13b8..00000000 --- a/sysdeps/generic/pt-mutexattr-getpshared.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_mutexattr_getpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr, - int *pshared) -{ - *pshared = attr->pshared; - return 0; -} diff --git a/sysdeps/generic/pt-mutexattr-gettype.c b/sysdeps/generic/pt-mutexattr-gettype.c deleted file mode 100644 index ff2caea4..00000000 --- a/sysdeps/generic/pt-mutexattr-gettype.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_mutexattr_gettype. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type) -{ - *type = attr->mutex_type; - return 0; -} diff --git a/sysdeps/generic/pt-mutexattr-init.c b/sysdeps/generic/pt-mutexattr-init.c deleted file mode 100644 index 2f23673c..00000000 --- a/sysdeps/generic/pt-mutexattr-init.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_mutexattr_init. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_init (pthread_mutexattr_t *attr) -{ - *attr = __pthread_default_mutexattr; - return 0; -} diff --git a/sysdeps/generic/pt-mutexattr-setprioceiling.c b/sysdeps/generic/pt-mutexattr-setprioceiling.c deleted file mode 100644 index a9bbd327..00000000 --- a/sysdeps/generic/pt-mutexattr-setprioceiling.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_mutexattr_setprioceiling. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr, - int prioceiling) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-mutexattr-setprotocol.c b/sysdeps/generic/pt-mutexattr-setprotocol.c deleted file mode 100644 index 9a0d1b1f..00000000 --- a/sysdeps/generic/pt-mutexattr-setprotocol.c +++ /dev/null @@ -1,42 +0,0 @@ -/* pthread_mutexattr_setprotocol. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, - int protocol) -{ - if (protocol == __pthread_default_mutexattr.protocol) - { - attr->protocol = protocol; - return 0; - } - - switch (protocol) - { - case PTHREAD_PRIO_NONE: - case PTHREAD_PRIO_INHERIT: - case PTHREAD_PRIO_PROTECT: - return ENOTSUP; - default: - return EINVAL; - } -} diff --git a/sysdeps/generic/pt-mutexattr-setpshared.c b/sysdeps/generic/pt-mutexattr-setpshared.c deleted file mode 100644 index bcbc4d91..00000000 --- a/sysdeps/generic/pt-mutexattr-setpshared.c +++ /dev/null @@ -1,39 +0,0 @@ -/* pthread_mutexattr_setpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, - int pshared) -{ - switch (pshared) - { - case PTHREAD_PROCESS_PRIVATE: - attr->pshared = pshared; - return 0; - - case PTHREAD_PROCESS_SHARED: - return ENOTSUP; - - default: - return EINVAL; - } -} diff --git a/sysdeps/generic/pt-mutexattr-settype.c b/sysdeps/generic/pt-mutexattr-settype.c deleted file mode 100644 index e7ae213a..00000000 --- a/sysdeps/generic/pt-mutexattr-settype.c +++ /dev/null @@ -1,37 +0,0 @@ -/* pthread_mutexattr_settype. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type) -{ - switch (type) - { - case PTHREAD_MUTEX_NORMAL: - case PTHREAD_MUTEX_ERRORCHECK: - case PTHREAD_MUTEX_RECURSIVE: - attr->mutex_type = type; - return 0; - - default: - return EINVAL; - } -} diff --git a/sysdeps/generic/pt-mutexattr.c b/sysdeps/generic/pt-mutexattr.c deleted file mode 100644 index d80a7d74..00000000 --- a/sysdeps/generic/pt-mutexattr.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Default mutex attributes. Generic version. - Copyright (C) 2000, 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -const struct __pthread_mutexattr __pthread_default_mutexattr = -{ - prioceiling: 0, - protocol: PTHREAD_PRIO_NONE, - pshared: PTHREAD_PROCESS_PRIVATE, - mutex_type: PTHREAD_MUTEX_DEFAULT -}; - -const struct __pthread_mutexattr __pthread_recursive_mutexattr = -{ - prioceiling: 0, - protocol: PTHREAD_PRIO_NONE, - pshared: PTHREAD_PROCESS_PRIVATE, - mutex_type: PTHREAD_MUTEX_RECURSIVE -}; diff --git a/sysdeps/generic/pt-once.c b/sysdeps/generic/pt-once.c deleted file mode 100644 index 5be5e484..00000000 --- a/sysdeps/generic/pt-once.c +++ /dev/null @@ -1,43 +0,0 @@ -/* pthread_once. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) -{ - if (once_control->run == 0) - { - __pthread_spin_lock (&once_control->lock); - - if (once_control->run == 0) - { - init_routine (); - __memory_barrier (); - once_control->run = 1; - } - - __pthread_spin_unlock (&once_control->lock); - } - - return 0; -} diff --git a/sysdeps/generic/pt-rwlock-attr.c b/sysdeps/generic/pt-rwlock-attr.c deleted file mode 100644 index 1587feef..00000000 --- a/sysdeps/generic/pt-rwlock-attr.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Default rwlock attributes. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -const struct __pthread_rwlockattr __pthread_default_rwlockattr = -{ - pshared: PTHREAD_PROCESS_PRIVATE -}; diff --git a/sysdeps/generic/pt-rwlock-destroy.c b/sysdeps/generic/pt-rwlock-destroy.c deleted file mode 100644 index 045eebd8..00000000 --- a/sysdeps/generic/pt-rwlock-destroy.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Destroy a rwlock. Generic version. - Copyright (C) 2002, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) -{ - return 0; -} - -strong_alias (_pthread_rwlock_destroy, pthread_rwlock_destroy); diff --git a/sysdeps/generic/pt-rwlock-init.c b/sysdeps/generic/pt-rwlock-init.c deleted file mode 100644 index c9ff9b28..00000000 --- a/sysdeps/generic/pt-rwlock-init.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Initialize a rwlock. Generic version. - Copyright (C) 2002, 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -int -_pthread_rwlock_init (pthread_rwlock_t *rwlock, - const pthread_rwlockattr_t *attr) -{ - *rwlock = (pthread_rwlock_t) __PTHREAD_RWLOCK_INITIALIZER; - - if (! attr - || memcmp (attr, &__pthread_default_rwlockattr, sizeof (*attr) == 0)) - /* Use the default attributes. */ - return 0; - - /* Non-default attributes. */ - - rwlock->__attr = malloc (sizeof *attr); - if (! rwlock->__attr) - return ENOMEM; - - *rwlock->__attr = *attr; - return 0; -} - -strong_alias (_pthread_rwlock_init, pthread_rwlock_init); diff --git a/sysdeps/generic/pt-rwlock-rdlock.c b/sysdeps/generic/pt-rwlock-rdlock.c deleted file mode 100644 index 480cf489..00000000 --- a/sysdeps/generic/pt-rwlock-rdlock.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Acquire a rwlock for reading. Generic version. - Copyright (C) 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -/* Implemented in pt-rwlock-timedrdlock.c. */ -extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, - const struct timespec *abstime); - -/* Acquire RWLOCK for reading, block if we can't get it. */ -int -pthread_rwlock_rdlock (struct __pthread_rwlock *rwlock) -{ - return __pthread_rwlock_timedrdlock_internal (rwlock, 0); -} diff --git a/sysdeps/generic/pt-rwlock-timedrdlock.c b/sysdeps/generic/pt-rwlock-timedrdlock.c deleted file mode 100644 index ba610fa5..00000000 --- a/sysdeps/generic/pt-rwlock-timedrdlock.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Acquire a rwlock for reading. Generic version. - Copyright (C) 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -/* Acquire the rwlock *RWLOCK for reading blocking until *ABSTIME if - it is already held. As a GNU extension, if TIMESPEC is NULL then - wait forever. */ -int -__pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, - const struct timespec *abstime) -{ - struct __pthread *self; - - __pthread_spin_lock (&rwlock->__lock); - if (__pthread_spin_trylock (&rwlock->__held) == 0) - /* Successfully acquired the lock. */ - { - assert (rwlock->readerqueue == 0); - assert (rwlock->writerqueue == 0); - assert (rwlock->readers == 0); - - rwlock->readers = 1; - __pthread_spin_unlock (&rwlock->__lock); - return 0; - } - else - /* Lock is held, but is held by a reader? */ - if (rwlock->readers > 0) - /* Just add ourself to number of readers. */ - { - assert (rwlock->readerqueue == 0); - rwlock->readers ++; - __pthread_spin_unlock (&rwlock->__lock); - return 0; - } - - /* The lock is busy. */ - - /* Better be blocked by a writer. */ - assert (rwlock->readers == 0); - - if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) - return EINVAL; - - self = _pthread_self (); - - /* Add ourself to the queue. */ - __pthread_enqueue (&rwlock->readerqueue, self); - __pthread_spin_unlock (&rwlock->__lock); - - /* Block the thread. */ - if (abstime) - { - error_t err; - - err = __pthread_timedblock (self, abstime); - if (err) - /* We timed out. We may need to disconnect ourself from the - waiter queue. - - FIXME: What do we do if we get a wakeup message before we - disconnect ourself? It may remain until the next time we - block. */ - { - assert (err == ETIMEDOUT); - - __pthread_spin_lock (&rwlock->__lock); - if (self->prevp) - /* Disconnect ourself. */ - __pthread_dequeue (self); - __pthread_spin_unlock (&rwlock->__lock); - - return err; - } - } - else - __pthread_block (self); - - - /* The reader count has already been increment by whoever woke us - up. */ - - assert (rwlock->readers > 0); - - return 0; -} - -int -pthread_rwlock_timedrdlock (struct __pthread_rwlock *rwlock, - const struct timespec *abstime) -{ - return __pthread_rwlock_timedrdlock_internal (rwlock, abstime); -} diff --git a/sysdeps/generic/pt-rwlock-timedwrlock.c b/sysdeps/generic/pt-rwlock-timedwrlock.c deleted file mode 100644 index 04eab51f..00000000 --- a/sysdeps/generic/pt-rwlock-timedwrlock.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Acquire a rwlock for writing. Generic version. - Copyright (C) 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -/* Acquire RWLOCK for writing blocking until *ABSTIME if we cannot get - it. As a special GNU extension, if ABSTIME is NULL then the wait - shall not time out. */ -int -__pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, - const struct timespec *abstime) -{ - struct __pthread *self; - - __pthread_spin_lock (&rwlock->__lock); - if (__pthread_spin_trylock (&rwlock->__held) == 0) - /* Successfully acquired the lock. */ - { - assert (rwlock->readerqueue == 0); - assert (rwlock->writerqueue == 0); - assert (rwlock->readers == 0); - - __pthread_spin_unlock (&rwlock->__lock); - return 0; - } - - /* The lock is busy. */ - - if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) - return EINVAL; - - self = _pthread_self (); - - /* Add ourselves to the queue. */ - __pthread_enqueue (&rwlock->writerqueue, self); - __pthread_spin_unlock (&rwlock->__lock); - - /* Block the thread. */ - if (abstime) - { - error_t err; - - err = __pthread_timedblock (self, abstime); - if (err) - /* We timed out. We may need to disconnect ourself from the - waiter queue. - - FIXME: What do we do if we get a wakeup message before we - disconnect ourself? It may remain until the next time we - block. */ - { - assert (err == ETIMEDOUT); - - __pthread_spin_lock (&rwlock->__lock); - if (self->prevp) - /* Disconnect ourself. */ - __pthread_dequeue (self); - __pthread_spin_unlock (&rwlock->__lock); - - return err; - } - } - else - __pthread_block (self); - - assert (rwlock->readers == 0); - - return 0; -} - -int -pthread_rwlock_timedwrlock (struct __pthread_rwlock *rwlock, - const struct timespec *abstime) -{ - return __pthread_rwlock_timedwrlock_internal (rwlock, abstime); -} diff --git a/sysdeps/generic/pt-rwlock-tryrdlock.c b/sysdeps/generic/pt-rwlock-tryrdlock.c deleted file mode 100644 index 2419efb1..00000000 --- a/sysdeps/generic/pt-rwlock-tryrdlock.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Try to acquire a rwlock for reading. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -/* Try to acquire RWLOCK. */ -int -pthread_rwlock_tryrdlock (struct __pthread_rwlock *rwlock) -{ - __pthread_spin_lock (&rwlock->__lock); - if (__pthread_spin_trylock (&rwlock->__held) == 0) - /* Successfully acquired the lock. */ - { - assert (rwlock->readerqueue == 0); - assert (rwlock->writerqueue == 0); - assert (rwlock->readers == 0); - - rwlock->readers = 1; - __pthread_spin_unlock (&rwlock->__lock); - return 0; - } - else - /* Lock is held, but is held by a reader? */ - if (rwlock->readers > 0) - { - assert (rwlock->readerqueue == 0); - rwlock->readers ++; - __pthread_spin_unlock (&rwlock->__lock); - return 0; - } - - /* The lock is busy. */ - - __pthread_spin_unlock (&rwlock->__lock); - - return EBUSY; -} diff --git a/sysdeps/generic/pt-rwlock-trywrlock.c b/sysdeps/generic/pt-rwlock-trywrlock.c deleted file mode 100644 index 6b9c5b56..00000000 --- a/sysdeps/generic/pt-rwlock-trywrlock.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Try to acquire a rwlock for writing. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -/* Try to acquire RWLOCK for writing. */ -int -pthread_rwlock_trywrlock (struct __pthread_rwlock *rwlock) -{ - __pthread_spin_lock (&rwlock->__lock); - if (__pthread_spin_trylock (&rwlock->__held) == 0) - /* Successfully acquired the lock. */ - { - assert (rwlock->readerqueue == 0); - assert (rwlock->writerqueue == 0); - assert (rwlock->readers == 0); - - __pthread_spin_unlock (&rwlock->__lock); - return 0; - } - - /* The lock is busy. */ - - __pthread_spin_unlock (&rwlock->__lock); - - return EBUSY; -} diff --git a/sysdeps/generic/pt-rwlock-unlock.c b/sysdeps/generic/pt-rwlock-unlock.c deleted file mode 100644 index fb23a0b9..00000000 --- a/sysdeps/generic/pt-rwlock-unlock.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Unlock a rwlock. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* Unlock *RWLOCK, rescheduling a waiting writer thread or, if there - are no threads waiting for a write lock, rescheduling the reader - threads. */ -int -pthread_rwlock_unlock (pthread_rwlock_t *rwlock) -{ - struct __pthread *wakeup; - - __pthread_spin_lock (&rwlock->__lock); - - assert (__pthread_spin_trylock (&rwlock->__held) == EBUSY); - - if (rwlock->readers > 1) - /* There are other readers. */ - { - rwlock->readers --; - __pthread_spin_unlock (&rwlock->__lock); - return 0; - } - - if (rwlock->readers == 1) - /* Last reader. */ - rwlock->readers = 0; - - - /* Wake someone else up. Try the writer queue first, then the - reader queue if that is empty. */ - - if (rwlock->writerqueue) - { - wakeup = rwlock->writerqueue; - __pthread_dequeue (wakeup); - - /* We do not unlock RWLOCK->held: we are transferring the ownership - to the thread that we are waking up. */ - - __pthread_spin_unlock (&rwlock->__lock); - __pthread_wakeup (wakeup); - - return 0; - } - - if (rwlock->readerqueue) - { - __pthread_queue_iterate (rwlock->readerqueue, wakeup) - rwlock->readers ++; - - wakeup = rwlock->readerqueue; - rwlock->readerqueue = 0; - - __pthread_spin_unlock (&rwlock->__lock); - - /* We can safely walk the list of waiting threads without holding - the lock since it is now decoupled from the rwlock. */ - __pthread_dequeuing_iterate (wakeup, wakeup) - __pthread_wakeup (wakeup); - - return 0; - } - - - /* Noone is waiting. Just unlock it. */ - - __pthread_spin_unlock (&rwlock->__held); - __pthread_spin_unlock (&rwlock->__lock); - return 0; -} diff --git a/sysdeps/generic/pt-rwlock-wrlock.c b/sysdeps/generic/pt-rwlock-wrlock.c deleted file mode 100644 index be85b906..00000000 --- a/sysdeps/generic/pt-rwlock-wrlock.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Acquire a rwlock for writing. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -/* Implemented in pt-rwlock-timedwrlock.c. */ -extern int __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, - const struct timespec *abstime); - -/* Acquire RWLOCK for writing. */ -int -pthread_rwlock_wrlock (struct __pthread_rwlock *rwlock) -{ - return __pthread_rwlock_timedwrlock_internal (rwlock, 0); -} diff --git a/sysdeps/generic/pt-rwlockattr-destroy.c b/sysdeps/generic/pt-rwlockattr-destroy.c deleted file mode 100644 index eabfcbe8..00000000 --- a/sysdeps/generic/pt-rwlockattr-destroy.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_rwlockattr_destroy. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) -{ - return 0; -} diff --git a/sysdeps/generic/pt-rwlockattr-getpshared.c b/sysdeps/generic/pt-rwlockattr-getpshared.c deleted file mode 100644 index e8752c0c..00000000 --- a/sysdeps/generic/pt-rwlockattr-getpshared.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pthread_rwlockattr_getpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, - int *pshared) -{ - *pshared = attr->pshared; - return 0; -} diff --git a/sysdeps/generic/pt-rwlockattr-init.c b/sysdeps/generic/pt-rwlockattr-init.c deleted file mode 100644 index 34da6bf0..00000000 --- a/sysdeps/generic/pt-rwlockattr-init.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_rwlockattr_init. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_rwlockattr_init (pthread_rwlockattr_t *attr) -{ - *attr = __pthread_default_rwlockattr; - return 0; -} diff --git a/sysdeps/generic/pt-rwlockattr-setpshared.c b/sysdeps/generic/pt-rwlockattr-setpshared.c deleted file mode 100644 index a861d034..00000000 --- a/sysdeps/generic/pt-rwlockattr-setpshared.c +++ /dev/null @@ -1,39 +0,0 @@ -/* pthread_rwlockattr_setpshared. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, - int pshared) -{ - switch (pshared) - { - case PTHREAD_PROCESS_PRIVATE: - attr->pshared = pshared; - return 0; - - case PTHREAD_PROCESS_SHARED: - return ENOTSUP; - - default: - return EINVAL; - } -} diff --git a/sysdeps/generic/pt-setconcurrency.c b/sysdeps/generic/pt-setconcurrency.c deleted file mode 100644 index cd55b1ba..00000000 --- a/sysdeps/generic/pt-setconcurrency.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Set the desired level of concurrency. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int __pthread_concurrency; - -int -pthread_setconcurrency (int new_level) -{ - if (new_level < 0) - return EINVAL; - - __pthread_concurrency = new_level; - - return 0; -} diff --git a/sysdeps/generic/pt-setschedparam.c b/sysdeps/generic/pt-setschedparam.c deleted file mode 100644 index a70b0796..00000000 --- a/sysdeps/generic/pt-setschedparam.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Set the scheduling parameters for a thread. Generic version. - Copyright (C) 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_setschedparam (pthread_t thread, int policy, - const struct sched_param *param) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-setschedprio.c b/sysdeps/generic/pt-setschedprio.c deleted file mode 100644 index 60668eb1..00000000 --- a/sysdeps/generic/pt-setschedprio.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Set the scheduling priority of a thread. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_setschedprio (pthread_t thread, int prio) -{ - return ENOSYS; -} diff --git a/sysdeps/generic/pt-setspecific.c b/sysdeps/generic/pt-setspecific.c deleted file mode 100644 index d520c5df..00000000 --- a/sysdeps/generic/pt-setspecific.c +++ /dev/null @@ -1,27 +0,0 @@ -/* pthread_setspecific. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -pthread_setspecific (pthread_key_t key, const void *value) -{ - return EINVAL; -} diff --git a/sysdeps/generic/pt-startup.c b/sysdeps/generic/pt-startup.c deleted file mode 100644 index c21a1819..00000000 --- a/sysdeps/generic/pt-startup.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Thread initialization. Generic version. - Copyright (C) 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -void -__pthread_startup (void) -{ -} diff --git a/sysdeps/generic/raise.c b/sysdeps/generic/raise.c deleted file mode 100644 index 410f557d..00000000 --- a/sysdeps/generic/raise.c +++ /dev/null @@ -1,41 +0,0 @@ -/* raise.c - Generic raise implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -raise (int signo) -{ - /* According to POSIX, if we implement threads (and we do), then - "the effect of the raise() function shall be equivalent to - calling: pthread_kill(pthread_self(), sig);" */ - -debug (0, ""); - int err = pthread_kill (pthread_self (), signo); -debug (0, ""); - if (err) - { - errno = err; - return -1; - } - - return 0; -} - diff --git a/sysdeps/generic/sem-close.c b/sysdeps/generic/sem-close.c deleted file mode 100644 index 9f48032f..00000000 --- a/sysdeps/generic/sem-close.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Close a named semaphore. Generic version. - Copyright (C) 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -__sem_close (sem_t *sem) -{ - errno = EOPNOTSUPP; - return -1; -} - -strong_alias (__sem_close, sem_close); diff --git a/sysdeps/generic/sem-destroy.c b/sysdeps/generic/sem-destroy.c deleted file mode 100644 index 6486599c..00000000 --- a/sysdeps/generic/sem-destroy.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Destroy a semaphore. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -__sem_destroy (sem_t *sem) -{ - if (sem->__queue) - /* There are threads waiting on *SEM. */ - { - errno = EBUSY; - return -1; - } - - return 0; -} - -strong_alias (__sem_destroy, sem_destroy); diff --git a/sysdeps/generic/sem-getvalue.c b/sysdeps/generic/sem-getvalue.c deleted file mode 100644 index 7762089b..00000000 --- a/sysdeps/generic/sem-getvalue.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Get the value of a semaphore. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int -__sem_getvalue (sem_t *restrict sem, int *restrict value) -{ - __pthread_spin_lock (&sem->__lock); - *value = sem->__value; - __pthread_spin_unlock (&sem->__lock); - - return 0; -} - -strong_alias (__sem_getvalue, sem_getvalue); diff --git a/sysdeps/generic/sem-init.c b/sysdeps/generic/sem-init.c deleted file mode 100644 index d2414f5d..00000000 --- a/sysdeps/generic/sem-init.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Initialize a semaphore. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -__sem_init (sem_t *sem, int pshared, unsigned value) -{ - if (pshared != 0) - { - errno = EOPNOTSUPP; - return -1; - } - -#ifdef SEM_VALUE_MAX - if (value > SEM_VALUE_MAX) - { - errno = EINVAL; - return -1; - } -#endif - - *sem = (sem_t) __SEMAPHORE_INITIALIZER (pshared, value); - return 0; -} - -strong_alias (__sem_init, sem_init); diff --git a/sysdeps/generic/sem-open.c b/sysdeps/generic/sem-open.c deleted file mode 100644 index bae87ed0..00000000 --- a/sysdeps/generic/sem-open.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Open a named semaphore. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -sem_t * -__sem_open (const char *name, int open_flags, ...) -{ - errno = EOPNOTSUPP; - return SEM_FAILED; -} - -strong_alias (__sem_open, sem_open); diff --git a/sysdeps/generic/sem-post.c b/sysdeps/generic/sem-post.c deleted file mode 100644 index 6d438bf2..00000000 --- a/sysdeps/generic/sem-post.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Post a semaphore. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -__sem_post (sem_t *sem) -{ - struct __pthread *wakeup; - - __pthread_spin_lock (&sem->__lock); - if (sem->__value > 0) - /* Do a quick up. */ - { - assert (! sem->__queue); - sem->__value ++; - __pthread_spin_unlock (&sem->__lock); - return 0; - } - - if (! sem->__queue) - /* No one waiting. */ - { - sem->__value = 1; - __pthread_spin_unlock (&sem->__lock); - return 0; - } - - /* Wake someone up. */ - - /* First dequeue someone. */ - wakeup = sem->__queue; - __pthread_dequeue (wakeup); - - /* Then drop the lock and transfer control. */ - __pthread_spin_unlock (&sem->__lock); - - __pthread_wakeup (wakeup); - - return 0; -} - -strong_alias (__sem_post, sem_post); diff --git a/sysdeps/generic/sem-timedwait.c b/sysdeps/generic/sem-timedwait.c deleted file mode 100644 index e34539a9..00000000 --- a/sysdeps/generic/sem-timedwait.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Wait on a semaphore with a timeout. Generic version. - Copyright (C) 2005, 2006, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -__sem_timedwait_internal (sem_t *restrict sem, - const struct timespec *restrict timeout) -{ - struct __pthread *self; - - __pthread_spin_lock (&sem->__lock); - if (sem->__value > 0) - /* Successful down. */ - { - sem->__value --; - __pthread_spin_unlock (&sem->__lock); - return 0; - } - - if (timeout && (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000)) - { - errno = EINVAL; - return -1; - } - - /* Add ourselves to the queue. */ - self = _pthread_self (); - - __pthread_enqueue (&sem->__queue, self); - __pthread_spin_unlock (&sem->__lock); - - /* Block the thread. */ - if (timeout) - { - error_t err; - - err = __pthread_timedblock (self, timeout); - if (err) - /* We timed out. We may need to disconnect ourself from the - waiter queue. - - FIXME: What do we do if we get a wakeup message before we - disconnect ourself? It may remain until the next time we - block. */ - { - assert (err == ETIMEDOUT); - - __pthread_spin_lock (&sem->__lock); - if (self->prevp) - __pthread_dequeue (self); - __pthread_spin_unlock (&sem->__lock); - - errno = err; - return -1; - } - } - else - __pthread_block (self); - - return 0; -} - -int -__sem_timedwait (sem_t *restrict sem, - const struct timespec *restrict timeout) -{ - return __sem_timedwait_internal (sem, timeout); -} - -strong_alias (__sem_timedwait, sem_timedwait); diff --git a/sysdeps/generic/sem-trywait.c b/sysdeps/generic/sem-trywait.c deleted file mode 100644 index 437e2822..00000000 --- a/sysdeps/generic/sem-trywait.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Lock a semaphore if it does not require blocking. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -__sem_trywait (sem_t *sem) -{ - __pthread_spin_lock (&sem->__lock); - if (sem->__value > 0) - /* Successful down. */ - { - sem->__value --; - __pthread_spin_unlock (&sem->__lock); - return 0; - } - __pthread_spin_unlock (&sem->__lock); - - errno = EAGAIN; - return -1; -} - -strong_alias (__sem_trywait, sem_trywait); diff --git a/sysdeps/generic/sem-unlink.c b/sysdeps/generic/sem-unlink.c deleted file mode 100644 index 570ed614..00000000 --- a/sysdeps/generic/sem-unlink.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Unlink a named semaphore. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -__sem_unlink (const char *name) -{ - errno = EOPNOTSUPP; - return -1; -} - -strong_alias (__sem_unlink, sem_unlink); diff --git a/sysdeps/generic/sem-wait.c b/sysdeps/generic/sem-wait.c deleted file mode 100644 index 8347480c..00000000 --- a/sysdeps/generic/sem-wait.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Wait on a semaphore. Generic version. - Copyright (C) 2005, 2006 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -extern int __sem_timedwait_internal (sem_t *restrict sem, - const struct timespec *restrict timeout); - -int -__sem_wait (sem_t *sem) -{ - return __sem_timedwait_internal (sem, 0); -} - -strong_alias (__sem_wait, sem_wait); diff --git a/sysdeps/generic/sigaddset.c b/sysdeps/generic/sigaddset.c deleted file mode 100644 index 14edb71c..00000000 --- a/sysdeps/generic/sigaddset.c +++ /dev/null @@ -1,35 +0,0 @@ -/* sigaddset.c - Generic sigaddset implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -sigaddset (sigset_t *sigset, int signo) -{ - if (signo <= 0 || signo >= NSIG) - { - errno = EINVAL; - return -1; - } - - *sigset |= sigmask (signo); - return 0; -} - diff --git a/sysdeps/generic/sigdelset.c b/sysdeps/generic/sigdelset.c deleted file mode 100644 index 5456467f..00000000 --- a/sysdeps/generic/sigdelset.c +++ /dev/null @@ -1,35 +0,0 @@ -/* sigdelset.c - Generic sigdelset implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -sigdelset (sigset_t *sigset, int signo) -{ - if (signo <= 0 || signo >= NSIG) - { - errno = EINVAL; - return -1; - } - - *sigset &= ~sigmask (signo); - return 0; -} - diff --git a/sysdeps/generic/sigemptyset.c b/sysdeps/generic/sigemptyset.c deleted file mode 100644 index 690c15b6..00000000 --- a/sysdeps/generic/sigemptyset.c +++ /dev/null @@ -1,29 +0,0 @@ -/* sigemptyset.c - Generic sigemptyset implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include - -int -sigemptyset (sigset_t *sigset) -{ - *sigset = 0; - return 0; -} - diff --git a/sysdeps/generic/sigfillset.c b/sysdeps/generic/sigfillset.c deleted file mode 100644 index f0ac0781..00000000 --- a/sysdeps/generic/sigfillset.c +++ /dev/null @@ -1,29 +0,0 @@ -/* sigfillset.c - Generic sigfillset implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include - -int -sigfillset (sigset_t *sigset) -{ - *sigset = (1ULL << (NSIG - 1)) - 1; - return 0; -} - diff --git a/sysdeps/generic/siginterrupt.c b/sysdeps/generic/siginterrupt.c deleted file mode 100644 index 0899efbb..00000000 --- a/sysdeps/generic/siginterrupt.c +++ /dev/null @@ -1,36 +0,0 @@ -/* siginterrupt.c - Generic siginterrupt implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -siginterrupt (int sig, int flag) -{ - int ret; - struct sigaction act; - - sigaction (sig, NULL, &act); - if (flag) - act.sa_flags &= ~SA_RESTART; - else - act.sa_flags |= SA_RESTART; - ret = sigaction(sig, &act, NULL); - return ret; -} diff --git a/sysdeps/generic/sigismember.c b/sysdeps/generic/sigismember.c deleted file mode 100644 index b3d65c97..00000000 --- a/sysdeps/generic/sigismember.c +++ /dev/null @@ -1,36 +0,0 @@ -/* sigismember.c - Generic sigismember implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -sigismember (const sigset_t *sigset, int signo) -{ - if (signo <= 0 || signo >= NSIG) - { - errno = EINVAL; - return -1; - } - - if (*sigset & sigmask (signo)) - return 1; - else - return 0; -} diff --git a/sysdeps/generic/signal.c b/sysdeps/generic/signal.c deleted file mode 100644 index 7555d0a1..00000000 --- a/sysdeps/generic/signal.c +++ /dev/null @@ -1,44 +0,0 @@ -/* signal.c - Generic signal implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -void (*signal (int sig, void (*handler)(int)))(int) -{ - struct sigaction sa; - - sa.sa_handler = handler; - sa.sa_flags = SA_RESTART; - - if (sigemptyset (&sa.sa_mask) < 0 - || sigaddset (&sa.sa_mask, sig) < 0) - return SIG_ERR; - - struct sigaction osa; - if (sigaction (sig, &sa, &osa) < 0) - return SIG_ERR; - - return osa.sa_handler; -} - -void (*bsd_signal (int sig, void (*func)(int)))(int) -{ - return signal (sig, func); -} diff --git a/sysdeps/generic/sigwait.c b/sysdeps/generic/sigwait.c deleted file mode 100644 index 7d10bf8b..00000000 --- a/sysdeps/generic/sigwait.c +++ /dev/null @@ -1,34 +0,0 @@ -/* sigwait.c - Generic sigwait implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include "sig-internal.h" - -int -sigwait (const sigset_t *restrict set, int *restrict signo) -{ - siginfo_t info; - - if (sigwaitinfo (set, &info) < 0) - return -1; - - *signo = info.si_signo; - return 0; -} - diff --git a/sysdeps/hurd/pt-destroy-specific.c b/sysdeps/hurd/pt-destroy-specific.c deleted file mode 100644 index 23c7fbc0..00000000 --- a/sysdeps/hurd/pt-destroy-specific.c +++ /dev/null @@ -1,79 +0,0 @@ -/* __pthread_destory_specific. Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -void -__pthread_destroy_specific (struct __pthread *thread) -{ - error_t err; - int i; - int seen_one; - - /* Check if there is any thread specific data. */ - if (! thread->thread_specifics) - return; - - __pthread_key_lock_ready (); - - /* Iterate and call the destructors on any thread specific data. */ - for (;;) - { - seen_one = 0; - - __pthread_mutex_lock (&__pthread_key_lock); - - for (i = 0; i < __pthread_key_count; i ++) - { - void *value; - - if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID) - break; - - value = hurd_ihash_find (thread->thread_specifics, i); - if (value) - { - err = hurd_ihash_remove (thread->thread_specifics, i); - assert (err == 1); - - if (__pthread_key_destructors[i]) - { - seen_one = 1; - __pthread_key_destructors[i] (value); - } - } - } - - __pthread_mutex_unlock (&__pthread_key_lock); - - if (! seen_one) - break; - - /* This may take a very long time. Let those blocking on - pthread_key_create or pthread_key_delete make progress. */ - sched_yield (); - } - - hurd_ihash_free (thread->thread_specifics); - thread->thread_specifics = 0; -} diff --git a/sysdeps/hurd/pt-getspecific.c b/sysdeps/hurd/pt-getspecific.c deleted file mode 100644 index 30605984..00000000 --- a/sysdeps/hurd/pt-getspecific.c +++ /dev/null @@ -1,37 +0,0 @@ -/* pthread_getspecific. Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -void * -pthread_getspecific (pthread_key_t key) -{ - struct __pthread *self; - - assert (key < __pthread_key_count); - - self = _pthread_self (); - if (! self->thread_specifics) - return 0; - - return hurd_ihash_find (self->thread_specifics, key); -} diff --git a/sysdeps/hurd/pt-init-specific.c b/sysdeps/hurd/pt-init-specific.c deleted file mode 100644 index c1bacbcb..00000000 --- a/sysdeps/hurd/pt-init-specific.c +++ /dev/null @@ -1,30 +0,0 @@ -/* __pthread_init_specific. Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -error_t -__pthread_init_specific (struct __pthread *thread) -{ - thread->thread_specifics = 0; - return 0; -} diff --git a/sysdeps/hurd/pt-key-create.c b/sysdeps/hurd/pt-key-create.c deleted file mode 100644 index b3e01412..00000000 --- a/sysdeps/hurd/pt-key-create.c +++ /dev/null @@ -1,109 +0,0 @@ -/* pthread_key_create. Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -pthread_mutex_t __pthread_key_lock; - -void (**__pthread_key_destructors) (void *arg); -int __pthread_key_size; -int __pthread_key_count; -int __pthread_key_invalid_count; - -int -pthread_key_create (pthread_key_t *key, void (*destructor) (void *)) -{ - /* Where to look for the next key slot. */ - static int index; - - __pthread_key_lock_ready (); - - __pthread_mutex_lock (&__pthread_key_lock); - - do_search: - /* Use the search hint and try to find a free slot. */ - for (; index < __pthread_key_count - && __pthread_key_destructors[index] != PTHREAD_KEY_INVALID; - index ++) - ; - - /* See if we actually found a free element. */ - if (index < __pthread_key_count) - { - assert (__pthread_key_destructors[index] == PTHREAD_KEY_INVALID); - assert (__pthread_key_invalid_count > 0); - - __pthread_key_invalid_count --; - __pthread_key_destructors[index] = destructor; - *key = index ++; - - __pthread_mutex_unlock (&__pthread_key_lock); - return 0; - } - - assert (index == __pthread_key_count); - - /* No space at the end. */ - if (__pthread_key_size == __pthread_key_count) - { - /* See if it is worth looking for a free element. */ - if (__pthread_key_invalid_count > 4 - && __pthread_key_invalid_count > __pthread_key_size / 8) - { - index = 0; - goto do_search; - } - - - /* Resize the array. */ - { - void *t; - int newsize; - - if (__pthread_key_size == 0) - newsize = 8; - else - newsize = __pthread_key_size * 2; - - t = realloc (__pthread_key_destructors, - newsize * sizeof (*__pthread_key_destructors)); - if (! t) - { - __pthread_mutex_unlock (&__pthread_key_lock); - return ENOMEM; - } - - __pthread_key_size = newsize; - __pthread_key_destructors = t; - } - } - - __pthread_key_destructors[index] = destructor; - *key = index; - - index ++; - __pthread_key_count ++; - - __pthread_mutex_unlock (&__pthread_key_lock); - return 0; -} diff --git a/sysdeps/hurd/pt-key-delete.c b/sysdeps/hurd/pt-key-delete.c deleted file mode 100644 index 2426bb11..00000000 --- a/sysdeps/hurd/pt-key-delete.c +++ /dev/null @@ -1,45 +0,0 @@ -/* pthread_key_delete. Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -int -pthread_key_delete (pthread_key_t key) -{ - error_t err = 0; - - __pthread_key_lock_ready (); - - __pthread_mutex_lock (&__pthread_key_lock); - - if (key < 0 || key >= __pthread_key_count - || __pthread_key_destructors[key] == PTHREAD_KEY_INVALID) - err = EINVAL; - else - { - __pthread_key_destructors[key] = PTHREAD_KEY_INVALID; - __pthread_key_invalid_count ++; - } - - __pthread_mutex_unlock (&__pthread_key_lock); - - return err; -} diff --git a/sysdeps/hurd/pt-key.h b/sysdeps/hurd/pt-key.h deleted file mode 100644 index 494e01d7..00000000 --- a/sysdeps/hurd/pt-key.h +++ /dev/null @@ -1,76 +0,0 @@ -/* pthread_key internal declatations for the Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#define PTHREAD_KEY_MEMBERS \ - hurd_ihash_t thread_specifics; - -#define PTHREAD_KEY_INVALID (void *) (-1) - - -/* __PTHREAD_KEY_DESTRUCTORS is an array of destructors with - __PTHREAD_KEY_SIZE elements. If an element with index less than - __PTHREAD_KEY_COUNT is invalid, it shall contain the value - PTHREAD_KEY_INVALID which shall be distinct from NULL. - - Normally, we just add new keys to the end of the array and realloc - it as necessary. The pthread_key_create routine may decide to - rescan the array if __PTHREAD_KEY_FREE is large. */ -extern void (**__pthread_key_destructors) (void *arg); -extern int __pthread_key_size; -extern int __pthread_key_count; -/* Number of invalid elements in the array. Does not include elements - for which memory has been allocated but which have not yet been - used (i.e. those elements with indexes greater than - __PTHREAD_KEY_COUNT). */ -extern int __pthread_key_invalid_count; - -/* Protects the above variables. This must be a recursive lock: the - destructors may call pthread_key_delete. */ -extern pthread_mutex_t __pthread_key_lock; - -#include - -static inline void -__pthread_key_lock_ready (void) -{ - static pthread_once_t o = PTHREAD_ONCE_INIT; - - void do_init (void) - { - int err; - pthread_mutexattr_t attr; - - err = pthread_mutexattr_init (&attr); - assert_perror (err); - - err = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); - assert_perror (err); - - err = pthread_mutex_init (&__pthread_key_lock, &attr); - assert_perror (err); - - err = pthread_mutexattr_destroy (&attr); - assert_perror (err); - } - - pthread_once (&o, do_init); -} diff --git a/sysdeps/hurd/pt-kill.c b/sysdeps/hurd/pt-kill.c deleted file mode 100644 index f970e065..00000000 --- a/sysdeps/hurd/pt-kill.c +++ /dev/null @@ -1,49 +0,0 @@ -/* pthread_kill. Hurd version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -int -pthread_kill (pthread_t thread, int sig) -{ - struct __pthread *pthread; - struct hurd_signal_detail detail; - struct hurd_sigstate *ss; - - /* Lookup the thread structure for THREAD. */ - pthread = __pthread_getid (thread); - if (pthread == NULL) - return ESRCH; - - ss = _hurd_thread_sigstate (pthread->kernel_thread); - assert (ss); - - detail.exc = 0; - detail.code = sig; - detail.error = 0; - - _hurd_raise_signal (ss, sig, &detail); - - return 0; -} diff --git a/sysdeps/hurd/pt-setspecific.c b/sysdeps/hurd/pt-setspecific.c deleted file mode 100644 index 89ca4d7f..00000000 --- a/sysdeps/hurd/pt-setspecific.c +++ /dev/null @@ -1,43 +0,0 @@ -/* pthread_setspecific. Generic version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -int -pthread_setspecific (pthread_key_t key, const void *value) -{ - error_t err; - struct __pthread *self = _pthread_self (); - - if (! self->thread_specifics) - { - err = hurd_ihash_create (&self->thread_specifics, HURD_IHASH_NO_LOCP); - if (err) - return ENOMEM; - } - - err = hurd_ihash_add (self->thread_specifics, key, (void *) value); - if (err) - return ENOMEM; - - return 0; -} diff --git a/sysdeps/ia32/bits/atomic.h b/sysdeps/ia32/bits/atomic.h deleted file mode 100644 index 0dfc1f60..00000000 --- a/sysdeps/ia32/bits/atomic.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Atomic operations. i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_ATOMIC_H -#define _BITS_ATOMIC_H 1 - -typedef __volatile int __atomic_t; - -static inline void -__atomic_inc (__atomic_t *__var) -{ - __asm__ __volatile ("lock; incl %0" : "=m" (*__var) : "m" (*__var)); -} - -static inline void -__atomic_dec (__atomic_t *__var) -{ - __asm__ __volatile ("lock; decl %0" : "=m" (*__var) : "m" (*__var)); -} - -static inline int -__atomic_dec_and_test (__atomic_t *__var) -{ - unsigned char __ret; - - __asm__ __volatile ("lock; decl %0; sete %1" - : "=m" (*__var), "=qm" (__ret) : "m" (*__var)); - return __ret != 0; -} - -/* We assume that an __atomicptr_t is only used for pointers to - word-aligned objects, and use the lowest bit for a simple lock. */ -typedef __volatile int * __atomicptr_t; - -/* Actually we don't implement that yet, and assume that we run on - something that has the i486 instruction set. */ -static inline int -__atomicptr_compare_and_swap (__atomicptr_t *__ptr, void *__oldval, - void * __newval) -{ - char __ret; - int __dummy; - - __asm__ __volatile ("lock; cmpxchgl %3, %1; sete %0" - : "=q" (__ret), "=m" (*__ptr), "=a" (__dummy) - : "r" (__newval), "m" (*__ptr), "a" (__oldval)); - return __ret; -} - -#endif diff --git a/sysdeps/ia32/bits/memory.h b/sysdeps/ia32/bits/memory.h deleted file mode 100644 index 932c4086..00000000 --- a/sysdeps/ia32/bits/memory.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Memory barrier operations. i386 version. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_MEMORY_H -#define _BITS_MEMORY_H 1 - -/* Prevent read and write reordering across this function. */ -static inline void -__memory_barrier (void) -{ - int i; - - /* Any lock'ed instruction will do. We just do a simple - increment. */ - __asm__ __volatile ("lock; incl %0" : "=m" (i) : "m" (i) : "memory"); -} - -/* Prevent read reordering across this function. */ -#define __memory_read_barrier __memory_barrier - -/* Prevent write reordering across this function. */ -#define __memory_write_barrier __memory_barrier - -#endif diff --git a/sysdeps/ia32/bits/spin-lock-inline.h b/sysdeps/ia32/bits/spin-lock-inline.h deleted file mode 100644 index e5ed3def..00000000 --- a/sysdeps/ia32/bits/spin-lock-inline.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Machine-specific definitions for spin locks. i386 version. - Copyright (C) 2000, 2005, 2008, 2009 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * Never include this file directly; use or instead. - */ - -#ifndef _BITS_SPIN_LOCK_INLINE_H -#define _BITS_SPIN_LOCK_INLINE_H 1 - -#include -#include - -__BEGIN_DECLS - -#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES - -# ifndef __EBUSY -# include -# define __EBUSY EBUSY -# endif - -# ifndef __PT_SPIN_INLINE -# define __PT_SPIN_INLINE __extern_inline -# endif - -__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_destroy (__pthread_spinlock_t *__lock) -{ - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, - int __pshared); - -__PT_SPIN_INLINE int -__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) -{ - *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_trylock (__pthread_spinlock_t *__lock) -{ - int __locked; - __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__locked), "=m" (*__lock) : "0" (1) : "memory"); - return __locked ? __EBUSY : 0; -} - -__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); -extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); - -__extern_inline int -__pthread_spin_lock (__pthread_spinlock_t *__lock) -{ - if (__pthread_spin_trylock (__lock)) - return _pthread_spin_lock (__lock); - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_unlock (__pthread_spinlock_t *__lock) -{ - int __unlocked; - __asm__ __volatile ("xchgl %0, %1" - : "=&r" (__unlocked), "=m" (*__lock) : "0" (0) : "memory"); - return 0; -} - -#endif /* Use extern inlines or force inlines. */ - -__END_DECLS - -#endif /* bits/spin-lock.h */ diff --git a/sysdeps/ia32/bits/spin-lock.h b/sysdeps/ia32/bits/spin-lock.h deleted file mode 100644 index 5ae81e18..00000000 --- a/sysdeps/ia32/bits/spin-lock.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Machine-specific definitions for spin locks. i386 version. - Copyright (C) 2000, 2005, 2008, 2009 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * Never include this file directly; use or instead. - */ - -#ifndef _BITS_SPIN_LOCK_H -#define _BITS_SPIN_LOCK_H 1 - -#include - -__BEGIN_DECLS - -/* The type of a spin lock object. */ -typedef __volatile int __pthread_spinlock_t; - -/* Initializer for a spin lock object. */ -# define __PTHREAD_SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) - -__END_DECLS - -#endif /* bits/spin-lock.h */ diff --git a/sysdeps/ia32/machine-sp.h b/sysdeps/ia32/machine-sp.h deleted file mode 100644 index cef6ab72..00000000 --- a/sysdeps/ia32/machine-sp.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Machine-specific function to return the stack pointer. i386 version. - Copyright (C) 1994, 1997, 2001, 2006 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. */ - -#ifndef _MACHINE_SP_H -#define _MACHINE_SP_H - -/* Return the current stack pointer. */ - -#define __thread_stack_pointer() ({ \ - register void *__sp__ asm("esp"); \ - __sp__; \ -}) - -#endif /* machine-sp.h */ diff --git a/sysdeps/ia32/pt-machdep.h b/sysdeps/ia32/pt-machdep.h deleted file mode 100644 index 6d456367..00000000 --- a/sysdeps/ia32/pt-machdep.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Machine dependent pthreads internal defenitions. i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _PT_MACHDEP_H -#define _PT_MACHDEP_H 1 - -struct pthread_mcontext -{ - void *pc; - void *sp; -}; - -#endif /* pt-machdep.h */ diff --git a/sysdeps/l4/bits/pthread-np.h b/sysdeps/l4/bits/pthread-np.h deleted file mode 100644 index 6a02bdc0..00000000 --- a/sysdeps/l4/bits/pthread-np.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Non-portable functions. L4 version. - Copyright (C) 2003, 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * Never include this file directly; use or instead. - */ - -#ifndef _BITS_PTHREAD_NP_H -#define _BITS_PTHREAD_NP_H 1 - -#include - -/* Add the thread TID to the internal kernel thread pool. */ -extern int pthread_pool_add_np (l4_thread_id_t tid); - -/* Get the first thread from the pool. */ -extern l4_thread_id_t pthread_pool_get_np (void); - -#endif /* bits/pthread-np.h */ diff --git a/sysdeps/l4/hurd/bits/pthread-np.h b/sysdeps/l4/hurd/bits/pthread-np.h deleted file mode 100644 index a90793df..00000000 --- a/sysdeps/l4/hurd/bits/pthread-np.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Non-portable functions. Viengoos version. - Copyright (C) 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * Never include this file directly; use or instead. - */ - -#ifndef _BITS_PTHREAD_NP_H -#define _BITS_PTHREAD_NP_H 1 - -#include - -int pthread_setactivity_np (addr_t activity); - -#endif /* bits/pthread-np.h */ diff --git a/sysdeps/l4/hurd/ia32/pt-machdep.c b/sysdeps/l4/hurd/ia32/pt-machdep.c deleted file mode 100644 index dbf5cd7e..00000000 --- a/sysdeps/l4/hurd/ia32/pt-machdep.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Machine dependent pthreads code. Hurd/i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* Nothing to do. */ diff --git a/sysdeps/l4/hurd/ia32/pt-setup.c b/sysdeps/l4/hurd/ia32/pt-setup.c deleted file mode 100644 index 579905c9..00000000 --- a/sysdeps/l4/hurd/ia32/pt-setup.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Setup thread stack. Viengoos/i386 version. - Copyright (C) 2000, 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include -#include - -/* The stack layout used on the i386 is: - - ----------------- - | ARG | - ----------------- - | START_ROUTINE | - ----------------- - | Return address | - ----------------- <- %ebp - | Frame pointer | - ----------------- - - We do the following: setup the stack to return to the entry routine. - - -*/ - -/* The stack contains: - - arg - start_routine - 0 <- fake return address - C entry_point -*/ -extern uintptr_t _pthread_entry_point; -__asm__ ("\n\ - .globl _pthread_entry_point, __pthread_entry_point\n\ -_pthread_entry_point:\n\ -__pthread_entry_point:\n\ - pushl $0\n\ - popf\n\ -\n\ - xor %ebp, %ebp\n\ - ret\n"); - -/* Set up the stack for THREAD, such that it appears as if - START_ROUTINE and ARG were passed to the new thread's entry-point. - Return the stack pointer for the new thread. We also take the - opportunity to install THREAD in our utcb. */ -static void * -stack_setup (struct __pthread *thread, - void *(*start_routine)(void *), void *arg, - void (*entry_point)(void *(*)(void *), void *)) -{ - uintptr_t *top; - - /* Calculate top of the new stack. */ - top = (uintptr_t *) ((uintptr_t) thread->stackaddr + thread->stacksize); - - /* Align on 0x10 for MMX operations. */ - top = (uintptr_t) top & ~0xf; - - if (start_routine) - { - /* Set up call frame. */ - *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ - *--top = (uintptr_t) start_routine; - *--top = 0; /* Fake return address. */ - *--top = (uintptr_t) entry_point; - } - - return top; -} - -int -__pthread_setup (struct __pthread *thread, - void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg) -{ - thread->mcontext.pc = (void *) &_pthread_entry_point; - thread->mcontext.sp = (void *) stack_setup (thread, start_routine, arg, - entry_point); - - if (__pthread_num_threads == 1) - return 0; - - assert (! ADDR_IS_VOID (thread->exception_area[0])); - - struct exception_page *exception_page = thread->exception_area_va; - - /* SP is set to the end of the exception area minus one word, which - is the location of the exception page. */ - exception_page->exception_handler_sp - = (uintptr_t) thread->exception_area_va + EXCEPTION_AREA_SIZE; - exception_page->exception_handler_sp -= sizeof (void *); - * (void **) exception_page->exception_handler_sp = thread->exception_area_va; - - exception_page->exception_handler_ip = (uintptr_t) &exception_handler_entry; - exception_page->exception_handler_end = (uintptr_t) &exception_handler_end; - - return 0; -} diff --git a/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c b/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c deleted file mode 100644 index 37ef8215..00000000 --- a/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c +++ /dev/null @@ -1,213 +0,0 @@ -/* signal-dispatch-lowlevel.c - ia32 specific signal handling functions. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include -#include - -#include -#include -#include -#include - -extern char _signal_dispatch_entry; -/* - 0(%esp) a pointer to the thread's struct signal_state. - - 4(%esp) a pointer to a siginfo_t. - - 8(%esp) is a pointer to the ss_flags field (or NULL). - - 12(%esp)+4 is the value of the sp when the thread was interrupted (intr_sp) - - 0(intr_sp) is the value of the ip when the thread was interrupted. - - 16(%esp) - 16 byte register save area -*/ -__asm__ ("\n\ - .globl _signal_dispatch_entry\n\ -_signal_dispatch_entry:\n\ - /* Save caller saved registers (16 bytes). */\n\ - mov %eax, 16(%esp)\n\ - mov %ecx, 16+4(%esp)\n\ - mov %edx, 16+8(%esp)\n\ - pushf\n\ - popl %eax\n\ - mov %eax, 16+12(%esp)\n\ -\n\ - /* Reset EFLAGS. */\n\ - cld\n\ - call signal_dispatch\n\ -\n\ - /* Get the original stack and begin restoration. */\n\ - mov 12(%esp), %edx\n\ -\n\ - /* Move the saved registers to the user stack. */\n\ - sub $16, %edx\n\ - /* eax. */\n\ - mov 16+0(%esp), %ecx\n\ - mov %ecx, 0(%edx)\n\ - /* ecx. */\n\ - mov 16+4(%esp), %ecx\n\ - mov %ecx, 4(%edx)\n\ - /* edx. */\n\ - mov 16+8(%esp), %ecx\n\ - mov %ecx, 8(%edx)\n\ - /* eflags. */\n\ - mov 16+12(%esp), %ecx\n\ - mov %ecx, 12(%edx)\n\ -\n\ - /* Get the pointer to the sigaltstack flags. */\n\ - mov 8(%esp), %ecx\n\ -\n\ - /* Restore the user stack. */\n\ - mov %edx, %esp\n\ -\n\ - /* Clear the SA_ONSTACK flag. */\n\ - and %ecx, %ecx\n\ - jz after_clear\n\ - lock; and $~1, 0(%ecx)\n\ -after_clear:\n\ -\n\ - /* Restore eflags, the scratch regs and the original sp and ip. */\n\ - popl %eax\n\ - popl %ecx\n\ - popl %edx\n\ - popf\n\ - ret\n"); - -extern char _signal_dispatch_entry_self; -/* - 0(%esp) is the return address (we ignore it) - - 4(%esp) is the sp to load - - Since we are returning to signal_dispatch_lowlevel's caller, we - also need to restore its frame pointer. */ -__asm__ ("\n\ - .globl _signal_dispatch_entry_self\n\ -_signal_dispatch_entry_self:\n\ - mov 0(%ebp), %ebp\n\ - mov 4(%esp), %esp\n\ - jmp _signal_dispatch_entry\n"); - -void -signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, - siginfo_t si) -{ - assert (pthread_mutex_trylock (&ss->lock) == EBUSY); - - struct __pthread *thread = __pthread_getid (tid); - - bool self = tid == pthread_self (); - - uintptr_t intr_sp; - - if (self) - { - /* The return address is just before the first argument. */ - intr_sp = (uintptr_t) &ss - 4; - assert (* (void **) intr_sp == __builtin_return_address (0)); - } - else - { - struct hurd_thread_exregs_in in; - memset (&in, 0, sizeof (in)); - struct hurd_thread_exregs_out out; - - error_t err; - err = rm_thread_exregs (ADDR_VOID, thread->object, - HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC - | HURD_EXREGS_GET_REGS, - in, &out); - if (err) - panic ("Failed to modify thread " ADDR_FMT, - ADDR_PRINTF (thread->object)); - - intr_sp = out.sp; - - /* Push the ip on the user stack. */ - intr_sp -= 4; - * (uintptr_t *) intr_sp = out.ip; - } - - bool altstack = false; - uintptr_t sp; - if (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) - || (ss->stack.ss_flags & SS_DISABLE) - || (ss->stack.ss_flags & SS_ONSTACK)) - { - assert (! self); - sp = intr_sp; - } - else - { - /* The stack grows down. */ - sp = (uintptr_t) ss->stack.ss_sp + ss->stack.ss_size; - - /* We know intimately that SS_ONSTACK is the least significant - bit. */ - assert (SS_ONSTACK == 1); - atomic_bit_set (&ss->stack.ss_flags, 0); - - altstack = true; - } - - /* Set up the call frame for a call to signal_dispatch_entry. */ - - /* Allocate a siginfo structure on the stack. */ - sp = sp - sizeof (siginfo_t); - siginfo_t *sip = (void *) sp; - /* Copy the user supplied values. */ - *sip = si; - - /* Add space for the 4 caller saved registers. */ - sp -= 4 * sizeof (uintptr_t); - - /* Save the interrupted sp. */ - sp -= 4; - * (uintptr_t *) sp = intr_sp; - - /* Address of the ss_flags. */ - sp -= 4; - if (altstack) - * (uintptr_t *) sp = (uintptr_t) &ss->stack.ss_flags; - else - * (uintptr_t *) sp = 0; - - /* Push the parameters to signal_dispatch. */ - - /* signal info structure. */ - sp -= 4; - * (uintptr_t *) sp = (uintptr_t) sip; - - /* The ss. */ - sp -= 4; - * (uintptr_t *) sp = (uintptr_t) ss; - - pthread_mutex_transfer_np (&ss->lock, tid); - - if (self) - ((void (*) (uintptr_t)) &_signal_dispatch_entry_self) ((uintptr_t) sp); - else - { - struct hurd_thread_exregs_in in; - struct hurd_thread_exregs_out out; - - in.sp = sp; - in.ip = (uintptr_t) &_signal_dispatch_entry; - - rm_thread_exregs (ADDR_VOID, thread->object, - HURD_EXREGS_SET_SP_IP - | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, - in, &out); - } -} diff --git a/sysdeps/l4/hurd/powerpc/pt-machdep.c b/sysdeps/l4/hurd/powerpc/pt-machdep.c deleted file mode 100644 index 754d203e..00000000 --- a/sysdeps/l4/hurd/powerpc/pt-machdep.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Machine dependent pthreads code. Hurd/PowerPC version. - Copyright (C) 2003 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* Nothing to do. */ diff --git a/sysdeps/l4/hurd/powerpc/pt-setup.c b/sysdeps/l4/hurd/powerpc/pt-setup.c deleted file mode 100644 index d3cf4ec3..00000000 --- a/sysdeps/l4/hurd/powerpc/pt-setup.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Setup thread stack. Hurd/PowerPC version. - Copyright (C) 2003 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -/* Arguments is passed in registers on the PowerPC. But the - exchange registers syscall only allows us to set the PC and the - stack pointer so we put the entry point and start function on - the stack. */ -struct start_info -{ - void (*entry_point) (void *(*)(void *), void *); - void *(*start_routine) (void *); - void *arg; -}; - -void first_entry_1 (void); - -/* Stage 1 entry function. The start_info structure is inlined on the - stack. Put values into registers and call entry function. */ -asm (" ;\ -first_entry_1: ;\ - lwz 0, 0(1) ;\ - lwz 3, 4(1) ;\ - lwz 4, 8(1) ;\ - mtctr 0 ;\ - bctrl ;\ -"); - -/* Set up the stack for THREAD, such that it appears as if - START_ROUTINE and ARG were passed to the new thread's entry-point. - Return the stack pointer for the new thread. We also take the - opportunity to install THREAD in our utcb. */ -static void * -stack_setup (struct __pthread *thread, - void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg) -{ - l4_word_t *top; - - /* Calculate top of the new stack. */ - top = (l4_word_t *) ((l4_word_t) thread->stackaddr + thread->stacksize); - - /* Initial stack frame. */ - top[-4] = 0; - top = top - 4; - - if (start_routine) - { - struct start_info *info = ((struct start_info *) top) - 1; - - info->entry_point = entry_point; - info->start_routine = start_routine; - info->arg = arg; - return (void *) info; - } - return top; -} - -int -__pthread_setup (struct __pthread *thread, - void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg) -{ - thread->mcontext.pc = first_entry_1; - thread->mcontext.sp = stack_setup (thread, entry_point, - start_routine, arg); - - if (l4_same_threads (thread->threadid, l4_myself ())) - l4_set_user_defined_handle ((l4_word_t) thread); - else - l4_set_user_defined_handle_of (thread->threadid, - (l4_word_t) thread); - return 0; -} diff --git a/sysdeps/l4/hurd/pt-block.c b/sysdeps/l4/hurd/pt-block.c deleted file mode 100644 index 2315b1c4..00000000 --- a/sysdeps/l4/hurd/pt-block.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Block a thread. Viengoos version. - Copyright (C) 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include - -/* Block THREAD. */ -void -__pthread_block (struct __pthread *thread) -{ - futex_wait (&thread->threadid, thread->threadid); -} diff --git a/sysdeps/l4/hurd/pt-kill.c b/sysdeps/l4/hurd/pt-kill.c deleted file mode 100644 index c72e82f4..00000000 --- a/sysdeps/l4/hurd/pt-kill.c +++ /dev/null @@ -1,3 +0,0 @@ -/* The generic version is good enough for us, however, the generic - Hurd on Mach version supplies a specialized version */ -#include "../generic/pt-kill.c" diff --git a/sysdeps/l4/hurd/pt-setactivity-np.c b/sysdeps/l4/hurd/pt-setactivity-np.c deleted file mode 100644 index f2f07233..00000000 --- a/sysdeps/l4/hurd/pt-setactivity-np.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Set a thread's activity activity. Viengoos version. - Copyright (C) 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include - -int -pthread_setactivity_np (addr_t activity) -{ - struct __pthread *self = _pthread_self (); - - struct hurd_thread_exregs_in in; - in.activity = activity; - - struct hurd_thread_exregs_out out; - int err = rm_thread_exregs (ADDR_VOID, self->object, - HURD_EXREGS_SET_ACTIVITY, - in, &out); - - return err; -} diff --git a/sysdeps/l4/hurd/pt-sigstate-destroy.c b/sysdeps/l4/hurd/pt-sigstate-destroy.c deleted file mode 100644 index 997a0369..00000000 --- a/sysdeps/l4/hurd/pt-sigstate-destroy.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Destroy the signal state. Hurd on L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -void -__pthread_sigstate_destroy (struct __pthread *thread) -{ - /* Nothing to do. */ -} diff --git a/sysdeps/l4/hurd/pt-sigstate-init.c b/sysdeps/l4/hurd/pt-sigstate-init.c deleted file mode 100644 index 4c40fdb3..00000000 --- a/sysdeps/l4/hurd/pt-sigstate-init.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Initialize the signal state. Hurd on L4 version. - Copyright (C) 2003, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include - -error_t -__pthread_sigstate_init (struct __pthread *thread) -{ - struct signal_state *ss = &thread->ss; - - memset (ss, 0, sizeof (*ss)); - - ss->stack.ss_flags = SS_DISABLE; - - int signo; - for (signo = 1; signo < NSIG; ++signo) - { - sigemptyset (&ss->actions[signo - 1].sa_mask); - ss->actions[signo - 1].sa_flags = SA_RESTART; - ss->actions[signo - 1].sa_handler = SIG_DFL; - ss->lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; - } - - return 0; -} diff --git a/sysdeps/l4/hurd/pt-sigstate.c b/sysdeps/l4/hurd/pt-sigstate.c deleted file mode 100644 index 66dd08cf..00000000 --- a/sysdeps/l4/hurd/pt-sigstate.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Set a thread's signal state. Hurd on L4 version. - Copyright (C) 2002, 2005, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -error_t -__pthread_sigstate (struct __pthread *thread, int how, - const sigset_t *set, sigset_t *oset, - int clear_pending) -{ - struct signal_state *ss = &thread->ss; - pthread_mutex_lock (&ss->lock); - - if (oset) - *oset = ss->blocked; - - if (set) - { - /* Mask out SIGKILL and SIGSTOP. */ - sigset_t s = *set; - sigdelset (&s, SIGKILL); - sigdelset (&s, SIGSTOP); - - switch (how) - { - case SIG_BLOCK: - ss->blocked |= s; - break; - case SIG_UNBLOCK: - ss->blocked &= ~s; - break; - case SIG_SETMASK: - ss->blocked = s; - break; - default: - errno = EINVAL; - pthread_mutex_unlock (&ss->lock); - return -1; - } - } - - if (clear_pending) - sigemptyset (&ss->pending); - - /* A "signal shall remain pending until it is unblocked" (2.4.1). - - "If there are any pending unblocked signals after the call to - sigprocmask(), at least one of those signals shall be delivered - before the call to sigprocmask() returns." - (pthread_sigmask). */ - sigset_t extant = ~ss->blocked & ss->pending; - if (! extant) - extant = ~ss->blocked & process_pending; - - pthread_mutex_unlock (&ss->lock); - - if (extant) - raise (l4_lsb64 (extant)); - - return 0; -} diff --git a/sysdeps/l4/hurd/pt-startup.c b/sysdeps/l4/hurd/pt-startup.c deleted file mode 100644 index b6461de7..00000000 --- a/sysdeps/l4/hurd/pt-startup.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Thread initialization. Hurd/L4 version. - Copyright (C) 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -void -__pthread_startup (void) -{ - struct __pthread *pthread = _pthread_self (); - pthread->threadid = l4_myself (); -} diff --git a/sysdeps/l4/hurd/pt-sysdep.c b/sysdeps/l4/hurd/pt-sysdep.c deleted file mode 100644 index c23364c7..00000000 --- a/sysdeps/l4/hurd/pt-sysdep.c +++ /dev/null @@ -1,61 +0,0 @@ -/* System dependent pthreads code. Hurd version. - Copyright (C) 2000, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -sched_yield (void) -{ - l4_yield (); - return 0; -} - -/* Forward. */ -static void init_routine (void (*) (void *), void *) - __attribute__ ((noreturn)); - -/* OK, the name of this variable isn't really appropriate, but I don't - want to change it yet. */ -void (*_pthread_init_routine)(void (*) (void *), void *) = &init_routine; - -/* This function is called from the Hurd-specific startup code. It - should return a new stack pointer for the main thread. The caller - will switch to this new stack before doing anything serious. */ -static void -init_routine (void (*entry) (void *), void *arg) -{ - /* Initialize the library. */ - __pthread_initialize (); - - struct __pthread *thread; - int err; - - /* Create the pthread structure for the main thread (i.e. us). */ - err = __pthread_create_internal (&thread, 0, - (void *(*)(void *)) entry, arg); - assert_perror (err); - - /* Switch stacks. */ - l4_start_sp_ip (l4_myself (), thread->mcontext.sp, - thread->mcontext.pc); -} diff --git a/sysdeps/l4/hurd/pt-sysdep.h b/sysdeps/l4/hurd/pt-sysdep.h deleted file mode 100644 index 08bcd143..00000000 --- a/sysdeps/l4/hurd/pt-sysdep.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Internal definitions for pthreads library. - Copyright (C) 2000, 2002, 2005, 2007, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _PT_SYSDEP_H -#define _PT_SYSDEP_H 1 - -#include -#include -#include - -/* XXX */ -#define _POSIX_THREAD_THREADS_MAX 64 - -/* The default stack size: 2MB. */ -#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) - -#include - -#define EXCEPTION_AREA_SIZE EXCEPTION_STACK_SIZE -#define EXCEPTION_AREA_SIZE_LOG2 EXCEPTION_STACK_SIZE_LOG2 -/* The exception page is the first object. */ -#define EXCEPTION_PAGE 0 - -#define PTHREAD_SYSDEP_MEMBERS \ - addr_t object; \ - l4_thread_id_t threadid; \ - addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; \ - void *exception_area_va; \ - l4_word_t my_errno; - -extern inline struct __pthread * -__attribute__((__always_inline__)) -_pthread_self (void) -{ - return (struct __pthread *) l4_user_defined_handle (); -} - -extern inline void -__attribute__((__always_inline__)) -__pthread_stack_dealloc (void *stackaddr, size_t stacksize) -{ - munmap (stackaddr, stacksize); -} - -#endif /* pt-sysdep.h */ diff --git a/sysdeps/l4/hurd/pt-thread-alloc.c b/sysdeps/l4/hurd/pt-thread-alloc.c deleted file mode 100644 index ada7b3b8..00000000 --- a/sysdeps/l4/hurd/pt-thread-alloc.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Allocate kernel thread. Viengoos version. - Copyright (C) 2007, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -extern struct hurd_startup_data *__hurd_startup_data; - -extern addr_t meta_data_activity; - -int -__pthread_thread_alloc (struct __pthread *thread) -{ - /* The main thread is already running of course. */ - if (__pthread_num_threads == 1) - { - thread->object = __hurd_startup_data->thread; - thread->threadid = l4_myself (); - return 0; - } - else - { - addr_t exception_area = as_alloc (EXCEPTION_AREA_SIZE_LOG2, 1, true); - - thread->exception_area_va - = ADDR_TO_PTR (addr_extend (exception_area, - 0, EXCEPTION_AREA_SIZE_LOG2)); - - int i; - for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) - { - addr_t slot = addr_chop (PTR_TO_ADDR (thread->exception_area_va - + i * PAGESIZE), - PAGESIZE_LOG2); - as_ensure (slot); - - struct storage storage = storage_alloc (ADDR_VOID, cap_page, - STORAGE_LONG_LIVED, - OBJECT_POLICY_DEFAULT, - slot); - if (ADDR_IS_VOID (storage.addr)) - { - int j; - for (j = 0; j < i; j ++) - storage_free (thread->exception_area[j], false); - as_free (exception_area, false); - return EAGAIN; - } - - thread->exception_area[i] = storage.addr; - } - - struct storage storage; - storage = storage_alloc (meta_data_activity, cap_thread, - /* Threads are rarely shortly lived. */ - STORAGE_MEDIUM_LIVED, OBJECT_POLICY_DEFAULT, - ADDR_VOID); - if (ADDR_IS_VOID (storage.addr)) - { - int j; - for (j = 0; j < EXCEPTION_AREA_SIZE / PAGESIZE; j ++) - storage_free (thread->exception_area[j], false); - as_free (exception_area, false); - return EAGAIN; - } - - thread->object = storage.addr; - } - - return 0; -} diff --git a/sysdeps/l4/hurd/pt-thread-halt.c b/sysdeps/l4/hurd/pt-thread-halt.c deleted file mode 100644 index 98fefaab..00000000 --- a/sysdeps/l4/hurd/pt-thread-halt.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Deallocate the kernel thread resources. Viengoos version. - Copyright (C) 2007, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -#include -#include -#include -#include - -/* If we try to deallocate our self, we will end up causing a - deadlock. Thus, when a thread tries to free itself, we add it - here. The next thread to free a thread will free it. */ -ss_mutex_t saved_object_lock; -static addr_t saved_object; - -void -__pthread_thread_halt (struct __pthread *thread, int need_dealloc) -{ - /* We may deallocate THREAD. First save any data we need. */ - - addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; - memcpy (exception_area, thread->exception_area, - sizeof (thread->exception_area)); - memset (thread->exception_area, 0, sizeof (thread->exception_area)); - - void *va = thread->exception_area_va; - - addr_t object = thread->object; - l4_thread_id_t tid = thread->threadid; - - if (need_dealloc) - __pthread_dealloc (thread); - - /* The THREAD data structure is no longer valid. */ - thread = NULL; - - /* Deallocate any saved object. */ - ss_mutex_lock (&saved_object_lock); - if (! ADDR_IS_VOID (saved_object)) - { - storage_free (saved_object, false); - saved_object = ADDR_VOID; - } - ss_mutex_unlock (&saved_object_lock); - - /* Free the exception area. */ - - /* Clean up the exception page. */ - exception_page_cleanup - (ADDR_TO_PTR (addr_extend (exception_area[EXCEPTION_PAGE], - 0, PAGESIZE_LOG2))); - - /* Free the storage. */ - int i; - for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) - { - assert (! ADDR_IS_VOID (exception_area[i])); - storage_free (exception_area[i], false); - } - - /* And the address space. */ - as_free (addr_chop (PTR_TO_ADDR (va), EXCEPTION_AREA_SIZE_LOG2), false); - - if (tid == l4_myself ()) - /* If we try to storage_free (storage.addr), we will freeze in the - middle. That's no good. We set SAVED_OBJECT to our thread - object and the next thread in will free us. */ - { - ss_mutex_lock (&saved_object_lock); - saved_object = object; - ss_mutex_unlock (&saved_object_lock); - } - else - storage_free (object, false); - - if (tid == l4_myself ()) - { - l4_send_timeout (l4_myself (), L4_NEVER); - panic ("Failed to stop thread %x.%x!", - l4_thread_no (l4_myself ()), l4_version (l4_myself ())); - } - else - thread_stop (object); -} diff --git a/sysdeps/l4/hurd/pt-thread-start.c b/sysdeps/l4/hurd/pt-thread-start.c deleted file mode 100644 index 9db399ce..00000000 --- a/sysdeps/l4/hurd/pt-thread-start.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Start thread. L4 version. - Copyright (C) 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include -#include - -#include - -int -__pthread_thread_start (struct __pthread *thread) -{ - error_t err; - - if (__pthread_num_threads == 1) - /* The main thread is already running of course. */ - { - assert (__pthread_total == 1); - assert (l4_is_thread_equal (l4_myself (), thread->threadid)); - l4_set_user_defined_handle ((l4_word_t) thread); - } - else - { - struct hurd_thread_exregs_in in; - struct hurd_thread_exregs_out out; - - in.aspace = ADDR (0, 0); - in.aspace_cap_properties = CAP_PROPERTIES_VOID; - in.aspace_cap_properties_flags = CAP_COPY_COPY_SOURCE_GUARD; - - in.activity = ADDR_VOID; - - in.exception_page = addr_chop (PTR_TO_ADDR (thread->exception_area_va), - PAGESIZE_LOG2); - - in.sp = (l4_word_t) thread->mcontext.sp; - in.ip = (l4_word_t) thread->mcontext.pc; - - in.user_handle = (l4_word_t) thread; - err = rm_thread_exregs (ADDR_VOID, thread->object, - HURD_EXREGS_SET_ASPACE - | HURD_EXREGS_SET_ACTIVITY - | HURD_EXREGS_SET_EXCEPTION_PAGE - | HURD_EXREGS_SET_SP_IP - | HURD_EXREGS_SET_USER_HANDLE - | HURD_EXREGS_START - | HURD_EXREGS_ABORT_IPC, - in, &out); - assert (err == 0); - } - return 0; -} diff --git a/sysdeps/l4/hurd/pt-wakeup.c b/sysdeps/l4/hurd/pt-wakeup.c deleted file mode 100644 index e568a6f9..00000000 --- a/sysdeps/l4/hurd/pt-wakeup.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Wakeup a thread. Viengoos version. - Copyright (C) 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include -#include - -/* Wakeup THREAD. */ -void -__pthread_wakeup (struct __pthread *thread) -{ - /* We need to loop here as the blocked thread may not yet be - blocked! Here's what happens when a thread blocks: it registers - itself as blocked, drops the relevant lock and then actually - blocks (via __pthread_block). This means that after dropping the - lock and before blocking, it may be interrupted and another - thread may try to wake it. */ - long ret; - do - { - ret = futex_wake (&thread->threadid, INT_MAX); - assertx (ret <= 1, "tid: %x, ret: %d", thread->threadid, ret); - - if (ret == 0) - l4_thread_switch (thread->threadid); - } - while (ret == 0); -} diff --git a/sysdeps/l4/hurd/sig-sysdep.h b/sysdeps/l4/hurd/sig-sysdep.h deleted file mode 100644 index 33e13857..00000000 --- a/sysdeps/l4/hurd/sig-sysdep.h +++ /dev/null @@ -1,69 +0,0 @@ -/* sig-sysdep.h - Hurd system specific header file. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include -#include - -struct utcb -{ - l4_word_t saved_sender; - l4_word_t saved_receiver; - l4_word_t saved_timeout; - l4_word_t saved_error_code; - l4_word_t saved_flags; - l4_word_t saved_br0; - l4_msg_t saved_message; -}; - -static inline void -utcb_state_save (struct utcb *buffer) -{ - l4_word_t *utcb = _L4_utcb (); - - buffer->saved_sender = utcb[_L4_UTCB_SENDER]; - buffer->saved_receiver = utcb[_L4_UTCB_RECEIVER]; - buffer->saved_timeout = utcb[_L4_UTCB_TIMEOUT]; - buffer->saved_error_code = utcb[_L4_UTCB_ERROR_CODE]; - buffer->saved_flags = utcb[_L4_UTCB_FLAGS]; - buffer->saved_br0 = utcb[_L4_UTCB_BR0]; - memcpy (&buffer->saved_message, - utcb, L4_NUM_MRS * sizeof (l4_word_t)); -} - -static inline void -utcb_state_restore (struct utcb *buffer) -{ - l4_word_t *utcb = _L4_utcb (); - - utcb[_L4_UTCB_SENDER] = buffer->saved_sender; - utcb[_L4_UTCB_RECEIVER] = buffer->saved_receiver; - utcb[_L4_UTCB_TIMEOUT] = buffer->saved_timeout; - utcb[_L4_UTCB_ERROR_CODE] = buffer->saved_error_code; - utcb[_L4_UTCB_FLAGS] = buffer->saved_flags; - utcb[_L4_UTCB_BR0] = buffer->saved_br0; - memcpy (utcb, &buffer->saved_message, - L4_NUM_MRS * sizeof (l4_word_t)); -} - -#define SIGNAL_DISPATCH_ENTRY \ - struct utcb buffer; utcb_state_save (&buffer); - -#define SIGNAL_DISPATCH_EXIT \ - utcb_state_restore (&buffer); diff --git a/sysdeps/l4/hurd/sigprocmask.c b/sysdeps/l4/hurd/sigprocmask.c deleted file mode 100644 index a38b3795..00000000 --- a/sysdeps/l4/hurd/sigprocmask.c +++ /dev/null @@ -1,41 +0,0 @@ -/* sigprocmask.c - Generic sigprocmask implementation. - Copyright (C) 2008 Free Software Foundation, Inc. - Written by Neal H. Walfield . - - This file is part of the GNU Hurd. - - The GNU Hurd 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 3 of - the License, or (at your option) any later version. - - The GNU Hurd 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 this program. If not, see - . */ - -#include -#include - -int -sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict old) -{ - struct __pthread *thread = _pthread_self (); - if (! thread) - /* Library is initializing. */ - { - assert (__pthread_num_threads == 1); - - /* We should get the default mask from the startup data structure. */ - if (old) - *old = 0; - - return 0; - } - - return pthread_sigmask (how, set, old); -} diff --git a/sysdeps/l4/pt-block.c b/sysdeps/l4/pt-block.c deleted file mode 100644 index 69e1d358..00000000 --- a/sysdeps/l4/pt-block.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Block a thread. L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -#include - -/* Block THREAD. */ -void -__pthread_block (struct __pthread *thread) -{ - debug (5, "%x.%x/%x blocking", - l4_thread_no (thread->threadid), l4_version (thread->threadid), - thread->threadid); - - l4_accept (L4_UNTYPED_WORDS_ACCEPTOR); - l4_msg_tag_t tag = l4_receive (l4_anythread); - if (l4_ipc_failed (tag)) - { - debug (1, "%x.%x failed to block: %d, offset: %x", - l4_thread_no (l4_myself ()), l4_version (l4_myself ()), - (l4_error_code () >> 1) & 0x7, - l4_error_code () >> 4); - assert (! l4_ipc_failed (tag)); - } - else - debug (5, "%x.%x unblocked", - l4_thread_no (thread->threadid), l4_version (thread->threadid)); -} diff --git a/sysdeps/l4/pt-docancel.c b/sysdeps/l4/pt-docancel.c deleted file mode 100644 index a3965d0d..00000000 --- a/sysdeps/l4/pt-docancel.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Cancel a thread. - Copyright (C) 2002, 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -static void -call_exit (void) -{ - pthread_exit (0); -} - -int -__pthread_do_cancel (struct __pthread *p) -{ - assert (p->cancel_pending == 1); - assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); - - if (l4_is_thread_equal (l4_myself (), p->threadid)) - call_exit (); - else - l4_start_sp_ip (p->threadid, (l4_word_t) p->mcontext.sp, - (l4_word_t) call_exit); - return 0; -} diff --git a/sysdeps/l4/pt-pool-np.c b/sysdeps/l4/pt-pool-np.c deleted file mode 100644 index e83022ba..00000000 --- a/sysdeps/l4/pt-pool-np.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Thread pool for L4 threads. - Copyright (C) 2004, 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; - -_L4_thread_id_t pool_list = l4_nilthread; - -/* Add the thread TID to the pthread kernel thread pool. */ -int -pthread_pool_add_np (l4_thread_id_t tid) -{ - __pthread_mutex_lock (&pool_lock); - /* FIXME: Do error checking. */ - l4_set_user_defined_handle_of (tid, pool_list); - pool_list = tid; - __pthread_mutex_unlock (&pool_lock); - - return 0; -} - - -/* Get the first thread from the pool. */ -l4_thread_id_t -pthread_pool_get_np (void) -{ - _L4_thread_id_t tid; - - __pthread_mutex_lock (&pool_lock); - /* FIXME: Do error checking. */ - tid = pool_list; - if (tid != l4_nilthread) - pool_list = l4_user_defined_handle_of (tid); - __pthread_mutex_unlock (&pool_lock); - return tid; -} diff --git a/sysdeps/l4/pt-spin.c b/sysdeps/l4/pt-spin.c deleted file mode 100644 index b6978b0c..00000000 --- a/sysdeps/l4/pt-spin.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Spin locks. L4 version. - Copyright (C) 2000, 2004 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include - -/* The default for single processor machines; don't spin, it's - pointless. */ -#ifndef __PTHREAD_SPIN_COUNT -# define __PTHREAD_SPIN_COUNT 1 -#endif - -/* The number of times to spin while trying to lock a spin lock object - before yielding the processor. */ -int __pthread_spin_count = __PTHREAD_SPIN_COUNT; - - -/* Lock the spin lock object LOCK. If the lock is held by another - thread spin until it becomes available. */ -int -_pthread_spin_lock (__pthread_spinlock_t *lock) -{ - l4_time_t timeout; - int i; - - /* Start with a small timeout of 2 microseconds, then back off - exponentially. */ - timeout = l4_time_period (2); - - while (1) - { - for (i = 0; i < __pthread_spin_count; i++) - { - if (__pthread_spin_trylock (lock) == 0) - return 0; - } - l4_sleep (timeout); - - timeout = l4_time_mul2 (timeout); - if (timeout == L4_NEVER) - timeout = L4_TIME_PERIOD_MAX; - } -} - -weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/sysdeps/l4/pt-stack-alloc.c b/sysdeps/l4/pt-stack-alloc.c deleted file mode 100644 index b7ec12b4..00000000 --- a/sysdeps/l4/pt-stack-alloc.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Allocate a new stack. L4 Hurd version. - Copyright (C) 2000, 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -#include - -/* Allocate a new stack of size STACKSIZE. If successful, store the - address of the newly allocated stack in *STACKADDR and return 0. - Otherwise return an error code (EINVAL for an invalid stack size, - EAGAIN if the system lacked the necessary resources to allocate a - new stack). */ -int -__pthread_stack_alloc (void **stackaddr, size_t stacksize) -{ - void *buffer = mmap (0, stacksize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (buffer == MAP_FAILED) - return EAGAIN; - - *stackaddr = buffer; - - return 0; -} diff --git a/sysdeps/l4/pt-thread-alloc.c b/sysdeps/l4/pt-thread-alloc.c deleted file mode 100644 index ec69afb5..00000000 --- a/sysdeps/l4/pt-thread-alloc.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Allocate kernel thread. L4 version. - Copyright (C) 2003, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -int -__pthread_thread_alloc (struct __pthread *thread) -{ - error_t err; - - /* The main thread is already running of course. */ - if (__pthread_num_threads == 1) - thread->threadid = l4_myself (); - else - { - thread->threadid = pthread_pool_get_np (); - if (thread->threadid != l4_nilthread) - return 0; - - return EAGAIN; - } - return 0; -} diff --git a/sysdeps/l4/pt-thread-dealloc.c b/sysdeps/l4/pt-thread-dealloc.c deleted file mode 100644 index c09e4860..00000000 --- a/sysdeps/l4/pt-thread-dealloc.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Deallocate the kernel thread resources. L4 version. - Copyright (C) 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Deallocate any kernel resources associated with THREAD except don't - halt the thread itself. On return, the thread will be marked as - dead and __pthread_halt will be called. */ -void -__pthread_thread_dealloc (struct __pthread *thread) -{ -} diff --git a/sysdeps/l4/pt-thread-halt.c b/sysdeps/l4/pt-thread-halt.c deleted file mode 100644 index aa2bf43d..00000000 --- a/sysdeps/l4/pt-thread-halt.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Deallocate the kernel thread resources. L4version. - Copyright (C) 2000, 2002, 2004 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -/* Deallocate the kernel thread resources associated with THREAD. */ -void -__pthread_thread_halt (struct __pthread *thread, int need_dealloc) -{ - l4_thread_id_t tid = thread->threadid; - - if (need_dealloc) - __pthread_dealloc (thread); - - /* There is potential race here: once if TID is the current thread, - then once we add TID to the pool, someone can reallocate it - before we call stop. However, to start the thread, the caller - atomically starts and sets the sp and ip, thus, if the stop has - not yet executed at that point, it won't. */ - - if (tid != l4_myself ()) - l4_stop (tid); - pthread_pool_add_np (tid); - if (tid == l4_myself ()) - l4_stop (tid); -} diff --git a/sysdeps/l4/pt-thread-start.c b/sysdeps/l4/pt-thread-start.c deleted file mode 100644 index 144c58bb..00000000 --- a/sysdeps/l4/pt-thread-start.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Start thread. L4 version. - Copyright (C) 2003, 2004, 2007 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Start THREAD. Get the kernel thread scheduled and running. */ -int -__pthread_thread_start (struct __pthread *thread) -{ - if (__pthread_num_threads == 1) - /* The main thread is already running of course. */ - { - assert (__pthread_total == 1); - assert (l4_is_thread_equal (l4_myself (), thread->threadid)); - } - else - l4_start_sp_ip (thread->threadid, (l4_word_t) thread->mcontext.sp, - (l4_word_t) thread->mcontext.pc); - return 0; -} diff --git a/sysdeps/l4/pt-timedblock.c b/sysdeps/l4/pt-timedblock.c deleted file mode 100644 index ce7972bd..00000000 --- a/sysdeps/l4/pt-timedblock.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Block a thread with a timeout. L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -/* Block THREAD. */ -error_t -__pthread_timedblock (struct __pthread *thread, - const struct timespec *abstime) -{ -#warning Need gettimeofday to implement properly. - __pthread_block (thread); - return 0; -} diff --git a/sysdeps/l4/pt-wakeup.c b/sysdeps/l4/pt-wakeup.c deleted file mode 100644 index de378465..00000000 --- a/sysdeps/l4/pt-wakeup.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Wakeup a thread. L4 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -#include - -/* Wakeup THREAD. */ -void -__pthread_wakeup (struct __pthread *thread) -{ - debug (5, "%x.%x/%x waking %x.%x/%x", - l4_thread_no (l4_myself ()), l4_version (l4_myself ()), l4_myself (), - l4_thread_no (thread->threadid), l4_version (thread->threadid), - thread->threadid); - - /* Signal the waiter. */ - l4_msg_t msg; - l4_msg_clear (msg); - l4_msg_set_untyped_words (msg, 0); - l4_msg_load (msg); - - l4_msg_tag_t tag = l4_send (thread->threadid); - if (l4_ipc_failed (tag)) - { - int err = l4_error_code (); - debug (1, "%x.%x failed to wake %x.%x: %s (%d)", - l4_thread_no (l4_myself ()), l4_version (l4_myself ()), - l4_thread_no (thread->threadid), l4_version (thread->threadid), - l4_strerror (err), err); - } - else - debug (5, "%x.%x woke %x.%x", - l4_thread_no (l4_myself ()), l4_version (l4_myself ()), - l4_thread_no (thread->threadid), l4_version (thread->threadid)); -} diff --git a/sysdeps/mach/bits/spin-lock-inline.h b/sysdeps/mach/bits/spin-lock-inline.h deleted file mode 100644 index f9f7c299..00000000 --- a/sysdeps/mach/bits/spin-lock-inline.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Definitions of user-visible names for spin locks. - Copyright (C) 1994, 1997, 2002, 2008, 2009 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. */ - -#ifndef _BITS_SPIN_LOCK_INLINE_H -#define _BITS_SPIN_LOCK_INLINE_H 1 - -#include -#include -#include /* This does all the work. */ - -__BEGIN_DECLS - -#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES - -# ifndef __EBUSY -# include -# define __EBUSY EBUSY -# endif - -# ifndef __PT_SPIN_INLINE -# define __PT_SPIN_INLINE __extern_inline -# endif - -__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_destroy (__pthread_spinlock_t *__lock) -{ - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, - int __pshared); - -__PT_SPIN_INLINE int -__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) -{ - *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER; - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_trylock (__pthread_spinlock_t *__lock) -{ - return __spin_try_lock (__lock) ? 0 : __EBUSY; -} - -__extern_inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); -extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); - -__extern_inline int -__pthread_spin_lock (__pthread_spinlock_t *__lock) -{ - if (__pthread_spin_trylock (__lock)) - return _pthread_spin_lock (__lock); - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_unlock (__pthread_spinlock_t *__lock) -{ - __spin_unlock (__lock); - return 0; -} - -#endif /* Use extern inlines or force inlines. */ - -__END_DECLS - -#endif /* bits/spin-lock.h */ diff --git a/sysdeps/mach/bits/spin-lock.h b/sysdeps/mach/bits/spin-lock.h deleted file mode 100644 index 537dac9d..00000000 --- a/sysdeps/mach/bits/spin-lock.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Definitions of user-visible names for spin locks. - Copyright (C) 1994, 1997, 2002, 2008, 2009 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. */ - -#ifndef _BITS_SPIN_LOCK_H -#define _BITS_SPIN_LOCK_H 1 - -#include -#include /* This does all the work. */ - -__BEGIN_DECLS - -/* The type of a spin lock object. */ -typedef __spin_lock_t __pthread_spinlock_t; - -/* Initializer for a spin lock object. */ -#ifndef __PTHREAD_SPIN_LOCK_INITIALIZER -#error __PTHREAD_SPIN_LOCK_INITIALIZER undefined: should be defined by . -#endif - -__END_DECLS - -#endif /* bits/spin-lock.h */ diff --git a/sysdeps/mach/hurd/ia32/pt-machdep.c b/sysdeps/mach/hurd/ia32/pt-machdep.c deleted file mode 100644 index face46c5..00000000 --- a/sysdeps/mach/hurd/ia32/pt-machdep.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Machine dependent pthreads code. Hurd/i386 version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include -#include - -int -__thread_set_pcsp (thread_t thread, - int set_ip, void *ip, - int set_sp, void *sp) -{ - error_t err; - struct i386_thread_state state; - mach_msg_type_number_t state_count; - - state_count = i386_THREAD_STATE_COUNT; - - err = __thread_get_state (thread, i386_THREAD_STATE, - (thread_state_t) &state, &state_count); - if (err) - return err; - - if (set_sp) - state.uesp = (unsigned int) sp; - if (set_ip) - state.eip = (unsigned int) ip; - - err = __thread_set_state (thread, i386_THREAD_STATE, - (thread_state_t) &state, - i386_THREAD_STATE_COUNT); - if (err) - return err; - - return 0; -} diff --git a/sysdeps/mach/hurd/ia32/pt-setup.c b/sysdeps/mach/hurd/ia32/pt-setup.c deleted file mode 100644 index ba438d6a..00000000 --- a/sysdeps/mach/hurd/ia32/pt-setup.c +++ /dev/null @@ -1,105 +0,0 @@ -/* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000, 2002, 2005, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* The stack layout used on the i386 is: - - ----------------- - | ARG | - ----------------- - | START_ROUTINE | - ----------------- - | 0 | - ----------------- - | | - | Fast TSD | - | | - ----------------- - - We need to reserve __hurd_threadvar_max `unsigned long int's' of - (fast) thread-specific data (TSD) for the Hurd. */ - -/* Set up the stack for THREAD, such that it appears as if - START_ROUTINE and ARG were passed to the new thread's entry-point. - Return the stack pointer for the new thread. */ -static void * -stack_setup (struct __pthread *thread, - void *(*start_routine)(void *), void *arg) -{ - error_t err; - uintptr_t *bottom, *top; - - /* Calculate the top of the new stack. */ - bottom = thread->stackaddr; - top = (uintptr_t *) ((uintptr_t) bottom + thread->stacksize); - - /* Next, make room for the TSDs. */ - top -= __hurd_threadvar_max; - - /* Save the self pointer. */ - top[_HURD_THREADVAR_THREAD] = (uintptr_t) thread; - - if (start_routine) - { - /* And then the call frame. */ - top -= 2; - top = (uintptr_t) top & ~0xf; - top[1] = (uintptr_t) arg; /* Argument to START_ROUTINE. */ - top[0] = (uintptr_t) start_routine; - *--top = 0; /* Fake return address. */ - } - - if (thread->guardsize) - { - err = __vm_protect (__mach_task_self (), (vm_address_t) bottom, - thread->guardsize, 0, 0); - assert_perror (err); - } - - return top; -} - -int -__pthread_setup (struct __pthread *thread, - void (*entry_point)(void *(*)(void *), void *), - void *(*start_routine)(void *), void *arg) -{ - error_t err; - mach_port_t ktid; - - thread->mcontext.pc = entry_point; - thread->mcontext.sp = stack_setup (thread, start_routine, arg); - - ktid = __mach_thread_self (); - if (thread->kernel_thread != ktid) - { - err = __thread_set_pcsp (thread->kernel_thread, - 1, thread->mcontext.pc, - 1, thread->mcontext.sp); - assert_perror (err); - } - __mach_port_deallocate (__mach_task_self (), ktid); - - return 0; -} diff --git a/sysdeps/mach/hurd/pt-attr-setstackaddr.c b/sysdeps/mach/hurd/pt-attr-setstackaddr.c deleted file mode 100644 index 1225ed5b..00000000 --- a/sysdeps/mach/hurd/pt-attr-setstackaddr.c +++ /dev/null @@ -1,35 +0,0 @@ -/* pthread_attr_setstackaddr. Hurd on Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -/* We use fixed sized stacks which require proper alignment. */ -#define __pthread_stacksize __pthread_default_attr.stacksize - -int -pthread_attr_setstackaddr (pthread_attr_t *attr, - void *stackaddr) -{ - if ((long) stackaddr & (__pthread_stacksize - 1)) - return EINVAL; - - attr->stackaddr = stackaddr; - return 0; -} diff --git a/sysdeps/mach/hurd/pt-attr-setstacksize.c b/sysdeps/mach/hurd/pt-attr-setstacksize.c deleted file mode 100644 index 6471c0a3..00000000 --- a/sysdeps/mach/hurd/pt-attr-setstacksize.c +++ /dev/null @@ -1,35 +0,0 @@ -/* pthread_attr_setstacksize. Hurd on Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -/* We use fixed sized stacks which require proper alignment. */ -#define __pthread_stacksize __pthread_default_attr.stacksize - -int -pthread_attr_setstacksize (pthread_attr_t *attr, - size_t stacksize) -{ - if (stacksize != __pthread_stacksize) - return EINVAL; - - attr->stacksize = stacksize; - return 0; -} diff --git a/sysdeps/mach/hurd/pt-docancel.c b/sysdeps/mach/hurd/pt-docancel.c deleted file mode 100644 index b81a5c70..00000000 --- a/sysdeps/mach/hurd/pt-docancel.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Cancel a thread. - Copyright (C) 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -static void -call_exit (void) -{ - pthread_exit (0); -} - -int -__pthread_do_cancel (struct __pthread *p) -{ - mach_port_t ktid; - int me; - - assert (p->cancel_pending == 1); - assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); - - ktid = __mach_thread_self (); - me = p->kernel_thread == ktid; - __mach_port_deallocate (__mach_task_self (), ktid); - - if (me) - call_exit (); - else - { - error_t err; - - err = __thread_suspend (p->kernel_thread); - assert_perror (err); - - err = __thread_abort (p->kernel_thread); - assert_perror (err); - - err = __thread_set_pcsp (p->kernel_thread, - 1, (void *) call_exit, 0, 0); - assert_perror (err); - - err = __thread_resume (p->kernel_thread); - assert_perror (err); - } - - return 0; -} diff --git a/sysdeps/mach/hurd/pt-sigstate-destroy.c b/sysdeps/mach/hurd/pt-sigstate-destroy.c deleted file mode 100644 index 8e56c5cf..00000000 --- a/sysdeps/mach/hurd/pt-sigstate-destroy.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Destroy the signal state. Hurd on Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include - -void -__pthread_sigstate_destroy (struct __pthread *thread) -{ - /* Nothing to do. */ -} diff --git a/sysdeps/mach/hurd/pt-sigstate-init.c b/sysdeps/mach/hurd/pt-sigstate-init.c deleted file mode 100644 index da5a9455..00000000 --- a/sysdeps/mach/hurd/pt-sigstate-init.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Initialize the signal state. Hurd on Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include - -error_t -__pthread_sigstate_init (struct __pthread *thread) -{ - void **location = - (void *) __hurd_threadvar_location_from_sp (_HURD_THREADVAR_SIGSTATE, - thread->stackaddr); - - /* The real initialization happens internally in glibc the first - time that _hurd_thead_sigstate is called. */ - *location = 0; - - return 0; -} diff --git a/sysdeps/mach/hurd/pt-sigstate.c b/sysdeps/mach/hurd/pt-sigstate.c deleted file mode 100644 index 68c79c5b..00000000 --- a/sysdeps/mach/hurd/pt-sigstate.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Set a thread's signal state. Hurd on Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include - -error_t -__pthread_sigstate (struct __pthread *thread, int how, - const sigset_t *set, sigset_t *oset, - int clear_pending) -{ - error_t err = 0; - struct hurd_sigstate *ss; - - ss = _hurd_thread_sigstate (thread->kernel_thread); - assert (ss); - - __pthread_spin_lock (&ss->lock); - - if (oset) - *oset = ss->blocked; - - if (set) - switch (how) - { - case SIG_BLOCK: - ss->blocked |= *set; - break; - - case SIG_SETMASK: - ss->blocked = *set; - break; - - case SIG_UNBLOCK: - ss->blocked &= ~*set; - break; - - default: - err = EINVAL; - break; - } - - if (! err && clear_pending) - __sigemptyset (&ss->pending); - - __pthread_spin_unlock (&ss->lock); - - return err; -} diff --git a/sysdeps/mach/hurd/pt-sysdep.c b/sysdeps/mach/hurd/pt-sysdep.c deleted file mode 100644 index 5e070067..00000000 --- a/sysdeps/mach/hurd/pt-sysdep.c +++ /dev/null @@ -1,72 +0,0 @@ -/* System dependent pthreads code. Hurd version. - Copyright (C) 2000, 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include -#include - -#include - -#include - -/* Forward. */ -static void *init_routine (void); - -/* OK, the name of this variable isn't really appropriate, but I don't - want to change it yet. */ -void *(*_cthread_init_routine)(void) = &init_routine; - -/* This function is called from the Hurd-specific startup code. It - should return a new stack pointer for the main thread. The caller - will switch to this new stack before doing anything serious. */ -static void * -init_routine (void) -{ - struct __pthread *thread; - int err; - - /* Initialize the library. */ - __pthread_initialize (); - - /* Create the pthread structure for the main thread (i.e. us). */ - err = __pthread_create_internal (&thread, 0, 0, 0); - assert_perror (err); - - ((void **) (__hurd_threadvar_stack_offset))[_HURD_THREADVAR_THREAD] - = thread; - - /* Decrease the number of threads, to take into account that the - signal thread (which will be created by the glibc startup code - when we return from here) shouldn't be seen as a user thread. */ - __pthread_total--; - - /* Make MiG code thread aware. */ - __mig_init (thread->stackaddr); - - /* Make sure we can find the per-thread variables. */ - __hurd_threadvar_stack_mask = ~(__pthread_default_attr.stacksize - 1); - __hurd_threadvar_stack_offset - = (__pthread_default_attr.stacksize - - __hurd_threadvar_max * sizeof (uintptr_t)); - - return thread->mcontext.sp; -} diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h deleted file mode 100644 index f14a1366..00000000 --- a/sysdeps/mach/hurd/pt-sysdep.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Internal defenitions for pthreads library. - Copyright (C) 2000, 2002, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _PT_SYSDEP_H -#define _PT_SYSDEP_H 1 - -#include - -#include - -/* XXX */ -#define _POSIX_THREAD_THREADS_MAX 64 - -/* The default stack size. */ -#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) - -#define PTHREAD_SYSDEP_MEMBERS \ - thread_t kernel_thread; \ - mach_msg_header_t wakeupmsg; \ - int have_kernel_resources; - -#define _HURD_THREADVAR_THREAD _HURD_THREADVAR_DYNAMIC_USER - -#define _pthread_self() \ - ({ \ - struct __pthread *thread; \ - \ - assert (__pthread_threads); \ - thread = *(struct __pthread **) \ - __hurd_threadvar_location (_HURD_THREADVAR_THREAD); \ - \ - assert (thread); \ - assert (({ mach_port_t ktid = __mach_thread_self (); \ - int ok = thread->kernel_thread == ktid; \ - __mach_port_deallocate (__mach_task_self (), ktid);\ - ok; })); \ - thread; \ - }) - -extern inline void -__attribute__((__always_inline__)) -__pthread_stack_dealloc (void *stackaddr, size_t stacksize) -{ - __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize); -} - -/* Change thread THREAD's program counter to PC if SET_PC is true and - its stack pointer to SP if SET_IP is true. */ -extern int __thread_set_pcsp (thread_t thread, - int set_pc, void *pc, - int set_sp, void *sp); - - -#endif /* pt-sysdep.h */ diff --git a/sysdeps/mach/pt-block.c b/sysdeps/mach/pt-block.c deleted file mode 100644 index a947b27c..00000000 --- a/sysdeps/mach/pt-block.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Block a thread. Mach version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include -#include - -#include - -/* Block THREAD. */ -void -__pthread_block (struct __pthread *thread) -{ - mach_msg_header_t msg; - error_t err; - - err = __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg, - thread->wakeupmsg.msgh_remote_port, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - assert_perror (err); -} diff --git a/sysdeps/mach/pt-spin.c b/sysdeps/mach/pt-spin.c deleted file mode 100644 index d9a2a32a..00000000 --- a/sysdeps/mach/pt-spin.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Spin locks. Mach version. - Copyright (C) 2002, 2004 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -/* In glibc. */ -extern void __spin_lock_solid (__pthread_spinlock_t *lock); - -/* Lock the spin lock object LOCK. If the lock is held by another - thread spin until it becomes available. */ -int -_pthread_spin_lock (__pthread_spinlock_t *lock) -{ - __spin_lock_solid (lock); - return 0; -} - -weak_alias (_pthread_spin_lock, pthread_spin_lock); -weak_alias (_pthread_spin_lock, __pthread_spin_lock); diff --git a/sysdeps/mach/pt-stack-alloc.c b/sysdeps/mach/pt-stack-alloc.c deleted file mode 100644 index 0956fc7d..00000000 --- a/sysdeps/mach/pt-stack-alloc.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Allocate a new stack. Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -#include -#include - -#include - -#define __pthread_stacksize __pthread_default_attr.stacksize - -/* The next address to use for stack allocation. */ -static vm_address_t next_stack_base = VM_MIN_ADDRESS; - - -/* Allocate a new stack of size STACKSIZE. If successful, store the - address of the newly allocated stack in *STACKADDR and return 0. - Otherwise return an error code (EINVAL for an invalid stack size, - EAGAIN if the system lacked the necessary resources to allocate a - new stack). */ -int -__pthread_stack_alloc (void **stackaddr, size_t stacksize) -{ - vm_offset_t base; - int i = 0; - - if (stacksize != __pthread_stacksize) - return EINVAL; - - get_stack: - i ++; - for (base = next_stack_base; - base < VM_MAX_ADDRESS - && __vm_allocate (__mach_task_self (), &base, - __pthread_stacksize, FALSE) != KERN_SUCCESS; - base += __pthread_stacksize) - ; - - if (base >= VM_MAX_ADDRESS) - { - if (i == 1) - { - next_stack_base = VM_MIN_ADDRESS; - goto get_stack; - } - else - return EAGAIN; - } - - if (base >= VM_MAX_ADDRESS) - return EAGAIN; - - next_stack_base = base + __pthread_stacksize; - - (*stackaddr) = (void *) base; - return 0; -} diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c deleted file mode 100644 index 3d7c0465..00000000 --- a/sysdeps/mach/pt-thread-alloc.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Start thread. Mach version. - Copyright (C) 2000, 2002, 2005, 2008 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -#include - -/* Prepare a wakeup message. */ -static error_t -create_wakeupmsg (struct __pthread *thread) -{ - kern_return_t err; - - /* Build wakeup message. */ - thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); - thread->wakeupmsg.msgh_size = 0; - - err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE, - &thread->wakeupmsg.msgh_remote_port); - if (err) - return EAGAIN; - - thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL; - thread->wakeupmsg.msgh_seqno = 0; - thread->wakeupmsg.msgh_id = 0; - - err = __mach_port_insert_right (__mach_task_self (), - thread->wakeupmsg.msgh_remote_port, - thread->wakeupmsg.msgh_remote_port, - MACH_MSG_TYPE_MAKE_SEND); - if (err) - { - __mach_port_destroy (__mach_task_self (), - thread->wakeupmsg.msgh_remote_port); - return EAGAIN; - } - - return 0; -} - -/* Allocate any resouces for THREAD. The new kernel thread should not - be eligible to be scheduled. */ -int -__pthread_thread_alloc (struct __pthread *thread) -{ - if (thread->have_kernel_resources) - return 0; - - error_t err; - - err = create_wakeupmsg (thread); - if (err) - return err; - - /* If there are no pthreads in the system then the pthread library - is bootstrapping and the main thread must create initialize - itself. The thread itself is already running, it just has not - pthread context. We want to reuse what it already has (including - the kernel thread), however, we must determine which thread is - the main thread. - - We cannot test if __pthread_total is one as we later decrement - before creating the signal thread. Currently, we check if - __pthread_num_threads--the number of allocated thread - structures--is one. __pthread_alloc has already been called in - __pthread_create_internal for us. This predicate could be improved, - however, it is sufficient for now. */ - if (__pthread_num_threads == 1) - { - assert (__pthread_total == 0); - thread->kernel_thread = __mach_thread_self (); - /* We implicitly hold a reference drop the one that we just - acquired. */ - __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); - } - else - { - err = __thread_create (__mach_task_self (), &thread->kernel_thread); - if (err) - return EAGAIN; - } - - thread->have_kernel_resources = 1; - - return 0; -} diff --git a/sysdeps/mach/pt-thread-dealloc.c b/sysdeps/mach/pt-thread-dealloc.c deleted file mode 100644 index 55d8c4d5..00000000 --- a/sysdeps/mach/pt-thread-dealloc.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Deallocate the kernel thread resources. Mach version. - Copyright (C) 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Deallocate any kernel resources associated with THREAD except don't - halt the thread itself. On return, the thread will be marked as - dead and __pthread_halt will be called. */ -void -__pthread_thread_dealloc (struct __pthread *thread) -{ - /* Why no assert? Easy. When Mach kills a task, it starts by - invalidating the task port and then terminating the threads one - by one. But while it is terminating them, they are still - eligible to be scheduled. Imagine we have two threads, one calls - exit, one calls pthread_exit. The second one may run this after - the mask port can been destroyed thus gratuitously triggering the - assert. */ - __mach_port_destroy (__mach_task_self (), - thread->wakeupmsg.msgh_remote_port); -} diff --git a/sysdeps/mach/pt-thread-halt.c b/sysdeps/mach/pt-thread-halt.c deleted file mode 100644 index 973cde1e..00000000 --- a/sysdeps/mach/pt-thread-halt.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Deallocate the kernel thread resources. Mach version. - Copyright (C) 2000, 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is - true, the function must call __pthread_dealloc on THREAD. - - NB: The thread executing this function may be the thread which is - being halted, thus the last action should be halting the thread - itself. */ -void -__pthread_thread_halt (struct __pthread *thread) -{ - error_t err = __thread_terminate (thread->kernel_thread); - assert_perror (err); -} diff --git a/sysdeps/mach/pt-thread-start.c b/sysdeps/mach/pt-thread-start.c deleted file mode 100644 index 11b017ff..00000000 --- a/sysdeps/mach/pt-thread-start.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Start thread. Mach version. - Copyright (C) 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -#include - -/* Start THREAD. Get the kernel thread scheduled and running. */ -int -__pthread_thread_start (struct __pthread *thread) -{ - error_t err; - - if (__pthread_num_threads == 1) - { - /* The main thread is already running: do nothing. */ - assert (__pthread_total == 1); - assert (({ mach_port_t ktid = __mach_thread_self (); - int ok = thread->kernel_thread == ktid; - __mach_port_deallocate (__mach_task_self (), - thread->kernel_thread); - ok; })); - } - else - { - err = __thread_resume (thread->kernel_thread); - assert_perror (err); - } - - return 0; -} diff --git a/sysdeps/mach/pt-timedblock.c b/sysdeps/mach/pt-timedblock.c deleted file mode 100644 index 6f547265..00000000 --- a/sysdeps/mach/pt-timedblock.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Block a thread with a timeout. Mach version. - Copyright (C) 2000, 2002, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include - -#include -#include - -#include - -/* Block THREAD. */ -error_t -__pthread_timedblock (struct __pthread *thread, - const struct timespec *abstime) -{ - error_t err; - mach_msg_header_t msg; - mach_msg_timeout_t timeout; - struct timeval now; - - /* We have an absolute time and now we have to convert it to a - relative time. Arg. */ - - err = gettimeofday(&now, NULL); - assert (! err); - - if (now.tv_sec > abstime->tv_sec - || (now.tv_sec == abstime->tv_sec - && now.tv_usec > ((abstime->tv_nsec + 999) / 1000))) - return ETIMEDOUT; - - timeout = (abstime->tv_sec - now.tv_sec) * 1000; - - if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec) - timeout += (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000; - else - /* Need to do a carry. */ - timeout -= (now.tv_usec + 999) / 1000 - - ((abstime->tv_nsec + 999999) / 1000000); - - err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, - sizeof msg, thread->wakeupmsg.msgh_remote_port, - timeout, MACH_PORT_NULL); - if (err == EMACH_RCV_TIMED_OUT) - return ETIMEDOUT; - - assert_perror (err); - return 0; -} diff --git a/sysdeps/mach/pt-wakeup.c b/sysdeps/mach/pt-wakeup.c deleted file mode 100644 index 4920d102..00000000 --- a/sysdeps/mach/pt-wakeup.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Wakeup a thread. Mach version. - 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include -#include - -#include - -/* Wakeup THREAD. */ -void -__pthread_wakeup (struct __pthread *thread) -{ - error_t err; - - err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG, - sizeof (thread->wakeupmsg), 0, MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - assert_perror (err); -} diff --git a/sysdeps/posix/pt-spin.c b/sysdeps/posix/pt-spin.c deleted file mode 100644 index cb809c64..00000000 --- a/sysdeps/posix/pt-spin.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Spin locks. - Copyright (C) 2000, 2004, 2005 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -/* The default for single processor machines; don't spin, it's - pointless. */ -#ifndef __PTHREAD_SPIN_COUNT -# define __PTHREAD_SPIN_COUNT 1 -#endif - -/* The number of times to spin while trying to lock a spin lock object - before yielding the processor. */ -int __pthread_spin_count = __PTHREAD_SPIN_COUNT; - - -/* Lock the spin lock object LOCK. If the lock is held by another - thread spin until it becomes available. */ -int -_pthread_spin_lock (__pthread_spinlock_t *lock) -{ - int i; - - while (1) - { - for (i = 0; i < __pthread_spin_count; i++) - { - if (__pthread_spin_trylock (lock) == 0) - return 0; - } - - __sched_yield (); - } -} - -weak_alias (_pthread_spin_lock, pthread_spin_lock); -weak_alias (_pthread_spin_lock, __pthread_spin_lock); diff --git a/sysdeps/powerpc/bits/machine-lock.h b/sysdeps/powerpc/bits/machine-lock.h deleted file mode 100644 index cba6b0a6..00000000 --- a/sysdeps/powerpc/bits/machine-lock.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Machine-specific definition for spin locks. PowerPC version. - Copyright (C) 1994,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. */ - -#ifndef _MACHINE_LOCK_H -#define _MACHINE_LOCK_H - -/* The type of a spin lock variable. */ - -typedef __volatile long int __spin_lock_t; - -/* Value to initialize `__spin_lock_t' variables to. */ - -#define __SPIN_LOCK_INITIALIZER 0L - - -#ifndef _EXTERN_INLINE -#define _EXTERN_INLINE extern __inline -#endif - -/* Unlock LOCK. */ - -_EXTERN_INLINE void -__spin_unlock (__spin_lock_t *__lock) -{ - long int __locked; - __asm__ __volatile__ ("\ -0: lwarx %0,0,%1\n\ - stwcx. %2,0,%1\n\ - bne- 0b\n\ -" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); -} - -/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ - -_EXTERN_INLINE int -__spin_try_lock (register __spin_lock_t *__lock) -{ - long int __rtn; - __asm__ __volatile__ ("\ -0: lwarx %0,0,%1\n\ - stwcx. %2,0,%1\n\ - bne- 0b\n\ -" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); - return !__rtn; -} - -/* Return nonzero if LOCK is locked. */ - -_EXTERN_INLINE int -__spin_lock_locked (__spin_lock_t *__lock) -{ - long int __rtn; - __asm__ __volatile__ ("\ -0: lwarx %0,0,%1\n\ - stwcx. %0,0,%1\n\ - bne- 0b\n\ -" : "=&r" (__rtn) : "r" (__lock) : "cr0"); - return __rtn; -} - - -#endif /* machine-lock.h */ diff --git a/sysdeps/powerpc/bits/memory.h b/sysdeps/powerpc/bits/memory.h deleted file mode 100644 index 96624c3e..00000000 --- a/sysdeps/powerpc/bits/memory.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Memory barrier operations. PowerPC version. - Copyright (C) 2003 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _BITS_MEMORY_H -#define _BITS_MEMORY_H 1 - -/* Prevent read and write reordering across this function. */ -inline void -__memory_barrier (void) -{ - asm ("sync" ::: "memory"); -} - -/* Prevent read reordering across this function. */ -#define __memory_read_barrier __memory_barrier - -/* Prevent write reordering across this function. */ -#define __memory_write_barrier __memory_barrier - -#endif diff --git a/sysdeps/powerpc/bits/spin-lock.h b/sysdeps/powerpc/bits/spin-lock.h deleted file mode 100644 index 1dc25710..00000000 --- a/sysdeps/powerpc/bits/spin-lock.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Machine-specific definitions for spin locks. PowerPC version. - Copyright (C) 2003 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * Never include this file directly; use or instead. - */ - -#ifndef _BITS_SPIN_LOCK_H -#define _BITS_SPIN_LOCK_H 1 - -#include - -__BEGIN_DECLS - -/* The type of a spin lock object. */ -typedef __volatile int __pthread_spinlock_t; - -/* Initializer for a spin lock object. */ -# define __SPIN_LOCK_INITIALIZER ((__pthread_spinlock_t) 0) - -#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES - -# ifndef __EBUSY -# include -# define __EBUSY EBUSY -# endif - -# ifndef __PT_SPIN_INLINE -# define __PT_SPIN_INLINE extern __inline -# endif - -__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_destroy (__pthread_spinlock_t *__lock) -{ - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock, - int __pshared); - -__PT_SPIN_INLINE int -__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared) -{ - *__lock = __SPIN_LOCK_INITIALIZER; - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_trylock (__pthread_spinlock_t *__lock) -{ - long int __rtn; - __asm__ __volatile__ ("\ -0: lwarx %0,0,%1\n\ - stwcx. %2,0,%1\n\ - bne- 0b\n\ -" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); - return __rtn ? __EBUSY : 0; -} - -extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); -extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); - -extern inline int -__pthread_spin_lock (__pthread_spinlock_t *__lock) -{ - if (__pthread_spin_trylock (__lock)) - return _pthread_spin_lock (__lock); - return 0; -} - -__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock); - -__PT_SPIN_INLINE int -__pthread_spin_unlock (__pthread_spinlock_t *__lock) -{ - long int __locked; - __asm__ __volatile__ ("\ -0: lwarx %0,0,%1\n\ - stwcx. %2,0,%1\n\ - bne- 0b\n\ -" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); -} - -#endif /* Use extern inlines or force inlines. */ - -__END_DECLS - -#endif /* bits/spin-lock.h */ diff --git a/sysdeps/powerpc/machine-sp.h b/sysdeps/powerpc/machine-sp.h deleted file mode 100644 index aa787c59..00000000 --- a/sysdeps/powerpc/machine-sp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Machine-specific function to return the stack pointer. i386 version. - Copyright (C) 1994,97,2001 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. */ - -#ifndef _MACHINE_SP_H -#define _MACHINE_SP_H - -/* Return the current stack pointer. */ - -#define __thread_stack_pointer() ({ \ - void *__sp__; \ - __asm__ ("mr %0, 1" : "=r" (__sp__)); \ - __sp__; \ -}) - -#endif /* machine-sp.h */ diff --git a/sysdeps/powerpc/pt-machdep.h b/sysdeps/powerpc/pt-machdep.h deleted file mode 100644 index 6d456367..00000000 --- a/sysdeps/powerpc/pt-machdep.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Machine dependent pthreads internal defenitions. i386 version. - Copyright (C) 2000 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef _PT_MACHDEP_H -#define _PT_MACHDEP_H 1 - -struct pthread_mcontext -{ - void *pc; - void *sp; -}; - -#endif /* pt-machdep.h */ diff --git a/tests/.cvsignore b/tests/.cvsignore deleted file mode 100644 index 70845e08..00000000 --- a/tests/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile.in diff --git a/tests/Makefile b/tests/Makefile deleted file mode 100644 index 9509c957..00000000 --- a/tests/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -CFLAGS=-Wall -g - -LDLIBS = -lpthread - -CHECK_SRC := test-1.c test-2.c test-3.c test-6.c test-7.c test-8.c \ - test-9.c test-10.c test-11.c test-12.c test-13.c test-14.c \ - test-15.c test-16.c - -CHECK_OBJS := $(addsuffix .o,$(basename $(notdir $(CHECK_SRC)))) -CHECK_PROGS := $(basename $(notdir $(CHECK_SRC))) \ - $(addsuffix -static, $(basename $(CHECK_SRC))) - -%-static: %.o - $(CC) -static $(CFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS) - -check: $(CHECK_OBJS) $(CHECK_PROGS) - for i in $(CHECK_PROGS); do \ - echo -n Running $$i...\ ; \ - if ./$$i 2>&1 > $$i.out; \ - then \ - echo Success.; \ - else \ - echo Failure.; \ - fi \ - done - -clean: - rm -f $(CHECK_OBJS) $(CHECK_PROGS) \ - $(addsuffix .out,$(basename $(notdir $(CHECK_PROGS)))) \ No newline at end of file diff --git a/tests/test-1.c b/tests/test-1.c deleted file mode 100644 index 318fd6e9..00000000 --- a/tests/test-1.c +++ /dev/null @@ -1,49 +0,0 @@ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#define THREADS 500 - -void * -foo (void *arg) -{ - pthread_mutex_t *mutex = arg; - pthread_mutex_lock (mutex); - pthread_mutex_unlock (mutex); - return mutex; -} - -int -main (int argc, char **argv) -{ - int i; - error_t err; - pthread_t tid[THREADS]; - pthread_mutex_t mutex[THREADS]; - - for (i = 0; i < THREADS; i ++) - { - pthread_mutex_init (&mutex[i], 0); - pthread_mutex_lock (&mutex[i]); - err = pthread_create (&tid[i], 0, foo, &mutex[i]); - if (err) - error (1, err, "pthread_create"); - sched_yield (); - } - - for (i = THREADS - 1; i >= 0; i --) - { - void *ret; - pthread_mutex_unlock (&mutex[i]); - err = pthread_join (tid[i], &ret); - if (err) - error (1, err, "pthread_join"); - assert (ret == &mutex[i]); - } - - return 0; -} diff --git a/tests/test-10.c b/tests/test-10.c deleted file mode 100644 index bec05c14..00000000 --- a/tests/test-10.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Test error checking mutexes. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include - -int -main (int argc, char **argv) -{ - error_t err; - pthread_mutexattr_t mattr; - pthread_mutex_t mutex; - - err = pthread_mutexattr_init (&mattr); - if (err) - error (1, err, "pthread_mutexattr_init"); - - err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_ERRORCHECK); - if (err) - error (1, err, "pthread_mutexattr_settype"); - - err = pthread_mutex_init (&mutex, &mattr); - if (err) - error (1, err, "pthread_mutex_init"); - - err = pthread_mutexattr_destroy (&mattr); - if (err) - error (1, err, "pthread_mutexattr_destroy"); - - err = pthread_mutex_lock (&mutex); - assert (err == 0); - - err = pthread_mutex_lock (&mutex); - assert (err == EDEADLK); - - err = pthread_mutex_unlock (&mutex); - assert (err == 0); - - err = pthread_mutex_unlock (&mutex); - assert (err == EPERM); - - return 0; -} diff --git a/tests/test-11.c b/tests/test-11.c deleted file mode 100644 index de779a40..00000000 --- a/tests/test-11.c +++ /dev/null @@ -1,143 +0,0 @@ -/* Test rwlocks. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include - -#define THREADS 1 - -int a; -int b; - -/* Get a read lock and assert that a == b. */ -void * -test1 (void *arg) -{ - error_t err; - pthread_rwlock_t *lock = arg; - int i; - - for (i = 0; i < 200; i ++) - { - err = pthread_rwlock_rdlock (lock); - assert (err == 0); - - assert (a == b); - - sched_yield (); - - assert (a == b); - - err = pthread_rwlock_unlock (lock); - assert (err == 0); - } - - return 0; -} - -int -main (int argc, char **argv) -{ - error_t err; - pthread_rwlockattr_t attr; - pthread_rwlock_t lock; - int pshared; - - int i; - pthread_t tid[THREADS]; - void *ret; - - err = pthread_rwlockattr_init (&attr); - if (err) - error (1, err, "pthread_rwlockattr_init"); - - err = pthread_rwlockattr_getpshared (&attr, &pshared); - if (err) - error (1, err, "pthread_rwlockattr_getpshared"); - - /* Assert the default state as mandated by POSIX. */ - assert (pshared == PTHREAD_PROCESS_PRIVATE); - - err = pthread_rwlockattr_setpshared (&attr, pshared); - if (err) - error (1, err, "pthread_rwlockattr_setpshared"); - - err = pthread_rwlock_init (&lock, &attr); - if (err) - error (1, err, "pthread_rwlock_init"); - - err = pthread_rwlockattr_destroy (&attr); - if (err) - error (1, err, "pthread_rwlockattr_destroy"); - - /* Now test the lock. */ - - for (i = 0; i < THREADS; i ++) - { - err = pthread_create (&tid[i], 0, test1, &lock); - if (err) - error (1, err, "pthread_create"); - } - - for (i = 0; i < 10; i ++) - { - sched_yield (); - - /* Get a write lock. */ - pthread_rwlock_wrlock (&lock); - /* Increment a and b giving other threads a chance to run in - between. */ - sched_yield (); - a ++; - sched_yield (); - b ++; - sched_yield (); - /* Unlock. */ - pthread_rwlock_unlock (&lock); - } - - for (i = 0; i < THREADS; i ++) - { - err = pthread_join (tid[i], &ret); - if (err) - error (1, err, "pthread_join"); - } - - /* Read lock it. */ - err = pthread_rwlock_tryrdlock (&lock); - assert (err == 0); - - /* Try to write lock it. It should fail with EBUSY. */ - err = pthread_rwlock_trywrlock (&lock); - assert (err == EBUSY); - - /* Drop the read lock. */ - err = pthread_rwlock_unlock (&lock); - assert (err == 0); - - /* Get a write lock. */ - err = pthread_rwlock_trywrlock (&lock); - assert (err == 0); - - /* Fail trying to acquire another write lock. */ - err = pthread_rwlock_trywrlock (&lock); - assert (err == EBUSY); - - /* Try to get a read lock which should also fail. */ - err = pthread_rwlock_tryrdlock (&lock); - assert (err == EBUSY); - - /* Unlock it. */ - err = pthread_rwlock_unlock (&lock); - assert (err == 0); - - - err = pthread_rwlock_destroy (&lock); - if (err) - error (1, err, "pthread_rwlock_destroy"); - - return 0; -} diff --git a/tests/test-12.c b/tests/test-12.c deleted file mode 100644 index 2b784908..00000000 --- a/tests/test-12.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Test concurrency level. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include - -int -main (int argc, char **argv) -{ - int i; - int err; - - i = pthread_getconcurrency (); - assert (i == 0); - - err = pthread_setconcurrency (-1); - assert (err == EINVAL); - - err = pthread_setconcurrency (4); - assert (err == 0); - - i = pthread_getconcurrency (); - assert (i == 4); - - return 0; -} diff --git a/tests/test-13.c b/tests/test-13.c deleted file mode 100644 index 13b09051..00000000 --- a/tests/test-13.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Test condition attributes and pthread_cond_timedwait. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -int -main (int argc, char **argv) -{ - error_t err; - int i; - pthread_condattr_t attr; - pthread_cond_t cond; - struct timespec ts; - pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; - struct timeval before, after; - int diff; - - err = pthread_condattr_init (&attr); - if (err) - error (1, err, "pthread_condattr_init"); - - err = pthread_condattr_getpshared (&attr, &i); - if (err) - error (1, err, "pthread_condattr_getpshared"); - assert (i == PTHREAD_PROCESS_PRIVATE); - - err = pthread_condattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); - assert (err == 0); - - err = pthread_cond_init (&cond, &attr); - if (err) - error (1, err, "pthread_cond_init"); - - err = pthread_condattr_destroy (&attr); - if (err) - error (1, err, "pthread_condattr_destroy"); - - gettimeofday (&before, 0); - ts.tv_sec = before.tv_sec + 1; - ts.tv_nsec = before.tv_usec * 1000; - - printf ("Starting wait @ %d\n", (int) before.tv_sec); - - pthread_mutex_lock (&m); - err = pthread_cond_timedwait (&cond, &m, &ts); - - gettimeofday (&after, 0); - - printf ("End wait @ %d (err = %d)\n", (int) after.tv_sec, err); - - assert (err == ETIMEDOUT); - - diff = after.tv_sec * 1000000 + after.tv_usec - - before.tv_sec * 1000000 - before.tv_usec; - - if (diff < 900000 || diff > 1100000) - error (1, EGRATUITOUS, "pthread_cond_timedwait waited %d us", diff); - - return 0; -} diff --git a/tests/test-14.c b/tests/test-14.c deleted file mode 100644 index b1dbfa66..00000000 --- a/tests/test-14.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Test pthread_mutex_timedlock. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -int -main (int argc, char **argv) -{ - error_t err; - struct timespec ts; - pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; - struct timeval before, after; - int diff; - - gettimeofday (&before, 0); - ts.tv_sec = before.tv_sec + 1; - ts.tv_nsec = before.tv_usec * 1000; - - printf ("Starting wait @ %d\n", (int) before.tv_sec); - - pthread_mutex_lock (&m); - /* A default mutex shall dead lock if locked twice. As such we do - not need spawn a second thread. */ - err = pthread_mutex_timedlock (&m, &ts); - assert (err == ETIMEDOUT); - - gettimeofday (&after, 0); - - printf ("End wait @ %d\n", (int) after.tv_sec); - - diff = after.tv_sec * 1000000 + after.tv_usec - - before.tv_sec * 1000000 - before.tv_usec; - - if (diff < 900000 || diff > 1100000) - error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); - - return 0; -} diff --git a/tests/test-15.c b/tests/test-15.c deleted file mode 100644 index 173f8b6b..00000000 --- a/tests/test-15.c +++ /dev/null @@ -1,87 +0,0 @@ -/* Test pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -#define THREADS 10 - -pthread_rwlock_t rwlock; - -void * -test (void *arg) -{ - error_t err; - int foo = (int) arg; - struct timespec ts; - struct timeval before, after; - int diff; - - gettimeofday (&before, 0); - ts.tv_sec = before.tv_sec + 1; - ts.tv_nsec = before.tv_usec * 1000; - - printf ("Thread %d starting wait @ %d\n", pthread_self (), - (int) before.tv_sec); - - if (foo % 2 == 0) - err = pthread_rwlock_timedrdlock (&rwlock, &ts); - else - err = pthread_rwlock_timedwrlock (&rwlock, &ts); - - assert (err == ETIMEDOUT); - - gettimeofday (&after, 0); - - printf ("Thread %d ending wait @ %d\n", pthread_self (), - (int) after.tv_sec); - - diff = after.tv_sec * 1000000 + after.tv_usec - - before.tv_sec * 1000000 - before.tv_usec; - - if (diff < 900000 || diff > 1100000) - error (1, EGRATUITOUS, "pthread_mutex_timedlock waited %d us", diff); - - return 0; -} - -int -main (int argc, char **argv) -{ - error_t err; - int i; - pthread_t tid[THREADS]; - - err = pthread_rwlock_init (&rwlock, 0); - if (err) - error (1, err, "pthread_rwlock_init"); - - /* Lock it so all the threads will block. */ - err = pthread_rwlock_wrlock (&rwlock); - assert (err == 0); - - for (i = 0; i < THREADS; i ++) - { - err = pthread_create (&tid[i], 0, test, (void *) i); - if (err) - error (1, err, "pthread_create"); - } - - for (i = 0; i < THREADS; i ++) - { - void *ret; - - err = pthread_join (tid[i], &ret); - if (err) - error (1, err, "pthread_join"); - - assert (ret == 0); - } - - return 0; -} diff --git a/tests/test-16.c b/tests/test-16.c deleted file mode 100644 index b6a52d01..00000000 --- a/tests/test-16.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Test pthread_kill.c. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include - -pthread_t testthread; - -int i; - -void * -test (void *arg) -{ - error_t err; - - printf ("test: %d\n", pthread_self ()); - - err = pthread_kill (pthread_self (), SIGINFO); - if (err) - error (1, err, "pthread_kill"); - - /* To avoid using condition variables in a signal handler. */ - while (i == 0) - sched_yield (); - - return 0; -} - -static void -handler (int sig, siginfo_t *info, void *context) -{ - assert (pthread_equal (pthread_self (), testthread)); - printf ("handler: %d\n", pthread_self ()); - i = 1; -} - -int -main (int argc, char **argv) -{ - error_t err; - struct sigaction sa; - void *ret; - - printf ("main: %d\n", pthread_self ()); - - sa.sa_handler = handler; - sa.sa_mask = 0; - sa.sa_flags = 0; - - err = sigaction (SIGINFO, &sa, 0); - if (err) - error (1, err, "sigaction"); - - err = pthread_create (&testthread, 0, test, 0); - if (err) - error (1, err, "pthread_create"); - - err = pthread_join (testthread, &ret); - if (err) - error (1, err, "pthread_join"); - - assert (ret == 0); - - return 0; -} diff --git a/tests/test-2.c b/tests/test-2.c deleted file mode 100644 index 701462e8..00000000 --- a/tests/test-2.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Test detachability. */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -void * -thread (void *arg) -{ - while (1) - sched_yield (); -} - -int -main (int argc, char **argv) -{ - int err; - pthread_t tid; - void *ret; - - err = pthread_create (&tid, 0, thread, 0); - if (err) - error (1, err, "pthread_create"); - - err = pthread_detach (tid); - if (err) - error (1, err, "pthread_detach"); - - err = pthread_detach (tid); - assert (err == EINVAL); - - err = pthread_join (tid, &ret); - assert (err == EINVAL); - - return 0; -} diff --git a/tests/test-3.c b/tests/test-3.c deleted file mode 100644 index 7db2e43f..00000000 --- a/tests/test-3.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Test the thread attribute get and set methods. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include - -int -main (int argc, char *argv[]) -{ - error_t err; - pthread_attr_t attr; - - int i; - struct sched_param sp; - void *p; - size_t sz; - - err = pthread_attr_init (&attr); - assert_perror (err); - - err = pthread_attr_destroy (&attr); - assert_perror (err); - - err = pthread_attr_init (&attr); - assert_perror (err); - -#define TEST1(foo, rv, v) \ - err = pthread_attr_get##foo (&attr, rv); \ - assert_perror (err); \ - \ - err = pthread_attr_set##foo (&attr, v); \ - assert_perror (err); - -#define TEST(foo, rv, v) TEST1(foo, rv, v) - - TEST(inheritsched, &i, i); - TEST(schedparam, &sp, &sp); - TEST(schedpolicy, &i, i); - TEST(scope, &i, i); - TEST(stackaddr, &p, p); - TEST(detachstate, &i, i); - TEST(guardsize, &sz, sz); - TEST(stacksize, &sz, sz); - - err = pthread_attr_getstack (&attr, &p, &sz); - assert_perror (err); - - err = pthread_attr_setstack (&attr, p, sz); - assert_perror (err); - - return 0; -} diff --git a/tests/test-4.c b/tests/test-4.c deleted file mode 100644 index de9c8fe4..00000000 --- a/tests/test-4.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Test the stack guard. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -size_t stacksize; - -void * -thr (void *arg) -{ - int i; - char *foo; - - foo = alloca (3 * stacksize / 4); - for (i = 0; i < sizeof foo; i ++) - foo[i] = -1; - - return (void *) 1; -} - -int -main (int argc, char *argv[]) -{ - error_t err; - pid_t child; - - child = fork (); - switch (child) - { - case -1: - error (1, errno, "fork"); - break; - - case 0: - { - pthread_attr_t attr; - pthread_t tid; - void *ret; - - err = pthread_attr_init (&attr); - assert_perror (err); - - err = pthread_attr_getstacksize (&attr, &stacksize); - assert_perror (err); - - err = pthread_attr_setguardsize (&attr, stacksize / 2); - if (err == ENOTSUP) - { - printf ("Stack guard attribute not supported.\n"); - return 1; - } - assert_perror (err); - - err = pthread_create (&tid, &attr, thr, 0); - assert_perror (err); - - err = pthread_attr_destroy (&attr); - assert_perror (err); - - err = pthread_join (tid, &ret); - /* Should never be successful. */ - printf ("Thread did not segfault!?!\n"); - assert_perror (err); - return 0; - } - - default: - { - pid_t pid; - int status; - - pid = waitpid (child, &status, 0); - printf ("pid = %d; child = %d; status = %d\n", pid, child, status); - assert (pid == child); - assert (status != 0); - } - } - - return 0; -} diff --git a/tests/test-5.c b/tests/test-5.c deleted file mode 100644 index 0f5000b2..00000000 --- a/tests/test-5.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Test signals. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include - -void * -thr (void *arg) -{ - * (int *)0 = 0; - return 0; -} - -int foobar; - -int -main (int argc, char *argv[]) -{ - error_t err; - pid_t child; - - struct rlimit limit; - - limit.rlim_cur = 0; - limit.rlim_max = 0; - - err = setrlimit (RLIMIT_CORE, &limit); - if (err) - error (1, err, "setrlimit"); - - child = fork (); - switch (child) - { - case -1: - error (1, errno, "fork"); - break; - - case 0: - { - pthread_t tid; - void *ret; - - err = pthread_create (&tid, 0, thr, 0); - if (err) - error (1, err, "pthread_create"); - - err = pthread_join (tid, &ret); - assert_perror (err); - - /* Should have never returned. Our parent expects us to fail - thus we succeed and indicate the error. */ - return 0; - } - - default: - { - pid_t pid; - int status; - - pid = waitpid (child, &status, 0); - printf ("pid = %d; child = %d; status = %d\n", pid, child, status); - assert (pid == child); - assert (status != 0); - } - } - - return 0; -} diff --git a/tests/test-6.c b/tests/test-6.c deleted file mode 100644 index 98aa8ba7..00000000 --- a/tests/test-6.c +++ /dev/null @@ -1,95 +0,0 @@ -#define _GNU_SOURCE - -#include -#include -#include -#include - -#define THREADS 500 -#define WAITS 3 - -void * -dowait (void *arg) -{ - pthread_barrier_t *barrier = arg; - int ret; - - ret = pthread_barrier_wait (barrier); - printf ("%d ", pthread_self ()); - return (void *) ret; -} - -int -main (int argc, char **argv) -{ - pthread_barrierattr_t attr; - pthread_barrier_t barrier; - - int i, j; - error_t err; - pthread_t tid[THREADS]; - - int havesyncs; - - err = pthread_barrierattr_init (&attr); - if (err) - error (1, err, "pthread_barrierattr_init"); - - err = pthread_barrierattr_getpshared (&attr, &i); - if (err) - error (1, err, "pthread_barrierattr_getpshared"); - assert (i == PTHREAD_PROCESS_PRIVATE || i == PTHREAD_PROCESS_SHARED); - - err = pthread_barrierattr_setpshared (&attr, PTHREAD_PROCESS_PRIVATE); - if (err) - error (1, err, "pthread_barrierattr_setpshared"); - - err = pthread_barrier_init (&barrier, &attr, THREADS + 1); - if (err) - error (1, err, "pthread_barrier_init"); - - for (j = 0; j < WAITS; j ++) - { - - for (i = 0; i < THREADS; i ++) - { - err = pthread_create (&tid[i], 0, dowait, &barrier); - if (err) - error (1, err, "pthread_create (%d)", i); - } - - printf ("Manager will now call pthread_barrier_wait.\n"); - - havesyncs - = pthread_barrier_wait (&barrier) == PTHREAD_BARRIER_SERIAL_THREAD - ? 1 : 0; - - for (i = THREADS - 1; i >= 0; i --) - { - void *ret; - err = pthread_join (tid[i], &ret); - if (err) - error (1, err, "pthread_join"); - - switch ((int) ret) - { - case 0: - break; - - case PTHREAD_BARRIER_SERIAL_THREAD: - havesyncs ++; - break; - - default: - assert (! "Unknown value returned from pthread_barrier_wait."); - break; - } - } - - printf ("\n"); - - assert (havesyncs == 1); - } - - return 0; -} diff --git a/tests/test-7.c b/tests/test-7.c deleted file mode 100644 index bd97acfa..00000000 --- a/tests/test-7.c +++ /dev/null @@ -1,66 +0,0 @@ -#define _GNU_SOURCE - -#include -#include -#include -#include - -#define THREADS 10 -#define KEYS 400 - -pthread_key_t key[KEYS]; - -void * -thr (void *arg) -{ - error_t err; - int i; - - for (i = 0; i < KEYS; i ++) - { - printf ("pthread_getspecific(%d).\n", key[i]); - assert (pthread_getspecific (key[i]) == NULL); - printf ("pthread_setspecific(%d, %d).\n", key[i], pthread_self ()); - err = pthread_setspecific (key[i], (void *) pthread_self ()); - printf ("pthread_setspecific(%d, %d) => %d.\n", key[i], pthread_self (), err); - assert_perror (err); - } - - return 0; -} - -int -main (int argc, char **argv) -{ - error_t err; - int i; - pthread_t tid[THREADS]; - - void des (void *val) - { - assert ((pthread_t) val == pthread_self ()); - } - - for (i = 0; i < KEYS; i ++) - err = pthread_key_create (&key[i], des); - - for (i = 0; i < THREADS; i ++) - { - err = pthread_create (&tid[i], 0, thr, 0); - if (err) - error (1, err, "pthread_create (%d)", i); - } - - for (i = 0; i < THREADS; i ++) - { - void *ret; - - err = pthread_join (tid[i], &ret); - if (err) - error (1, err, "pthread_join"); - - assert (ret == 0); - } - - return 0; -} diff --git a/tests/test-8.c b/tests/test-8.c deleted file mode 100644 index 85a7f8f6..00000000 --- a/tests/test-8.c +++ /dev/null @@ -1,60 +0,0 @@ -#define _GNU_SOURCE - -#include -#include -#include -#include - -#define THREADS 10 - -pthread_once_t inc_var_once = PTHREAD_ONCE_INIT; -int var; - -void -inc_var (void) -{ - var ++; -} - -void * -thr (void *arg) -{ - int i; - - for (i = 0; i < 500; i ++) - pthread_once (&inc_var_once, inc_var); - - return 0; -} - -int -main (int argc, char **argv) -{ - error_t err; - int i; - pthread_t tid[THREADS]; - - for (i = 0; i < THREADS; i ++) - { - err = pthread_create (&tid[i], 0, thr, 0); - if (err) - error (1, err, "pthread_create (%d)", i); - } - - assert (thr (0) == 0); - - for (i = 0; i < THREADS; i ++) - { - void *ret; - - err = pthread_join (tid[i], &ret); - if (err) - error (1, err, "pthread_join"); - - assert (ret == 0); - } - - assert (var == 1); - - return 0; -} diff --git a/tests/test-9.c b/tests/test-9.c deleted file mode 100644 index 82051570..00000000 --- a/tests/test-9.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Test recursive mutexes. */ - -#define _GNU_SOURCE - -#include -#include -#include -#include - -#define THREADS 10 - -int foo; - -void * -thr (void *arg) -{ - int i; - - pthread_mutex_lock (arg); - - foo = pthread_self (); - - for (i = 0; i < 500; i ++) - pthread_mutex_lock (arg); - for (i = 0; i < 500; i ++) - pthread_mutex_unlock (arg); - - assert (foo == pthread_self ()); - - pthread_mutex_unlock (arg); - - return 0; -} - -int -main (int argc, char **argv) -{ - error_t err; - int i; - pthread_t tid[THREADS]; - pthread_mutexattr_t mattr; - pthread_mutex_t mutex; - - err = pthread_mutexattr_init (&mattr); - if (err) - error (1, err, "pthread_mutexattr_init"); - - err = pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_RECURSIVE); - if (err) - error (1, err, "pthread_mutexattr_settype"); - - err = pthread_mutex_init (&mutex, &mattr); - if (err) - error (1, err, "pthread_mutex_init"); - - err = pthread_mutexattr_destroy (&mattr); - if (err) - error (1, err, "pthread_mutexattr_destroy"); - - pthread_mutex_lock (&mutex); - pthread_mutex_lock (&mutex); - pthread_mutex_unlock (&mutex); - pthread_mutex_unlock (&mutex); - - for (i = 0; i < THREADS; i ++) - { - err = pthread_create (&tid[i], 0, thr, &mutex); - if (err) - error (1, err, "pthread_create (%d)", i); - } - - for (i = 0; i < THREADS; i ++) - { - void *ret; - - err = pthread_join (tid[i], &ret); - if (err) - error (1, err, "pthread_join"); - - assert (ret == 0); - } - - err = pthread_mutex_destroy (&mutex); - if (err) - error (1, err, "pthread_mutex_destroy"); - - return 0; -} -- cgit v1.2.3 From ae5f861010e23248573efa3addbcd3f115c7d9d4 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 1 Aug 2010 01:06:33 +0200 Subject: move file to libpthread/ --- libpthread/pt-yield.c | 26 ++++++++++++++++++++++++++ pthread/pt-yield.c | 26 -------------------------- 2 files changed, 26 insertions(+), 26 deletions(-) create mode 100644 libpthread/pt-yield.c delete mode 100644 pthread/pt-yield.c diff --git a/libpthread/pt-yield.c b/libpthread/pt-yield.c new file mode 100644 index 00000000..27848bb7 --- /dev/null +++ b/libpthread/pt-yield.c @@ -0,0 +1,26 @@ +/* Yield the processor to another thread or process. + Copyright (C) 2010 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +int pthread_yield(void) +{ + return sched_yield (); +} diff --git a/pthread/pt-yield.c b/pthread/pt-yield.c deleted file mode 100644 index 27848bb7..00000000 --- a/pthread/pt-yield.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Yield the processor to another thread or process. - Copyright (C) 2010 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 Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -int pthread_yield(void) -{ - return sched_yield (); -} -- cgit v1.2.3 From 41ad1a2b52b6479c778a908c3dacee29c47619db Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Thu, 14 Aug 2008 15:24:00 +0200 Subject: 2008-08-14 Madhusudan.C.S * ChangeLog: New file added to procfs * AUTHORS: New file added to procfs * COPYING: New file added to procfs * README: New file added to procfs * Makefile: New file added to procfs * bootstrap.c: New file added to procfs * netfs.c: New file added to procfs * node.c: New file added to procfs * procfs.c: New file added to procfs * procfs.h: New file added to procfs * procfs_dir.c: New file added to procfs * procfs_nonpid_files.c: New file added to procfs * procfs_pid.h: New file added to procfs * procfs_pid_files.c: New file added to procfs --- AUTHORS | 10 + bootstrap.c | 95 +++++++++ netfs.c | 466 ++++++++++++++++++++++++++++++++++++++++ node.c | 195 +++++++++++++++++ procfs.c | 149 +++++++++++++ procfs.h | 218 +++++++++++++++++++ procfs_dir.c | 575 ++++++++++++++++++++++++++++++++++++++++++++++++++ procfs_nonpid_files.c | 462 ++++++++++++++++++++++++++++++++++++++++ procfs_pid.h | 86 ++++++++ procfs_pid_files.c | 570 +++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 2826 insertions(+) create mode 100644 AUTHORS create mode 100644 bootstrap.c create mode 100644 netfs.c create mode 100644 node.c create mode 100644 procfs.c create mode 100644 procfs.h create mode 100644 procfs_dir.c create mode 100644 procfs_nonpid_files.c create mode 100644 procfs_pid.h create mode 100644 procfs_pid_files.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..622b6488 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,10 @@ +Written By +~~~~~~~~~~ + +Madhusudan.C.S + + +Mentored By +~~~~~~~~~~~ + +Olaf Buddenhagen diff --git a/bootstrap.c b/bootstrap.c new file mode 100644 index 00000000..73d31f00 --- /dev/null +++ b/bootstrap.c @@ -0,0 +1,95 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + bootstrap.c -- This file is functions for starting up + and initializers for the procfs translator + defined in procfs.h + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#include +#include +#include + +#include "procfs.h" + +struct ps_context *ps_context; + +/* This function is used to initialize the whole translator, can be + effect called as bootstrapping the translator. */ +error_t procfs_init () +{ + error_t err; + + err = ps_context_create (getproc (), &ps_context); + + return err; +} + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs) +{ + error_t err; + /* This is the enclosing directory for this filesystem's + root node */ + struct procfs_dir *topmost_root_dir; + + /* And also a topmost-root node, just used for locking + TOPMOST_ROOT_DIR. */ + struct node *topmost_root; + + /* The new node for the filesystem's root. */ + struct procfs *new = malloc (sizeof (struct procfs)); + + if (! new) + return ENOMEM; + + new->fsid = fsid; + new->next_inode = 2; + + hurd_ihash_init (&new->inode_mappings, + offsetof (struct procfs_dir_entry, inode_locp)); + spin_lock_init (&new->inode_mappings_lock); + + topmost_root = netfs_make_node (0); + if (! topmost_root) + err = ENOMEM; + else + { + err = procfs_dir_create (new, topmost_root, procfs_root, + &topmost_root_dir); + if (! err) + { + /* ADDITIONAL BOOTSTRAPPING OF THE ROOT NODE */ + err = procfs_dir_null_lookup (topmost_root_dir, &new->root); + } + } + + if (err) + { + hurd_ihash_destroy (&new->inode_mappings); + free (new); + } + else + *fs = new; + + return err; +} + diff --git a/netfs.c b/netfs.c new file mode 100644 index 00000000..31ffe1b5 --- /dev/null +++ b/netfs.c @@ -0,0 +1,466 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "procfs.h" + +/* Trivial definitions. */ + +/* Make sure that NP->nn_stat is filled with current information. CRED + identifies the user responsible for the operation. */ +error_t +netfs_validate_stat (struct node *node, struct iouser *cred) +{ + return procfs_refresh_node (node); +} + +/* This should sync the file NODE completely to disk, for the user CRED. If + WAIT is set, return only after sync is completely finished. */ +error_t +netfs_attempt_sync (struct iouser *cred, struct node *node, int wait) +{ + return 0; +} + +/* Attempt to create a new directory named NAME in DIR for USER with mode + MODE. */ +error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, + char *name, mode_t mode) +{ + return EROFS; +} + +/* Attempt to remove directory named NAME in DIR for USER. */ +error_t netfs_attempt_rmdir (struct iouser *user, + struct node *dir, char *name) +{ + return EROFS; +} + +/* Attempt to set the passive translator record for FILE to ARGZ (of length + ARGZLEN) for user CRED. */ +error_t netfs_set_translator (struct iouser *cred, struct node *node, + char *argz, size_t argzlen) +{ + return EROFS; +} + +/* Attempt to create a file named NAME in DIR for USER with MODE. Set *NODE + to the new node upon return. On any error, clear *NODE. *NODE should be + locked on success; no matter what, unlock DIR before returning. */ +error_t +netfs_attempt_create_file (struct iouser *user, struct node *dir, + char *name, mode_t mode, struct node **node) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* Node NODE is being opened by USER, with FLAGS. NEWNODE is nonzero if we + just created this node. Return an error if we should not permit the open + to complete because of a permission restriction. */ +error_t +netfs_check_open_permissions (struct iouser *user, struct node *node, + int flags, int newnode) +{ + error_t err = procfs_refresh_node (node); + if (!err && (flags & O_READ)) + err = fshelp_access (&node->nn_stat, S_IREAD, user); + if (!err && (flags & O_WRITE)) + err = fshelp_access (&node->nn_stat, S_IWRITE, user); + if (!err && (flags & O_EXEC)) + err = fshelp_access (&node->nn_stat, S_IEXEC, user); + return err; +} + +/* This should attempt a utimes call for the user specified by CRED on node + NODE, to change the atime to ATIME and the mtime to MTIME. */ +error_t +netfs_attempt_utimes (struct iouser *cred, struct node *node, + struct timespec *atime, struct timespec *mtime) +{ + error_t err = procfs_refresh_node (node); + int flags = TOUCH_CTIME; + + if (! err) + err = fshelp_isowner (&node->nn_stat, cred); + + if (! err) + { + if (atime) + node->nn_stat.st_atim = *atime; + else + flags |= TOUCH_ATIME; + + if (mtime) + node->nn_stat.st_mtim = *mtime; + else + flags |= TOUCH_MTIME; + + fshelp_touch (&node->nn_stat, flags, procfs_maptime); + } + + return err; +} + +/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and O_EXEC) + in *TYPES for file NODE and user CRED. */ +error_t +netfs_report_access (struct iouser *cred, struct node *node, int *types) +{ + error_t err = procfs_refresh_node (node); + + if (! err) + { + *types = 0; + if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + } + + return err; +} + +/* The granularity with which we allocate space to return our result. */ +#define DIRENTS_CHUNK_SIZE (8*1024) + +/* Returned directory entries are aligned to blocks this many bytes long. + Must be a power of two. */ +#define DIRENT_ALIGN 4 +#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) + +/* Length is structure before the name + the name + '\0', all + padded to a four-byte alignment. */ +#define DIRENT_LEN(name_len) \ + ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ + & ~(DIRENT_ALIGN - 1)) + + + +/* Fetch a directory */ +error_t +netfs_get_dirents (struct iouser *cred, struct node *dir, + int first_entry, int max_entries, char **data, + mach_msg_type_number_t *data_len, + vm_size_t max_data_len, int *data_entries) +{ + error_t err = procfs_refresh_node (dir); + struct procfs_dir_entry *dir_entry; + + if (! err) + { + if (dir->nn->dir) + { + if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root)) + { + for (dir_entry = dir->nn->dir->ordered; first_entry > 0 && + dir_entry; first_entry--, + dir_entry = dir_entry->ordered_next); + if (! dir_entry ) + max_entries = 0; + + if (max_entries != 0) + { + size_t size = 0; + char *p; + int count = 0; + + + if (max_data_len == 0) + size = DIRENTS_CHUNK_SIZE; + else if (max_data_len > DIRENTS_CHUNK_SIZE) + size = DIRENTS_CHUNK_SIZE; + else + size = max_data_len; + + *data = mmap (0, size, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + err = ((void *) *data == (void *) -1) ? errno : 0; + + if (! err) + { + p = *data; + + /* This gets all the actual entries present. */ + + while ((max_entries == -1 || count < max_entries) && dir_entry) + { + struct dirent hdr; + size_t name_len = strlen (dir_entry->name); + size_t sz = DIRENT_LEN (name_len); + int entry_type = IFTODT (dir_entry->stat.st_mode); + + if ((p - *data) + sz > size) + { + if (max_data_len > 0) + break; + else /* The Buffer Size must be increased. */ + { + vm_address_t extension = (vm_address_t)(*data + size); + err = vm_allocate (mach_task_self (), &extension, + DIRENTS_CHUNK_SIZE, 0); + + if (err) + break; + + size += DIRENTS_CHUNK_SIZE; + } + } + + hdr.d_namlen = name_len; + hdr.d_fileno = dir_entry->stat.st_ino; + hdr.d_reclen = sz; + hdr.d_type = entry_type; + + memcpy (p, &hdr, DIRENT_NAME_OFFS); + strcpy (p + DIRENT_NAME_OFFS, dir_entry->name); + + p += sz; + + count++; + dir_entry = dir_entry->ordered_next; + } + + if (err) + munmap (*data, size); + else + { + vm_address_t alloc_end = (vm_address_t)(*data + size); + vm_address_t real_end = round_page (p); + if (alloc_end > real_end) + munmap ((caddr_t) real_end, alloc_end - real_end); + *data_len = p - *data; + *data_entries = count; + } + } + } + else + { + *data_len = 0; + *data_entries = 0; + } + } + } + else + return ENOTDIR; + } + + return err; +} + +/* Lookup NAME in DIR for USER; set *NODE to the found name upon return. If + the name was not found, then return ENOENT. On any error, clear *NODE. + (*NODE, if found, should be locked, this call should unlock DIR no matter + what.) */ +error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, + char *name, struct node **node) +{ + error_t err = procfs_refresh_node (dir); + + if (! err) + err = procfs_dir_lookup (dir->nn->dir, name, node); + + return err; +} + +/* Delete NAME in DIR for USER. */ +error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, + char *name) +{ + return EROFS; +} + +/* Note that in this one call, neither of the specific nodes are locked. */ +error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, + char *fromname, struct node *todir, + char *toname, int excl) +{ + return EROFS; +} + +/* This should attempt a chmod call for the user specified by CRED on node + NODE, to change the owner to UID and the group to GID. */ +error_t netfs_attempt_chown (struct iouser *cred, struct node *node, + uid_t uid, uid_t gid) +{ + return EROFS; +} + +/* This should attempt a chauthor call for the user specified by CRED on node + NODE, to change the author to AUTHOR. */ +error_t netfs_attempt_chauthor (struct iouser *cred, struct node *node, + uid_t author) +{ + return EROFS; +} + +/* This should attempt a chmod call for the user specified by CRED on node + NODE, to change the mode to MODE. Unlike the normal Unix and Hurd meaning + of chmod, this function is also used to attempt to change files into other + types. If such a transition is attempted which is impossible, then return + EOPNOTSUPP. */ +error_t netfs_attempt_chmod (struct iouser *cred, struct node *node, + mode_t mode) +{ + return EROFS; +} + +/* Attempt to turn NODE (user CRED) into a symlink with target NAME. */ +error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *node, + char *name) +{ + return EROFS; +} + +/* Attempt to turn NODE (user CRED) into a device. TYPE is either S_IFBLK or + S_IFCHR. */ +error_t netfs_attempt_mkdev (struct iouser *cred, struct node *node, + mode_t type, dev_t indexes) +{ + return EROFS; +} + + +/* This should attempt a chflags call for the user specified by CRED on node + NODE, to change the flags to FLAGS. */ +error_t netfs_attempt_chflags (struct iouser *cred, struct node *node, + int flags) +{ + return EROFS; +} + +/* This should attempt to set the size of the file NODE (for user CRED) to + SIZE bytes long. */ +error_t netfs_attempt_set_size (struct iouser *cred, struct node *node, + off_t size) +{ + return EROFS; +} + +/* This should attempt to fetch filesystem status information for the remote + filesystem, for the user CRED. */ +error_t +netfs_attempt_statfs (struct iouser *cred, struct node *node, + struct statfs *st) +{ + bzero (st, sizeof *st); + st->f_type = PROCFILESYSTEM; + st->f_fsid = getpid (); + return 0; +} + +/* This should sync the entire remote filesystem. If WAIT is set, return + only after sync is completely finished. */ +error_t netfs_attempt_syncfs (struct iouser *cred, int wait) +{ + return 0; +} + +/* Create a link in DIR with name NAME to FILE for USER. Note that neither + DIR nor FILE are locked. If EXCL is set, do not delete the target, but + return EEXIST if NAME is already found in DIR. */ +error_t netfs_attempt_link (struct iouser *user, struct node *dir, + struct node *file, char *name, int excl) +{ + return EROFS; +} + +/* Attempt to create an anonymous file related to DIR for USER with MODE. + Set *NODE to the returned file upon success. No matter what, unlock DIR. */ +error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, + mode_t mode, struct node **node) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* Read the contents of NODE (a symlink), for USER, into BUF. */ +error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) +{ + error_t err = procfs_refresh_node (node); + if (! err) + { + struct procfs_dir_entry *dir_entry = node->nn->dir_entry; + if (dir_entry) + bcopy (dir_entry->symlink_target, buf, node->nn_stat.st_size); + else + err = EINVAL; + } + return err; +} + +/* Read from the file NODE for user CRED starting at OFFSET and continuing for + up to *LEN bytes. Put the data at DATA. Set *LEN to the amount + successfully read upon return. */ +error_t netfs_attempt_read (struct iouser *cred, struct node *node, + off_t offset, size_t *len, void *data) +{ + error_t err; + err = procfs_refresh_node (node); + + if (! err) + { + if (*len > 0) + procfs_write_files_contents (node, offset, + len, data); + if (*len > 0) + if (offset >= *len) + *len = 0; + } + + return err; +} + +/* Write to the file NODE for user CRED starting at OFFSET and continuing for up + to *LEN bytes from DATA. Set *LEN to the amount seccessfully written upon + return. */ +error_t netfs_attempt_write (struct iouser *cred, struct node *node, + off_t offset, size_t *len, void *data) +{ + return EROFS; +} + +/* The user must define this function. Node NP is all done; free + all its associated storage. */ +void netfs_node_norefs (struct node *np) +{ + mutex_lock (&np->lock); + *np->prevp = np->next; + np->next->prevp = np->prevp; + procfs_remove_node (np); +} + diff --git a/node.c b/node.c new file mode 100644 index 00000000..f11fa7b0 --- /dev/null +++ b/node.c @@ -0,0 +1,195 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + node.c -- This file contains function defintions to handle + node creation and destruction. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "procfs.h" + +/* Return a new node in NODE, with a name NAME, and return the + new node with a single reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, struct node **node) +{ + struct node *new; + struct netnode *nn = malloc (sizeof (struct netnode)); + error_t err; + + if (! nn) + return ENOMEM; + if (! fs_path) + fs_path = strdup (""); + nn->fs = dir_entry->dir->fs; + nn->dir_entry = dir_entry; + nn->dir = NULL; + nn->fs_path = strdup (fs_path); + + new = netfs_make_node (nn); + if (! new) + { + free (nn); + return ENOMEM; + } + + fshelp_touch (&new->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, + procfs_maptime); + + spin_lock (&nn->fs->inode_mappings_lock); + err = hurd_ihash_add (&nn->fs->inode_mappings, dir_entry->stat.st_ino, dir_entry); + spin_unlock (&nn->fs->inode_mappings_lock); + + if (err) + { + free (nn); + free (new); + return err; + } + + dir_entry->node = new; + *node = new; + + return 0; +} + +/* Update the directory entry for NAME to reflect ST and SYMLINK_TARGET. + True is returned if successful, or false if there was a memory allocation + error. TIMESTAMP is used to record the time of this update. */ +static void +update_entry (struct procfs_dir_entry *dir_entry, const struct stat *st, + const char *symlink_target, time_t timestamp) +{ + ino_t ino; + struct procfs *fs = dir_entry->dir->fs; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (st) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *st; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; +} + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node) +{ + struct netnode *nn = node->nn; + struct procfs_dir_entry *dir_entry = nn->dir_entry; + + if (! dir_entry) + /* This is a deleted node, don't attempt to do anything. */ + return 0; + else + { + error_t err = 0; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + struct procfs_dir *dir = dir_entry->dir; + + mutex_lock (&dir->node->lock); + + if (! dir_entry->self_p) + /* This is a deleted entry, just awaiting disposal; do so. */ + { +#if 0 + nn->dir_entry = 0; + free_entry (dir_entry); + return 0; +#endif + } + + else if (dir_entry->noent) + err = ENOENT; + else + { + if (*(dir_entry->name)) + { + err = procfs_dir_refresh (dir_entry->dir, + dir_entry->dir->node == dir_entry->dir->fs->root); + if (!err && dir_entry->noent) + err = ENOENT; + + if (err == ENOENT) + { + dir_entry->noent = 1; /* A negative entry. */ + dir_entry->name_timestamp = timestamp; + } + } + else + { + /* Refresh the root node with the old stat + information. */ + update_entry (dir_entry, &netfs_root_node->nn_stat, NULL, timestamp); + } + } + + node->nn_stat = dir_entry->stat; + node->nn_translated = S_ISLNK (dir_entry->stat.st_mode) ? S_IFLNK : 0; + if (!nn->dir && S_ISDIR (dir_entry->stat.st_mode)) + procfs_dir_create (nn->fs, node, nn->fs_path, &nn->dir); + + mutex_unlock (&dir->node->lock); + + return err; + } +} + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node) +{ + + /* STUB */ + + return 0; +} diff --git a/procfs.c b/procfs.c new file mode 100644 index 00000000..1fd0d619 --- /dev/null +++ b/procfs.c @@ -0,0 +1,149 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.c -- This file is the main file of the translator. + This has important definitions and initializes + the translator + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "procfs.h" + +/* Defines this Tanslator Name */ +char *netfs_server_name = PROCFS_SERVER_NAME; +char *netfs_server_version = PROCFS_SERVER_VERSION; +int netfs_maxsymlinks = 12; + +static const struct argp_child argp_children[] = + { + {&netfs_std_startup_argp, 0, NULL, 0}, + {0} + }; + + +const char *argp_program_version = "/proc pseudo-filesystem (" PROCFS_SERVER_NAME + ") " PROCFS_SERVER_VERSION "\n" +"Copyright (C) 2008 Free Software Foundation\n" +"This is free software; see the source for copying conditions. There is NO\n" +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +"\n"; + +static char *args_doc = "PROCFSROOT"; +static char *doc = "proc pseudo-filesystem for Hurd implemented as a translator. " +"This is still under very humble and initial stages of development.\n" +"Any Contribution or help is welcome. The code may not even compile"; + + +/* The Filesystem */ +struct procfs *procfs; + +/* The FILESYSTEM component of PROCFS_FS. */ +char *procfs_root = ""; + +volatile struct mapped_time_value *procfs_maptime; + +/* Startup options. */ +static const struct argp_option procfs_options[] = + { + { 0 } + }; + + +/* argp parser function for parsing single procfs command line options */ +static error_t +parse_procfs_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case ARGP_KEY_ARG: + if (state->arg_num > 1) + argp_usage (state); + break; + + case ARGP_KEY_NO_ARGS: + argp_usage(state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } +} + +/* Program entry point. */ +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t bootstrap, underlying_node; + struct stat underlying_stat; + + struct argp argp = + { + procfs_options, parse_procfs_opt, + args_doc, doc, argp_children, + NULL, NULL + }; + + + /* Parse the command line arguments */ +// argp_parse (&argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + + netfs_init (); + + if (maptime_map (0, 0, &procfs_maptime)) + { + perror (PROCFS_SERVER_NAME ": Cannot map time"); + return 1; + } + + procfs_init (); + + err = procfs_create (procfs_root, getpid (), &procfs); + if (err) + error (4, err, "%s", procfs_root); + + /* Create our root node */ + netfs_root_node = procfs->root; + + /* Start netfs activities */ + underlying_node = netfs_startup (bootstrap, 0); + if (io_stat (underlying_node, &underlying_stat)) + error (1, err, "cannot stat underling node"); + + /* Initialize stat information of the root node. */ + netfs_root_node->nn_stat = underlying_stat; + netfs_root_node->nn_stat.st_mode = + S_IFDIR | (underlying_stat.st_mode & ~S_IFMT & ~S_ITRANS); + + for (;;) + netfs_server_loop (); + return 1; +} diff --git a/procfs.h b/procfs.h new file mode 100644 index 00000000..95d4ee35 --- /dev/null +++ b/procfs.h @@ -0,0 +1,218 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.h -- This file is the main header file of this + translator. This has important header + definitions for constants and functions + used in the translator. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#ifndef __PROCFS_H__ +#define __PROCFS_H__ + +#define PROCFS_SERVER_NAME "procfs" +#define PROCFS_SERVER_VERSION "0.0.1" + +/* /proc Filesystem type. */ +#define PROCFILESYSTEM "procfs" + +#define NUMBER_OF_FILES_PER_PID 1 +#define JIFFY_ADJUST 100 +#define PAGES_TO_BYTES(pages) ((pages) * sysconf(_SC_PAGESIZE)) +#define BYTES_TO_PAGES(bytes) ((bytes) / sysconf(_SC_PAGESIZE)) + +#include +#include +#include +#include +#include +#include + +/* A single entry in a directory. */ +struct procfs_dir_entry +{ + char *name; /* Name of this entry */ + size_t hv; /* Hash value of NAME */ + + /* The active node referred to by this name (may be 0). + NETFS_NODE_REFCNT_LOCK should be held while frobbing this. */ + struct node *node; + + struct stat stat; + char *symlink_target; + time_t stat_timestamp; + + /* The directory to which this entry belongs. */ + struct procfs_dir *dir; + + /* Link to next entry in hash bucket, and address of previous entry's (or + hash table's) pointer to this entry. If the SELF_P field is 0, then + this is a deleted entry, awaiting final disposal. */ + struct procfs_dir_entry *next, **self_p; + + /* Next entry in 'directory order', or 0 if none known. */ + struct procfs_dir_entry *ordered_next, **ordered_self_p; + + /* When the presence/absence of this file was last checked. */ + time_t name_timestamp; + + hurd_ihash_locp_t inode_locp; /* Used for removing this entry */ + + int noent : 1; /* A negative lookup result. */ + int valid : 1; /* Marker for GC'ing. */ +}; + +/* A directory. */ +struct procfs_dir +{ + /* Number of entries in HTABLE. */ + size_t num_entries; + + /* The number of entries that have nodes attached. We keep an additional + reference to our node if there are any, to prevent it from going away. */ + size_t num_live_entries; + + /* Hash table of entries. */ + struct procfs_dir_entry **htable; + size_t htable_len; /* # of elements in HTABLE (not bytes). */ + + /* List of dir entries in 'directory order', in a linked list using the + ORDERED_NEXT and ORDERED_SELF_P fields in each entry. Not all entries + in HTABLE need be in this list. */ + struct procfs_dir_entry *ordered; + + /* The filesystem node that this is the directory for. */ + struct node *node; + + /* The filesystem this directory is in. */ + struct procfs *fs; + + /* The path to this directory in the filesystem. */ + const char *fs_path; + + time_t stat_timestamp; + time_t name_timestamp; + +}; + + +/* libnetfs node structure */ +struct netnode +{ + /* Name of this node */ + char *name; + + /* The path in the filesystem that corresponds + this node. */ + char *fs_path; + + /* The directory entry for this node. */ + struct procfs_dir_entry *dir_entry; + + /* The proc filesystem */ + struct procfs *fs; + + /* inode number, assigned to this netnode structure. */ + unsigned int inode_num; + + /* If this is a directory, the contents, or 0 if not fetched. */ + struct procfs_dir *dir; + + /* pointer to node structure, assigned to this node. */ + struct node *node; + + /* links to the previous and next nodes in the list */ + struct netnode *nextnode, *prevnode; + + /* link to parent netnode of this file or directory */ + struct netnode *parent; + + /* link to the first child netnode of this directory */ + struct netnode *child_first; +}; + +/* The actual procfs filesystem structure */ +struct procfs +{ + /* Root of the filesystem. */ + struct node *root; + + /* Inode numbers are assigned sequentially in order of creation. */ + ino_t next_inode; + int fsid; + + /* A hash table mapping inode numbers to directory entries. */ + struct hurd_ihash inode_mappings; + spin_lock_t inode_mappings_lock; +}; + +extern struct procfs *procfs; + +extern volatile struct mapped_time_value *procfs_maptime; + +extern struct ps_context *ps_context; + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs); + +/* Initialize the procfs filesystem for use. */ +error_t procfs_init (); + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node); + +/* Return a new node in NODE, with a name NAME, + and return the new node with a single + reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, + struct node **node); + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node); + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir); + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_remove (struct procfs_dir *dir); + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot); + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node); + +#endif /* __PROCFS_H__ */ diff --git a/procfs_dir.c b/procfs_dir.c new file mode 100644 index 00000000..b9b0410e --- /dev/null +++ b/procfs_dir.c @@ -0,0 +1,575 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_dir.c -- This file contains definitions to perform + directory operations such as creating, + removing and refreshing directories. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + + +#include +#include +#include +#include +#include + +#include "procfs.h" + +/* Initial HASHTABLE length for the new directories to be created. */ +#define INIT_HTABLE_LEN 5 + +struct procfs_dir_entry **cur_entry; + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir) +{ + struct procfs_dir *new = malloc (sizeof (struct procfs_dir)); + if (!new) + return ENOMEM; + struct procfs_dir_entry **htable = calloc (INIT_HTABLE_LEN, + sizeof (struct procfs_dir_entry *)); + if (!htable) + return ENOMEM; + + /* Hold a reference to the new dir's node. */ + spin_lock (&netfs_node_refcnt_lock); + node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + new->num_entries = 0; + new->num_live_entries = 0; + new->htable_len = INIT_HTABLE_LEN; + new->htable = htable; + new->ordered = NULL; + new->fs_path = path; + new->fs = fs; + new->node = node; + new->stat_timestamp = 0; + new->name_timestamp = 0; + + *dir = new; + + return 0; +} + +/* Put the directory entry DIR_ENTRY into the hash table HTABLE. */ +static void +insert (struct procfs_dir_entry *dir_entry, + struct procfs_dir_entry **htable, size_t htable_len) +{ + struct procfs_dir_entry **new_htable = &htable[dir_entry->hv % htable_len]; + if (*new_htable) + (*new_htable)->self_p = &dir_entry->next; + dir_entry->next = *new_htable; + dir_entry->self_p = new_htable; + *new_htable = dir_entry; +} + +/* Calculate NAME's hash value. */ +static size_t +hash (const char *name) +{ + size_t hash_value = 0; + while (*name) + hash_value = ((hash_value << 5) + *name++) & 0xFFFFFF; + return hash_value; +} + +/* Extend the existing hashtable for DIR to accomodate values for new length + NEW_LEN. We retain all the previous entries. */ +static error_t +rehash (struct procfs_dir *dir, size_t new_len) +{ + int count; + size_t old_len = dir->htable_len; + struct procfs_dir_entry **old_htable = dir->htable; + struct procfs_dir_entry **new_htable = (struct procfs_dir_entry **) + malloc (new_len * sizeof (struct procfs_dir_entry *)); + + if (! new_htable) + return ENOMEM; + + bzero (new_htable, new_len * sizeof (struct procfs_dir_entry *)); + + for (count = 0; count < old_len; count++) + while (old_htable[count]) + { + struct procfs_dir_entry *dir_entry = old_htable[count]; + + /* Remove DIR_ENTRY from the old table */ + old_htable[count] = dir_entry->next; + + insert (dir_entry, new_htable, new_len); + } + + free (old_htable); + + dir->htable = new_htable; + dir->htable_len = new_len; + + return 0; +} + +/* Lookup NAME in DIR and return its entry. If there is no such entry, and + DNEW, the decision variable, is true, then a new entry is allocated and + returned, otherwise 0 is returned (if DNEW is true then 0 can be returned + if a memory allocation error occurs). */ +struct procfs_dir_entry * +lookup_entry (struct procfs_dir *dir, const char *name, int dnew) +{ + size_t hv = hash (name); + struct procfs_dir_entry *dir_entry = dir->htable[hv % dir->htable_len]; + + while (dir_entry && strcmp (name, dir_entry->name) != 0) + dir_entry = dir_entry->next; + + if (!dir_entry && dnew) + { + if (dir->num_entries > dir->htable_len) + /* Grow the hash table. */ + if (rehash (dir, (dir->htable_len + 1) * 2 - 1) != 0) + return 0; + + dir_entry = + (struct procfs_dir_entry *) malloc (sizeof (struct procfs_dir_entry)); + + if (dir_entry) + { + dir_entry->hv = hv; + dir_entry->name = strdup (name); + dir_entry->node = 0; + dir_entry->dir = dir; + dir_entry->stat_timestamp = 0; + bzero (&dir_entry->stat, sizeof dir_entry->stat); + dir_entry->symlink_target = 0; + dir_entry->noent = 0; + dir_entry->valid = 0; + dir_entry->name_timestamp = 0; + dir_entry->ordered_next = 0; + dir_entry->ordered_self_p = 0; + dir_entry->next = 0; + dir_entry->self_p = 0; + insert (dir_entry, dir->htable, dir->htable_len); + dir->num_entries++; + } + } + + return dir_entry; +} + + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node) +{ + struct procfs_dir_entry *dir_entry = 0; + error_t err = 0; + char *fs_path = dir->fs_path; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + if (*name == '\0' || strcmp (name, ".") == 0) + /* Current directory -- just add an additional reference to DIR's node + and return it. */ + { + netfs_nref (dir->node); + *node = dir->node; + return 0; + } + else if (strcmp (name, "..") == 0) + /* Parent directory. */ + { + if (dir->node->nn->dir_entry) + { + *node = dir->node->nn->dir_entry->dir->node; + mutex_lock (&(*node)->lock); + netfs_nref (*node); + } + else + { + err = ENOENT; /* No .. */ + *node = 0; + } + + mutex_unlock (&dir->node->lock); + + return err; + } + + err = procfs_dir_refresh (dir, dir->node == dir->fs->root); + if (!err && !dir_entry) + dir_entry = lookup_entry (dir, name, 0); + + if (! err) + { + if (dir_entry && !dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go + away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into E. */ + { + if (! fs_path) + err = EROFS; + + if (! err) + { + err = procfs_create_node (dir_entry, fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to + children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + } + + if (! err) + { + *node = dir_entry->node; + /* We have to unlock DIR's node before locking the child node + because the locking order is always child-parent. We know + the child node won't go away because we already hold the + additional reference to it. */ + mutex_unlock (&dir->node->lock); + mutex_lock (&dir_entry->node->lock); + } + } + else + err = ENOENT; + } + + if (err) + { + *node = 0; + mutex_unlock (&dir->node->lock); + } + +#if 0 + if (fs_path) + free (fs_path); +#endif + + return err; +} + +/* Lookup the null name in DIR, and return a node for it in NODE. Unlike + procfs_dir_lookup, this won't attempt to validate the existance of the + entry (to avoid opening a new connection if possible) -- that will happen + the first time the entry is refreshed. Also unlink ftpfs_dir_lookup, this + function doesn't expect DIR to be locked, and won't return *NODE locked. + This function is only used for bootstrapping the root node. */ +error_t +procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) +{ + struct procfs_dir_entry *dir_entry; + error_t err = 0; + + dir_entry = lookup_entry (dir, "", 1); + if (! dir_entry) + return ENOMEM; + + if (! dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into DIR_ENTRY. */ + { + err = procfs_create_node (dir_entry, dir->fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + + if (! err) + *node = dir_entry->node; + } + else + err = ENOENT; + + return err; +} + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_remove (struct procfs_dir *dir) +{ + + /* STUB */ + + return 0; +} + +/* Make all the directory entries invalid */ +static void +make_dir_invalid (struct procfs_dir *dir) +{ + int count; + size_t len = dir->htable_len; + struct procfs_dir_entry **htable = dir->htable; + struct procfs_dir_entry *dir_entry; + + for (count = 0; count < len; count++) + { + dir_entry = htable[count]; + while (dir_entry) + { + dir_entry->valid = 0; + dir_entry = dir_entry->next; + } + } +} + +/* Checks if the DIR name is in list of + Active pids. */ +int is_in_pid_list (struct procfs_dir *dir) +{ + int dir_name; + int count; + pid_t *pids = NULL; + int pidslen = 0; + error_t err; + + if (dir->node->nn) + { + dir_name = atoi (dir->node->nn->dir_entry->name); + err = proc_getallpids (getproc (), &pids, &pidslen); + + for (count = 0; count < pidslen; ++count) + if (pids[count] == dir_name) + return 1; + } + + return 0; + +} + +/* Checks if DIR is a directory that + represents a pid. */ +int check_parent (struct procfs_dir *dir) +{ + if (dir == dir->fs->root) + return 0; + else + if (is_in_pid_list (dir)) + return 1; + else + return 0; + +} + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) +{ + error_t err; + int is_parent_pid; + struct node *node; + make_dir_invalid (dir); + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + cur_entry = &dir->ordered; + if (isroot) + err = procfs_fill_root_dir(dir, timestamp); + else + { + err = update_dir_entries (dir, timestamp); + is_parent_pid = check_parent (dir); + if (is_parent_pid) + err = procfs_create_files (dir, &node, timestamp); + } + + return err; +} + +/* Update the directory entry for NAME to reflect STAT and SYMLINK_TARGET. + This also creates a valid linked list of entries imposing ordering on + them. */ +struct procfs_dir_entry* +update_entries_list (struct procfs_dir *dir, const char *name, + const struct stat *stat, time_t timestamp, + const char *symlink_target) +{ + ino_t ino; + struct procfs_dir_entry *dir_entry = lookup_entry (dir, name, 1); + struct procfs *fs = dir->fs; + + if (! dir_entry) + return ENOMEM; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (stat) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *stat; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; + + dir_entry->valid = 1; + + if (! dir_entry->ordered_self_p) + /* Position DIR_ENTRY in the ordered chain following the previously seen entry. */ + { + /* The PREV_ENTRY_NEXT_P field holds a pointer to the NEXT-field of the + previous entry, or a pointer to the ORDERED field in the directory. */ + dir_entry->ordered_self_p = cur_entry; + + if (*dir_entry->ordered_self_p) + /* Update the self_p pointer of the previous successor. */ + (*dir_entry->ordered_self_p)->ordered_self_p = &dir_entry->ordered_next; + + /* DIR_ENTRY comes before the previous successor. */ + dir_entry->ordered_next = *dir_entry->ordered_self_p; + + *dir_entry->ordered_self_p = dir_entry; /* Put DIR_ENTRY there. */ + } + + /* Put the next entry after this one. */ + cur_entry = &dir_entry->ordered_next; + + return dir_entry; +} + +/* Fills DIR, the root directory with all the pids of + processes running in the system as directories. */ +error_t +procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) +{ + error_t err; + char *data; + pid_t *pids; + int pidslen; + struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); + stat->st_mode = S_IFDIR; + + int count; + char *dir_name_pid; + struct node *node; + struct procfs_dir *new_dir; + struct procfs_dir_entry *dir_entry; + + pids = NULL; + pidslen = 0; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + { + for (count = 0; count < pidslen; count++) + { + if (asprintf (&dir_name_pid, "%d", pids[count]) == -1) + return errno; + +#if 0 + node = (struct node *) malloc (sizeof (struct node)); + new_dir = (struct procfs_dir *) malloc (sizeof (struct procfs_dir )); + + if (! node || ! new_dir ) + return ENOMEM; +#endif + dir_entry = update_entries_list (dir, dir_name_pid, + stat, timestamp, NULL); + err = procfs_create_node (dir_entry, dir_name_pid, &node); + + procfs_dir_create (dir->fs, node, + dir_name_pid, &new_dir); + free(dir_name_pid); + } + } + + if ((err = procfs_create_uptime (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_stat (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_version (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_meminfo (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_loadavg (dir, &node, timestamp)) != 0) + return err; + + return 0; +} + +error_t update_dir_entries (struct procfs_dir *dir) +{ + /* STUB */ + return 0; +} diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c new file mode 100644 index 00000000..104ae8b3 --- /dev/null +++ b/procfs_nonpid_files.c @@ -0,0 +1,462 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_nonpid_files.c -- This file contains function definitions + to create and update the non-Per PID + files and their contents. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on vmstat.c code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "procfs.h" + +typedef long long val_t; +#define BADVAL ((val_t) - 1LL) + +/* default pager port (must be privileged to fetch this). */ +mach_port_t def_pager; +struct default_pager_info def_pager_info; + +error_t procfs_create_uptime (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "uptime") == -1) + return errno; + if (asprintf (&file_path, "%s", "uptime") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_version(struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "version") == -1) + return errno; + if (asprintf (&file_path, "%s", "version") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return 0; +} + +error_t procfs_create_stat (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s", "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_meminfo (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "meminfo") == -1) + return errno; + if (asprintf (&file_path, "%s", "meminfo") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_loadavg (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "loadavg") == -1) + return errno; + if (asprintf (&file_path, "%s", "loadavg") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t get_uptime (double *uptime_secs) +{ + struct timeval boot_time, uptime, now; + error_t err; + struct proc_stat *ps; + + err = _proc_stat_create (1, ps_context, &ps); + + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + time_value_t *const tv = &proc_stat_task_basic_info (ps)->creation_time; + boot_time.tv_sec = tv->seconds; + boot_time.tv_usec = tv->microseconds; + if (gettimeofday (&now, 0) < 0) + error (0, errno, "gettimeofday"); + timersub (&now, &boot_time, &uptime); + *uptime_secs = (double)uptime.tv_sec + ((double)uptime.tv_usec / 1000000); + } + + _proc_stat_free (ps); + return err; +} + +error_t get_total_times (double *total_user_time_secs , double *total_system_time_secs ) +{ + error_t err; + pid_t *pids; + int pidslen = 0, count; + struct proc_stat *ps; + struct task_thread_times_info live_threads_times; + + *total_user_time_secs = 0; + *total_system_time_secs = 0; + + pids = NULL; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + for (count = 0; count < pidslen; count++) + { + err = _proc_stat_create (pids[count], ps_context, &ps); + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + *total_user_time_secs += + ((double) (proc_stat_task_basic_info (ps)->user_time.seconds)) + + (((double) (proc_stat_task_basic_info (ps)->user_time.microseconds)) / + (1000 * 1000)); + + *total_system_time_secs += + ((double) (proc_stat_task_basic_info (ps)->system_time.seconds)) + + (((double) (proc_stat_task_basic_info (ps)->system_time.microseconds)) / (1000 * 1000)); + + error_t err = set_field_value (ps, PSTAT_TASK); + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + *total_user_time_secs += ((double) (live_threads_times.user_time.seconds)) + + (((double) (live_threads_times.user_time.microseconds)) / (1000 * 1000)); + *total_system_time_secs += ((double) (live_threads_times.system_time.seconds)) + + (((double) (live_threads_times.system_time.microseconds)) / (1000 * 1000)); + + } + } + } + _proc_stat_free (ps); + } + + return err; +} + +error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *stat_data; + error_t err; + double uptime_secs, total_user_time_secs; + double total_system_time_secs, idle_time_secs; + + err = get_uptime (&uptime_secs); + if (! err) + { + err = get_total_times (&total_user_time_secs, &total_system_time_secs); + if (! err) + { + idle_time_secs = uptime_secs - + total_system_time_secs; + + /* If the values are multiplied by 100, it iss done so to adjust + values in seconds to jiffies. */ + if (asprintf (&stat_data, "cpu %ld %ld %ld %ld %ld %ld %d %d %d\n" + "cpu0 %ld %ld %ld %ld %ld %ld %d %d %d\n" + "intr %ld %ld %ld %ld %ld %ld %d %d %d\n", + (long)(total_user_time_secs * 100), 0, + (long)(total_system_time_secs * 100), + (long) (idle_time_secs * 100), 0, 0, 0, 0, + 0, (long)(total_user_time_secs * 100), 0, + (long)(total_system_time_secs * 100), + (long)(idle_time_secs * 100), 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == -1) + return errno; + } + } + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + return err; +} + +/* Makes sure the default pager port and associated + info exists, and returns 0 if not (after printing + an error). */ +static int +ensure_def_pager_info () +{ + error_t err; + + if (def_pager == MACH_PORT_NULL) + { + mach_port_t host; + + err = get_privileged_ports (&host, 0); + if (err == EPERM) + { + /* We are not root, so try opening the /servers file. */ + def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); + if (def_pager == MACH_PORT_NULL) + { + error (0, errno, _SERVERS_DEFPAGER); + return 0; + } + } + if (def_pager == MACH_PORT_NULL) + { + if (err) + { + error (0, err, "get_privileged_ports"); + return 0; + } + + err = vm_set_default_memory_manager (host, &def_pager); + mach_port_deallocate (mach_task_self (), host); + + if (err) + { + error (0, err, "vm_set_default_memory_manager"); + return 0; + } + } + } + + if (!MACH_PORT_VALID (def_pager)) + { + if (def_pager == MACH_PORT_NULL) + { + error (0, 0, + "No default pager running, so no swap information available"); + def_pager = MACH_PORT_DEAD; /* so we don't try again */ + } + return 0; + } + + err = default_pager_info (def_pager, &def_pager_info); + if (err) + error (0, err, "default_pager_info"); + return (err == 0); +} + +#define SWAP_FIELD(getter, expr) \ + static val_t getter () \ + { return ensure_def_pager_info () ? (val_t) (expr) : BADVAL; } + +SWAP_FIELD (get_swap_size, def_pager_info.dpi_total_space) +SWAP_FIELD (get_swap_free, def_pager_info.dpi_free_space) +SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) +SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space + - def_pager_info.dpi_free_space)) + +error_t procfs_write_nonpid_meminfo (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *meminfo_data; + error_t err; + struct vm_statistics vmstats; + + err = vm_statistics (mach_task_self (), &vmstats); + + unsigned long mem_size = ((vmstats.free_count + + vmstats.active_count + vmstats.inactive_count + + vmstats.wire_count) * vmstats.pagesize) / 1024; + + if (! err) + if (asprintf (&meminfo_data, "MemTotal:\t%lu kB\n" + "MemFree:\t%lu kB\n" + "Buffers:\t%ld kB\n" + "Cached:\t\t%ld kB\n" + "SwapCached:\t%ld kB\n" + "Active:\t\t%lu kB\n" + "Inactive:\t%lu kB\n" + "HighTotal:\t%lu kB\n" + "HighFree:\t%lu kB\n" + "LowTotal:\t%lu kB\n" + "LowFree:\t%lu kB\n" + "SwapTotal:\t%lu kB\n" + "SwapFree:\t%lu kB\n", + mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, + (PAGES_TO_BYTES(vmstats.active_count)) / 1024, + (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, + get_swap_size (), get_swap_free ()) == -1) + return errno; + + memcpy (data, meminfo_data, strlen(meminfo_data)); + *len = strlen (data); + + free (meminfo_data); + return err; +} + +error_t procfs_write_nonpid_loadavg (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *loadavg_data; + error_t err; + processor_set_info_t info; + natural_t *count; + struct host_load_info *load; + mach_port_t host; + + err = ps_host_load_info (&load); + if (err) + error (0, err, "ps_host_load_info"); + + if (! err) + if (asprintf (&loadavg_data, "%.2f %.2f %.2f %d/%d %d\n", + (double)load->avenrun[0] / (double)LOAD_SCALE, + (double)load->avenrun[1] / (double)LOAD_SCALE, + (double)load->avenrun[2] / (double)LOAD_SCALE, 0, 0, 0) == -1) + return errno; + + memcpy (data, loadavg_data, strlen(loadavg_data)); + *len = strlen (data); + + free (loadavg_data); + return err; +} + +error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *uptime_data; + error_t err; + double uptime_secs, total_user_time_secs; + double total_system_time_secs, idle_time_secs; + + err = get_uptime (&uptime_secs); + if (! err) + { + err = get_total_times (&total_user_time_secs, + &total_system_time_secs); + if (! err) + { + idle_time_secs = uptime_secs - + total_system_time_secs; + + if (asprintf (&uptime_data, "%.2f %.2f \n", + uptime_secs, idle_time_secs) == -1) + return errno; + } + } + + + memcpy (data, uptime_data, strlen(uptime_data)); + *len = strlen (data); + + free (uptime_data); + return err; +} diff --git a/procfs_pid.h b/procfs_pid.h new file mode 100644 index 00000000..811cca84 --- /dev/null +++ b/procfs_pid.h @@ -0,0 +1,86 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid.h -- This is the header file of which contains defintions + for structure of directory with PID as the name and + structure of each file in this directory. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#ifndef __PROCFS_PID_H__ +#define __PROCFS_PID_H__ + +struct procfs_pid_files +{ + struct procfs_cwd *procfs_cwd; + struct procfs_environ *procfs_environ; + struct procfs_cpu *procfs_cpu; + struct procfs_root *procfs_root; + struct procfs_exe *procfs_exe; + struct procfs_stat *_procfs_stat; + struct procfs_statm *procfs_statm; +}; + +struct procfs_stat +{ + pid_t pid; + char *comm; + char *state; + pid_t ppid; + pid_t pgid; + pid_t sid; + int tty_nr; + pid_t tty_pgrp; + unsigned flags; + long unsigned minflt; + long unsigned cminflt; + long unsigned majflt; + long unsigned cmajflt; + time_t utime; + time_t stime; + time_t cutime; + time_t cstime; + long priority; + long nice; + long num_threads; + long itrealvalue; + long long unsigned starttime; + long unsigned vsize; + long rss; + long unsigned rlim; + long unsigned startcode; + long unsigned endcode; + long unsigned startstack; + long unsigned kstkesp; + long unsigned kstkeip; + long unsigned signal; + long unsigned blocked; + long unsigned sigignore; + long unsigned sigcatch; + long unsigned wchan; + long unsigned nswap; + long unsigned cnswap; + int exit_signal; + int processor; + unsigned rt_priority; + unsigned policy; + long long unsigned delayacct_blkio_ticks; +}; + +#endif diff --git a/procfs_pid_files.c b/procfs_pid_files.c new file mode 100644 index 00000000..1012510b --- /dev/null +++ b/procfs_pid_files.c @@ -0,0 +1,570 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid_files.c -- This file contains definitions to perform + file operations such as creating, writing to, + reading from and removing files that holds + information for each process with PID + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + +*/ + +#include +#include +#include +#include +#include +#include + +#include "procfs.h" +#include "procfs_pid.h" + +/* Update the files named NAME within the directory named + PID also with SYMLINK TARGET if necessary. */ +struct procfs_dir_entry* +update_pid_entries (struct procfs_dir *dir, const char *name, + time_t timestamp, + const char *symlink_target) +{ + struct procfs_dir_entry *dir_entry; + struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); + stat->st_mode = S_IFREG; + + dir_entry = update_entries_list (dir, name, stat, + timestamp, symlink_target); + + return dir_entry; +} + +/* Creates files to store process information for DIR + whose names are pids and returns these files in *NODE. */ +error_t +procfs_create_files (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "status") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "status") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "cmdline") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "cmdline") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "statm") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "statm") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + +#if 0 + nodes_list = &node_stat; + nodes_list++; + node = nodes_list; +#endif + + return err; +} + +/* Check if the PSTAT_FLAG is set in the corresponding PS + structure, if not set it and check again and return error + status accordingly. */ +error_t set_field_value (struct proc_stat *ps, int pstat_flag) +{ + error_t err; + + if (! (ps->flags & pstat_flag)) + { + err = proc_stat_set_flags (ps, pstat_flag); + if (err) + return err; + + /* This second check is done since ps.h specifies to + do so since the previous call would not have set + the required value. */ + if (! (ps->flags & pstat_flag)) + return EGRATUITOUS; + } + + return 0; +} + +/* Adjusts TIME_VAL structure having Seconds and + Microseconds into the value in jiffies. The + value of jiffy is a hack to adjust to what + procps uses. */ +time_t adjust_jiffy_time (time_value_t time_val) +{ + time_t jiffy_time = time_val.seconds * JIFFY_ADJUST; + jiffy_time += (time_val.microseconds * JIFFY_ADJUST) + / (1000 * 1000); + + return jiffy_time; +} + +/* Extract the user and system time for the live threads of + the process. This information is directly retrieved from + MACH since neither libps not proc makes this available. */ +error_t get_task_thread_times (task_t task, + struct task_thread_times_info *live_threads_times) +{ + error_t err; + size_t tkcount = TASK_THREAD_TIMES_INFO_COUNT; + + err = task_info (task, TASK_THREAD_TIMES_INFO, + (task_info_t) live_threads_times, &tkcount); + if (err == MACH_SEND_INVALID_DEST) + err = ESRCH; + + return err; +} + +/* Obtains the User Time in UTIME and System Time in STIME from + MACH directly since this is neither made available by libps + nor by proc server. */ +error_t get_live_threads_time (struct proc_stat *ps, + time_t *utime, time_t *stime) +{ + struct task_thread_times_info live_threads_times; + error_t err = set_field_value (ps, PSTAT_TASK); + + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + *utime = adjust_jiffy_time ( + live_threads_times.user_time); + *stime = adjust_jiffy_time ( + live_threads_times.system_time); + } + } + + return err; +} + +/* Get the data for stat file into the structure + PROCFS_STAT. */ +error_t get_stat_data (pid_t pid, + struct procfs_stat **procfs_stat) +{ + error_t err; + struct procfs_stat *new = (struct procfs_stat *) + malloc (sizeof (struct procfs_stat)); + + struct proc_stat *ps; + time_t utime, stime; + + err = _proc_stat_create (pid, ps_context, &ps); + + new->pid = pid; + + if (! err) + { + err = set_field_value (ps, PSTAT_ARGS); + if (! err) + asprintf (&new->comm, "%s", ps->args); + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + { + if (ps->state & PSTAT_STATE_P_STOP) + new->state = strdup ("T"); + if (ps->state & PSTAT_STATE_P_ZOMBIE) + new->state = strdup ("Z"); + if (ps->state & PSTAT_STATE_P_FG) + new->state = strdup ("+"); + if (ps->state & PSTAT_STATE_P_SESSLDR) + new->state = strdup ("s"); + if (ps->state & PSTAT_STATE_P_LOGINLDR) + new->state = strdup ("l"); + if (ps->state & PSTAT_STATE_P_FORKED) + new->state = strdup ("f"); + if (ps->state & PSTAT_STATE_P_NOMSG) + new->state = strdup ("m"); + if (ps->state & PSTAT_STATE_P_NOPARENT) + new->state = strdup ("p"); + if (ps->state & PSTAT_STATE_P_ORPHAN) + new->state = strdup ("o"); + if (ps->state & PSTAT_STATE_P_TRACE) + new->state = strdup ("x"); + if (ps->state & PSTAT_STATE_P_WAIT) + new->state = strdup ("w"); + if (ps->state & PSTAT_STATE_P_GETMSG) + new->state = strdup ("g"); + } + + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + new->ppid = ps->proc_info->ppid; + new->pgid = ps->proc_info->pgrp; + new->sid = ps->proc_info->session; + new->tty_pgrp = ps->proc_info->pgrp; + } + else + { + new->ppid = 0; + new->pgid = 0; + new->sid = 0; + new->tty_pgrp = 0; + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + new->flags = ps->state; + else + new->flags = 0; + + err = set_field_value (ps, PSTAT_TASK_EVENTS); + if (! err) + { + new->minflt = ps->task_events_info->faults; + new->majflt = ps->task_events_info->pageins; + } + else + { + new->minflt = 0; + new->majflt = 0; + } + + /* This seems to be a bit inconsistent with setting of other + fields in this code. There are two reasons for this. + 1. The actual information required is not made available + by libps which should be directly obtained from MACH. + 2. The same code which is required to get the information + have to be reused in procfs_nonpid_files.c */ + err = get_live_threads_time (ps, &utime, &stime); + if (! err) + { + new->utime = utime; + new->stime = stime; + } + else + { + new->utime = 0; + new->stime = 0; + } + + err = set_field_value (ps, PSTAT_TASK_BASIC); + if (! err) + { + new->cutime = adjust_jiffy_time ( + ps->task_basic_info->user_time); + new->cstime = adjust_jiffy_time ( + ps->task_basic_info->system_time); + + new->priority = ps->task_basic_info->base_priority; + new->starttime = adjust_jiffy_time ( + ps->task_basic_info->creation_time); + + new->vsize = ps->task_basic_info->virtual_size; + new->rss = ps->task_basic_info->resident_size; + } + else + { + new->cutime = 0; + new->cstime = 0; + new->priority = 0; + new->starttime = 0; + new->vsize = 0; + new->rss = 0; + } + + new->nice = getpriority (0, pid); + + err = set_field_value (ps, PSTAT_NUM_THREADS); + if (! err) + new->num_threads = ps->num_threads; + else + new->num_threads = 0; + + /* Not Supported in Linux 2.6 or later. */ + new->tty_nr = 0; + new->itrealvalue = 0; + new->nswap = 0; + new->cnswap = 0; + + /* Temporarily set to 0 until correct + values are found .*/ + new->cminflt = 0; + new->cmajflt = 0; + new->rlim = 0; + new->startcode = 0; + new->endcode = 0; + new->startstack = 0; + new->kstkesp = 0; + new->kstkeip = 0; + new->signal = 0; + new->blocked = 0; + new->sigignore = 0; + new->sigcatch = 0; + new->wchan = 0; + new->exit_signal = 0; + new->processor = 0; + new->rt_priority = 0; + new->policy = 0; + new->delayacct_blkio_ticks = 0; + + *procfs_stat = new; + _proc_stat_free (ps); + + return err; +} + +/* Writes required process information to stat file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_write_stat_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + error_t err; + char *stat_data; + struct procfs_stat *procfs_stat; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + + err = get_stat_data (pid, &procfs_stat); + + if (asprintf (&stat_data, "%d (%s) %s %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu \n", + procfs_stat->pid, procfs_stat->comm, + procfs_stat->state, procfs_stat->ppid, + procfs_stat->pgid, procfs_stat->sid, + procfs_stat->tty_nr, procfs_stat->tty_pgrp, + procfs_stat->flags, procfs_stat->minflt, + procfs_stat->cminflt, procfs_stat->majflt, + procfs_stat->cmajflt, procfs_stat->utime, + procfs_stat->stime, procfs_stat->cutime, + procfs_stat->cstime, procfs_stat->priority, + procfs_stat->nice, procfs_stat->num_threads, + procfs_stat->itrealvalue, procfs_stat->starttime, + procfs_stat->vsize, BYTES_TO_PAGES(procfs_stat->rss), + procfs_stat->rlim, procfs_stat->startcode, + procfs_stat->endcode, procfs_stat->startstack, + procfs_stat->kstkesp, procfs_stat->kstkeip, + procfs_stat->signal, procfs_stat->blocked, + procfs_stat->sigignore, procfs_stat->sigcatch, + procfs_stat->wchan, procfs_stat->nswap, + procfs_stat->cnswap, procfs_stat->exit_signal, + procfs_stat->processor, procfs_stat->rt_priority, + procfs_stat->policy, + procfs_stat->delayacct_blkio_ticks) == -1) + return errno; + + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + free (procfs_stat); + + return err; +} + +/* Writes required process's command line information + to cmline file within the directory represented by + pid. Return the data in DATA and actual length to + be written in LEN. */ +error_t +procfs_write_cmdline_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *cmdline_data; + error_t err; + struct proc_stat *ps; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = set_field_value (ps, PSTAT_ARGS); + + if (! err) + if (asprintf (&cmdline_data, "%s \n", ps->args) == -1) + return errno; + + memcpy (data, cmdline_data, strlen(cmdline_data)); + *len = strlen (data); + + _proc_stat_free (ps); + free (cmdline_data); + return err; +} + +/* Writes required process's information that is represented by + stat and statm in a human readable format to status file + within the directory represented by pid. Return the data + in DATA and actual length to be written in LEN. */ +error_t +procfs_write_status_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *status_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&status_data, "Name:\t%s\nState:\t%s\nTgid:\t%d\nPid:\t%d\n", procfs_stat->comm, procfs_stat->state, procfs_stat->pid, procfs_stat->pid) == -1) + return errno; + + memcpy (data, status_data, strlen(status_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (status_data); + free (procfs_stat); + + return err; +} + +/* Writes required process information to statm file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_write_statm_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *statm_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&statm_data, "%lu %ld %d %d %d %d %d\n", + BYTES_TO_PAGES(procfs_stat->vsize), + BYTES_TO_PAGES(procfs_stat->rss), + 0, 0, 0, 0, 0) == -1) + return errno; + + memcpy (data, statm_data, strlen(statm_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (statm_data); + free (procfs_stat); + + return err; +} + +/* Writes required process information to each of files + within directory represented by pid, for files specified + by NODE. Return the data in DATA and actual length of + data in LEN. */ +error_t +procfs_write_files_contents (struct node *node, + off_t offset, size_t *len, void *data) +{ + error_t err; + + if (! strcmp (node->nn->dir_entry->name, "stat")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_stat (node->nn->dir_entry, + offset, len, data); + else + err = procfs_write_stat_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "cmdline")) + err = procfs_write_cmdline_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "status")) + err = procfs_write_status_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "statm")) + err = procfs_write_statm_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "meminfo")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_meminfo (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "loadavg")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_loadavg (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "uptime")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_uptime (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + return err; +} -- cgit v1.2.3 From 688a421a1aef82d2688909f106c4a70172530b81 Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 17:15:00 +0200 Subject: 2008-08-14 Madhusudan.C.S * procfs.h: (jiffy_t): New typedef. * procfs_pid.h: "procfs.h" is included. (struct procfs_pid_files): Changed all the occurrences of time_t to jiffy_t. * procfs_pid_files.c: Removed "procfs.h". (adjust_jiffy_time): Changed return type from time_t to jiffy_t. Changed the type of jiffy_time variable from time_t to jiffy_t. (get_live_threads_time): Changed the type of utime and stime from time_t to jiffy_t. (get_stat_data): Changed the type of utime and stime from time_t to jiffy_t. --- procfs.h | 2 ++ procfs_pid.h | 10 ++++++---- procfs_pid_files.c | 9 ++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/procfs.h b/procfs.h index 95d4ee35..fa2fb7f7 100644 --- a/procfs.h +++ b/procfs.h @@ -53,6 +53,8 @@ #include #include +typedef unsigned long long jiffy_t; + /* A single entry in a directory. */ struct procfs_dir_entry { diff --git a/procfs_pid.h b/procfs_pid.h index 811cca84..566c83ea 100644 --- a/procfs_pid.h +++ b/procfs_pid.h @@ -26,6 +26,8 @@ #ifndef __PROCFS_PID_H__ #define __PROCFS_PID_H__ +#include "procfs.h" + struct procfs_pid_files { struct procfs_cwd *procfs_cwd; @@ -52,10 +54,10 @@ struct procfs_stat long unsigned cminflt; long unsigned majflt; long unsigned cmajflt; - time_t utime; - time_t stime; - time_t cutime; - time_t cstime; + jiffy_t utime; + jiffy_t stime; + jiffy_t cutime; + jiffy_t cstime; long priority; long nice; long num_threads; diff --git a/procfs_pid_files.c b/procfs_pid_files.c index 1012510b..55cc52c1 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -37,7 +37,6 @@ #include #include -#include "procfs.h" #include "procfs_pid.h" /* Update the files named NAME within the directory named @@ -148,9 +147,9 @@ error_t set_field_value (struct proc_stat *ps, int pstat_flag) Microseconds into the value in jiffies. The value of jiffy is a hack to adjust to what procps uses. */ -time_t adjust_jiffy_time (time_value_t time_val) +jiffy_t adjust_jiffy_time (time_value_t time_val) { - time_t jiffy_time = time_val.seconds * JIFFY_ADJUST; + jiffy_t jiffy_time = time_val.seconds * JIFFY_ADJUST; jiffy_time += (time_val.microseconds * JIFFY_ADJUST) / (1000 * 1000); @@ -178,7 +177,7 @@ error_t get_task_thread_times (task_t task, MACH directly since this is neither made available by libps nor by proc server. */ error_t get_live_threads_time (struct proc_stat *ps, - time_t *utime, time_t *stime) + jiffy_t *utime, jiffy_t *stime) { struct task_thread_times_info live_threads_times; error_t err = set_field_value (ps, PSTAT_TASK); @@ -208,7 +207,7 @@ error_t get_stat_data (pid_t pid, malloc (sizeof (struct procfs_stat)); struct proc_stat *ps; - time_t utime, stime; + jiffy_t utime, stime; err = _proc_stat_create (pid, ps_context, &ps); -- cgit v1.2.3 From 415e86d598c4e15d69b5f558d305b735462083bc Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 17:27:00 +0200 Subject: 2008-08-18 Madhusudan.C.S * procfs_nonpid_files.c: (procfs_write_nonpid_version): New function. * procfs_pid_files.c: (procfs_write_files_contents): Add a check to find if the read is requested for the version file and corresponding a call to it. --- procfs_nonpid_files.c | 18 +++++++++++++++++- procfs_pid_files.c | 7 +++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index 104ae8b3..ab1341ff 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -269,7 +269,7 @@ error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, idle_time_secs = uptime_secs - total_system_time_secs; - /* If the values are multiplied by 100, it iss done so to adjust + /* If the values are multiplied by 100, it is done so to adjust values in seconds to jiffies. */ if (asprintf (&stat_data, "cpu %ld %ld %ld %ld %ld %ld %d %d %d\n" "cpu0 %ld %ld %ld %ld %ld %ld %d %d %d\n" @@ -460,3 +460,19 @@ error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, free (uptime_data); return err; } + +error_t procfs_write_nonpid_version (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *version_data; + error_t err = 0; + + if (asprintf (&version_data, "Linux version 2.6.18\n", NULL) == -1) + return errno; + + memcpy (data, version_data, strlen(version_data)); + *len = strlen (data); + + free (version_data); + return err; +} diff --git a/procfs_pid_files.c b/procfs_pid_files.c index 55cc52c1..3ad77340 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -565,5 +565,12 @@ procfs_write_files_contents (struct node *node, else err = ENOENT; + if (! strcmp (node->nn->dir_entry->name, "version")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_write_nonpid_version (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + return err; } -- cgit v1.2.3 From ac38ed88929c70c4ede56816c053bf170c9c2efd Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 19:34:00 +0200 Subject: 2008-08-18 Madhusudan.C.S * procfs_nonpid_files.c: (get_uptime): Changed the parameter type from double to struct timeval. Changed the parameter name from uptime_secs to uptime. Removed uptime variable. Changed timersub to use the passed pointer instead of the local variable. Removed the calculation of uptime_secs. (get_total_times): Changed the parameters type from double to struct timeval. Changed the parameters name from total_user_time_secs to total_user_time and total_system_time_secs to total_system_time. New variables total_user_time_tmp, total_system_time_tmp and tmpval of type struct timeval. Call timerclear to clear the tmp variables. Remove calculation of times in seconds and do the same on struct timeval variables throughout using the timeradd macro. Assign values of temporary local variables to the pointers passed as parameters. (procfs_write_nonpid_stat): Replaced variables that hold time in seconds with struct timeval type variables and jiffy_t type variables. Argument to get_uptime changed from uptime_secs to uptime. Arguments to get_total_times changed from total_user_time_secs to total_user_time and total_system_time_secs to total_system_time. Replace arithematic time subtraction with timersub macro. Convert all the times in struct timeval type variables to jiffy_t type. Changed the type casting for the asprintf arguments to be compatible with jiffy_t type. (procfs_write_nonpid_uptime): Replaced variables that hold time in seconds with struct timeval type variables. Argument to get_uptime changed from uptime_secs to uptime. Arguments to get_total_times changed from total_user_time_secs to total_user_time and total_system_time_secs to total_system_time. Replace arithematic time subtraction with timersub macro. Convert all the times in struct timeval type variables to seconds. --- procfs_nonpid_files.c | 138 +++++++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 51 deletions(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index ab1341ff..9cb0c57a 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -166,9 +166,9 @@ error_t procfs_create_loadavg (struct procfs_dir *dir, return err; } -error_t get_uptime (double *uptime_secs) +error_t get_uptime (struct timeval *uptime) { - struct timeval boot_time, uptime, now; + struct timeval boot_time, now; error_t err; struct proc_stat *ps; @@ -188,15 +188,15 @@ error_t get_uptime (double *uptime_secs) boot_time.tv_usec = tv->microseconds; if (gettimeofday (&now, 0) < 0) error (0, errno, "gettimeofday"); - timersub (&now, &boot_time, &uptime); - *uptime_secs = (double)uptime.tv_sec + ((double)uptime.tv_usec / 1000000); + timersub (&now, &boot_time, uptime); } _proc_stat_free (ps); return err; } -error_t get_total_times (double *total_user_time_secs , double *total_system_time_secs ) +error_t get_total_times (struct timeval *total_user_time, + struct timeval *total_system_time) { error_t err; pid_t *pids; @@ -204,8 +204,12 @@ error_t get_total_times (double *total_user_time_secs , double *total_system_tim struct proc_stat *ps; struct task_thread_times_info live_threads_times; - *total_user_time_secs = 0; - *total_system_time_secs = 0; + struct timeval total_user_time_tmp; + struct timeval total_system_time_tmp; + struct timeval tmpval; + + timerclear (&total_user_time_tmp); + timerclear (&total_system_time_tmp); pids = NULL; err = proc_getallpids (getproc (), &pids, &pidslen); @@ -222,33 +226,40 @@ error_t get_total_times (double *total_user_time_secs , double *total_system_tim err = EGRATUITOUS; if (! err) - { - *total_user_time_secs += - ((double) (proc_stat_task_basic_info (ps)->user_time.seconds)) + - (((double) (proc_stat_task_basic_info (ps)->user_time.microseconds)) / - (1000 * 1000)); + { + tmpval.tv_sec = proc_stat_task_basic_info (ps)->user_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->user_time.seconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = proc_stat_task_basic_info (ps)->system_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->system_time.seconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); - *total_system_time_secs += - ((double) (proc_stat_task_basic_info (ps)->system_time.seconds)) + - (((double) (proc_stat_task_basic_info (ps)->system_time.microseconds)) / (1000 * 1000)); - error_t err = set_field_value (ps, PSTAT_TASK); if (! err) { err = get_task_thread_times (ps->task, &live_threads_times); if (! err) { - *total_user_time_secs += ((double) (live_threads_times.user_time.seconds)) + - (((double) (live_threads_times.user_time.microseconds)) / (1000 * 1000)); - *total_system_time_secs += ((double) (live_threads_times.system_time.seconds)) + - (((double) (live_threads_times.system_time.microseconds)) / (1000 * 1000)); - + tmpval.tv_sec = live_threads_times.user_time.seconds; + tmpval.tv_usec = live_threads_times.user_time.microseconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = live_threads_times.system_time.seconds; + tmpval.tv_usec = live_threads_times.system_time.microseconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); } } } _proc_stat_free (ps); } - + + total_user_time->tv_sec = total_user_time_tmp.tv_sec; + total_user_time->tv_usec = total_user_time_tmp.tv_usec; + + total_system_time->tv_sec = total_system_time_tmp.tv_sec; + total_system_time->tv_usec = total_system_time_tmp.tv_usec; + return err; } @@ -257,30 +268,45 @@ error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, { char *stat_data; error_t err; - double uptime_secs, total_user_time_secs; - double total_system_time_secs, idle_time_secs; + jiffy_t total_user_time_jiffy, total_system_time_jiffy; + jiffy_t idle_time_jiffy; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; - err = get_uptime (&uptime_secs); + err = get_uptime (&uptime); + if (! err) { - err = get_total_times (&total_user_time_secs, &total_system_time_secs); + err = get_total_times (&total_user_time, &total_system_time); + if (! err) { - idle_time_secs = uptime_secs - - total_system_time_secs; - - /* If the values are multiplied by 100, it is done so to adjust - values in seconds to jiffies. */ - if (asprintf (&stat_data, "cpu %ld %ld %ld %ld %ld %ld %d %d %d\n" - "cpu0 %ld %ld %ld %ld %ld %ld %d %d %d\n" - "intr %ld %ld %ld %ld %ld %ld %d %d %d\n", - (long)(total_user_time_secs * 100), 0, - (long)(total_system_time_secs * 100), - (long) (idle_time_secs * 100), 0, 0, 0, 0, - 0, (long)(total_user_time_secs * 100), 0, - (long)(total_system_time_secs * 100), - (long)(idle_time_secs * 100), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == -1) + timersub (&uptime, &total_system_time, + &idle_time); + + total_user_time_jiffy = 100 * ((double) total_user_time.tv_sec + + (double) total_user_time.tv_usec / (1000 * 1000)); + total_system_time_jiffy = 100 * ((double) total_system_time.tv_sec + + (double) total_system_time.tv_usec / (1000 * 1000)); + idle_time_jiffy = 100 * ((double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000)); + + if (asprintf (&stat_data, "cpu %llu %llu %llu %llu %llu %llu %d %d %d\n" + "cpu0 %llu %llu %llu %llu %llu %llu %d %d %d\n" + "intr %llu %llu %llu %llu %llu %llu %d %d %d\n", + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0) == -1) return errno; } } @@ -434,23 +460,33 @@ error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, { char *uptime_data; error_t err; - double uptime_secs, total_user_time_secs; - double total_system_time_secs, idle_time_secs; + double uptime_secs, idle_time_secs; + + struct timeval uptime_val; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; + - err = get_uptime (&uptime_secs); + err = get_uptime (&uptime); if (! err) { - err = get_total_times (&total_user_time_secs, - &total_system_time_secs); + err = get_total_times (&total_user_time, + &total_system_time); if (! err) { - idle_time_secs = uptime_secs - - total_system_time_secs; - - if (asprintf (&uptime_data, "%.2f %.2f \n", + timersub (&uptime, &total_system_time, + &idle_time); + + uptime_secs = (double) uptime.tv_sec + + (double) uptime.tv_usec / (1000 * 1000); + + idle_time_secs = (double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000); + + if (asprintf (&uptime_data, "%.2f %.2f\n", uptime_secs, idle_time_secs) == -1) return errno; - } + } } -- cgit v1.2.3 From b0c18505223662500cd54a0b901efcd69a761077 Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Mon, 18 Aug 2008 20:26:00 +0200 Subject: 2008-08-18 Madhusudan.C.S * procfs_nonpid_files.c: (procfs_write_nonpid_stat): Changed to procfs_read_nonpid_stat. (procfs_write_nonpid_meminfo): Changed to procfs_read_nonpid_meminfo. (procfs_write_nonpid_loadavg): Changed to procfs_read_nonpid_loadavg. (procfs_write_nonpid_uptime): Changed to procfs_read_nonpid_uptime. (procfs_write_nonpid_version):Changed to procfs_read_nonpid_version. * procfs_pid_files.c: (procfs_write_stat_file): Changed to procfs_read_stat_file. Changed the comment correspondingly from Write to Read. (procfs_write_cmdline_file ): Changed to procfs_read_cmdline_file. Changed the comment correspondingly from Write to Read. (procfs_write_status_file): Changed to procfs_read_status_file. Changed the comment correspondingly from Write to Read. (procfs_write_statm_file): Changed to procfs_read_statm_file. Changed the comment correspondingly from Write to Read. (procfs_write_files_contents): Changed to procfs_read_files_contents. Changed the comment correspondingly from Write to Read. Changed the call to procfs_write_nonpid_stat to procfs_read_nonpid_stat. Changed the call to procfs_write_stat_file to procfs_read_stat_file. Changed the call to procfs_write_cmdline_file to procfs_read_cmdline_file. Changed the call to procfs_write_status_file to procfs_read_status_file. Changed the call to procfs_write_statm_file to procfs_read_statm_file. Changed the call to procfs_write_nonpid_meminfo to procfs_read_nonpid_meminfo. Changed the call to procfs_write_nonpid_loadavg to procfs_read_nonpid_loadavg. Changed the call to procfs_write_nonpid_uptime to procfs_read_nonpid_uptime. Changed the call to procfs_write_nonpid_version to procfs_read_nonpid_version. netfs.c: (netfs_attempt_read): Changed the call from procfs_write_files_contents to procfs_read_files_contents. --- netfs.c | 2 +- procfs_nonpid_files.c | 10 +++++----- procfs_pid_files.c | 46 +++++++++++++++++++++++----------------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/netfs.c b/netfs.c index 31ffe1b5..7e00e4d4 100644 --- a/netfs.c +++ b/netfs.c @@ -435,7 +435,7 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *node, if (! err) { if (*len > 0) - procfs_write_files_contents (node, offset, + procfs_read_files_contents (node, offset, len, data); if (*len > 0) if (offset >= *len) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index 9cb0c57a..15c09190 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -263,7 +263,7 @@ error_t get_total_times (struct timeval *total_user_time, return err; } -error_t procfs_write_nonpid_stat (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_stat (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *stat_data; @@ -387,7 +387,7 @@ SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space - def_pager_info.dpi_free_space)) -error_t procfs_write_nonpid_meminfo (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *meminfo_data; @@ -427,7 +427,7 @@ error_t procfs_write_nonpid_meminfo (struct dir_entry *dir_entry, return err; } -error_t procfs_write_nonpid_loadavg (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_loadavg (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *loadavg_data; @@ -455,7 +455,7 @@ error_t procfs_write_nonpid_loadavg (struct dir_entry *dir_entry, return err; } -error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_uptime (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *uptime_data; @@ -497,7 +497,7 @@ error_t procfs_write_nonpid_uptime (struct dir_entry *dir_entry, return err; } -error_t procfs_write_nonpid_version (struct dir_entry *dir_entry, +error_t procfs_read_nonpid_version (struct dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *version_data; diff --git a/procfs_pid_files.c b/procfs_pid_files.c index 3ad77340..ed3a3bdc 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -367,12 +367,12 @@ error_t get_stat_data (pid_t pid, return err; } -/* Writes required process information to stat file +/* Reads required process information from stat file within the directory represented by pid. Return the data in DATA and actual length to be written in LEN. */ error_t -procfs_write_stat_file (struct procfs_dir_entry *dir_entry, +procfs_read_stat_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { error_t err; @@ -417,12 +417,12 @@ procfs_write_stat_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process's command line information - to cmline file within the directory represented by - pid. Return the data in DATA and actual length to - be written in LEN. */ +/* Reads required process's command line information + from cmline file within the directory represented + by pid. Return the data in DATA and actual length + to be written in LEN. */ error_t -procfs_write_cmdline_file (struct procfs_dir_entry *dir_entry, +procfs_read_cmdline_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *cmdline_data; @@ -445,12 +445,12 @@ procfs_write_cmdline_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process's information that is represented by - stat and statm in a human readable format to status file +/* Reads required process's information that is represented by + stat and statm in a human readable format from status file within the directory represented by pid. Return the data in DATA and actual length to be written in LEN. */ error_t -procfs_write_status_file (struct procfs_dir_entry *dir_entry, +procfs_read_status_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *status_data; @@ -478,12 +478,12 @@ procfs_write_status_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process information to statm file +/* Reads required process information from statm file within the directory represented by pid. Return the data in DATA and actual length to be written in LEN. */ error_t -procfs_write_statm_file (struct procfs_dir_entry *dir_entry, +procfs_read_statm_file (struct procfs_dir_entry *dir_entry, off_t offset, size_t *len, void *data) { char *statm_data; @@ -514,60 +514,60 @@ procfs_write_statm_file (struct procfs_dir_entry *dir_entry, return err; } -/* Writes required process information to each of files +/* Reads required process information from each of files within directory represented by pid, for files specified by NODE. Return the data in DATA and actual length of data in LEN. */ error_t -procfs_write_files_contents (struct node *node, +procfs_read_files_contents (struct node *node, off_t offset, size_t *len, void *data) { error_t err; if (! strcmp (node->nn->dir_entry->name, "stat")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_stat (node->nn->dir_entry, + err = procfs_read_nonpid_stat (node->nn->dir_entry, offset, len, data); else - err = procfs_write_stat_file (node->nn->dir_entry, + err = procfs_read_stat_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "cmdline")) - err = procfs_write_cmdline_file (node->nn->dir_entry, + err = procfs_read_cmdline_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "status")) - err = procfs_write_status_file (node->nn->dir_entry, + err = procfs_read_status_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "statm")) - err = procfs_write_statm_file (node->nn->dir_entry, + err = procfs_read_statm_file (node->nn->dir_entry, offset, len, data); if (! strcmp (node->nn->dir_entry->name, "meminfo")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_meminfo (node->nn->dir_entry, + err = procfs_read_nonpid_meminfo (node->nn->dir_entry, offset, len, data); else err = ENOENT; if (! strcmp (node->nn->dir_entry->name, "loadavg")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_loadavg (node->nn->dir_entry, + err = procfs_read_nonpid_loadavg (node->nn->dir_entry, offset, len, data); else err = ENOENT; if (! strcmp (node->nn->dir_entry->name, "uptime")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_uptime (node->nn->dir_entry, + err = procfs_read_nonpid_uptime (node->nn->dir_entry, offset, len, data); else err = ENOENT; if (! strcmp (node->nn->dir_entry->name, "version")) if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_write_nonpid_version (node->nn->dir_entry, + err = procfs_read_nonpid_version (node->nn->dir_entry, offset, len, data); else err = ENOENT; -- cgit v1.2.3 From 19953dc4ba760988f611d03dffc4b5549077d2fc Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Sat, 30 Aug 2008 22:20:00 +0200 Subject: 2008-08-29 Madhusudan.C.S * AUTHORS: File removed. * COPYING: Likewise. * README: Likewise. --- AUTHORS | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 622b6488..00000000 --- a/AUTHORS +++ /dev/null @@ -1,10 +0,0 @@ -Written By -~~~~~~~~~~ - -Madhusudan.C.S - - -Mentored By -~~~~~~~~~~~ - -Olaf Buddenhagen -- cgit v1.2.3 From 391c62031b4fe6fa0a2f031d9f6dcf4dcd04e5ce Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Sat, 30 Aug 2008 22:48:00 +0200 Subject: 2008-08-30 Madhusudan.C.S * procfs_dir.c: (procfs_dir_create): Assign newly created directory to its pointer in netnode. (procfs_dir_remove): Removed function. (free_entry): New function. (ordered_unlink): Likewise. (delete): Likewise. (sweep): Likewise. (procfs_dir_entries_remove): Likewise. (is_in_pid_list): Removed call to make_dir_invalid (). (procfs_fill_root_dir): struct stat *stat -> struct stat stat. Add Read and Execute permissions to all in stat.st_mode. Set stat.st_nlink to 1. Set stat.st_size to 0. Add struct proc_stat *ps definition. Set struct proc_stat data from _proc_stat_create () function and set stat.st_uid and stat.st_gid from the data in that structure. * procfs_pid_files.c: (update_pid_entries): Add Read permissions to all in stat->st_mode. --- procfs_dir.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++------- procfs_pid_files.c | 2 +- 2 files changed, 105 insertions(+), 16 deletions(-) diff --git a/procfs_dir.c b/procfs_dir.c index b9b0410e..f76e6a4b 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -77,6 +77,9 @@ error_t procfs_dir_create (struct procfs *fs, struct node *node, *dir = new; + if (fs->root != 0) + node->nn->dir = new; + return 0; } @@ -343,14 +346,50 @@ procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) return err; } -/* Remove the specified DIR and free all its allocated - storage. */ -void procfs_dir_remove (struct procfs_dir *dir) +/* Free the directory entry DIR_ENTRY and all resources it consumes. */ +void +free_entry (struct procfs_dir_entry *dir_entry) { - /* STUB */ + assert (! dir_entry->self_p); /* We should only free deleted nodes. */ + free (dir_entry->name); + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + free (dir_entry->node->nn->dir); + free (dir_entry->node->nn); + free (dir_entry->node); + free (dir_entry); +} + +/* Remove DIR_ENTRY from its position in the ordered_next chain. */ +static void +ordered_unlink (struct procfs_dir_entry *dir_entry) +{ + if (dir_entry->ordered_self_p) + *dir_entry->ordered_self_p = dir_entry->ordered_next; + if (dir_entry->ordered_next) + dir_entry->ordered_next->self_p = dir_entry->ordered_self_p; +} + +/* Delete DIR_ENTRY from its directory, freeing any resources it holds. */ +static void +delete (struct procfs_dir_entry *dir_entry, struct procfs_dir *dir) +{ + dir->num_entries--; - return 0; + /* Take out of the hash chain. */ + if (dir_entry->self_p) + *dir_entry->self_p = dir_entry->next; + if (dir_entry->next) + dir_entry->next->self_p = dir_entry->self_p; + + /* Take out of the directory ordered list. */ + ordered_unlink (dir_entry); + + /* If there's a node attached, we'll delete the entry whenever it goes + away, otherwise, just delete it now. */ + if (! dir_entry->node) + free_entry (dir_entry); } /* Make all the directory entries invalid */ @@ -373,6 +412,41 @@ make_dir_invalid (struct procfs_dir *dir) } } +/* Delete any entries in DIR which don't have their valid bit set. */ +static void +sweep (struct procfs_dir *dir) +{ + size_t len = dir->htable_len, i; + struct procfs_dir_entry **htable = dir->htable, *dir_entry; + + for (i = 0; i < len; i++) + { + dir_entry = htable[i]; + while (dir_entry) + { + if (!dir_entry->valid && !dir_entry->noent && dir->num_entries) + delete (dir_entry, dir); + dir_entry = dir_entry->next; + } + if (htable[i]) + { + free (htable[i]); + htable[i] = 0; + } + + } + +} + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_entries_remove (struct procfs_dir *dir) +{ + /* Free all entries. */ + make_dir_invalid (dir); + sweep (dir); +} + /* Checks if the DIR name is in list of Active pids. */ int is_in_pid_list (struct procfs_dir *dir) @@ -417,7 +491,6 @@ error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) error_t err; int is_parent_pid; struct node *node; - make_dir_invalid (dir); struct timeval tv; maptime_read (procfs_maptime, &tv); @@ -513,14 +586,18 @@ procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) char *data; pid_t *pids; int pidslen; - struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); - stat->st_mode = S_IFDIR; + struct stat stat; + stat.st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | + S_IROTH | S_IXOTH; + stat.st_nlink = 1; + stat.st_size = 0; int count; char *dir_name_pid; struct node *node; struct procfs_dir *new_dir; struct procfs_dir_entry *dir_entry; + struct proc_stat *ps; pids = NULL; pidslen = 0; @@ -540,13 +617,25 @@ procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) if (! node || ! new_dir ) return ENOMEM; #endif - dir_entry = update_entries_list (dir, dir_name_pid, - stat, timestamp, NULL); - err = procfs_create_node (dir_entry, dir_name_pid, &node); - - procfs_dir_create (dir->fs, node, - dir_name_pid, &new_dir); - free(dir_name_pid); + err = _proc_stat_create (pids[count], ps_context, &ps); + if (! err) + { + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + stat.st_uid = proc_stat_proc_info (ps)->owner; + stat.st_gid = proc_stat_proc_info (ps)->pgrp; + + dir_entry = update_entries_list (dir, dir_name_pid, + &stat, timestamp, NULL); + err = procfs_create_node (dir_entry, dir_name_pid, &node); + + procfs_dir_create (dir->fs, node, + dir_name_pid, &new_dir); + free(dir_name_pid); + _proc_stat_free (ps); + } + } } } diff --git a/procfs_pid_files.c b/procfs_pid_files.c index ed3a3bdc..46861531 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -48,7 +48,7 @@ update_pid_entries (struct procfs_dir *dir, const char *name, { struct procfs_dir_entry *dir_entry; struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); - stat->st_mode = S_IFREG; + stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; dir_entry = update_entries_list (dir, name, stat, timestamp, symlink_target); -- cgit v1.2.3 From db2336ab8d2c9e0f6ddf057918a3a19d5a31de97 Mon Sep 17 00:00:00 2001 From: "Madhusudan.C.S" Date: Tue, 2 Sep 2008 00:33:00 +0200 Subject: 2008-09-02 Madhusudan.C.S * netfs.c: (netfs_get_dirents): Add call to procfs_dir_entries_remove(). --- netfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/netfs.c b/netfs.c index 7e00e4d4..4f6fd5ce 100644 --- a/netfs.c +++ b/netfs.c @@ -278,6 +278,7 @@ netfs_get_dirents (struct iouser *cred, struct node *dir, return ENOTDIR; } + procfs_dir_entries_remove (dir->nn->dir); return err; } -- cgit v1.2.3 From 2f4aea7d25b7aeca6ee36126a375644acfab3cee Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 12 Dec 2008 01:48:00 +0100 Subject: 2008-12-12 Samuel Thibault * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Divide by 1024 value returned by get_swap_size and get_swap_free to get kilobytes. --- procfs_nonpid_files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index 15c09190..d8b3a7d1 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -417,7 +417,7 @@ error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, (PAGES_TO_BYTES(vmstats.active_count)) / 1024, (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, - get_swap_size (), get_swap_free ()) == -1) + get_swap_size () / 1024, get_swap_free () / 1024) == -1) return errno; memcpy (data, meminfo_data, strlen(meminfo_data)); -- cgit v1.2.3 From bb60526834227fddb97e14bd80fccc405932e352 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 31 May 2010 02:23:00 +0200 Subject: 2010-05-31 Samuel Thibault * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Print swap sizes using %llu. --- procfs_nonpid_files.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index d8b3a7d1..2c1209ee 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -412,8 +412,8 @@ error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, "HighFree:\t%lu kB\n" "LowTotal:\t%lu kB\n" "LowFree:\t%lu kB\n" - "SwapTotal:\t%lu kB\n" - "SwapFree:\t%lu kB\n", + "SwapTotal:\t%llu kB\n" + "SwapFree:\t%llu kB\n", mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, (PAGES_TO_BYTES(vmstats.active_count)) / 1024, (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, -- cgit v1.2.3 From c3b69fde7feae1954c7f1bd64af630bb26cc8fdc Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 1 Aug 2010 01:50:21 +0200 Subject: Move files to procfs to merge along hurd --- bootstrap.c | 95 ------- netfs.c | 467 ------------------------------ node.c | 195 ------------- procfs.c | 149 ---------- procfs.h | 220 -------------- procfs/ChangeLog | 177 ++++++++++++ procfs/Makefile | 30 ++ procfs/bootstrap.c | 95 +++++++ procfs/netfs.c | 467 ++++++++++++++++++++++++++++++ procfs/node.c | 195 +++++++++++++ procfs/procfs.c | 149 ++++++++++ procfs/procfs.h | 220 ++++++++++++++ procfs/procfs_dir.c | 664 +++++++++++++++++++++++++++++++++++++++++++ procfs/procfs_nonpid_files.c | 514 +++++++++++++++++++++++++++++++++ procfs/procfs_pid.h | 88 ++++++ procfs/procfs_pid_files.c | 576 +++++++++++++++++++++++++++++++++++++ procfs_dir.c | 664 ------------------------------------------- procfs_nonpid_files.c | 514 --------------------------------- procfs_pid.h | 88 ------ procfs_pid_files.c | 576 ------------------------------------- 20 files changed, 3175 insertions(+), 2968 deletions(-) delete mode 100644 bootstrap.c delete mode 100644 netfs.c delete mode 100644 node.c delete mode 100644 procfs.c delete mode 100644 procfs.h create mode 100644 procfs/ChangeLog create mode 100644 procfs/Makefile create mode 100644 procfs/bootstrap.c create mode 100644 procfs/netfs.c create mode 100644 procfs/node.c create mode 100644 procfs/procfs.c create mode 100644 procfs/procfs.h create mode 100644 procfs/procfs_dir.c create mode 100644 procfs/procfs_nonpid_files.c create mode 100644 procfs/procfs_pid.h create mode 100644 procfs/procfs_pid_files.c delete mode 100644 procfs_dir.c delete mode 100644 procfs_nonpid_files.c delete mode 100644 procfs_pid.h delete mode 100644 procfs_pid_files.c diff --git a/bootstrap.c b/bootstrap.c deleted file mode 100644 index 73d31f00..00000000 --- a/bootstrap.c +++ /dev/null @@ -1,95 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - bootstrap.c -- This file is functions for starting up - and initializers for the procfs translator - defined in procfs.h - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. -*/ - -#include -#include -#include - -#include "procfs.h" - -struct ps_context *ps_context; - -/* This function is used to initialize the whole translator, can be - effect called as bootstrapping the translator. */ -error_t procfs_init () -{ - error_t err; - - err = ps_context_create (getproc (), &ps_context); - - return err; -} - -/* Create a new procfs filesystem. */ -error_t procfs_create (char *procfs_root, int fsid, - struct procfs **fs) -{ - error_t err; - /* This is the enclosing directory for this filesystem's - root node */ - struct procfs_dir *topmost_root_dir; - - /* And also a topmost-root node, just used for locking - TOPMOST_ROOT_DIR. */ - struct node *topmost_root; - - /* The new node for the filesystem's root. */ - struct procfs *new = malloc (sizeof (struct procfs)); - - if (! new) - return ENOMEM; - - new->fsid = fsid; - new->next_inode = 2; - - hurd_ihash_init (&new->inode_mappings, - offsetof (struct procfs_dir_entry, inode_locp)); - spin_lock_init (&new->inode_mappings_lock); - - topmost_root = netfs_make_node (0); - if (! topmost_root) - err = ENOMEM; - else - { - err = procfs_dir_create (new, topmost_root, procfs_root, - &topmost_root_dir); - if (! err) - { - /* ADDITIONAL BOOTSTRAPPING OF THE ROOT NODE */ - err = procfs_dir_null_lookup (topmost_root_dir, &new->root); - } - } - - if (err) - { - hurd_ihash_destroy (&new->inode_mappings); - free (new); - } - else - *fs = new; - - return err; -} - diff --git a/netfs.c b/netfs.c deleted file mode 100644 index 4f6fd5ce..00000000 --- a/netfs.c +++ /dev/null @@ -1,467 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "procfs.h" - -/* Trivial definitions. */ - -/* Make sure that NP->nn_stat is filled with current information. CRED - identifies the user responsible for the operation. */ -error_t -netfs_validate_stat (struct node *node, struct iouser *cred) -{ - return procfs_refresh_node (node); -} - -/* This should sync the file NODE completely to disk, for the user CRED. If - WAIT is set, return only after sync is completely finished. */ -error_t -netfs_attempt_sync (struct iouser *cred, struct node *node, int wait) -{ - return 0; -} - -/* Attempt to create a new directory named NAME in DIR for USER with mode - MODE. */ -error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, - char *name, mode_t mode) -{ - return EROFS; -} - -/* Attempt to remove directory named NAME in DIR for USER. */ -error_t netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - return EROFS; -} - -/* Attempt to set the passive translator record for FILE to ARGZ (of length - ARGZLEN) for user CRED. */ -error_t netfs_set_translator (struct iouser *cred, struct node *node, - char *argz, size_t argzlen) -{ - return EROFS; -} - -/* Attempt to create a file named NAME in DIR for USER with MODE. Set *NODE - to the new node upon return. On any error, clear *NODE. *NODE should be - locked on success; no matter what, unlock DIR before returning. */ -error_t -netfs_attempt_create_file (struct iouser *user, struct node *dir, - char *name, mode_t mode, struct node **node) -{ - *node = NULL; - mutex_unlock (&dir->lock); - return EROFS; -} - -/* Node NODE is being opened by USER, with FLAGS. NEWNODE is nonzero if we - just created this node. Return an error if we should not permit the open - to complete because of a permission restriction. */ -error_t -netfs_check_open_permissions (struct iouser *user, struct node *node, - int flags, int newnode) -{ - error_t err = procfs_refresh_node (node); - if (!err && (flags & O_READ)) - err = fshelp_access (&node->nn_stat, S_IREAD, user); - if (!err && (flags & O_WRITE)) - err = fshelp_access (&node->nn_stat, S_IWRITE, user); - if (!err && (flags & O_EXEC)) - err = fshelp_access (&node->nn_stat, S_IEXEC, user); - return err; -} - -/* This should attempt a utimes call for the user specified by CRED on node - NODE, to change the atime to ATIME and the mtime to MTIME. */ -error_t -netfs_attempt_utimes (struct iouser *cred, struct node *node, - struct timespec *atime, struct timespec *mtime) -{ - error_t err = procfs_refresh_node (node); - int flags = TOUCH_CTIME; - - if (! err) - err = fshelp_isowner (&node->nn_stat, cred); - - if (! err) - { - if (atime) - node->nn_stat.st_atim = *atime; - else - flags |= TOUCH_ATIME; - - if (mtime) - node->nn_stat.st_mtim = *mtime; - else - flags |= TOUCH_MTIME; - - fshelp_touch (&node->nn_stat, flags, procfs_maptime); - } - - return err; -} - -/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and O_EXEC) - in *TYPES for file NODE and user CRED. */ -error_t -netfs_report_access (struct iouser *cred, struct node *node, int *types) -{ - error_t err = procfs_refresh_node (node); - - if (! err) - { - *types = 0; - if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - } - - return err; -} - -/* The granularity with which we allocate space to return our result. */ -#define DIRENTS_CHUNK_SIZE (8*1024) - -/* Returned directory entries are aligned to blocks this many bytes long. - Must be a power of two. */ -#define DIRENT_ALIGN 4 -#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) - -/* Length is structure before the name + the name + '\0', all - padded to a four-byte alignment. */ -#define DIRENT_LEN(name_len) \ - ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ - & ~(DIRENT_ALIGN - 1)) - - - -/* Fetch a directory */ -error_t -netfs_get_dirents (struct iouser *cred, struct node *dir, - int first_entry, int max_entries, char **data, - mach_msg_type_number_t *data_len, - vm_size_t max_data_len, int *data_entries) -{ - error_t err = procfs_refresh_node (dir); - struct procfs_dir_entry *dir_entry; - - if (! err) - { - if (dir->nn->dir) - { - if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root)) - { - for (dir_entry = dir->nn->dir->ordered; first_entry > 0 && - dir_entry; first_entry--, - dir_entry = dir_entry->ordered_next); - if (! dir_entry ) - max_entries = 0; - - if (max_entries != 0) - { - size_t size = 0; - char *p; - int count = 0; - - - if (max_data_len == 0) - size = DIRENTS_CHUNK_SIZE; - else if (max_data_len > DIRENTS_CHUNK_SIZE) - size = DIRENTS_CHUNK_SIZE; - else - size = max_data_len; - - *data = mmap (0, size, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - - err = ((void *) *data == (void *) -1) ? errno : 0; - - if (! err) - { - p = *data; - - /* This gets all the actual entries present. */ - - while ((max_entries == -1 || count < max_entries) && dir_entry) - { - struct dirent hdr; - size_t name_len = strlen (dir_entry->name); - size_t sz = DIRENT_LEN (name_len); - int entry_type = IFTODT (dir_entry->stat.st_mode); - - if ((p - *data) + sz > size) - { - if (max_data_len > 0) - break; - else /* The Buffer Size must be increased. */ - { - vm_address_t extension = (vm_address_t)(*data + size); - err = vm_allocate (mach_task_self (), &extension, - DIRENTS_CHUNK_SIZE, 0); - - if (err) - break; - - size += DIRENTS_CHUNK_SIZE; - } - } - - hdr.d_namlen = name_len; - hdr.d_fileno = dir_entry->stat.st_ino; - hdr.d_reclen = sz; - hdr.d_type = entry_type; - - memcpy (p, &hdr, DIRENT_NAME_OFFS); - strcpy (p + DIRENT_NAME_OFFS, dir_entry->name); - - p += sz; - - count++; - dir_entry = dir_entry->ordered_next; - } - - if (err) - munmap (*data, size); - else - { - vm_address_t alloc_end = (vm_address_t)(*data + size); - vm_address_t real_end = round_page (p); - if (alloc_end > real_end) - munmap ((caddr_t) real_end, alloc_end - real_end); - *data_len = p - *data; - *data_entries = count; - } - } - } - else - { - *data_len = 0; - *data_entries = 0; - } - } - } - else - return ENOTDIR; - } - - procfs_dir_entries_remove (dir->nn->dir); - return err; -} - -/* Lookup NAME in DIR for USER; set *NODE to the found name upon return. If - the name was not found, then return ENOENT. On any error, clear *NODE. - (*NODE, if found, should be locked, this call should unlock DIR no matter - what.) */ -error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, - char *name, struct node **node) -{ - error_t err = procfs_refresh_node (dir); - - if (! err) - err = procfs_dir_lookup (dir->nn->dir, name, node); - - return err; -} - -/* Delete NAME in DIR for USER. */ -error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) -{ - return EROFS; -} - -/* Note that in this one call, neither of the specific nodes are locked. */ -error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, - char *fromname, struct node *todir, - char *toname, int excl) -{ - return EROFS; -} - -/* This should attempt a chmod call for the user specified by CRED on node - NODE, to change the owner to UID and the group to GID. */ -error_t netfs_attempt_chown (struct iouser *cred, struct node *node, - uid_t uid, uid_t gid) -{ - return EROFS; -} - -/* This should attempt a chauthor call for the user specified by CRED on node - NODE, to change the author to AUTHOR. */ -error_t netfs_attempt_chauthor (struct iouser *cred, struct node *node, - uid_t author) -{ - return EROFS; -} - -/* This should attempt a chmod call for the user specified by CRED on node - NODE, to change the mode to MODE. Unlike the normal Unix and Hurd meaning - of chmod, this function is also used to attempt to change files into other - types. If such a transition is attempted which is impossible, then return - EOPNOTSUPP. */ -error_t netfs_attempt_chmod (struct iouser *cred, struct node *node, - mode_t mode) -{ - return EROFS; -} - -/* Attempt to turn NODE (user CRED) into a symlink with target NAME. */ -error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *node, - char *name) -{ - return EROFS; -} - -/* Attempt to turn NODE (user CRED) into a device. TYPE is either S_IFBLK or - S_IFCHR. */ -error_t netfs_attempt_mkdev (struct iouser *cred, struct node *node, - mode_t type, dev_t indexes) -{ - return EROFS; -} - - -/* This should attempt a chflags call for the user specified by CRED on node - NODE, to change the flags to FLAGS. */ -error_t netfs_attempt_chflags (struct iouser *cred, struct node *node, - int flags) -{ - return EROFS; -} - -/* This should attempt to set the size of the file NODE (for user CRED) to - SIZE bytes long. */ -error_t netfs_attempt_set_size (struct iouser *cred, struct node *node, - off_t size) -{ - return EROFS; -} - -/* This should attempt to fetch filesystem status information for the remote - filesystem, for the user CRED. */ -error_t -netfs_attempt_statfs (struct iouser *cred, struct node *node, - struct statfs *st) -{ - bzero (st, sizeof *st); - st->f_type = PROCFILESYSTEM; - st->f_fsid = getpid (); - return 0; -} - -/* This should sync the entire remote filesystem. If WAIT is set, return - only after sync is completely finished. */ -error_t netfs_attempt_syncfs (struct iouser *cred, int wait) -{ - return 0; -} - -/* Create a link in DIR with name NAME to FILE for USER. Note that neither - DIR nor FILE are locked. If EXCL is set, do not delete the target, but - return EEXIST if NAME is already found in DIR. */ -error_t netfs_attempt_link (struct iouser *user, struct node *dir, - struct node *file, char *name, int excl) -{ - return EROFS; -} - -/* Attempt to create an anonymous file related to DIR for USER with MODE. - Set *NODE to the returned file upon success. No matter what, unlock DIR. */ -error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, - mode_t mode, struct node **node) -{ - *node = NULL; - mutex_unlock (&dir->lock); - return EROFS; -} - -/* Read the contents of NODE (a symlink), for USER, into BUF. */ -error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) -{ - error_t err = procfs_refresh_node (node); - if (! err) - { - struct procfs_dir_entry *dir_entry = node->nn->dir_entry; - if (dir_entry) - bcopy (dir_entry->symlink_target, buf, node->nn_stat.st_size); - else - err = EINVAL; - } - return err; -} - -/* Read from the file NODE for user CRED starting at OFFSET and continuing for - up to *LEN bytes. Put the data at DATA. Set *LEN to the amount - successfully read upon return. */ -error_t netfs_attempt_read (struct iouser *cred, struct node *node, - off_t offset, size_t *len, void *data) -{ - error_t err; - err = procfs_refresh_node (node); - - if (! err) - { - if (*len > 0) - procfs_read_files_contents (node, offset, - len, data); - if (*len > 0) - if (offset >= *len) - *len = 0; - } - - return err; -} - -/* Write to the file NODE for user CRED starting at OFFSET and continuing for up - to *LEN bytes from DATA. Set *LEN to the amount seccessfully written upon - return. */ -error_t netfs_attempt_write (struct iouser *cred, struct node *node, - off_t offset, size_t *len, void *data) -{ - return EROFS; -} - -/* The user must define this function. Node NP is all done; free - all its associated storage. */ -void netfs_node_norefs (struct node *np) -{ - mutex_lock (&np->lock); - *np->prevp = np->next; - np->next->prevp = np->prevp; - procfs_remove_node (np); -} - diff --git a/node.c b/node.c deleted file mode 100644 index f11fa7b0..00000000 --- a/node.c +++ /dev/null @@ -1,195 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - node.c -- This file contains function defintions to handle - node creation and destruction. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. -*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "procfs.h" - -/* Return a new node in NODE, with a name NAME, and return the - new node with a single reference in NODE. */ -error_t procfs_create_node (struct procfs_dir_entry *dir_entry, - const char *fs_path, struct node **node) -{ - struct node *new; - struct netnode *nn = malloc (sizeof (struct netnode)); - error_t err; - - if (! nn) - return ENOMEM; - if (! fs_path) - fs_path = strdup (""); - nn->fs = dir_entry->dir->fs; - nn->dir_entry = dir_entry; - nn->dir = NULL; - nn->fs_path = strdup (fs_path); - - new = netfs_make_node (nn); - if (! new) - { - free (nn); - return ENOMEM; - } - - fshelp_touch (&new->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, - procfs_maptime); - - spin_lock (&nn->fs->inode_mappings_lock); - err = hurd_ihash_add (&nn->fs->inode_mappings, dir_entry->stat.st_ino, dir_entry); - spin_unlock (&nn->fs->inode_mappings_lock); - - if (err) - { - free (nn); - free (new); - return err; - } - - dir_entry->node = new; - *node = new; - - return 0; -} - -/* Update the directory entry for NAME to reflect ST and SYMLINK_TARGET. - True is returned if successful, or false if there was a memory allocation - error. TIMESTAMP is used to record the time of this update. */ -static void -update_entry (struct procfs_dir_entry *dir_entry, const struct stat *st, - const char *symlink_target, time_t timestamp) -{ - ino_t ino; - struct procfs *fs = dir_entry->dir->fs; - - if (dir_entry->stat.st_ino) - ino = dir_entry->stat.st_ino; - else - ino = fs->next_inode++; - - dir_entry->name_timestamp = timestamp; - - if (st) - /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ - { - dir_entry->stat = *st; - dir_entry->stat_timestamp = timestamp; - - if (!dir_entry->symlink_target || !symlink_target - || strcmp (dir_entry->symlink_target, symlink_target) != 0) - { - if (dir_entry->symlink_target) - free (dir_entry->symlink_target); - dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; - } - } - - /* The st_ino field is always valid. */ - dir_entry->stat.st_ino = ino; - dir_entry->stat.st_fsid = fs->fsid; - dir_entry->stat.st_fstype = PROCFILESYSTEM; -} - -/* Refresh stat information for NODE */ -error_t procfs_refresh_node (struct node *node) -{ - struct netnode *nn = node->nn; - struct procfs_dir_entry *dir_entry = nn->dir_entry; - - if (! dir_entry) - /* This is a deleted node, don't attempt to do anything. */ - return 0; - else - { - error_t err = 0; - - struct timeval tv; - maptime_read (procfs_maptime, &tv); - - time_t timestamp = tv.tv_sec; - - struct procfs_dir *dir = dir_entry->dir; - - mutex_lock (&dir->node->lock); - - if (! dir_entry->self_p) - /* This is a deleted entry, just awaiting disposal; do so. */ - { -#if 0 - nn->dir_entry = 0; - free_entry (dir_entry); - return 0; -#endif - } - - else if (dir_entry->noent) - err = ENOENT; - else - { - if (*(dir_entry->name)) - { - err = procfs_dir_refresh (dir_entry->dir, - dir_entry->dir->node == dir_entry->dir->fs->root); - if (!err && dir_entry->noent) - err = ENOENT; - - if (err == ENOENT) - { - dir_entry->noent = 1; /* A negative entry. */ - dir_entry->name_timestamp = timestamp; - } - } - else - { - /* Refresh the root node with the old stat - information. */ - update_entry (dir_entry, &netfs_root_node->nn_stat, NULL, timestamp); - } - } - - node->nn_stat = dir_entry->stat; - node->nn_translated = S_ISLNK (dir_entry->stat.st_mode) ? S_IFLNK : 0; - if (!nn->dir && S_ISDIR (dir_entry->stat.st_mode)) - procfs_dir_create (nn->fs, node, nn->fs_path, &nn->dir); - - mutex_unlock (&dir->node->lock); - - return err; - } -} - -/* Remove NODE from its entry */ -error_t procfs_remove_node (struct node *node) -{ - - /* STUB */ - - return 0; -} diff --git a/procfs.c b/procfs.c deleted file mode 100644 index 1fd0d619..00000000 --- a/procfs.c +++ /dev/null @@ -1,149 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs.c -- This file is the main file of the translator. - This has important definitions and initializes - the translator - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "procfs.h" - -/* Defines this Tanslator Name */ -char *netfs_server_name = PROCFS_SERVER_NAME; -char *netfs_server_version = PROCFS_SERVER_VERSION; -int netfs_maxsymlinks = 12; - -static const struct argp_child argp_children[] = - { - {&netfs_std_startup_argp, 0, NULL, 0}, - {0} - }; - - -const char *argp_program_version = "/proc pseudo-filesystem (" PROCFS_SERVER_NAME - ") " PROCFS_SERVER_VERSION "\n" -"Copyright (C) 2008 Free Software Foundation\n" -"This is free software; see the source for copying conditions. There is NO\n" -"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." -"\n"; - -static char *args_doc = "PROCFSROOT"; -static char *doc = "proc pseudo-filesystem for Hurd implemented as a translator. " -"This is still under very humble and initial stages of development.\n" -"Any Contribution or help is welcome. The code may not even compile"; - - -/* The Filesystem */ -struct procfs *procfs; - -/* The FILESYSTEM component of PROCFS_FS. */ -char *procfs_root = ""; - -volatile struct mapped_time_value *procfs_maptime; - -/* Startup options. */ -static const struct argp_option procfs_options[] = - { - { 0 } - }; - - -/* argp parser function for parsing single procfs command line options */ -static error_t -parse_procfs_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case ARGP_KEY_ARG: - if (state->arg_num > 1) - argp_usage (state); - break; - - case ARGP_KEY_NO_ARGS: - argp_usage(state); - break; - - default: - return ARGP_ERR_UNKNOWN; - } -} - -/* Program entry point. */ -int -main (int argc, char **argv) -{ - error_t err; - mach_port_t bootstrap, underlying_node; - struct stat underlying_stat; - - struct argp argp = - { - procfs_options, parse_procfs_opt, - args_doc, doc, argp_children, - NULL, NULL - }; - - - /* Parse the command line arguments */ -// argp_parse (&argp, argc, argv, 0, 0, 0); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - - netfs_init (); - - if (maptime_map (0, 0, &procfs_maptime)) - { - perror (PROCFS_SERVER_NAME ": Cannot map time"); - return 1; - } - - procfs_init (); - - err = procfs_create (procfs_root, getpid (), &procfs); - if (err) - error (4, err, "%s", procfs_root); - - /* Create our root node */ - netfs_root_node = procfs->root; - - /* Start netfs activities */ - underlying_node = netfs_startup (bootstrap, 0); - if (io_stat (underlying_node, &underlying_stat)) - error (1, err, "cannot stat underling node"); - - /* Initialize stat information of the root node. */ - netfs_root_node->nn_stat = underlying_stat; - netfs_root_node->nn_stat.st_mode = - S_IFDIR | (underlying_stat.st_mode & ~S_IFMT & ~S_ITRANS); - - for (;;) - netfs_server_loop (); - return 1; -} diff --git a/procfs.h b/procfs.h deleted file mode 100644 index fa2fb7f7..00000000 --- a/procfs.h +++ /dev/null @@ -1,220 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs.h -- This file is the main header file of this - translator. This has important header - definitions for constants and functions - used in the translator. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - - A portion of the code in this file is based on ftpfs code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - - Copyright (C) 1997,98,2002 Free Software Foundation, Inc. - Written by Miles Bader - This file is part of the GNU Hurd. -*/ - -#ifndef __PROCFS_H__ -#define __PROCFS_H__ - -#define PROCFS_SERVER_NAME "procfs" -#define PROCFS_SERVER_VERSION "0.0.1" - -/* /proc Filesystem type. */ -#define PROCFILESYSTEM "procfs" - -#define NUMBER_OF_FILES_PER_PID 1 -#define JIFFY_ADJUST 100 -#define PAGES_TO_BYTES(pages) ((pages) * sysconf(_SC_PAGESIZE)) -#define BYTES_TO_PAGES(bytes) ((bytes) / sysconf(_SC_PAGESIZE)) - -#include -#include -#include -#include -#include -#include - -typedef unsigned long long jiffy_t; - -/* A single entry in a directory. */ -struct procfs_dir_entry -{ - char *name; /* Name of this entry */ - size_t hv; /* Hash value of NAME */ - - /* The active node referred to by this name (may be 0). - NETFS_NODE_REFCNT_LOCK should be held while frobbing this. */ - struct node *node; - - struct stat stat; - char *symlink_target; - time_t stat_timestamp; - - /* The directory to which this entry belongs. */ - struct procfs_dir *dir; - - /* Link to next entry in hash bucket, and address of previous entry's (or - hash table's) pointer to this entry. If the SELF_P field is 0, then - this is a deleted entry, awaiting final disposal. */ - struct procfs_dir_entry *next, **self_p; - - /* Next entry in 'directory order', or 0 if none known. */ - struct procfs_dir_entry *ordered_next, **ordered_self_p; - - /* When the presence/absence of this file was last checked. */ - time_t name_timestamp; - - hurd_ihash_locp_t inode_locp; /* Used for removing this entry */ - - int noent : 1; /* A negative lookup result. */ - int valid : 1; /* Marker for GC'ing. */ -}; - -/* A directory. */ -struct procfs_dir -{ - /* Number of entries in HTABLE. */ - size_t num_entries; - - /* The number of entries that have nodes attached. We keep an additional - reference to our node if there are any, to prevent it from going away. */ - size_t num_live_entries; - - /* Hash table of entries. */ - struct procfs_dir_entry **htable; - size_t htable_len; /* # of elements in HTABLE (not bytes). */ - - /* List of dir entries in 'directory order', in a linked list using the - ORDERED_NEXT and ORDERED_SELF_P fields in each entry. Not all entries - in HTABLE need be in this list. */ - struct procfs_dir_entry *ordered; - - /* The filesystem node that this is the directory for. */ - struct node *node; - - /* The filesystem this directory is in. */ - struct procfs *fs; - - /* The path to this directory in the filesystem. */ - const char *fs_path; - - time_t stat_timestamp; - time_t name_timestamp; - -}; - - -/* libnetfs node structure */ -struct netnode -{ - /* Name of this node */ - char *name; - - /* The path in the filesystem that corresponds - this node. */ - char *fs_path; - - /* The directory entry for this node. */ - struct procfs_dir_entry *dir_entry; - - /* The proc filesystem */ - struct procfs *fs; - - /* inode number, assigned to this netnode structure. */ - unsigned int inode_num; - - /* If this is a directory, the contents, or 0 if not fetched. */ - struct procfs_dir *dir; - - /* pointer to node structure, assigned to this node. */ - struct node *node; - - /* links to the previous and next nodes in the list */ - struct netnode *nextnode, *prevnode; - - /* link to parent netnode of this file or directory */ - struct netnode *parent; - - /* link to the first child netnode of this directory */ - struct netnode *child_first; -}; - -/* The actual procfs filesystem structure */ -struct procfs -{ - /* Root of the filesystem. */ - struct node *root; - - /* Inode numbers are assigned sequentially in order of creation. */ - ino_t next_inode; - int fsid; - - /* A hash table mapping inode numbers to directory entries. */ - struct hurd_ihash inode_mappings; - spin_lock_t inode_mappings_lock; -}; - -extern struct procfs *procfs; - -extern volatile struct mapped_time_value *procfs_maptime; - -extern struct ps_context *ps_context; - -/* Create a new procfs filesystem. */ -error_t procfs_create (char *procfs_root, int fsid, - struct procfs **fs); - -/* Initialize the procfs filesystem for use. */ -error_t procfs_init (); - -/* Refresh stat information for NODE */ -error_t procfs_refresh_node (struct node *node); - -/* Return a new node in NODE, with a name NAME, - and return the new node with a single - reference in NODE. */ -error_t procfs_create_node (struct procfs_dir_entry *dir_entry, - const char *fs_path, - struct node **node); - -/* Remove NODE from its entry */ -error_t procfs_remove_node (struct node *node); - -/* Return in DIR a new procfs directory, in the filesystem FS, - with node NODE and path PATH. */ -error_t procfs_dir_create (struct procfs *fs, struct node *node, - const char *path, struct procfs_dir **dir); - -/* Remove the specified DIR and free all its allocated - storage. */ -void procfs_dir_remove (struct procfs_dir *dir); - -/* Refresh DIR. */ -error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot); - -/* Lookup NAME in DIR, returning its entry, or an error. - *NODE will contain the result node, locked, and with - an additional reference, or 0 if an error occurs. */ -error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, - struct node **node); - -#endif /* __PROCFS_H__ */ diff --git a/procfs/ChangeLog b/procfs/ChangeLog new file mode 100644 index 00000000..47cbeaf2 --- /dev/null +++ b/procfs/ChangeLog @@ -0,0 +1,177 @@ +2010-05-31 Samuel Thibault + + * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Print swap sizes + using %llu. + +2008-12-12 Samuel Thibault + + * procfs_nonpid_files.c (procfs_read_nonpid_meminfo): Divide by + 1024 value returned by get_swap_size and get_swap_free to get + kilobytes. + +2008-09-02 Madhusudan.C.S + + * netfs.c: (netfs_get_dirents): Add call to + procfs_dir_entries_remove(). + +2008-08-30 Madhusudan.C.S + + * procfs_dir.c: (procfs_dir_create): Assign newly created directory to + its pointer in netnode. + (procfs_dir_remove): Removed function. + (free_entry): New function. + (ordered_unlink): Likewise. + (delete): Likewise. + (sweep): Likewise. + (procfs_dir_entries_remove): Likewise. + (is_in_pid_list): Removed call to make_dir_invalid (). + (procfs_fill_root_dir): struct stat *stat -> struct stat stat. + Add Read and Execute permissions to all in stat.st_mode. + Set stat.st_nlink to 1. + Set stat.st_size to 0. + Add struct proc_stat *ps definition. + Set struct proc_stat data from _proc_stat_create () function and + set stat.st_uid and stat.st_gid from the data in that structure. + * procfs_pid_files.c: (update_pid_entries): Add Read permissions + to all in stat->st_mode. + +2008-08-29 Madhusudan.C.S + + * AUTHORS: File removed. + * COPYING: Likewise. + * README: Likewise. + +2008-08-29 Madhusudan.C.S + + * Makefile: (Copyright): 1997, 2000 -> 2008. + (CC): Removed. + (CFLAGS): Removed. + (INCLUDES): Removed. + (all): Removed. + ($(target)): Removed. + (%.o): Removed. + (HURDLIBS): -lnetfs -> netfs, -lfshelp -> fshelp, + -liohelp -> iohelp, -lthreads -> threads, -lports -> ports, + -lihash -> ihash, -lps -> ps, -lshouldbeinlibc -> shouldbeinlibc. + (include): Add include ../Makeconf + +2008-08-18 Madhusudan.C.S + + * procfs_nonpid_files.c: (procfs_write_nonpid_stat): Changed to + procfs_read_nonpid_stat. + (procfs_write_nonpid_meminfo): Changed to procfs_read_nonpid_meminfo. + (procfs_write_nonpid_loadavg): Changed to procfs_read_nonpid_loadavg. + (procfs_write_nonpid_uptime): Changed to procfs_read_nonpid_uptime. + (procfs_write_nonpid_version):Changed to procfs_read_nonpid_version. + * procfs_pid_files.c: (procfs_write_stat_file): Changed to + procfs_read_stat_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_cmdline_file ): Changed to procfs_read_cmdline_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_status_file): Changed to procfs_read_status_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_statm_file): Changed to procfs_read_statm_file. + Changed the comment correspondingly from Write to Read. + (procfs_write_files_contents): Changed to procfs_read_files_contents. + Changed the comment correspondingly from Write to Read. + Changed the call to procfs_write_nonpid_stat to procfs_read_nonpid_stat. + Changed the call to procfs_write_stat_file to procfs_read_stat_file. + Changed the call to procfs_write_cmdline_file to + procfs_read_cmdline_file. + Changed the call to procfs_write_status_file to + procfs_read_status_file. + Changed the call to procfs_write_statm_file to + procfs_read_statm_file. + Changed the call to procfs_write_nonpid_meminfo to + procfs_read_nonpid_meminfo. + Changed the call to procfs_write_nonpid_loadavg to + procfs_read_nonpid_loadavg. + Changed the call to procfs_write_nonpid_uptime to + procfs_read_nonpid_uptime. + Changed the call to procfs_write_nonpid_version to + procfs_read_nonpid_version. + netfs.c: (netfs_attempt_read): Changed the call from + procfs_write_files_contents to procfs_read_files_contents. + +2008-08-18 Madhusudan.C.S + + * README: Initial Documentation. + +2008-08-18 Madhusudan.C.S + + * procfs_nonpid_files.c: (get_uptime): Changed the parameter type from + double to struct timeval. + Changed the parameter name from uptime_secs to uptime. + Removed uptime variable. + Changed timersub to use the passed pointer instead of the local + variable. + Removed the calculation of uptime_secs. + (get_total_times): Changed the parameters type from double to struct + timeval. + Changed the parameters name from total_user_time_secs to + total_user_time and total_system_time_secs to total_system_time. + New variables total_user_time_tmp, total_system_time_tmp and tmpval + of type struct timeval. + Call timerclear to clear the tmp variables. + Remove calculation of times in seconds and do the same on struct + timeval variables throughout using the timeradd macro. + Assign values of temporary local variables to the pointers passed + as parameters. + (procfs_write_nonpid_stat): Replaced variables that hold time in + seconds with struct timeval type variables and jiffy_t type variables. + Argument to get_uptime changed from uptime_secs to uptime. + Arguments to get_total_times changed from total_user_time_secs to + total_user_time and total_system_time_secs to total_system_time. + Replace arithematic time subtraction with timersub macro. + Convert all the times in struct timeval type variables to jiffy_t type. + Changed the type casting for the asprintf arguments to be compatible + with jiffy_t type. + (procfs_write_nonpid_uptime): Replaced variables that hold time in + seconds with struct timeval type variables. + Argument to get_uptime changed from uptime_secs to uptime. + Arguments to get_total_times changed from total_user_time_secs to + total_user_time and total_system_time_secs to total_system_time. + Replace arithematic time subtraction with timersub macro. + Convert all the times in struct timeval type variables to seconds. + +2008-08-18 Madhusudan.C.S + + * procfs_nonpid_files.c: (procfs_write_nonpid_version): New function. + * procfs_pid_files.c: (procfs_write_files_contents): Add a check + to find if the read is requested for the version file and + corresponding a call to it. + +2008-08-14 Madhusudan.C.S + + * procfs.h: (jiffy_t): New typedef. + * procfs_pid.h: "procfs.h" is included. + (struct procfs_pid_files): Changed all the occurrences of time_t to + jiffy_t. + * procfs_pid_files.c: Removed "procfs.h". + (adjust_jiffy_time): Changed return type from time_t to jiffy_t. + Changed the type of jiffy_time variable from time_t to jiffy_t. + (get_live_threads_time): Changed the type of utime and stime from + time_t to jiffy_t. + (get_stat_data): Changed the type of utime and stime from time_t to + jiffy_t. + +2008-08-14 Madhusudan.C.S + + * ChangeLog: New file. + * AUTHORS: New file. + * COPYING: New file. + * README: New file. + * Makefile: New file. + * bootstrap.c: New file. + * netfs.c: New file. + * node.c: New file. + * procfs.c: New file. + * procfs.h: New file. + * procfs_dir.c: New file. + * procfs_nonpid_files.c: New file. + * procfs_pid.h: New file. + * procfs_pid_files.c: New file. + +2008-05-13 Madhusudan.C.S + + * /sources/hurd/procfs: New directory added to the repository. diff --git a/procfs/Makefile b/procfs/Makefile new file mode 100644 index 00000000..500a2371 --- /dev/null +++ b/procfs/Makefile @@ -0,0 +1,30 @@ +# Makefile - for procfs +# +# Copyright (C) 2008 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2, 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +dir := procfs +makemode := server + +target = procfs + +SRCS = procfs.c bootstrap.c netfs.c procfs_dir.c node.c procfs_pid_files.c procfs_nonpid_files.c +LCLHDRS = procfs.h procfs_pid.h + +OBJS = $(SRCS:.c=.o) +HURDLIBS = netfs fshelp iohelp threads ports ihash ps shouldbeinlibc + +include ../Makeconf diff --git a/procfs/bootstrap.c b/procfs/bootstrap.c new file mode 100644 index 00000000..73d31f00 --- /dev/null +++ b/procfs/bootstrap.c @@ -0,0 +1,95 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + bootstrap.c -- This file is functions for starting up + and initializers for the procfs translator + defined in procfs.h + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#include +#include +#include + +#include "procfs.h" + +struct ps_context *ps_context; + +/* This function is used to initialize the whole translator, can be + effect called as bootstrapping the translator. */ +error_t procfs_init () +{ + error_t err; + + err = ps_context_create (getproc (), &ps_context); + + return err; +} + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs) +{ + error_t err; + /* This is the enclosing directory for this filesystem's + root node */ + struct procfs_dir *topmost_root_dir; + + /* And also a topmost-root node, just used for locking + TOPMOST_ROOT_DIR. */ + struct node *topmost_root; + + /* The new node for the filesystem's root. */ + struct procfs *new = malloc (sizeof (struct procfs)); + + if (! new) + return ENOMEM; + + new->fsid = fsid; + new->next_inode = 2; + + hurd_ihash_init (&new->inode_mappings, + offsetof (struct procfs_dir_entry, inode_locp)); + spin_lock_init (&new->inode_mappings_lock); + + topmost_root = netfs_make_node (0); + if (! topmost_root) + err = ENOMEM; + else + { + err = procfs_dir_create (new, topmost_root, procfs_root, + &topmost_root_dir); + if (! err) + { + /* ADDITIONAL BOOTSTRAPPING OF THE ROOT NODE */ + err = procfs_dir_null_lookup (topmost_root_dir, &new->root); + } + } + + if (err) + { + hurd_ihash_destroy (&new->inode_mappings); + free (new); + } + else + *fs = new; + + return err; +} + diff --git a/procfs/netfs.c b/procfs/netfs.c new file mode 100644 index 00000000..4f6fd5ce --- /dev/null +++ b/procfs/netfs.c @@ -0,0 +1,467 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "procfs.h" + +/* Trivial definitions. */ + +/* Make sure that NP->nn_stat is filled with current information. CRED + identifies the user responsible for the operation. */ +error_t +netfs_validate_stat (struct node *node, struct iouser *cred) +{ + return procfs_refresh_node (node); +} + +/* This should sync the file NODE completely to disk, for the user CRED. If + WAIT is set, return only after sync is completely finished. */ +error_t +netfs_attempt_sync (struct iouser *cred, struct node *node, int wait) +{ + return 0; +} + +/* Attempt to create a new directory named NAME in DIR for USER with mode + MODE. */ +error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, + char *name, mode_t mode) +{ + return EROFS; +} + +/* Attempt to remove directory named NAME in DIR for USER. */ +error_t netfs_attempt_rmdir (struct iouser *user, + struct node *dir, char *name) +{ + return EROFS; +} + +/* Attempt to set the passive translator record for FILE to ARGZ (of length + ARGZLEN) for user CRED. */ +error_t netfs_set_translator (struct iouser *cred, struct node *node, + char *argz, size_t argzlen) +{ + return EROFS; +} + +/* Attempt to create a file named NAME in DIR for USER with MODE. Set *NODE + to the new node upon return. On any error, clear *NODE. *NODE should be + locked on success; no matter what, unlock DIR before returning. */ +error_t +netfs_attempt_create_file (struct iouser *user, struct node *dir, + char *name, mode_t mode, struct node **node) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* Node NODE is being opened by USER, with FLAGS. NEWNODE is nonzero if we + just created this node. Return an error if we should not permit the open + to complete because of a permission restriction. */ +error_t +netfs_check_open_permissions (struct iouser *user, struct node *node, + int flags, int newnode) +{ + error_t err = procfs_refresh_node (node); + if (!err && (flags & O_READ)) + err = fshelp_access (&node->nn_stat, S_IREAD, user); + if (!err && (flags & O_WRITE)) + err = fshelp_access (&node->nn_stat, S_IWRITE, user); + if (!err && (flags & O_EXEC)) + err = fshelp_access (&node->nn_stat, S_IEXEC, user); + return err; +} + +/* This should attempt a utimes call for the user specified by CRED on node + NODE, to change the atime to ATIME and the mtime to MTIME. */ +error_t +netfs_attempt_utimes (struct iouser *cred, struct node *node, + struct timespec *atime, struct timespec *mtime) +{ + error_t err = procfs_refresh_node (node); + int flags = TOUCH_CTIME; + + if (! err) + err = fshelp_isowner (&node->nn_stat, cred); + + if (! err) + { + if (atime) + node->nn_stat.st_atim = *atime; + else + flags |= TOUCH_ATIME; + + if (mtime) + node->nn_stat.st_mtim = *mtime; + else + flags |= TOUCH_MTIME; + + fshelp_touch (&node->nn_stat, flags, procfs_maptime); + } + + return err; +} + +/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and O_EXEC) + in *TYPES for file NODE and user CRED. */ +error_t +netfs_report_access (struct iouser *cred, struct node *node, int *types) +{ + error_t err = procfs_refresh_node (node); + + if (! err) + { + *types = 0; + if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + } + + return err; +} + +/* The granularity with which we allocate space to return our result. */ +#define DIRENTS_CHUNK_SIZE (8*1024) + +/* Returned directory entries are aligned to blocks this many bytes long. + Must be a power of two. */ +#define DIRENT_ALIGN 4 +#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) + +/* Length is structure before the name + the name + '\0', all + padded to a four-byte alignment. */ +#define DIRENT_LEN(name_len) \ + ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ + & ~(DIRENT_ALIGN - 1)) + + + +/* Fetch a directory */ +error_t +netfs_get_dirents (struct iouser *cred, struct node *dir, + int first_entry, int max_entries, char **data, + mach_msg_type_number_t *data_len, + vm_size_t max_data_len, int *data_entries) +{ + error_t err = procfs_refresh_node (dir); + struct procfs_dir_entry *dir_entry; + + if (! err) + { + if (dir->nn->dir) + { + if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root)) + { + for (dir_entry = dir->nn->dir->ordered; first_entry > 0 && + dir_entry; first_entry--, + dir_entry = dir_entry->ordered_next); + if (! dir_entry ) + max_entries = 0; + + if (max_entries != 0) + { + size_t size = 0; + char *p; + int count = 0; + + + if (max_data_len == 0) + size = DIRENTS_CHUNK_SIZE; + else if (max_data_len > DIRENTS_CHUNK_SIZE) + size = DIRENTS_CHUNK_SIZE; + else + size = max_data_len; + + *data = mmap (0, size, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + err = ((void *) *data == (void *) -1) ? errno : 0; + + if (! err) + { + p = *data; + + /* This gets all the actual entries present. */ + + while ((max_entries == -1 || count < max_entries) && dir_entry) + { + struct dirent hdr; + size_t name_len = strlen (dir_entry->name); + size_t sz = DIRENT_LEN (name_len); + int entry_type = IFTODT (dir_entry->stat.st_mode); + + if ((p - *data) + sz > size) + { + if (max_data_len > 0) + break; + else /* The Buffer Size must be increased. */ + { + vm_address_t extension = (vm_address_t)(*data + size); + err = vm_allocate (mach_task_self (), &extension, + DIRENTS_CHUNK_SIZE, 0); + + if (err) + break; + + size += DIRENTS_CHUNK_SIZE; + } + } + + hdr.d_namlen = name_len; + hdr.d_fileno = dir_entry->stat.st_ino; + hdr.d_reclen = sz; + hdr.d_type = entry_type; + + memcpy (p, &hdr, DIRENT_NAME_OFFS); + strcpy (p + DIRENT_NAME_OFFS, dir_entry->name); + + p += sz; + + count++; + dir_entry = dir_entry->ordered_next; + } + + if (err) + munmap (*data, size); + else + { + vm_address_t alloc_end = (vm_address_t)(*data + size); + vm_address_t real_end = round_page (p); + if (alloc_end > real_end) + munmap ((caddr_t) real_end, alloc_end - real_end); + *data_len = p - *data; + *data_entries = count; + } + } + } + else + { + *data_len = 0; + *data_entries = 0; + } + } + } + else + return ENOTDIR; + } + + procfs_dir_entries_remove (dir->nn->dir); + return err; +} + +/* Lookup NAME in DIR for USER; set *NODE to the found name upon return. If + the name was not found, then return ENOENT. On any error, clear *NODE. + (*NODE, if found, should be locked, this call should unlock DIR no matter + what.) */ +error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, + char *name, struct node **node) +{ + error_t err = procfs_refresh_node (dir); + + if (! err) + err = procfs_dir_lookup (dir->nn->dir, name, node); + + return err; +} + +/* Delete NAME in DIR for USER. */ +error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, + char *name) +{ + return EROFS; +} + +/* Note that in this one call, neither of the specific nodes are locked. */ +error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, + char *fromname, struct node *todir, + char *toname, int excl) +{ + return EROFS; +} + +/* This should attempt a chmod call for the user specified by CRED on node + NODE, to change the owner to UID and the group to GID. */ +error_t netfs_attempt_chown (struct iouser *cred, struct node *node, + uid_t uid, uid_t gid) +{ + return EROFS; +} + +/* This should attempt a chauthor call for the user specified by CRED on node + NODE, to change the author to AUTHOR. */ +error_t netfs_attempt_chauthor (struct iouser *cred, struct node *node, + uid_t author) +{ + return EROFS; +} + +/* This should attempt a chmod call for the user specified by CRED on node + NODE, to change the mode to MODE. Unlike the normal Unix and Hurd meaning + of chmod, this function is also used to attempt to change files into other + types. If such a transition is attempted which is impossible, then return + EOPNOTSUPP. */ +error_t netfs_attempt_chmod (struct iouser *cred, struct node *node, + mode_t mode) +{ + return EROFS; +} + +/* Attempt to turn NODE (user CRED) into a symlink with target NAME. */ +error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *node, + char *name) +{ + return EROFS; +} + +/* Attempt to turn NODE (user CRED) into a device. TYPE is either S_IFBLK or + S_IFCHR. */ +error_t netfs_attempt_mkdev (struct iouser *cred, struct node *node, + mode_t type, dev_t indexes) +{ + return EROFS; +} + + +/* This should attempt a chflags call for the user specified by CRED on node + NODE, to change the flags to FLAGS. */ +error_t netfs_attempt_chflags (struct iouser *cred, struct node *node, + int flags) +{ + return EROFS; +} + +/* This should attempt to set the size of the file NODE (for user CRED) to + SIZE bytes long. */ +error_t netfs_attempt_set_size (struct iouser *cred, struct node *node, + off_t size) +{ + return EROFS; +} + +/* This should attempt to fetch filesystem status information for the remote + filesystem, for the user CRED. */ +error_t +netfs_attempt_statfs (struct iouser *cred, struct node *node, + struct statfs *st) +{ + bzero (st, sizeof *st); + st->f_type = PROCFILESYSTEM; + st->f_fsid = getpid (); + return 0; +} + +/* This should sync the entire remote filesystem. If WAIT is set, return + only after sync is completely finished. */ +error_t netfs_attempt_syncfs (struct iouser *cred, int wait) +{ + return 0; +} + +/* Create a link in DIR with name NAME to FILE for USER. Note that neither + DIR nor FILE are locked. If EXCL is set, do not delete the target, but + return EEXIST if NAME is already found in DIR. */ +error_t netfs_attempt_link (struct iouser *user, struct node *dir, + struct node *file, char *name, int excl) +{ + return EROFS; +} + +/* Attempt to create an anonymous file related to DIR for USER with MODE. + Set *NODE to the returned file upon success. No matter what, unlock DIR. */ +error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, + mode_t mode, struct node **node) +{ + *node = NULL; + mutex_unlock (&dir->lock); + return EROFS; +} + +/* Read the contents of NODE (a symlink), for USER, into BUF. */ +error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) +{ + error_t err = procfs_refresh_node (node); + if (! err) + { + struct procfs_dir_entry *dir_entry = node->nn->dir_entry; + if (dir_entry) + bcopy (dir_entry->symlink_target, buf, node->nn_stat.st_size); + else + err = EINVAL; + } + return err; +} + +/* Read from the file NODE for user CRED starting at OFFSET and continuing for + up to *LEN bytes. Put the data at DATA. Set *LEN to the amount + successfully read upon return. */ +error_t netfs_attempt_read (struct iouser *cred, struct node *node, + off_t offset, size_t *len, void *data) +{ + error_t err; + err = procfs_refresh_node (node); + + if (! err) + { + if (*len > 0) + procfs_read_files_contents (node, offset, + len, data); + if (*len > 0) + if (offset >= *len) + *len = 0; + } + + return err; +} + +/* Write to the file NODE for user CRED starting at OFFSET and continuing for up + to *LEN bytes from DATA. Set *LEN to the amount seccessfully written upon + return. */ +error_t netfs_attempt_write (struct iouser *cred, struct node *node, + off_t offset, size_t *len, void *data) +{ + return EROFS; +} + +/* The user must define this function. Node NP is all done; free + all its associated storage. */ +void netfs_node_norefs (struct node *np) +{ + mutex_lock (&np->lock); + *np->prevp = np->next; + np->next->prevp = np->prevp; + procfs_remove_node (np); +} + diff --git a/procfs/node.c b/procfs/node.c new file mode 100644 index 00000000..f11fa7b0 --- /dev/null +++ b/procfs/node.c @@ -0,0 +1,195 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + node.c -- This file contains function defintions to handle + node creation and destruction. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "procfs.h" + +/* Return a new node in NODE, with a name NAME, and return the + new node with a single reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, struct node **node) +{ + struct node *new; + struct netnode *nn = malloc (sizeof (struct netnode)); + error_t err; + + if (! nn) + return ENOMEM; + if (! fs_path) + fs_path = strdup (""); + nn->fs = dir_entry->dir->fs; + nn->dir_entry = dir_entry; + nn->dir = NULL; + nn->fs_path = strdup (fs_path); + + new = netfs_make_node (nn); + if (! new) + { + free (nn); + return ENOMEM; + } + + fshelp_touch (&new->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, + procfs_maptime); + + spin_lock (&nn->fs->inode_mappings_lock); + err = hurd_ihash_add (&nn->fs->inode_mappings, dir_entry->stat.st_ino, dir_entry); + spin_unlock (&nn->fs->inode_mappings_lock); + + if (err) + { + free (nn); + free (new); + return err; + } + + dir_entry->node = new; + *node = new; + + return 0; +} + +/* Update the directory entry for NAME to reflect ST and SYMLINK_TARGET. + True is returned if successful, or false if there was a memory allocation + error. TIMESTAMP is used to record the time of this update. */ +static void +update_entry (struct procfs_dir_entry *dir_entry, const struct stat *st, + const char *symlink_target, time_t timestamp) +{ + ino_t ino; + struct procfs *fs = dir_entry->dir->fs; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (st) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *st; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; +} + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node) +{ + struct netnode *nn = node->nn; + struct procfs_dir_entry *dir_entry = nn->dir_entry; + + if (! dir_entry) + /* This is a deleted node, don't attempt to do anything. */ + return 0; + else + { + error_t err = 0; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + struct procfs_dir *dir = dir_entry->dir; + + mutex_lock (&dir->node->lock); + + if (! dir_entry->self_p) + /* This is a deleted entry, just awaiting disposal; do so. */ + { +#if 0 + nn->dir_entry = 0; + free_entry (dir_entry); + return 0; +#endif + } + + else if (dir_entry->noent) + err = ENOENT; + else + { + if (*(dir_entry->name)) + { + err = procfs_dir_refresh (dir_entry->dir, + dir_entry->dir->node == dir_entry->dir->fs->root); + if (!err && dir_entry->noent) + err = ENOENT; + + if (err == ENOENT) + { + dir_entry->noent = 1; /* A negative entry. */ + dir_entry->name_timestamp = timestamp; + } + } + else + { + /* Refresh the root node with the old stat + information. */ + update_entry (dir_entry, &netfs_root_node->nn_stat, NULL, timestamp); + } + } + + node->nn_stat = dir_entry->stat; + node->nn_translated = S_ISLNK (dir_entry->stat.st_mode) ? S_IFLNK : 0; + if (!nn->dir && S_ISDIR (dir_entry->stat.st_mode)) + procfs_dir_create (nn->fs, node, nn->fs_path, &nn->dir); + + mutex_unlock (&dir->node->lock); + + return err; + } +} + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node) +{ + + /* STUB */ + + return 0; +} diff --git a/procfs/procfs.c b/procfs/procfs.c new file mode 100644 index 00000000..1fd0d619 --- /dev/null +++ b/procfs/procfs.c @@ -0,0 +1,149 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.c -- This file is the main file of the translator. + This has important definitions and initializes + the translator + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "procfs.h" + +/* Defines this Tanslator Name */ +char *netfs_server_name = PROCFS_SERVER_NAME; +char *netfs_server_version = PROCFS_SERVER_VERSION; +int netfs_maxsymlinks = 12; + +static const struct argp_child argp_children[] = + { + {&netfs_std_startup_argp, 0, NULL, 0}, + {0} + }; + + +const char *argp_program_version = "/proc pseudo-filesystem (" PROCFS_SERVER_NAME + ") " PROCFS_SERVER_VERSION "\n" +"Copyright (C) 2008 Free Software Foundation\n" +"This is free software; see the source for copying conditions. There is NO\n" +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +"\n"; + +static char *args_doc = "PROCFSROOT"; +static char *doc = "proc pseudo-filesystem for Hurd implemented as a translator. " +"This is still under very humble and initial stages of development.\n" +"Any Contribution or help is welcome. The code may not even compile"; + + +/* The Filesystem */ +struct procfs *procfs; + +/* The FILESYSTEM component of PROCFS_FS. */ +char *procfs_root = ""; + +volatile struct mapped_time_value *procfs_maptime; + +/* Startup options. */ +static const struct argp_option procfs_options[] = + { + { 0 } + }; + + +/* argp parser function for parsing single procfs command line options */ +static error_t +parse_procfs_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case ARGP_KEY_ARG: + if (state->arg_num > 1) + argp_usage (state); + break; + + case ARGP_KEY_NO_ARGS: + argp_usage(state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } +} + +/* Program entry point. */ +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t bootstrap, underlying_node; + struct stat underlying_stat; + + struct argp argp = + { + procfs_options, parse_procfs_opt, + args_doc, doc, argp_children, + NULL, NULL + }; + + + /* Parse the command line arguments */ +// argp_parse (&argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + + netfs_init (); + + if (maptime_map (0, 0, &procfs_maptime)) + { + perror (PROCFS_SERVER_NAME ": Cannot map time"); + return 1; + } + + procfs_init (); + + err = procfs_create (procfs_root, getpid (), &procfs); + if (err) + error (4, err, "%s", procfs_root); + + /* Create our root node */ + netfs_root_node = procfs->root; + + /* Start netfs activities */ + underlying_node = netfs_startup (bootstrap, 0); + if (io_stat (underlying_node, &underlying_stat)) + error (1, err, "cannot stat underling node"); + + /* Initialize stat information of the root node. */ + netfs_root_node->nn_stat = underlying_stat; + netfs_root_node->nn_stat.st_mode = + S_IFDIR | (underlying_stat.st_mode & ~S_IFMT & ~S_ITRANS); + + for (;;) + netfs_server_loop (); + return 1; +} diff --git a/procfs/procfs.h b/procfs/procfs.h new file mode 100644 index 00000000..fa2fb7f7 --- /dev/null +++ b/procfs/procfs.h @@ -0,0 +1,220 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs.h -- This file is the main header file of this + translator. This has important header + definitions for constants and functions + used in the translator. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#ifndef __PROCFS_H__ +#define __PROCFS_H__ + +#define PROCFS_SERVER_NAME "procfs" +#define PROCFS_SERVER_VERSION "0.0.1" + +/* /proc Filesystem type. */ +#define PROCFILESYSTEM "procfs" + +#define NUMBER_OF_FILES_PER_PID 1 +#define JIFFY_ADJUST 100 +#define PAGES_TO_BYTES(pages) ((pages) * sysconf(_SC_PAGESIZE)) +#define BYTES_TO_PAGES(bytes) ((bytes) / sysconf(_SC_PAGESIZE)) + +#include +#include +#include +#include +#include +#include + +typedef unsigned long long jiffy_t; + +/* A single entry in a directory. */ +struct procfs_dir_entry +{ + char *name; /* Name of this entry */ + size_t hv; /* Hash value of NAME */ + + /* The active node referred to by this name (may be 0). + NETFS_NODE_REFCNT_LOCK should be held while frobbing this. */ + struct node *node; + + struct stat stat; + char *symlink_target; + time_t stat_timestamp; + + /* The directory to which this entry belongs. */ + struct procfs_dir *dir; + + /* Link to next entry in hash bucket, and address of previous entry's (or + hash table's) pointer to this entry. If the SELF_P field is 0, then + this is a deleted entry, awaiting final disposal. */ + struct procfs_dir_entry *next, **self_p; + + /* Next entry in 'directory order', or 0 if none known. */ + struct procfs_dir_entry *ordered_next, **ordered_self_p; + + /* When the presence/absence of this file was last checked. */ + time_t name_timestamp; + + hurd_ihash_locp_t inode_locp; /* Used for removing this entry */ + + int noent : 1; /* A negative lookup result. */ + int valid : 1; /* Marker for GC'ing. */ +}; + +/* A directory. */ +struct procfs_dir +{ + /* Number of entries in HTABLE. */ + size_t num_entries; + + /* The number of entries that have nodes attached. We keep an additional + reference to our node if there are any, to prevent it from going away. */ + size_t num_live_entries; + + /* Hash table of entries. */ + struct procfs_dir_entry **htable; + size_t htable_len; /* # of elements in HTABLE (not bytes). */ + + /* List of dir entries in 'directory order', in a linked list using the + ORDERED_NEXT and ORDERED_SELF_P fields in each entry. Not all entries + in HTABLE need be in this list. */ + struct procfs_dir_entry *ordered; + + /* The filesystem node that this is the directory for. */ + struct node *node; + + /* The filesystem this directory is in. */ + struct procfs *fs; + + /* The path to this directory in the filesystem. */ + const char *fs_path; + + time_t stat_timestamp; + time_t name_timestamp; + +}; + + +/* libnetfs node structure */ +struct netnode +{ + /* Name of this node */ + char *name; + + /* The path in the filesystem that corresponds + this node. */ + char *fs_path; + + /* The directory entry for this node. */ + struct procfs_dir_entry *dir_entry; + + /* The proc filesystem */ + struct procfs *fs; + + /* inode number, assigned to this netnode structure. */ + unsigned int inode_num; + + /* If this is a directory, the contents, or 0 if not fetched. */ + struct procfs_dir *dir; + + /* pointer to node structure, assigned to this node. */ + struct node *node; + + /* links to the previous and next nodes in the list */ + struct netnode *nextnode, *prevnode; + + /* link to parent netnode of this file or directory */ + struct netnode *parent; + + /* link to the first child netnode of this directory */ + struct netnode *child_first; +}; + +/* The actual procfs filesystem structure */ +struct procfs +{ + /* Root of the filesystem. */ + struct node *root; + + /* Inode numbers are assigned sequentially in order of creation. */ + ino_t next_inode; + int fsid; + + /* A hash table mapping inode numbers to directory entries. */ + struct hurd_ihash inode_mappings; + spin_lock_t inode_mappings_lock; +}; + +extern struct procfs *procfs; + +extern volatile struct mapped_time_value *procfs_maptime; + +extern struct ps_context *ps_context; + +/* Create a new procfs filesystem. */ +error_t procfs_create (char *procfs_root, int fsid, + struct procfs **fs); + +/* Initialize the procfs filesystem for use. */ +error_t procfs_init (); + +/* Refresh stat information for NODE */ +error_t procfs_refresh_node (struct node *node); + +/* Return a new node in NODE, with a name NAME, + and return the new node with a single + reference in NODE. */ +error_t procfs_create_node (struct procfs_dir_entry *dir_entry, + const char *fs_path, + struct node **node); + +/* Remove NODE from its entry */ +error_t procfs_remove_node (struct node *node); + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir); + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_remove (struct procfs_dir *dir); + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot); + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node); + +#endif /* __PROCFS_H__ */ diff --git a/procfs/procfs_dir.c b/procfs/procfs_dir.c new file mode 100644 index 00000000..f76e6a4b --- /dev/null +++ b/procfs/procfs_dir.c @@ -0,0 +1,664 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_dir.c -- This file contains definitions to perform + directory operations such as creating, + removing and refreshing directories. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + + +#include +#include +#include +#include +#include + +#include "procfs.h" + +/* Initial HASHTABLE length for the new directories to be created. */ +#define INIT_HTABLE_LEN 5 + +struct procfs_dir_entry **cur_entry; + +/* Return in DIR a new procfs directory, in the filesystem FS, + with node NODE and path PATH. */ +error_t procfs_dir_create (struct procfs *fs, struct node *node, + const char *path, struct procfs_dir **dir) +{ + struct procfs_dir *new = malloc (sizeof (struct procfs_dir)); + if (!new) + return ENOMEM; + struct procfs_dir_entry **htable = calloc (INIT_HTABLE_LEN, + sizeof (struct procfs_dir_entry *)); + if (!htable) + return ENOMEM; + + /* Hold a reference to the new dir's node. */ + spin_lock (&netfs_node_refcnt_lock); + node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + new->num_entries = 0; + new->num_live_entries = 0; + new->htable_len = INIT_HTABLE_LEN; + new->htable = htable; + new->ordered = NULL; + new->fs_path = path; + new->fs = fs; + new->node = node; + new->stat_timestamp = 0; + new->name_timestamp = 0; + + *dir = new; + + if (fs->root != 0) + node->nn->dir = new; + + return 0; +} + +/* Put the directory entry DIR_ENTRY into the hash table HTABLE. */ +static void +insert (struct procfs_dir_entry *dir_entry, + struct procfs_dir_entry **htable, size_t htable_len) +{ + struct procfs_dir_entry **new_htable = &htable[dir_entry->hv % htable_len]; + if (*new_htable) + (*new_htable)->self_p = &dir_entry->next; + dir_entry->next = *new_htable; + dir_entry->self_p = new_htable; + *new_htable = dir_entry; +} + +/* Calculate NAME's hash value. */ +static size_t +hash (const char *name) +{ + size_t hash_value = 0; + while (*name) + hash_value = ((hash_value << 5) + *name++) & 0xFFFFFF; + return hash_value; +} + +/* Extend the existing hashtable for DIR to accomodate values for new length + NEW_LEN. We retain all the previous entries. */ +static error_t +rehash (struct procfs_dir *dir, size_t new_len) +{ + int count; + size_t old_len = dir->htable_len; + struct procfs_dir_entry **old_htable = dir->htable; + struct procfs_dir_entry **new_htable = (struct procfs_dir_entry **) + malloc (new_len * sizeof (struct procfs_dir_entry *)); + + if (! new_htable) + return ENOMEM; + + bzero (new_htable, new_len * sizeof (struct procfs_dir_entry *)); + + for (count = 0; count < old_len; count++) + while (old_htable[count]) + { + struct procfs_dir_entry *dir_entry = old_htable[count]; + + /* Remove DIR_ENTRY from the old table */ + old_htable[count] = dir_entry->next; + + insert (dir_entry, new_htable, new_len); + } + + free (old_htable); + + dir->htable = new_htable; + dir->htable_len = new_len; + + return 0; +} + +/* Lookup NAME in DIR and return its entry. If there is no such entry, and + DNEW, the decision variable, is true, then a new entry is allocated and + returned, otherwise 0 is returned (if DNEW is true then 0 can be returned + if a memory allocation error occurs). */ +struct procfs_dir_entry * +lookup_entry (struct procfs_dir *dir, const char *name, int dnew) +{ + size_t hv = hash (name); + struct procfs_dir_entry *dir_entry = dir->htable[hv % dir->htable_len]; + + while (dir_entry && strcmp (name, dir_entry->name) != 0) + dir_entry = dir_entry->next; + + if (!dir_entry && dnew) + { + if (dir->num_entries > dir->htable_len) + /* Grow the hash table. */ + if (rehash (dir, (dir->htable_len + 1) * 2 - 1) != 0) + return 0; + + dir_entry = + (struct procfs_dir_entry *) malloc (sizeof (struct procfs_dir_entry)); + + if (dir_entry) + { + dir_entry->hv = hv; + dir_entry->name = strdup (name); + dir_entry->node = 0; + dir_entry->dir = dir; + dir_entry->stat_timestamp = 0; + bzero (&dir_entry->stat, sizeof dir_entry->stat); + dir_entry->symlink_target = 0; + dir_entry->noent = 0; + dir_entry->valid = 0; + dir_entry->name_timestamp = 0; + dir_entry->ordered_next = 0; + dir_entry->ordered_self_p = 0; + dir_entry->next = 0; + dir_entry->self_p = 0; + insert (dir_entry, dir->htable, dir->htable_len); + dir->num_entries++; + } + } + + return dir_entry; +} + + +/* Lookup NAME in DIR, returning its entry, or an error. + *NODE will contain the result node, locked, and with + an additional reference, or 0 if an error occurs. */ +error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, + struct node **node) +{ + struct procfs_dir_entry *dir_entry = 0; + error_t err = 0; + char *fs_path = dir->fs_path; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + + if (*name == '\0' || strcmp (name, ".") == 0) + /* Current directory -- just add an additional reference to DIR's node + and return it. */ + { + netfs_nref (dir->node); + *node = dir->node; + return 0; + } + else if (strcmp (name, "..") == 0) + /* Parent directory. */ + { + if (dir->node->nn->dir_entry) + { + *node = dir->node->nn->dir_entry->dir->node; + mutex_lock (&(*node)->lock); + netfs_nref (*node); + } + else + { + err = ENOENT; /* No .. */ + *node = 0; + } + + mutex_unlock (&dir->node->lock); + + return err; + } + + err = procfs_dir_refresh (dir, dir->node == dir->fs->root); + if (!err && !dir_entry) + dir_entry = lookup_entry (dir, name, 0); + + if (! err) + { + if (dir_entry && !dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go + away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into E. */ + { + if (! fs_path) + err = EROFS; + + if (! err) + { + err = procfs_create_node (dir_entry, fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to + children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + } + + if (! err) + { + *node = dir_entry->node; + /* We have to unlock DIR's node before locking the child node + because the locking order is always child-parent. We know + the child node won't go away because we already hold the + additional reference to it. */ + mutex_unlock (&dir->node->lock); + mutex_lock (&dir_entry->node->lock); + } + } + else + err = ENOENT; + } + + if (err) + { + *node = 0; + mutex_unlock (&dir->node->lock); + } + +#if 0 + if (fs_path) + free (fs_path); +#endif + + return err; +} + +/* Lookup the null name in DIR, and return a node for it in NODE. Unlike + procfs_dir_lookup, this won't attempt to validate the existance of the + entry (to avoid opening a new connection if possible) -- that will happen + the first time the entry is refreshed. Also unlink ftpfs_dir_lookup, this + function doesn't expect DIR to be locked, and won't return *NODE locked. + This function is only used for bootstrapping the root node. */ +error_t +procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) +{ + struct procfs_dir_entry *dir_entry; + error_t err = 0; + + dir_entry = lookup_entry (dir, "", 1); + if (! dir_entry) + return ENOMEM; + + if (! dir_entry->noent) + /* We've got a dir entry, get a node for it. */ + { + /* If there's already a node, add a ref so that it doesn't go away. */ + spin_lock (&netfs_node_refcnt_lock); + if (dir_entry->node) + dir_entry->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + + if (! dir_entry->node) + /* No node; make one and install it into DIR_ENTRY. */ + { + err = procfs_create_node (dir_entry, dir->fs_path, &dir_entry->node); + + if (!err && dir->num_live_entries++ == 0) + /* Keep a reference to dir's node corresponding to children. */ + { + spin_lock (&netfs_node_refcnt_lock); + dir->node->references++; + spin_unlock (&netfs_node_refcnt_lock); + } + } + + if (! err) + *node = dir_entry->node; + } + else + err = ENOENT; + + return err; +} + +/* Free the directory entry DIR_ENTRY and all resources it consumes. */ +void +free_entry (struct procfs_dir_entry *dir_entry) +{ + + assert (! dir_entry->self_p); /* We should only free deleted nodes. */ + free (dir_entry->name); + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + free (dir_entry->node->nn->dir); + free (dir_entry->node->nn); + free (dir_entry->node); + free (dir_entry); +} + +/* Remove DIR_ENTRY from its position in the ordered_next chain. */ +static void +ordered_unlink (struct procfs_dir_entry *dir_entry) +{ + if (dir_entry->ordered_self_p) + *dir_entry->ordered_self_p = dir_entry->ordered_next; + if (dir_entry->ordered_next) + dir_entry->ordered_next->self_p = dir_entry->ordered_self_p; +} + +/* Delete DIR_ENTRY from its directory, freeing any resources it holds. */ +static void +delete (struct procfs_dir_entry *dir_entry, struct procfs_dir *dir) +{ + dir->num_entries--; + + /* Take out of the hash chain. */ + if (dir_entry->self_p) + *dir_entry->self_p = dir_entry->next; + if (dir_entry->next) + dir_entry->next->self_p = dir_entry->self_p; + + /* Take out of the directory ordered list. */ + ordered_unlink (dir_entry); + + /* If there's a node attached, we'll delete the entry whenever it goes + away, otherwise, just delete it now. */ + if (! dir_entry->node) + free_entry (dir_entry); +} + +/* Make all the directory entries invalid */ +static void +make_dir_invalid (struct procfs_dir *dir) +{ + int count; + size_t len = dir->htable_len; + struct procfs_dir_entry **htable = dir->htable; + struct procfs_dir_entry *dir_entry; + + for (count = 0; count < len; count++) + { + dir_entry = htable[count]; + while (dir_entry) + { + dir_entry->valid = 0; + dir_entry = dir_entry->next; + } + } +} + +/* Delete any entries in DIR which don't have their valid bit set. */ +static void +sweep (struct procfs_dir *dir) +{ + size_t len = dir->htable_len, i; + struct procfs_dir_entry **htable = dir->htable, *dir_entry; + + for (i = 0; i < len; i++) + { + dir_entry = htable[i]; + while (dir_entry) + { + if (!dir_entry->valid && !dir_entry->noent && dir->num_entries) + delete (dir_entry, dir); + dir_entry = dir_entry->next; + } + if (htable[i]) + { + free (htable[i]); + htable[i] = 0; + } + + } + +} + +/* Remove the specified DIR and free all its allocated + storage. */ +void procfs_dir_entries_remove (struct procfs_dir *dir) +{ + /* Free all entries. */ + make_dir_invalid (dir); + sweep (dir); +} + +/* Checks if the DIR name is in list of + Active pids. */ +int is_in_pid_list (struct procfs_dir *dir) +{ + int dir_name; + int count; + pid_t *pids = NULL; + int pidslen = 0; + error_t err; + + if (dir->node->nn) + { + dir_name = atoi (dir->node->nn->dir_entry->name); + err = proc_getallpids (getproc (), &pids, &pidslen); + + for (count = 0; count < pidslen; ++count) + if (pids[count] == dir_name) + return 1; + } + + return 0; + +} + +/* Checks if DIR is a directory that + represents a pid. */ +int check_parent (struct procfs_dir *dir) +{ + if (dir == dir->fs->root) + return 0; + else + if (is_in_pid_list (dir)) + return 1; + else + return 0; + +} + +/* Refresh DIR. */ +error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) +{ + error_t err; + int is_parent_pid; + struct node *node; + + struct timeval tv; + maptime_read (procfs_maptime, &tv); + + time_t timestamp = tv.tv_sec; + cur_entry = &dir->ordered; + if (isroot) + err = procfs_fill_root_dir(dir, timestamp); + else + { + err = update_dir_entries (dir, timestamp); + is_parent_pid = check_parent (dir); + if (is_parent_pid) + err = procfs_create_files (dir, &node, timestamp); + } + + return err; +} + +/* Update the directory entry for NAME to reflect STAT and SYMLINK_TARGET. + This also creates a valid linked list of entries imposing ordering on + them. */ +struct procfs_dir_entry* +update_entries_list (struct procfs_dir *dir, const char *name, + const struct stat *stat, time_t timestamp, + const char *symlink_target) +{ + ino_t ino; + struct procfs_dir_entry *dir_entry = lookup_entry (dir, name, 1); + struct procfs *fs = dir->fs; + + if (! dir_entry) + return ENOMEM; + + if (dir_entry->stat.st_ino) + ino = dir_entry->stat.st_ino; + else + ino = fs->next_inode++; + + dir_entry->name_timestamp = timestamp; + + if (stat) + /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ + { + dir_entry->stat = *stat; + dir_entry->stat_timestamp = timestamp; + + if (!dir_entry->symlink_target || !symlink_target + || strcmp (dir_entry->symlink_target, symlink_target) != 0) + { + if (dir_entry->symlink_target) + free (dir_entry->symlink_target); + dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; + } + } + + /* The st_ino field is always valid. */ + dir_entry->stat.st_ino = ino; + dir_entry->stat.st_fsid = fs->fsid; + dir_entry->stat.st_fstype = PROCFILESYSTEM; + + dir_entry->valid = 1; + + if (! dir_entry->ordered_self_p) + /* Position DIR_ENTRY in the ordered chain following the previously seen entry. */ + { + /* The PREV_ENTRY_NEXT_P field holds a pointer to the NEXT-field of the + previous entry, or a pointer to the ORDERED field in the directory. */ + dir_entry->ordered_self_p = cur_entry; + + if (*dir_entry->ordered_self_p) + /* Update the self_p pointer of the previous successor. */ + (*dir_entry->ordered_self_p)->ordered_self_p = &dir_entry->ordered_next; + + /* DIR_ENTRY comes before the previous successor. */ + dir_entry->ordered_next = *dir_entry->ordered_self_p; + + *dir_entry->ordered_self_p = dir_entry; /* Put DIR_ENTRY there. */ + } + + /* Put the next entry after this one. */ + cur_entry = &dir_entry->ordered_next; + + return dir_entry; +} + +/* Fills DIR, the root directory with all the pids of + processes running in the system as directories. */ +error_t +procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) +{ + error_t err; + char *data; + pid_t *pids; + int pidslen; + struct stat stat; + stat.st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | + S_IROTH | S_IXOTH; + stat.st_nlink = 1; + stat.st_size = 0; + + int count; + char *dir_name_pid; + struct node *node; + struct procfs_dir *new_dir; + struct procfs_dir_entry *dir_entry; + struct proc_stat *ps; + + pids = NULL; + pidslen = 0; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + { + for (count = 0; count < pidslen; count++) + { + if (asprintf (&dir_name_pid, "%d", pids[count]) == -1) + return errno; + +#if 0 + node = (struct node *) malloc (sizeof (struct node)); + new_dir = (struct procfs_dir *) malloc (sizeof (struct procfs_dir )); + + if (! node || ! new_dir ) + return ENOMEM; +#endif + err = _proc_stat_create (pids[count], ps_context, &ps); + if (! err) + { + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + stat.st_uid = proc_stat_proc_info (ps)->owner; + stat.st_gid = proc_stat_proc_info (ps)->pgrp; + + dir_entry = update_entries_list (dir, dir_name_pid, + &stat, timestamp, NULL); + err = procfs_create_node (dir_entry, dir_name_pid, &node); + + procfs_dir_create (dir->fs, node, + dir_name_pid, &new_dir); + free(dir_name_pid); + _proc_stat_free (ps); + } + } + } + } + + if ((err = procfs_create_uptime (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_stat (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_version (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_meminfo (dir, &node, timestamp)) != 0) + return err; + + if ((err = procfs_create_loadavg (dir, &node, timestamp)) != 0) + return err; + + return 0; +} + +error_t update_dir_entries (struct procfs_dir *dir) +{ + /* STUB */ + return 0; +} diff --git a/procfs/procfs_nonpid_files.c b/procfs/procfs_nonpid_files.c new file mode 100644 index 00000000..2c1209ee --- /dev/null +++ b/procfs/procfs_nonpid_files.c @@ -0,0 +1,514 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_nonpid_files.c -- This file contains function definitions + to create and update the non-Per PID + files and their contents. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on vmstat.c code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + + Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Written by Miles Bader + This file is part of the GNU Hurd. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "procfs.h" + +typedef long long val_t; +#define BADVAL ((val_t) - 1LL) + +/* default pager port (must be privileged to fetch this). */ +mach_port_t def_pager; +struct default_pager_info def_pager_info; + +error_t procfs_create_uptime (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "uptime") == -1) + return errno; + if (asprintf (&file_path, "%s", "uptime") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_version(struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "version") == -1) + return errno; + if (asprintf (&file_path, "%s", "version") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return 0; +} + +error_t procfs_create_stat (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s", "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_meminfo (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "meminfo") == -1) + return errno; + if (asprintf (&file_path, "%s", "meminfo") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t procfs_create_loadavg (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "loadavg") == -1) + return errno; + if (asprintf (&file_path, "%s", "loadavg") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + return err; +} + +error_t get_uptime (struct timeval *uptime) +{ + struct timeval boot_time, now; + error_t err; + struct proc_stat *ps; + + err = _proc_stat_create (1, ps_context, &ps); + + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + time_value_t *const tv = &proc_stat_task_basic_info (ps)->creation_time; + boot_time.tv_sec = tv->seconds; + boot_time.tv_usec = tv->microseconds; + if (gettimeofday (&now, 0) < 0) + error (0, errno, "gettimeofday"); + timersub (&now, &boot_time, uptime); + } + + _proc_stat_free (ps); + return err; +} + +error_t get_total_times (struct timeval *total_user_time, + struct timeval *total_system_time) +{ + error_t err; + pid_t *pids; + int pidslen = 0, count; + struct proc_stat *ps; + struct task_thread_times_info live_threads_times; + + struct timeval total_user_time_tmp; + struct timeval total_system_time_tmp; + struct timeval tmpval; + + timerclear (&total_user_time_tmp); + timerclear (&total_system_time_tmp); + + pids = NULL; + err = proc_getallpids (getproc (), &pids, &pidslen); + + if (!err) + for (count = 0; count < pidslen; count++) + { + err = _proc_stat_create (pids[count], ps_context, &ps); + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (!err && !(ps->flags & PSTAT_TASK_BASIC)) + err = EGRATUITOUS; + + if (! err) + { + tmpval.tv_sec = proc_stat_task_basic_info (ps)->user_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->user_time.seconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = proc_stat_task_basic_info (ps)->system_time.seconds; + tmpval.tv_usec = proc_stat_task_basic_info (ps)->system_time.seconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); + + error_t err = set_field_value (ps, PSTAT_TASK); + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + tmpval.tv_sec = live_threads_times.user_time.seconds; + tmpval.tv_usec = live_threads_times.user_time.microseconds; + timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); + + tmpval.tv_sec = live_threads_times.system_time.seconds; + tmpval.tv_usec = live_threads_times.system_time.microseconds; + timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); + } + } + } + _proc_stat_free (ps); + } + + total_user_time->tv_sec = total_user_time_tmp.tv_sec; + total_user_time->tv_usec = total_user_time_tmp.tv_usec; + + total_system_time->tv_sec = total_system_time_tmp.tv_sec; + total_system_time->tv_usec = total_system_time_tmp.tv_usec; + + return err; +} + +error_t procfs_read_nonpid_stat (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *stat_data; + error_t err; + jiffy_t total_user_time_jiffy, total_system_time_jiffy; + jiffy_t idle_time_jiffy; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; + + err = get_uptime (&uptime); + + if (! err) + { + err = get_total_times (&total_user_time, &total_system_time); + + if (! err) + { + timersub (&uptime, &total_system_time, + &idle_time); + + total_user_time_jiffy = 100 * ((double) total_user_time.tv_sec + + (double) total_user_time.tv_usec / (1000 * 1000)); + total_system_time_jiffy = 100 * ((double) total_system_time.tv_sec + + (double) total_system_time.tv_usec / (1000 * 1000)); + idle_time_jiffy = 100 * ((double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000)); + + if (asprintf (&stat_data, "cpu %llu %llu %llu %llu %llu %llu %d %d %d\n" + "cpu0 %llu %llu %llu %llu %llu %llu %d %d %d\n" + "intr %llu %llu %llu %llu %llu %llu %d %d %d\n", + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + total_user_time_jiffy, (long long unsigned) 0, + total_system_time_jiffy, idle_time_jiffy, + (long long unsigned) 0, (long long unsigned) 0, + 0, 0, 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0, + (long long unsigned) 0, (long long unsigned) 0) == -1) + return errno; + } + } + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + return err; +} + +/* Makes sure the default pager port and associated + info exists, and returns 0 if not (after printing + an error). */ +static int +ensure_def_pager_info () +{ + error_t err; + + if (def_pager == MACH_PORT_NULL) + { + mach_port_t host; + + err = get_privileged_ports (&host, 0); + if (err == EPERM) + { + /* We are not root, so try opening the /servers file. */ + def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); + if (def_pager == MACH_PORT_NULL) + { + error (0, errno, _SERVERS_DEFPAGER); + return 0; + } + } + if (def_pager == MACH_PORT_NULL) + { + if (err) + { + error (0, err, "get_privileged_ports"); + return 0; + } + + err = vm_set_default_memory_manager (host, &def_pager); + mach_port_deallocate (mach_task_self (), host); + + if (err) + { + error (0, err, "vm_set_default_memory_manager"); + return 0; + } + } + } + + if (!MACH_PORT_VALID (def_pager)) + { + if (def_pager == MACH_PORT_NULL) + { + error (0, 0, + "No default pager running, so no swap information available"); + def_pager = MACH_PORT_DEAD; /* so we don't try again */ + } + return 0; + } + + err = default_pager_info (def_pager, &def_pager_info); + if (err) + error (0, err, "default_pager_info"); + return (err == 0); +} + +#define SWAP_FIELD(getter, expr) \ + static val_t getter () \ + { return ensure_def_pager_info () ? (val_t) (expr) : BADVAL; } + +SWAP_FIELD (get_swap_size, def_pager_info.dpi_total_space) +SWAP_FIELD (get_swap_free, def_pager_info.dpi_free_space) +SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) +SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space + - def_pager_info.dpi_free_space)) + +error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *meminfo_data; + error_t err; + struct vm_statistics vmstats; + + err = vm_statistics (mach_task_self (), &vmstats); + + unsigned long mem_size = ((vmstats.free_count + + vmstats.active_count + vmstats.inactive_count + + vmstats.wire_count) * vmstats.pagesize) / 1024; + + if (! err) + if (asprintf (&meminfo_data, "MemTotal:\t%lu kB\n" + "MemFree:\t%lu kB\n" + "Buffers:\t%ld kB\n" + "Cached:\t\t%ld kB\n" + "SwapCached:\t%ld kB\n" + "Active:\t\t%lu kB\n" + "Inactive:\t%lu kB\n" + "HighTotal:\t%lu kB\n" + "HighFree:\t%lu kB\n" + "LowTotal:\t%lu kB\n" + "LowFree:\t%lu kB\n" + "SwapTotal:\t%llu kB\n" + "SwapFree:\t%llu kB\n", + mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, + (PAGES_TO_BYTES(vmstats.active_count)) / 1024, + (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, + get_swap_size () / 1024, get_swap_free () / 1024) == -1) + return errno; + + memcpy (data, meminfo_data, strlen(meminfo_data)); + *len = strlen (data); + + free (meminfo_data); + return err; +} + +error_t procfs_read_nonpid_loadavg (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *loadavg_data; + error_t err; + processor_set_info_t info; + natural_t *count; + struct host_load_info *load; + mach_port_t host; + + err = ps_host_load_info (&load); + if (err) + error (0, err, "ps_host_load_info"); + + if (! err) + if (asprintf (&loadavg_data, "%.2f %.2f %.2f %d/%d %d\n", + (double)load->avenrun[0] / (double)LOAD_SCALE, + (double)load->avenrun[1] / (double)LOAD_SCALE, + (double)load->avenrun[2] / (double)LOAD_SCALE, 0, 0, 0) == -1) + return errno; + + memcpy (data, loadavg_data, strlen(loadavg_data)); + *len = strlen (data); + + free (loadavg_data); + return err; +} + +error_t procfs_read_nonpid_uptime (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *uptime_data; + error_t err; + double uptime_secs, idle_time_secs; + + struct timeval uptime_val; + struct timeval uptime, total_user_time, total_system_time; + struct timeval idle_time; + + + err = get_uptime (&uptime); + if (! err) + { + err = get_total_times (&total_user_time, + &total_system_time); + if (! err) + { + timersub (&uptime, &total_system_time, + &idle_time); + + uptime_secs = (double) uptime.tv_sec + + (double) uptime.tv_usec / (1000 * 1000); + + idle_time_secs = (double) idle_time.tv_sec + + (double) idle_time.tv_usec / (1000 * 1000); + + if (asprintf (&uptime_data, "%.2f %.2f\n", + uptime_secs, idle_time_secs) == -1) + return errno; + } + } + + + memcpy (data, uptime_data, strlen(uptime_data)); + *len = strlen (data); + + free (uptime_data); + return err; +} + +error_t procfs_read_nonpid_version (struct dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *version_data; + error_t err = 0; + + if (asprintf (&version_data, "Linux version 2.6.18\n", NULL) == -1) + return errno; + + memcpy (data, version_data, strlen(version_data)); + *len = strlen (data); + + free (version_data); + return err; +} diff --git a/procfs/procfs_pid.h b/procfs/procfs_pid.h new file mode 100644 index 00000000..566c83ea --- /dev/null +++ b/procfs/procfs_pid.h @@ -0,0 +1,88 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid.h -- This is the header file of which contains defintions + for structure of directory with PID as the name and + structure of each file in this directory. + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +*/ + +#ifndef __PROCFS_PID_H__ +#define __PROCFS_PID_H__ + +#include "procfs.h" + +struct procfs_pid_files +{ + struct procfs_cwd *procfs_cwd; + struct procfs_environ *procfs_environ; + struct procfs_cpu *procfs_cpu; + struct procfs_root *procfs_root; + struct procfs_exe *procfs_exe; + struct procfs_stat *_procfs_stat; + struct procfs_statm *procfs_statm; +}; + +struct procfs_stat +{ + pid_t pid; + char *comm; + char *state; + pid_t ppid; + pid_t pgid; + pid_t sid; + int tty_nr; + pid_t tty_pgrp; + unsigned flags; + long unsigned minflt; + long unsigned cminflt; + long unsigned majflt; + long unsigned cmajflt; + jiffy_t utime; + jiffy_t stime; + jiffy_t cutime; + jiffy_t cstime; + long priority; + long nice; + long num_threads; + long itrealvalue; + long long unsigned starttime; + long unsigned vsize; + long rss; + long unsigned rlim; + long unsigned startcode; + long unsigned endcode; + long unsigned startstack; + long unsigned kstkesp; + long unsigned kstkeip; + long unsigned signal; + long unsigned blocked; + long unsigned sigignore; + long unsigned sigcatch; + long unsigned wchan; + long unsigned nswap; + long unsigned cnswap; + int exit_signal; + int processor; + unsigned rt_priority; + unsigned policy; + long long unsigned delayacct_blkio_ticks; +}; + +#endif diff --git a/procfs/procfs_pid_files.c b/procfs/procfs_pid_files.c new file mode 100644 index 00000000..46861531 --- /dev/null +++ b/procfs/procfs_pid_files.c @@ -0,0 +1,576 @@ +/* procfs -- a translator for providing GNU/Linux compatible + proc pseudo-filesystem + + procfs_pid_files.c -- This file contains definitions to perform + file operations such as creating, writing to, + reading from and removing files that holds + information for each process with PID + + Copyright (C) 2008, FSF. + Written as a Summer of Code Project + + + procfs is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + procfs 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + + A portion of the code in this file is based on ftpfs code + present in the hurd repositories copyrighted to FSF. The + Copyright notice from that file is given below. + +*/ + +#include +#include +#include +#include +#include +#include + +#include "procfs_pid.h" + +/* Update the files named NAME within the directory named + PID also with SYMLINK TARGET if necessary. */ +struct procfs_dir_entry* +update_pid_entries (struct procfs_dir *dir, const char *name, + time_t timestamp, + const char *symlink_target) +{ + struct procfs_dir_entry *dir_entry; + struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); + stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + + dir_entry = update_entries_list (dir, name, stat, + timestamp, symlink_target); + + return dir_entry; +} + +/* Creates files to store process information for DIR + whose names are pids and returns these files in *NODE. */ +error_t +procfs_create_files (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + int err; + char *file_name, *file_path; + struct procfs_dir_entry *dir_entry; + + if (asprintf (&file_name, "%s", "stat") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "stat") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "status") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "status") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "cmdline") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "cmdline") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + + if (asprintf (&file_name, "%s", "statm") == -1) + return errno; + if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "statm") == -1) + return errno; + + dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); + err = procfs_create_node (dir_entry, file_path, node); + + free (file_name); + free (file_path); + +#if 0 + nodes_list = &node_stat; + nodes_list++; + node = nodes_list; +#endif + + return err; +} + +/* Check if the PSTAT_FLAG is set in the corresponding PS + structure, if not set it and check again and return error + status accordingly. */ +error_t set_field_value (struct proc_stat *ps, int pstat_flag) +{ + error_t err; + + if (! (ps->flags & pstat_flag)) + { + err = proc_stat_set_flags (ps, pstat_flag); + if (err) + return err; + + /* This second check is done since ps.h specifies to + do so since the previous call would not have set + the required value. */ + if (! (ps->flags & pstat_flag)) + return EGRATUITOUS; + } + + return 0; +} + +/* Adjusts TIME_VAL structure having Seconds and + Microseconds into the value in jiffies. The + value of jiffy is a hack to adjust to what + procps uses. */ +jiffy_t adjust_jiffy_time (time_value_t time_val) +{ + jiffy_t jiffy_time = time_val.seconds * JIFFY_ADJUST; + jiffy_time += (time_val.microseconds * JIFFY_ADJUST) + / (1000 * 1000); + + return jiffy_time; +} + +/* Extract the user and system time for the live threads of + the process. This information is directly retrieved from + MACH since neither libps not proc makes this available. */ +error_t get_task_thread_times (task_t task, + struct task_thread_times_info *live_threads_times) +{ + error_t err; + size_t tkcount = TASK_THREAD_TIMES_INFO_COUNT; + + err = task_info (task, TASK_THREAD_TIMES_INFO, + (task_info_t) live_threads_times, &tkcount); + if (err == MACH_SEND_INVALID_DEST) + err = ESRCH; + + return err; +} + +/* Obtains the User Time in UTIME and System Time in STIME from + MACH directly since this is neither made available by libps + nor by proc server. */ +error_t get_live_threads_time (struct proc_stat *ps, + jiffy_t *utime, jiffy_t *stime) +{ + struct task_thread_times_info live_threads_times; + error_t err = set_field_value (ps, PSTAT_TASK); + + if (! err) + { + err = get_task_thread_times (ps->task, &live_threads_times); + if (! err) + { + *utime = adjust_jiffy_time ( + live_threads_times.user_time); + *stime = adjust_jiffy_time ( + live_threads_times.system_time); + } + } + + return err; +} + +/* Get the data for stat file into the structure + PROCFS_STAT. */ +error_t get_stat_data (pid_t pid, + struct procfs_stat **procfs_stat) +{ + error_t err; + struct procfs_stat *new = (struct procfs_stat *) + malloc (sizeof (struct procfs_stat)); + + struct proc_stat *ps; + jiffy_t utime, stime; + + err = _proc_stat_create (pid, ps_context, &ps); + + new->pid = pid; + + if (! err) + { + err = set_field_value (ps, PSTAT_ARGS); + if (! err) + asprintf (&new->comm, "%s", ps->args); + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + { + if (ps->state & PSTAT_STATE_P_STOP) + new->state = strdup ("T"); + if (ps->state & PSTAT_STATE_P_ZOMBIE) + new->state = strdup ("Z"); + if (ps->state & PSTAT_STATE_P_FG) + new->state = strdup ("+"); + if (ps->state & PSTAT_STATE_P_SESSLDR) + new->state = strdup ("s"); + if (ps->state & PSTAT_STATE_P_LOGINLDR) + new->state = strdup ("l"); + if (ps->state & PSTAT_STATE_P_FORKED) + new->state = strdup ("f"); + if (ps->state & PSTAT_STATE_P_NOMSG) + new->state = strdup ("m"); + if (ps->state & PSTAT_STATE_P_NOPARENT) + new->state = strdup ("p"); + if (ps->state & PSTAT_STATE_P_ORPHAN) + new->state = strdup ("o"); + if (ps->state & PSTAT_STATE_P_TRACE) + new->state = strdup ("x"); + if (ps->state & PSTAT_STATE_P_WAIT) + new->state = strdup ("w"); + if (ps->state & PSTAT_STATE_P_GETMSG) + new->state = strdup ("g"); + } + + err = set_field_value (ps, PSTAT_PROC_INFO); + if (! err) + { + new->ppid = ps->proc_info->ppid; + new->pgid = ps->proc_info->pgrp; + new->sid = ps->proc_info->session; + new->tty_pgrp = ps->proc_info->pgrp; + } + else + { + new->ppid = 0; + new->pgid = 0; + new->sid = 0; + new->tty_pgrp = 0; + } + + err = set_field_value (ps, PSTAT_STATE); + if (! err) + new->flags = ps->state; + else + new->flags = 0; + + err = set_field_value (ps, PSTAT_TASK_EVENTS); + if (! err) + { + new->minflt = ps->task_events_info->faults; + new->majflt = ps->task_events_info->pageins; + } + else + { + new->minflt = 0; + new->majflt = 0; + } + + /* This seems to be a bit inconsistent with setting of other + fields in this code. There are two reasons for this. + 1. The actual information required is not made available + by libps which should be directly obtained from MACH. + 2. The same code which is required to get the information + have to be reused in procfs_nonpid_files.c */ + err = get_live_threads_time (ps, &utime, &stime); + if (! err) + { + new->utime = utime; + new->stime = stime; + } + else + { + new->utime = 0; + new->stime = 0; + } + + err = set_field_value (ps, PSTAT_TASK_BASIC); + if (! err) + { + new->cutime = adjust_jiffy_time ( + ps->task_basic_info->user_time); + new->cstime = adjust_jiffy_time ( + ps->task_basic_info->system_time); + + new->priority = ps->task_basic_info->base_priority; + new->starttime = adjust_jiffy_time ( + ps->task_basic_info->creation_time); + + new->vsize = ps->task_basic_info->virtual_size; + new->rss = ps->task_basic_info->resident_size; + } + else + { + new->cutime = 0; + new->cstime = 0; + new->priority = 0; + new->starttime = 0; + new->vsize = 0; + new->rss = 0; + } + + new->nice = getpriority (0, pid); + + err = set_field_value (ps, PSTAT_NUM_THREADS); + if (! err) + new->num_threads = ps->num_threads; + else + new->num_threads = 0; + + /* Not Supported in Linux 2.6 or later. */ + new->tty_nr = 0; + new->itrealvalue = 0; + new->nswap = 0; + new->cnswap = 0; + + /* Temporarily set to 0 until correct + values are found .*/ + new->cminflt = 0; + new->cmajflt = 0; + new->rlim = 0; + new->startcode = 0; + new->endcode = 0; + new->startstack = 0; + new->kstkesp = 0; + new->kstkeip = 0; + new->signal = 0; + new->blocked = 0; + new->sigignore = 0; + new->sigcatch = 0; + new->wchan = 0; + new->exit_signal = 0; + new->processor = 0; + new->rt_priority = 0; + new->policy = 0; + new->delayacct_blkio_ticks = 0; + + *procfs_stat = new; + _proc_stat_free (ps); + + return err; +} + +/* Reads required process information from stat file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_read_stat_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + error_t err; + char *stat_data; + struct procfs_stat *procfs_stat; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + + err = get_stat_data (pid, &procfs_stat); + + if (asprintf (&stat_data, "%d (%s) %s %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu \n", + procfs_stat->pid, procfs_stat->comm, + procfs_stat->state, procfs_stat->ppid, + procfs_stat->pgid, procfs_stat->sid, + procfs_stat->tty_nr, procfs_stat->tty_pgrp, + procfs_stat->flags, procfs_stat->minflt, + procfs_stat->cminflt, procfs_stat->majflt, + procfs_stat->cmajflt, procfs_stat->utime, + procfs_stat->stime, procfs_stat->cutime, + procfs_stat->cstime, procfs_stat->priority, + procfs_stat->nice, procfs_stat->num_threads, + procfs_stat->itrealvalue, procfs_stat->starttime, + procfs_stat->vsize, BYTES_TO_PAGES(procfs_stat->rss), + procfs_stat->rlim, procfs_stat->startcode, + procfs_stat->endcode, procfs_stat->startstack, + procfs_stat->kstkesp, procfs_stat->kstkeip, + procfs_stat->signal, procfs_stat->blocked, + procfs_stat->sigignore, procfs_stat->sigcatch, + procfs_stat->wchan, procfs_stat->nswap, + procfs_stat->cnswap, procfs_stat->exit_signal, + procfs_stat->processor, procfs_stat->rt_priority, + procfs_stat->policy, + procfs_stat->delayacct_blkio_ticks) == -1) + return errno; + + + memcpy (data, stat_data, strlen(stat_data)); + *len = strlen (data); + + free (stat_data); + free (procfs_stat); + + return err; +} + +/* Reads required process's command line information + from cmline file within the directory represented + by pid. Return the data in DATA and actual length + to be written in LEN. */ +error_t +procfs_read_cmdline_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *cmdline_data; + error_t err; + struct proc_stat *ps; + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = set_field_value (ps, PSTAT_ARGS); + + if (! err) + if (asprintf (&cmdline_data, "%s \n", ps->args) == -1) + return errno; + + memcpy (data, cmdline_data, strlen(cmdline_data)); + *len = strlen (data); + + _proc_stat_free (ps); + free (cmdline_data); + return err; +} + +/* Reads required process's information that is represented by + stat and statm in a human readable format from status file + within the directory represented by pid. Return the data + in DATA and actual length to be written in LEN. */ +error_t +procfs_read_status_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *status_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&status_data, "Name:\t%s\nState:\t%s\nTgid:\t%d\nPid:\t%d\n", procfs_stat->comm, procfs_stat->state, procfs_stat->pid, procfs_stat->pid) == -1) + return errno; + + memcpy (data, status_data, strlen(status_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (status_data); + free (procfs_stat); + + return err; +} + +/* Reads required process information from statm file + within the directory represented by pid. Return + the data in DATA and actual length to be written + in LEN. */ +error_t +procfs_read_statm_file (struct procfs_dir_entry *dir_entry, + off_t offset, size_t *len, void *data) +{ + char *statm_data; + error_t err; + struct proc_stat *ps; + struct procfs_stat *procfs_stat; + + pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); + err = _proc_stat_create (pid, ps_context, &ps); + + err = get_stat_data (pid, &procfs_stat); + + if (! err) + if (asprintf (&statm_data, "%lu %ld %d %d %d %d %d\n", + BYTES_TO_PAGES(procfs_stat->vsize), + BYTES_TO_PAGES(procfs_stat->rss), + 0, 0, 0, 0, 0) == -1) + return errno; + + memcpy (data, statm_data, strlen(statm_data)); + *len = strlen (data); + + _proc_stat_free (ps); + + free (statm_data); + free (procfs_stat); + + return err; +} + +/* Reads required process information from each of files + within directory represented by pid, for files specified + by NODE. Return the data in DATA and actual length of + data in LEN. */ +error_t +procfs_read_files_contents (struct node *node, + off_t offset, size_t *len, void *data) +{ + error_t err; + + if (! strcmp (node->nn->dir_entry->name, "stat")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_stat (node->nn->dir_entry, + offset, len, data); + else + err = procfs_read_stat_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "cmdline")) + err = procfs_read_cmdline_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "status")) + err = procfs_read_status_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "statm")) + err = procfs_read_statm_file (node->nn->dir_entry, + offset, len, data); + + if (! strcmp (node->nn->dir_entry->name, "meminfo")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_meminfo (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "loadavg")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_loadavg (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "uptime")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_uptime (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + if (! strcmp (node->nn->dir_entry->name, "version")) + if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) + err = procfs_read_nonpid_version (node->nn->dir_entry, + offset, len, data); + else + err = ENOENT; + + return err; +} diff --git a/procfs_dir.c b/procfs_dir.c deleted file mode 100644 index f76e6a4b..00000000 --- a/procfs_dir.c +++ /dev/null @@ -1,664 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_dir.c -- This file contains definitions to perform - directory operations such as creating, - removing and refreshing directories. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - - A portion of the code in this file is based on ftpfs code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - - Copyright (C) 1997,98,2002 Free Software Foundation, Inc. - Written by Miles Bader - This file is part of the GNU Hurd. -*/ - - -#include -#include -#include -#include -#include - -#include "procfs.h" - -/* Initial HASHTABLE length for the new directories to be created. */ -#define INIT_HTABLE_LEN 5 - -struct procfs_dir_entry **cur_entry; - -/* Return in DIR a new procfs directory, in the filesystem FS, - with node NODE and path PATH. */ -error_t procfs_dir_create (struct procfs *fs, struct node *node, - const char *path, struct procfs_dir **dir) -{ - struct procfs_dir *new = malloc (sizeof (struct procfs_dir)); - if (!new) - return ENOMEM; - struct procfs_dir_entry **htable = calloc (INIT_HTABLE_LEN, - sizeof (struct procfs_dir_entry *)); - if (!htable) - return ENOMEM; - - /* Hold a reference to the new dir's node. */ - spin_lock (&netfs_node_refcnt_lock); - node->references++; - spin_unlock (&netfs_node_refcnt_lock); - - new->num_entries = 0; - new->num_live_entries = 0; - new->htable_len = INIT_HTABLE_LEN; - new->htable = htable; - new->ordered = NULL; - new->fs_path = path; - new->fs = fs; - new->node = node; - new->stat_timestamp = 0; - new->name_timestamp = 0; - - *dir = new; - - if (fs->root != 0) - node->nn->dir = new; - - return 0; -} - -/* Put the directory entry DIR_ENTRY into the hash table HTABLE. */ -static void -insert (struct procfs_dir_entry *dir_entry, - struct procfs_dir_entry **htable, size_t htable_len) -{ - struct procfs_dir_entry **new_htable = &htable[dir_entry->hv % htable_len]; - if (*new_htable) - (*new_htable)->self_p = &dir_entry->next; - dir_entry->next = *new_htable; - dir_entry->self_p = new_htable; - *new_htable = dir_entry; -} - -/* Calculate NAME's hash value. */ -static size_t -hash (const char *name) -{ - size_t hash_value = 0; - while (*name) - hash_value = ((hash_value << 5) + *name++) & 0xFFFFFF; - return hash_value; -} - -/* Extend the existing hashtable for DIR to accomodate values for new length - NEW_LEN. We retain all the previous entries. */ -static error_t -rehash (struct procfs_dir *dir, size_t new_len) -{ - int count; - size_t old_len = dir->htable_len; - struct procfs_dir_entry **old_htable = dir->htable; - struct procfs_dir_entry **new_htable = (struct procfs_dir_entry **) - malloc (new_len * sizeof (struct procfs_dir_entry *)); - - if (! new_htable) - return ENOMEM; - - bzero (new_htable, new_len * sizeof (struct procfs_dir_entry *)); - - for (count = 0; count < old_len; count++) - while (old_htable[count]) - { - struct procfs_dir_entry *dir_entry = old_htable[count]; - - /* Remove DIR_ENTRY from the old table */ - old_htable[count] = dir_entry->next; - - insert (dir_entry, new_htable, new_len); - } - - free (old_htable); - - dir->htable = new_htable; - dir->htable_len = new_len; - - return 0; -} - -/* Lookup NAME in DIR and return its entry. If there is no such entry, and - DNEW, the decision variable, is true, then a new entry is allocated and - returned, otherwise 0 is returned (if DNEW is true then 0 can be returned - if a memory allocation error occurs). */ -struct procfs_dir_entry * -lookup_entry (struct procfs_dir *dir, const char *name, int dnew) -{ - size_t hv = hash (name); - struct procfs_dir_entry *dir_entry = dir->htable[hv % dir->htable_len]; - - while (dir_entry && strcmp (name, dir_entry->name) != 0) - dir_entry = dir_entry->next; - - if (!dir_entry && dnew) - { - if (dir->num_entries > dir->htable_len) - /* Grow the hash table. */ - if (rehash (dir, (dir->htable_len + 1) * 2 - 1) != 0) - return 0; - - dir_entry = - (struct procfs_dir_entry *) malloc (sizeof (struct procfs_dir_entry)); - - if (dir_entry) - { - dir_entry->hv = hv; - dir_entry->name = strdup (name); - dir_entry->node = 0; - dir_entry->dir = dir; - dir_entry->stat_timestamp = 0; - bzero (&dir_entry->stat, sizeof dir_entry->stat); - dir_entry->symlink_target = 0; - dir_entry->noent = 0; - dir_entry->valid = 0; - dir_entry->name_timestamp = 0; - dir_entry->ordered_next = 0; - dir_entry->ordered_self_p = 0; - dir_entry->next = 0; - dir_entry->self_p = 0; - insert (dir_entry, dir->htable, dir->htable_len); - dir->num_entries++; - } - } - - return dir_entry; -} - - -/* Lookup NAME in DIR, returning its entry, or an error. - *NODE will contain the result node, locked, and with - an additional reference, or 0 if an error occurs. */ -error_t procfs_dir_lookup (struct procfs_dir *dir, const char *name, - struct node **node) -{ - struct procfs_dir_entry *dir_entry = 0; - error_t err = 0; - char *fs_path = dir->fs_path; - - struct timeval tv; - maptime_read (procfs_maptime, &tv); - - time_t timestamp = tv.tv_sec; - - if (*name == '\0' || strcmp (name, ".") == 0) - /* Current directory -- just add an additional reference to DIR's node - and return it. */ - { - netfs_nref (dir->node); - *node = dir->node; - return 0; - } - else if (strcmp (name, "..") == 0) - /* Parent directory. */ - { - if (dir->node->nn->dir_entry) - { - *node = dir->node->nn->dir_entry->dir->node; - mutex_lock (&(*node)->lock); - netfs_nref (*node); - } - else - { - err = ENOENT; /* No .. */ - *node = 0; - } - - mutex_unlock (&dir->node->lock); - - return err; - } - - err = procfs_dir_refresh (dir, dir->node == dir->fs->root); - if (!err && !dir_entry) - dir_entry = lookup_entry (dir, name, 0); - - if (! err) - { - if (dir_entry && !dir_entry->noent) - /* We've got a dir entry, get a node for it. */ - { - /* If there's already a node, add a ref so that it doesn't go - away. */ - spin_lock (&netfs_node_refcnt_lock); - if (dir_entry->node) - dir_entry->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - - if (! dir_entry->node) - /* No node; make one and install it into E. */ - { - if (! fs_path) - err = EROFS; - - if (! err) - { - err = procfs_create_node (dir_entry, fs_path, &dir_entry->node); - - if (!err && dir->num_live_entries++ == 0) - /* Keep a reference to dir's node corresponding to - children. */ - { - spin_lock (&netfs_node_refcnt_lock); - dir->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - } - } - } - - if (! err) - { - *node = dir_entry->node; - /* We have to unlock DIR's node before locking the child node - because the locking order is always child-parent. We know - the child node won't go away because we already hold the - additional reference to it. */ - mutex_unlock (&dir->node->lock); - mutex_lock (&dir_entry->node->lock); - } - } - else - err = ENOENT; - } - - if (err) - { - *node = 0; - mutex_unlock (&dir->node->lock); - } - -#if 0 - if (fs_path) - free (fs_path); -#endif - - return err; -} - -/* Lookup the null name in DIR, and return a node for it in NODE. Unlike - procfs_dir_lookup, this won't attempt to validate the existance of the - entry (to avoid opening a new connection if possible) -- that will happen - the first time the entry is refreshed. Also unlink ftpfs_dir_lookup, this - function doesn't expect DIR to be locked, and won't return *NODE locked. - This function is only used for bootstrapping the root node. */ -error_t -procfs_dir_null_lookup (struct procfs_dir *dir, struct node **node) -{ - struct procfs_dir_entry *dir_entry; - error_t err = 0; - - dir_entry = lookup_entry (dir, "", 1); - if (! dir_entry) - return ENOMEM; - - if (! dir_entry->noent) - /* We've got a dir entry, get a node for it. */ - { - /* If there's already a node, add a ref so that it doesn't go away. */ - spin_lock (&netfs_node_refcnt_lock); - if (dir_entry->node) - dir_entry->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - - if (! dir_entry->node) - /* No node; make one and install it into DIR_ENTRY. */ - { - err = procfs_create_node (dir_entry, dir->fs_path, &dir_entry->node); - - if (!err && dir->num_live_entries++ == 0) - /* Keep a reference to dir's node corresponding to children. */ - { - spin_lock (&netfs_node_refcnt_lock); - dir->node->references++; - spin_unlock (&netfs_node_refcnt_lock); - } - } - - if (! err) - *node = dir_entry->node; - } - else - err = ENOENT; - - return err; -} - -/* Free the directory entry DIR_ENTRY and all resources it consumes. */ -void -free_entry (struct procfs_dir_entry *dir_entry) -{ - - assert (! dir_entry->self_p); /* We should only free deleted nodes. */ - free (dir_entry->name); - if (dir_entry->symlink_target) - free (dir_entry->symlink_target); - free (dir_entry->node->nn->dir); - free (dir_entry->node->nn); - free (dir_entry->node); - free (dir_entry); -} - -/* Remove DIR_ENTRY from its position in the ordered_next chain. */ -static void -ordered_unlink (struct procfs_dir_entry *dir_entry) -{ - if (dir_entry->ordered_self_p) - *dir_entry->ordered_self_p = dir_entry->ordered_next; - if (dir_entry->ordered_next) - dir_entry->ordered_next->self_p = dir_entry->ordered_self_p; -} - -/* Delete DIR_ENTRY from its directory, freeing any resources it holds. */ -static void -delete (struct procfs_dir_entry *dir_entry, struct procfs_dir *dir) -{ - dir->num_entries--; - - /* Take out of the hash chain. */ - if (dir_entry->self_p) - *dir_entry->self_p = dir_entry->next; - if (dir_entry->next) - dir_entry->next->self_p = dir_entry->self_p; - - /* Take out of the directory ordered list. */ - ordered_unlink (dir_entry); - - /* If there's a node attached, we'll delete the entry whenever it goes - away, otherwise, just delete it now. */ - if (! dir_entry->node) - free_entry (dir_entry); -} - -/* Make all the directory entries invalid */ -static void -make_dir_invalid (struct procfs_dir *dir) -{ - int count; - size_t len = dir->htable_len; - struct procfs_dir_entry **htable = dir->htable; - struct procfs_dir_entry *dir_entry; - - for (count = 0; count < len; count++) - { - dir_entry = htable[count]; - while (dir_entry) - { - dir_entry->valid = 0; - dir_entry = dir_entry->next; - } - } -} - -/* Delete any entries in DIR which don't have their valid bit set. */ -static void -sweep (struct procfs_dir *dir) -{ - size_t len = dir->htable_len, i; - struct procfs_dir_entry **htable = dir->htable, *dir_entry; - - for (i = 0; i < len; i++) - { - dir_entry = htable[i]; - while (dir_entry) - { - if (!dir_entry->valid && !dir_entry->noent && dir->num_entries) - delete (dir_entry, dir); - dir_entry = dir_entry->next; - } - if (htable[i]) - { - free (htable[i]); - htable[i] = 0; - } - - } - -} - -/* Remove the specified DIR and free all its allocated - storage. */ -void procfs_dir_entries_remove (struct procfs_dir *dir) -{ - /* Free all entries. */ - make_dir_invalid (dir); - sweep (dir); -} - -/* Checks if the DIR name is in list of - Active pids. */ -int is_in_pid_list (struct procfs_dir *dir) -{ - int dir_name; - int count; - pid_t *pids = NULL; - int pidslen = 0; - error_t err; - - if (dir->node->nn) - { - dir_name = atoi (dir->node->nn->dir_entry->name); - err = proc_getallpids (getproc (), &pids, &pidslen); - - for (count = 0; count < pidslen; ++count) - if (pids[count] == dir_name) - return 1; - } - - return 0; - -} - -/* Checks if DIR is a directory that - represents a pid. */ -int check_parent (struct procfs_dir *dir) -{ - if (dir == dir->fs->root) - return 0; - else - if (is_in_pid_list (dir)) - return 1; - else - return 0; - -} - -/* Refresh DIR. */ -error_t procfs_dir_refresh (struct procfs_dir *dir, int isroot) -{ - error_t err; - int is_parent_pid; - struct node *node; - - struct timeval tv; - maptime_read (procfs_maptime, &tv); - - time_t timestamp = tv.tv_sec; - cur_entry = &dir->ordered; - if (isroot) - err = procfs_fill_root_dir(dir, timestamp); - else - { - err = update_dir_entries (dir, timestamp); - is_parent_pid = check_parent (dir); - if (is_parent_pid) - err = procfs_create_files (dir, &node, timestamp); - } - - return err; -} - -/* Update the directory entry for NAME to reflect STAT and SYMLINK_TARGET. - This also creates a valid linked list of entries imposing ordering on - them. */ -struct procfs_dir_entry* -update_entries_list (struct procfs_dir *dir, const char *name, - const struct stat *stat, time_t timestamp, - const char *symlink_target) -{ - ino_t ino; - struct procfs_dir_entry *dir_entry = lookup_entry (dir, name, 1); - struct procfs *fs = dir->fs; - - if (! dir_entry) - return ENOMEM; - - if (dir_entry->stat.st_ino) - ino = dir_entry->stat.st_ino; - else - ino = fs->next_inode++; - - dir_entry->name_timestamp = timestamp; - - if (stat) - /* The ST and SYMLINK_TARGET parameters are only valid if ST isn't 0. */ - { - dir_entry->stat = *stat; - dir_entry->stat_timestamp = timestamp; - - if (!dir_entry->symlink_target || !symlink_target - || strcmp (dir_entry->symlink_target, symlink_target) != 0) - { - if (dir_entry->symlink_target) - free (dir_entry->symlink_target); - dir_entry->symlink_target = symlink_target ? strdup (symlink_target) : 0; - } - } - - /* The st_ino field is always valid. */ - dir_entry->stat.st_ino = ino; - dir_entry->stat.st_fsid = fs->fsid; - dir_entry->stat.st_fstype = PROCFILESYSTEM; - - dir_entry->valid = 1; - - if (! dir_entry->ordered_self_p) - /* Position DIR_ENTRY in the ordered chain following the previously seen entry. */ - { - /* The PREV_ENTRY_NEXT_P field holds a pointer to the NEXT-field of the - previous entry, or a pointer to the ORDERED field in the directory. */ - dir_entry->ordered_self_p = cur_entry; - - if (*dir_entry->ordered_self_p) - /* Update the self_p pointer of the previous successor. */ - (*dir_entry->ordered_self_p)->ordered_self_p = &dir_entry->ordered_next; - - /* DIR_ENTRY comes before the previous successor. */ - dir_entry->ordered_next = *dir_entry->ordered_self_p; - - *dir_entry->ordered_self_p = dir_entry; /* Put DIR_ENTRY there. */ - } - - /* Put the next entry after this one. */ - cur_entry = &dir_entry->ordered_next; - - return dir_entry; -} - -/* Fills DIR, the root directory with all the pids of - processes running in the system as directories. */ -error_t -procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) -{ - error_t err; - char *data; - pid_t *pids; - int pidslen; - struct stat stat; - stat.st_mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | - S_IROTH | S_IXOTH; - stat.st_nlink = 1; - stat.st_size = 0; - - int count; - char *dir_name_pid; - struct node *node; - struct procfs_dir *new_dir; - struct procfs_dir_entry *dir_entry; - struct proc_stat *ps; - - pids = NULL; - pidslen = 0; - err = proc_getallpids (getproc (), &pids, &pidslen); - - if (!err) - { - for (count = 0; count < pidslen; count++) - { - if (asprintf (&dir_name_pid, "%d", pids[count]) == -1) - return errno; - -#if 0 - node = (struct node *) malloc (sizeof (struct node)); - new_dir = (struct procfs_dir *) malloc (sizeof (struct procfs_dir )); - - if (! node || ! new_dir ) - return ENOMEM; -#endif - err = _proc_stat_create (pids[count], ps_context, &ps); - if (! err) - { - err = set_field_value (ps, PSTAT_PROC_INFO); - if (! err) - { - stat.st_uid = proc_stat_proc_info (ps)->owner; - stat.st_gid = proc_stat_proc_info (ps)->pgrp; - - dir_entry = update_entries_list (dir, dir_name_pid, - &stat, timestamp, NULL); - err = procfs_create_node (dir_entry, dir_name_pid, &node); - - procfs_dir_create (dir->fs, node, - dir_name_pid, &new_dir); - free(dir_name_pid); - _proc_stat_free (ps); - } - } - } - } - - if ((err = procfs_create_uptime (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_stat (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_version (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_meminfo (dir, &node, timestamp)) != 0) - return err; - - if ((err = procfs_create_loadavg (dir, &node, timestamp)) != 0) - return err; - - return 0; -} - -error_t update_dir_entries (struct procfs_dir *dir) -{ - /* STUB */ - return 0; -} diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c deleted file mode 100644 index 2c1209ee..00000000 --- a/procfs_nonpid_files.c +++ /dev/null @@ -1,514 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_nonpid_files.c -- This file contains function definitions - to create and update the non-Per PID - files and their contents. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - - A portion of the code in this file is based on vmstat.c code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - - Copyright (C) 1997,98,2002 Free Software Foundation, Inc. - Written by Miles Bader - This file is part of the GNU Hurd. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "procfs.h" - -typedef long long val_t; -#define BADVAL ((val_t) - 1LL) - -/* default pager port (must be privileged to fetch this). */ -mach_port_t def_pager; -struct default_pager_info def_pager_info; - -error_t procfs_create_uptime (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "uptime") == -1) - return errno; - if (asprintf (&file_path, "%s", "uptime") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t procfs_create_version(struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "version") == -1) - return errno; - if (asprintf (&file_path, "%s", "version") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return 0; -} - -error_t procfs_create_stat (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "stat") == -1) - return errno; - if (asprintf (&file_path, "%s", "stat") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t procfs_create_meminfo (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "meminfo") == -1) - return errno; - if (asprintf (&file_path, "%s", "meminfo") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t procfs_create_loadavg (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "loadavg") == -1) - return errno; - if (asprintf (&file_path, "%s", "loadavg") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - return err; -} - -error_t get_uptime (struct timeval *uptime) -{ - struct timeval boot_time, now; - error_t err; - struct proc_stat *ps; - - err = _proc_stat_create (1, ps_context, &ps); - - if (err) - return err; - - err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); - if (!err && !(ps->flags & PSTAT_TASK_BASIC)) - err = EGRATUITOUS; - - if (! err) - { - time_value_t *const tv = &proc_stat_task_basic_info (ps)->creation_time; - boot_time.tv_sec = tv->seconds; - boot_time.tv_usec = tv->microseconds; - if (gettimeofday (&now, 0) < 0) - error (0, errno, "gettimeofday"); - timersub (&now, &boot_time, uptime); - } - - _proc_stat_free (ps); - return err; -} - -error_t get_total_times (struct timeval *total_user_time, - struct timeval *total_system_time) -{ - error_t err; - pid_t *pids; - int pidslen = 0, count; - struct proc_stat *ps; - struct task_thread_times_info live_threads_times; - - struct timeval total_user_time_tmp; - struct timeval total_system_time_tmp; - struct timeval tmpval; - - timerclear (&total_user_time_tmp); - timerclear (&total_system_time_tmp); - - pids = NULL; - err = proc_getallpids (getproc (), &pids, &pidslen); - - if (!err) - for (count = 0; count < pidslen; count++) - { - err = _proc_stat_create (pids[count], ps_context, &ps); - if (err) - return err; - - err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); - if (!err && !(ps->flags & PSTAT_TASK_BASIC)) - err = EGRATUITOUS; - - if (! err) - { - tmpval.tv_sec = proc_stat_task_basic_info (ps)->user_time.seconds; - tmpval.tv_usec = proc_stat_task_basic_info (ps)->user_time.seconds; - timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); - - tmpval.tv_sec = proc_stat_task_basic_info (ps)->system_time.seconds; - tmpval.tv_usec = proc_stat_task_basic_info (ps)->system_time.seconds; - timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); - - error_t err = set_field_value (ps, PSTAT_TASK); - if (! err) - { - err = get_task_thread_times (ps->task, &live_threads_times); - if (! err) - { - tmpval.tv_sec = live_threads_times.user_time.seconds; - tmpval.tv_usec = live_threads_times.user_time.microseconds; - timeradd (&total_user_time_tmp, &tmpval, &total_user_time_tmp); - - tmpval.tv_sec = live_threads_times.system_time.seconds; - tmpval.tv_usec = live_threads_times.system_time.microseconds; - timeradd (&total_system_time_tmp, &tmpval, &total_system_time_tmp); - } - } - } - _proc_stat_free (ps); - } - - total_user_time->tv_sec = total_user_time_tmp.tv_sec; - total_user_time->tv_usec = total_user_time_tmp.tv_usec; - - total_system_time->tv_sec = total_system_time_tmp.tv_sec; - total_system_time->tv_usec = total_system_time_tmp.tv_usec; - - return err; -} - -error_t procfs_read_nonpid_stat (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *stat_data; - error_t err; - jiffy_t total_user_time_jiffy, total_system_time_jiffy; - jiffy_t idle_time_jiffy; - struct timeval uptime, total_user_time, total_system_time; - struct timeval idle_time; - - err = get_uptime (&uptime); - - if (! err) - { - err = get_total_times (&total_user_time, &total_system_time); - - if (! err) - { - timersub (&uptime, &total_system_time, - &idle_time); - - total_user_time_jiffy = 100 * ((double) total_user_time.tv_sec + - (double) total_user_time.tv_usec / (1000 * 1000)); - total_system_time_jiffy = 100 * ((double) total_system_time.tv_sec + - (double) total_system_time.tv_usec / (1000 * 1000)); - idle_time_jiffy = 100 * ((double) idle_time.tv_sec + - (double) idle_time.tv_usec / (1000 * 1000)); - - if (asprintf (&stat_data, "cpu %llu %llu %llu %llu %llu %llu %d %d %d\n" - "cpu0 %llu %llu %llu %llu %llu %llu %d %d %d\n" - "intr %llu %llu %llu %llu %llu %llu %d %d %d\n", - total_user_time_jiffy, (long long unsigned) 0, - total_system_time_jiffy, idle_time_jiffy, - (long long unsigned) 0, (long long unsigned) 0, - 0, 0, 0, - total_user_time_jiffy, (long long unsigned) 0, - total_system_time_jiffy, idle_time_jiffy, - (long long unsigned) 0, (long long unsigned) 0, - 0, 0, 0, - (long long unsigned) 0, - (long long unsigned) 0, (long long unsigned) 0, (long long unsigned) 0, - (long long unsigned) 0, - (long long unsigned) 0, (long long unsigned) 0, - (long long unsigned) 0, (long long unsigned) 0) == -1) - return errno; - } - } - - memcpy (data, stat_data, strlen(stat_data)); - *len = strlen (data); - - free (stat_data); - return err; -} - -/* Makes sure the default pager port and associated - info exists, and returns 0 if not (after printing - an error). */ -static int -ensure_def_pager_info () -{ - error_t err; - - if (def_pager == MACH_PORT_NULL) - { - mach_port_t host; - - err = get_privileged_ports (&host, 0); - if (err == EPERM) - { - /* We are not root, so try opening the /servers file. */ - def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); - if (def_pager == MACH_PORT_NULL) - { - error (0, errno, _SERVERS_DEFPAGER); - return 0; - } - } - if (def_pager == MACH_PORT_NULL) - { - if (err) - { - error (0, err, "get_privileged_ports"); - return 0; - } - - err = vm_set_default_memory_manager (host, &def_pager); - mach_port_deallocate (mach_task_self (), host); - - if (err) - { - error (0, err, "vm_set_default_memory_manager"); - return 0; - } - } - } - - if (!MACH_PORT_VALID (def_pager)) - { - if (def_pager == MACH_PORT_NULL) - { - error (0, 0, - "No default pager running, so no swap information available"); - def_pager = MACH_PORT_DEAD; /* so we don't try again */ - } - return 0; - } - - err = default_pager_info (def_pager, &def_pager_info); - if (err) - error (0, err, "default_pager_info"); - return (err == 0); -} - -#define SWAP_FIELD(getter, expr) \ - static val_t getter () \ - { return ensure_def_pager_info () ? (val_t) (expr) : BADVAL; } - -SWAP_FIELD (get_swap_size, def_pager_info.dpi_total_space) -SWAP_FIELD (get_swap_free, def_pager_info.dpi_free_space) -SWAP_FIELD (get_swap_page_size, def_pager_info.dpi_page_size) -SWAP_FIELD (get_swap_active, (def_pager_info.dpi_total_space - - def_pager_info.dpi_free_space)) - -error_t procfs_read_nonpid_meminfo (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *meminfo_data; - error_t err; - struct vm_statistics vmstats; - - err = vm_statistics (mach_task_self (), &vmstats); - - unsigned long mem_size = ((vmstats.free_count + - vmstats.active_count + vmstats.inactive_count + - vmstats.wire_count) * vmstats.pagesize) / 1024; - - if (! err) - if (asprintf (&meminfo_data, "MemTotal:\t%lu kB\n" - "MemFree:\t%lu kB\n" - "Buffers:\t%ld kB\n" - "Cached:\t\t%ld kB\n" - "SwapCached:\t%ld kB\n" - "Active:\t\t%lu kB\n" - "Inactive:\t%lu kB\n" - "HighTotal:\t%lu kB\n" - "HighFree:\t%lu kB\n" - "LowTotal:\t%lu kB\n" - "LowFree:\t%lu kB\n" - "SwapTotal:\t%llu kB\n" - "SwapFree:\t%llu kB\n", - mem_size, (PAGES_TO_BYTES(vmstats.free_count)) / 1024 , 0, 0, 0, - (PAGES_TO_BYTES(vmstats.active_count)) / 1024, - (PAGES_TO_BYTES(vmstats.inactive_count)) / 1024, 0, 0, 0, 0, - get_swap_size () / 1024, get_swap_free () / 1024) == -1) - return errno; - - memcpy (data, meminfo_data, strlen(meminfo_data)); - *len = strlen (data); - - free (meminfo_data); - return err; -} - -error_t procfs_read_nonpid_loadavg (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *loadavg_data; - error_t err; - processor_set_info_t info; - natural_t *count; - struct host_load_info *load; - mach_port_t host; - - err = ps_host_load_info (&load); - if (err) - error (0, err, "ps_host_load_info"); - - if (! err) - if (asprintf (&loadavg_data, "%.2f %.2f %.2f %d/%d %d\n", - (double)load->avenrun[0] / (double)LOAD_SCALE, - (double)load->avenrun[1] / (double)LOAD_SCALE, - (double)load->avenrun[2] / (double)LOAD_SCALE, 0, 0, 0) == -1) - return errno; - - memcpy (data, loadavg_data, strlen(loadavg_data)); - *len = strlen (data); - - free (loadavg_data); - return err; -} - -error_t procfs_read_nonpid_uptime (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *uptime_data; - error_t err; - double uptime_secs, idle_time_secs; - - struct timeval uptime_val; - struct timeval uptime, total_user_time, total_system_time; - struct timeval idle_time; - - - err = get_uptime (&uptime); - if (! err) - { - err = get_total_times (&total_user_time, - &total_system_time); - if (! err) - { - timersub (&uptime, &total_system_time, - &idle_time); - - uptime_secs = (double) uptime.tv_sec + - (double) uptime.tv_usec / (1000 * 1000); - - idle_time_secs = (double) idle_time.tv_sec + - (double) idle_time.tv_usec / (1000 * 1000); - - if (asprintf (&uptime_data, "%.2f %.2f\n", - uptime_secs, idle_time_secs) == -1) - return errno; - } - } - - - memcpy (data, uptime_data, strlen(uptime_data)); - *len = strlen (data); - - free (uptime_data); - return err; -} - -error_t procfs_read_nonpid_version (struct dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *version_data; - error_t err = 0; - - if (asprintf (&version_data, "Linux version 2.6.18\n", NULL) == -1) - return errno; - - memcpy (data, version_data, strlen(version_data)); - *len = strlen (data); - - free (version_data); - return err; -} diff --git a/procfs_pid.h b/procfs_pid.h deleted file mode 100644 index 566c83ea..00000000 --- a/procfs_pid.h +++ /dev/null @@ -1,88 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_pid.h -- This is the header file of which contains defintions - for structure of directory with PID as the name and - structure of each file in this directory. - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. -*/ - -#ifndef __PROCFS_PID_H__ -#define __PROCFS_PID_H__ - -#include "procfs.h" - -struct procfs_pid_files -{ - struct procfs_cwd *procfs_cwd; - struct procfs_environ *procfs_environ; - struct procfs_cpu *procfs_cpu; - struct procfs_root *procfs_root; - struct procfs_exe *procfs_exe; - struct procfs_stat *_procfs_stat; - struct procfs_statm *procfs_statm; -}; - -struct procfs_stat -{ - pid_t pid; - char *comm; - char *state; - pid_t ppid; - pid_t pgid; - pid_t sid; - int tty_nr; - pid_t tty_pgrp; - unsigned flags; - long unsigned minflt; - long unsigned cminflt; - long unsigned majflt; - long unsigned cmajflt; - jiffy_t utime; - jiffy_t stime; - jiffy_t cutime; - jiffy_t cstime; - long priority; - long nice; - long num_threads; - long itrealvalue; - long long unsigned starttime; - long unsigned vsize; - long rss; - long unsigned rlim; - long unsigned startcode; - long unsigned endcode; - long unsigned startstack; - long unsigned kstkesp; - long unsigned kstkeip; - long unsigned signal; - long unsigned blocked; - long unsigned sigignore; - long unsigned sigcatch; - long unsigned wchan; - long unsigned nswap; - long unsigned cnswap; - int exit_signal; - int processor; - unsigned rt_priority; - unsigned policy; - long long unsigned delayacct_blkio_ticks; -}; - -#endif diff --git a/procfs_pid_files.c b/procfs_pid_files.c deleted file mode 100644 index 46861531..00000000 --- a/procfs_pid_files.c +++ /dev/null @@ -1,576 +0,0 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs_pid_files.c -- This file contains definitions to perform - file operations such as creating, writing to, - reading from and removing files that holds - information for each process with PID - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - - procfs is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - procfs 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - - A portion of the code in this file is based on ftpfs code - present in the hurd repositories copyrighted to FSF. The - Copyright notice from that file is given below. - -*/ - -#include -#include -#include -#include -#include -#include - -#include "procfs_pid.h" - -/* Update the files named NAME within the directory named - PID also with SYMLINK TARGET if necessary. */ -struct procfs_dir_entry* -update_pid_entries (struct procfs_dir *dir, const char *name, - time_t timestamp, - const char *symlink_target) -{ - struct procfs_dir_entry *dir_entry; - struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); - stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; - - dir_entry = update_entries_list (dir, name, stat, - timestamp, symlink_target); - - return dir_entry; -} - -/* Creates files to store process information for DIR - whose names are pids and returns these files in *NODE. */ -error_t -procfs_create_files (struct procfs_dir *dir, - struct node **node, - time_t timestamp) -{ - int err; - char *file_name, *file_path; - struct procfs_dir_entry *dir_entry; - - if (asprintf (&file_name, "%s", "stat") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "stat") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - if (asprintf (&file_name, "%s", "status") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "status") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - if (asprintf (&file_name, "%s", "cmdline") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "cmdline") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - - if (asprintf (&file_name, "%s", "statm") == -1) - return errno; - if (asprintf (&file_path, "%s/%s", dir->node->nn->dir_entry->name, "statm") == -1) - return errno; - - dir_entry = update_pid_entries (dir, file_name, timestamp, NULL); - err = procfs_create_node (dir_entry, file_path, node); - - free (file_name); - free (file_path); - -#if 0 - nodes_list = &node_stat; - nodes_list++; - node = nodes_list; -#endif - - return err; -} - -/* Check if the PSTAT_FLAG is set in the corresponding PS - structure, if not set it and check again and return error - status accordingly. */ -error_t set_field_value (struct proc_stat *ps, int pstat_flag) -{ - error_t err; - - if (! (ps->flags & pstat_flag)) - { - err = proc_stat_set_flags (ps, pstat_flag); - if (err) - return err; - - /* This second check is done since ps.h specifies to - do so since the previous call would not have set - the required value. */ - if (! (ps->flags & pstat_flag)) - return EGRATUITOUS; - } - - return 0; -} - -/* Adjusts TIME_VAL structure having Seconds and - Microseconds into the value in jiffies. The - value of jiffy is a hack to adjust to what - procps uses. */ -jiffy_t adjust_jiffy_time (time_value_t time_val) -{ - jiffy_t jiffy_time = time_val.seconds * JIFFY_ADJUST; - jiffy_time += (time_val.microseconds * JIFFY_ADJUST) - / (1000 * 1000); - - return jiffy_time; -} - -/* Extract the user and system time for the live threads of - the process. This information is directly retrieved from - MACH since neither libps not proc makes this available. */ -error_t get_task_thread_times (task_t task, - struct task_thread_times_info *live_threads_times) -{ - error_t err; - size_t tkcount = TASK_THREAD_TIMES_INFO_COUNT; - - err = task_info (task, TASK_THREAD_TIMES_INFO, - (task_info_t) live_threads_times, &tkcount); - if (err == MACH_SEND_INVALID_DEST) - err = ESRCH; - - return err; -} - -/* Obtains the User Time in UTIME and System Time in STIME from - MACH directly since this is neither made available by libps - nor by proc server. */ -error_t get_live_threads_time (struct proc_stat *ps, - jiffy_t *utime, jiffy_t *stime) -{ - struct task_thread_times_info live_threads_times; - error_t err = set_field_value (ps, PSTAT_TASK); - - if (! err) - { - err = get_task_thread_times (ps->task, &live_threads_times); - if (! err) - { - *utime = adjust_jiffy_time ( - live_threads_times.user_time); - *stime = adjust_jiffy_time ( - live_threads_times.system_time); - } - } - - return err; -} - -/* Get the data for stat file into the structure - PROCFS_STAT. */ -error_t get_stat_data (pid_t pid, - struct procfs_stat **procfs_stat) -{ - error_t err; - struct procfs_stat *new = (struct procfs_stat *) - malloc (sizeof (struct procfs_stat)); - - struct proc_stat *ps; - jiffy_t utime, stime; - - err = _proc_stat_create (pid, ps_context, &ps); - - new->pid = pid; - - if (! err) - { - err = set_field_value (ps, PSTAT_ARGS); - if (! err) - asprintf (&new->comm, "%s", ps->args); - } - - err = set_field_value (ps, PSTAT_STATE); - if (! err) - { - if (ps->state & PSTAT_STATE_P_STOP) - new->state = strdup ("T"); - if (ps->state & PSTAT_STATE_P_ZOMBIE) - new->state = strdup ("Z"); - if (ps->state & PSTAT_STATE_P_FG) - new->state = strdup ("+"); - if (ps->state & PSTAT_STATE_P_SESSLDR) - new->state = strdup ("s"); - if (ps->state & PSTAT_STATE_P_LOGINLDR) - new->state = strdup ("l"); - if (ps->state & PSTAT_STATE_P_FORKED) - new->state = strdup ("f"); - if (ps->state & PSTAT_STATE_P_NOMSG) - new->state = strdup ("m"); - if (ps->state & PSTAT_STATE_P_NOPARENT) - new->state = strdup ("p"); - if (ps->state & PSTAT_STATE_P_ORPHAN) - new->state = strdup ("o"); - if (ps->state & PSTAT_STATE_P_TRACE) - new->state = strdup ("x"); - if (ps->state & PSTAT_STATE_P_WAIT) - new->state = strdup ("w"); - if (ps->state & PSTAT_STATE_P_GETMSG) - new->state = strdup ("g"); - } - - err = set_field_value (ps, PSTAT_PROC_INFO); - if (! err) - { - new->ppid = ps->proc_info->ppid; - new->pgid = ps->proc_info->pgrp; - new->sid = ps->proc_info->session; - new->tty_pgrp = ps->proc_info->pgrp; - } - else - { - new->ppid = 0; - new->pgid = 0; - new->sid = 0; - new->tty_pgrp = 0; - } - - err = set_field_value (ps, PSTAT_STATE); - if (! err) - new->flags = ps->state; - else - new->flags = 0; - - err = set_field_value (ps, PSTAT_TASK_EVENTS); - if (! err) - { - new->minflt = ps->task_events_info->faults; - new->majflt = ps->task_events_info->pageins; - } - else - { - new->minflt = 0; - new->majflt = 0; - } - - /* This seems to be a bit inconsistent with setting of other - fields in this code. There are two reasons for this. - 1. The actual information required is not made available - by libps which should be directly obtained from MACH. - 2. The same code which is required to get the information - have to be reused in procfs_nonpid_files.c */ - err = get_live_threads_time (ps, &utime, &stime); - if (! err) - { - new->utime = utime; - new->stime = stime; - } - else - { - new->utime = 0; - new->stime = 0; - } - - err = set_field_value (ps, PSTAT_TASK_BASIC); - if (! err) - { - new->cutime = adjust_jiffy_time ( - ps->task_basic_info->user_time); - new->cstime = adjust_jiffy_time ( - ps->task_basic_info->system_time); - - new->priority = ps->task_basic_info->base_priority; - new->starttime = adjust_jiffy_time ( - ps->task_basic_info->creation_time); - - new->vsize = ps->task_basic_info->virtual_size; - new->rss = ps->task_basic_info->resident_size; - } - else - { - new->cutime = 0; - new->cstime = 0; - new->priority = 0; - new->starttime = 0; - new->vsize = 0; - new->rss = 0; - } - - new->nice = getpriority (0, pid); - - err = set_field_value (ps, PSTAT_NUM_THREADS); - if (! err) - new->num_threads = ps->num_threads; - else - new->num_threads = 0; - - /* Not Supported in Linux 2.6 or later. */ - new->tty_nr = 0; - new->itrealvalue = 0; - new->nswap = 0; - new->cnswap = 0; - - /* Temporarily set to 0 until correct - values are found .*/ - new->cminflt = 0; - new->cmajflt = 0; - new->rlim = 0; - new->startcode = 0; - new->endcode = 0; - new->startstack = 0; - new->kstkesp = 0; - new->kstkeip = 0; - new->signal = 0; - new->blocked = 0; - new->sigignore = 0; - new->sigcatch = 0; - new->wchan = 0; - new->exit_signal = 0; - new->processor = 0; - new->rt_priority = 0; - new->policy = 0; - new->delayacct_blkio_ticks = 0; - - *procfs_stat = new; - _proc_stat_free (ps); - - return err; -} - -/* Reads required process information from stat file - within the directory represented by pid. Return - the data in DATA and actual length to be written - in LEN. */ -error_t -procfs_read_stat_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - error_t err; - char *stat_data; - struct procfs_stat *procfs_stat; - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - - err = get_stat_data (pid, &procfs_stat); - - if (asprintf (&stat_data, "%d (%s) %s %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu \n", - procfs_stat->pid, procfs_stat->comm, - procfs_stat->state, procfs_stat->ppid, - procfs_stat->pgid, procfs_stat->sid, - procfs_stat->tty_nr, procfs_stat->tty_pgrp, - procfs_stat->flags, procfs_stat->minflt, - procfs_stat->cminflt, procfs_stat->majflt, - procfs_stat->cmajflt, procfs_stat->utime, - procfs_stat->stime, procfs_stat->cutime, - procfs_stat->cstime, procfs_stat->priority, - procfs_stat->nice, procfs_stat->num_threads, - procfs_stat->itrealvalue, procfs_stat->starttime, - procfs_stat->vsize, BYTES_TO_PAGES(procfs_stat->rss), - procfs_stat->rlim, procfs_stat->startcode, - procfs_stat->endcode, procfs_stat->startstack, - procfs_stat->kstkesp, procfs_stat->kstkeip, - procfs_stat->signal, procfs_stat->blocked, - procfs_stat->sigignore, procfs_stat->sigcatch, - procfs_stat->wchan, procfs_stat->nswap, - procfs_stat->cnswap, procfs_stat->exit_signal, - procfs_stat->processor, procfs_stat->rt_priority, - procfs_stat->policy, - procfs_stat->delayacct_blkio_ticks) == -1) - return errno; - - - memcpy (data, stat_data, strlen(stat_data)); - *len = strlen (data); - - free (stat_data); - free (procfs_stat); - - return err; -} - -/* Reads required process's command line information - from cmline file within the directory represented - by pid. Return the data in DATA and actual length - to be written in LEN. */ -error_t -procfs_read_cmdline_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *cmdline_data; - error_t err; - struct proc_stat *ps; - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - err = _proc_stat_create (pid, ps_context, &ps); - - err = set_field_value (ps, PSTAT_ARGS); - - if (! err) - if (asprintf (&cmdline_data, "%s \n", ps->args) == -1) - return errno; - - memcpy (data, cmdline_data, strlen(cmdline_data)); - *len = strlen (data); - - _proc_stat_free (ps); - free (cmdline_data); - return err; -} - -/* Reads required process's information that is represented by - stat and statm in a human readable format from status file - within the directory represented by pid. Return the data - in DATA and actual length to be written in LEN. */ -error_t -procfs_read_status_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *status_data; - error_t err; - struct proc_stat *ps; - struct procfs_stat *procfs_stat; - - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - err = _proc_stat_create (pid, ps_context, &ps); - - err = get_stat_data (pid, &procfs_stat); - - if (! err) - if (asprintf (&status_data, "Name:\t%s\nState:\t%s\nTgid:\t%d\nPid:\t%d\n", procfs_stat->comm, procfs_stat->state, procfs_stat->pid, procfs_stat->pid) == -1) - return errno; - - memcpy (data, status_data, strlen(status_data)); - *len = strlen (data); - - _proc_stat_free (ps); - - free (status_data); - free (procfs_stat); - - return err; -} - -/* Reads required process information from statm file - within the directory represented by pid. Return - the data in DATA and actual length to be written - in LEN. */ -error_t -procfs_read_statm_file (struct procfs_dir_entry *dir_entry, - off_t offset, size_t *len, void *data) -{ - char *statm_data; - error_t err; - struct proc_stat *ps; - struct procfs_stat *procfs_stat; - - pid_t pid = atoi (dir_entry->dir->node->nn->dir_entry->name); - err = _proc_stat_create (pid, ps_context, &ps); - - err = get_stat_data (pid, &procfs_stat); - - if (! err) - if (asprintf (&statm_data, "%lu %ld %d %d %d %d %d\n", - BYTES_TO_PAGES(procfs_stat->vsize), - BYTES_TO_PAGES(procfs_stat->rss), - 0, 0, 0, 0, 0) == -1) - return errno; - - memcpy (data, statm_data, strlen(statm_data)); - *len = strlen (data); - - _proc_stat_free (ps); - - free (statm_data); - free (procfs_stat); - - return err; -} - -/* Reads required process information from each of files - within directory represented by pid, for files specified - by NODE. Return the data in DATA and actual length of - data in LEN. */ -error_t -procfs_read_files_contents (struct node *node, - off_t offset, size_t *len, void *data) -{ - error_t err; - - if (! strcmp (node->nn->dir_entry->name, "stat")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_stat (node->nn->dir_entry, - offset, len, data); - else - err = procfs_read_stat_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "cmdline")) - err = procfs_read_cmdline_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "status")) - err = procfs_read_status_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "statm")) - err = procfs_read_statm_file (node->nn->dir_entry, - offset, len, data); - - if (! strcmp (node->nn->dir_entry->name, "meminfo")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_meminfo (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - if (! strcmp (node->nn->dir_entry->name, "loadavg")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_loadavg (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - if (! strcmp (node->nn->dir_entry->name, "uptime")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_uptime (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - if (! strcmp (node->nn->dir_entry->name, "version")) - if (! strcmp (node->nn->dir_entry->dir->fs_path, "")) - err = procfs_read_nonpid_version (node->nn->dir_entry, - offset, len, data); - else - err = ENOENT; - - return err; -} -- cgit v1.2.3 From 7e0dc553966e9ac1d0506e8cce9ae3f4708f124b Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Fri, 13 Aug 2010 19:05:13 +0200 Subject: update_pid_entries(): fix awkwardly indented uninitialized memory leak * procfs_pid_files.c (update_pid_entries): Replace dynamic allocation of `stat' with automatic allocation. Memset `stat' to 0. --- procfs_pid_files.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/procfs_pid_files.c b/procfs_pid_files.c index 46861531..d44a2a22 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -46,14 +46,12 @@ update_pid_entries (struct procfs_dir *dir, const char *name, time_t timestamp, const char *symlink_target) { - struct procfs_dir_entry *dir_entry; - struct stat *stat = (struct stat *) malloc (sizeof (struct stat)); - stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + struct stat stat; - dir_entry = update_entries_list (dir, name, stat, - timestamp, symlink_target); + memset (&stat, 0, sizeof stat); + stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; - return dir_entry; + return update_entries_list (dir, name, &stat, timestamp, symlink_target); } /* Creates files to store process information for DIR -- cgit v1.2.3 From 0e63733ee60d0b9fa56ec47bdb088d4b835ec217 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Fri, 13 Aug 2010 19:05:14 +0200 Subject: Set an appropriate st_mode on symlinks. * procfs_pid_files.c (update_pid_entries): When symlink_target is not NULL, set st_size to the symlink length and st_mode to S_IFLNK | 0777. --- procfs_pid_files.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/procfs_pid_files.c b/procfs_pid_files.c index d44a2a22..26a0af33 100644 --- a/procfs_pid_files.c +++ b/procfs_pid_files.c @@ -49,7 +49,16 @@ update_pid_entries (struct procfs_dir *dir, const char *name, struct stat stat; memset (&stat, 0, sizeof stat); - stat->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + if (symlink_target) + { + stat.st_size = strlen (symlink_target); + stat.st_mode = S_IFLNK | 0777; + } + else + { + stat.st_size = 0; + stat.st_mode = S_IFREG | 0444; + } return update_entries_list (dir, name, &stat, timestamp, symlink_target); } -- cgit v1.2.3 From 7070feccb2e4d135d5620805de6cec177722b837 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 16 Aug 2010 13:36:52 +0200 Subject: Implement /proc/mounts as a symlink to /etc/mtab * procfs_nonpid_files.c (procfs_create_mounts): New function. * procfs_dir.c (procfs_fill_root_dir): Call procfs_create_mounts. Signed-off-by: Jeremie Koenig --- procfs_dir.c | 3 +++ procfs_nonpid_files.c | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/procfs_dir.c b/procfs_dir.c index f76e6a4b..bd1e49d6 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -654,6 +654,9 @@ procfs_fill_root_dir(struct procfs_dir *dir, time_t timestamp) if ((err = procfs_create_loadavg (dir, &node, timestamp)) != 0) return err; + if ((err = procfs_create_mounts (dir, &node, timestamp)) != 0) + return err; + return 0; } diff --git a/procfs_nonpid_files.c b/procfs_nonpid_files.c index 2c1209ee..f1300666 100644 --- a/procfs_nonpid_files.c +++ b/procfs_nonpid_files.c @@ -166,6 +166,19 @@ error_t procfs_create_loadavg (struct procfs_dir *dir, return err; } +error_t procfs_create_mounts (struct procfs_dir *dir, + struct node **node, + time_t timestamp) +{ + struct procfs_dir_entry *dir_entry; + int err; + + dir_entry = update_pid_entries (dir, "mounts", timestamp, "/etc/mtab"); + err = procfs_create_node (dir_entry, "mounts", node); + + return err; +} + error_t get_uptime (struct timeval *uptime) { struct timeval boot_time, now; -- cgit v1.2.3 From 1083606b7f97f0284039aa197f7b2181f902d0bb Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 09:43:29 +0000 Subject: Basic infrastructure * procfs.h: New file; basic interfaces for procfs nodes. * procfs.c: New file; implement the basic infrastructure. * netfs.c: New file; bridge libnetfs and the procfs interfaces. * main.c: New file; mostly a "Hello, World!" for now. * Makefile: New file; standalone for now. --- main.c | 58 ++++++++++ netfs.c | 391 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ procfs.c | 90 +++++++++++++++ procfs.h | 40 +++++++ 4 files changed, 579 insertions(+) create mode 100644 main.c create mode 100644 netfs.c create mode 100644 procfs.c create mode 100644 procfs.h diff --git a/main.c b/main.c new file mode 100644 index 00000000..cafd0c9a --- /dev/null +++ b/main.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include "procfs.h" + +static error_t get_contents (void *hook, void **contents, size_t *contents_len) +{ + static const char hello[] = "Hello, World!\n"; + *contents = (void *) hello; + *contents_len = sizeof hello - 1; + return 0; +} + +static error_t get_entries (void *hook, void **contents, size_t *contents_len) +{ + static const char entries[] = "hello"; + *contents = (void *) entries; + *contents_len = sizeof entries; + return 0; +} + +static error_t lookup (void *hook, const char *name, struct node **np) +{ + static const struct procfs_node_ops ops = { .get_contents = get_contents }; + + if (strcmp (name, "hello")) + return ENOENT; + + *np = procfs_make_node (&ops, NULL); + if (! *np) + return ENOMEM; + + return 0; +} + +int main (int argc, char **argv) +{ + static const struct procfs_node_ops ops = { + .get_contents = get_entries, + .lookup = lookup, + }; + mach_port_t bootstrap; + + argp_parse (&netfs_std_startup_argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "Must be started as a translator"); + + netfs_init (); + netfs_root_node = procfs_make_node (&ops, NULL); + + netfs_startup (bootstrap, 0); + for (;;) + netfs_server_loop (); +} + diff --git a/netfs.c b/netfs.c new file mode 100644 index 00000000..58665085 --- /dev/null +++ b/netfs.c @@ -0,0 +1,391 @@ +#include +#include +#include +#include +#include +#include +#include "procfs.h" + +#define PROCFS_SERVER_NAME "procfs" +#define PROCFS_SERVER_VERSION "0.1.0" +#define PROCFS_MAXSYMLINKS 16 + + +/* Interesting libnetfs callback functions. */ + +/* The user must define this variable. Set this to the name of the + filesystem server. */ +char *netfs_server_name = PROCFS_SERVER_NAME; + +/* The user must define this variables. Set this to be the server + version number. */ +char *netfs_server_version = PROCFS_SERVER_VERSION; + +/* Maximum number of symlinks to follow before returning ELOOP. */ +int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; + +/* The user must define this function. Read from the locked file NP + for user CRED starting at OFFSET and continuing for up to *LEN + bytes. Put the data at DATA. Set *LEN to the amount successfully + read upon return. */ +error_t netfs_attempt_read (struct iouser *cred, struct node *np, + loff_t offset, size_t *len, void *data) +{ + char *contents; + size_t contents_len; + error_t err; + + err = procfs_get_contents (np, (void **) &contents, &contents_len); + if (err) + return err; + + contents += offset; + contents_len -= offset; + + if (*len > contents_len) + *len = contents_len; + if (*len < 0) + *len = 0; + + memcpy (data, contents, *len); + return 0; +} + +/* The user must define this function. Read the contents of locked + node NP (a symlink), for USER, into BUF. */ +error_t netfs_attempt_readlink (struct iouser *user, struct node *np, + char *buf) +{ + return EIO; +} + +/* Helper function for netfs_get_dirents() below. CONTENTS is an argz + vector of directory entry names, as returned by procfs_get_contents(). + Convert at most NENTRIES of them to dirent structures, put them in + DATA (if not NULL), write the number of entries processed in *AMT and + return the required/used space in DATACNT. */ +static int putentries (char *contents, size_t contents_len, int nentries, + char *data, mach_msg_type_number_t *datacnt) +{ + int i; + + *datacnt = 0; + for (i = 0; contents_len && (nentries < 0 || i < nentries); i++) + { + int namlen = strlen (contents); + int reclen = sizeof (struct dirent) + namlen; + + if (data) + { + struct dirent *d = (struct dirent *) (data + *datacnt); + d->d_fileno = 42; /* XXX */ + d->d_namlen = namlen; + d->d_reclen = reclen; + d->d_type = DT_UNKNOWN; + strcpy (d->d_name, contents); + } + + *datacnt += reclen; + contents += namlen + 1; + contents_len -= namlen + 1; + } + + return i; +} + +/* The user must define this function. Fill the array *DATA of size + BUFSIZE with up to NENTRIES dirents from DIR (which is locked) + starting with entry ENTRY for user CRED. The number of entries in + the array is stored in *AMT and the number of bytes in *DATACNT. + If the supplied buffer is not large enough to hold the data, it + should be grown. */ +error_t netfs_get_dirents (struct iouser *cred, struct node *dir, + int entry, int nentries, char **data, + mach_msg_type_number_t *datacnt, + vm_size_t bufsize, int *amt) +{ + char *contents; + size_t contents_len; + error_t err; + + err = procfs_get_contents (dir, (void **) &contents, &contents_len); + if (err) + return err; + + /* We depend on the fact that CONTENTS is terminated. */ + assert (contents_len == 0 || contents[contents_len - 1] == '\0'); + + /* Skip to the first requested entry. */ + while (contents_len && entry--) + { + int ofs = strlen (contents) + 1; + contents += ofs; + contents_len -= ofs; + } + + /* Allocate a buffer if necessary. */ + putentries (contents, contents_len, nentries, NULL, datacnt); + if (bufsize < *datacnt) + { + void *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); + if (n == MAP_FAILED) + return ENOMEM; + + *data = n; + } + + /* Do the actual conversion. */ + *amt = putentries (contents, contents_len, nentries, *data, datacnt); + + return 0; +} + +/* The user must define this function. Lookup NAME in DIR (which is + locked) for USER; set *NP to the found name upon return. If the + name was not found, then return ENOENT. On any error, clear *NP. + (*NP, if found, should be locked and a reference to it generated. + This call should unlock DIR no matter what.) */ +error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, + char *name, struct node **np) +{ + error_t err; + + err = procfs_lookup (dir, name, np); + if (! err) + mutex_lock (&(*np)->lock); + + mutex_unlock (&dir->lock); + return err; +} + +/* The user must define this function. Node NP has no more references; + free all its associated storage. */ +void netfs_node_norefs (struct node *np) +{ + procfs_cleanup (np); + free (np); +} + + +/* Libnetfs callbacks managed with libfshelp. */ + +/* The user must define this function. Locked node NP is being opened + by USER, with FLAGS. NEWNODE is nonzero if we just created this + node. Return an error if we should not permit the open to complete + because of a permission restriction. */ +error_t netfs_check_open_permissions (struct iouser *user, struct node *np, + int flags, int newnode) +{ + error_t err = 0; + if (!err && (flags & O_READ)) + err = fshelp_access (&np->nn_stat, S_IREAD, user); + if (!err && (flags & O_WRITE)) + err = fshelp_access (&np->nn_stat, S_IWRITE, user); + if (!err && (flags & O_EXEC)) + err = fshelp_access (&np->nn_stat, S_IEXEC, user); + return err; +} + +/* The user must define this function. Return the valid access + types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for + locked file NP and user CRED. */ +error_t netfs_report_access (struct iouser *cred, struct node *np, + int *types) +{ + *types = 0; + if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + return 0; +} + + +/* Trivial or unsupported libnetfs callbacks. */ + +/* The user must define this function. Make sure that NP->nn_stat is + filled with the most current information. CRED identifies the user + responsible for the operation. NP is locked. */ +error_t netfs_validate_stat (struct node *np, struct iouser *cred) +{ + return 0; +} + +/* The user must define this function. This should attempt a chmod + call for the user specified by CRED on locked node NP, to change + the owner to UID and the group to GID. */ +error_t netfs_attempt_chown (struct iouser *cred, struct node *np, + uid_t uid, uid_t gid) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a chauthor + call for the user specified by CRED on locked node NP, thereby + changing the author to AUTHOR. */ +error_t netfs_attempt_chauthor (struct iouser *cred, struct node *np, + uid_t author) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a chmod + call for the user specified by CRED on locked node NODE, to change + the mode to MODE. Unlike the normal Unix and Hurd meaning of + chmod, this function is also used to attempt to change files into + other types. If such a transition is attempted which is + impossible, then return EOPNOTSUPP. */ +error_t netfs_attempt_chmod (struct iouser *cred, struct node *np, + mode_t mode) +{ + return EROFS; +} + +/* The user must define this function. Attempt to turn locked node NP + (user CRED) into a symlink with target NAME. */ +error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *np, + char *name) +{ + return EROFS; +} + +/* The user must define this function. Attempt to turn NODE (user + CRED) into a device. TYPE is either S_IFBLK or S_IFCHR. NP is + locked. */ +error_t netfs_attempt_mkdev (struct iouser *cred, struct node *np, + mode_t type, dev_t indexes) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a chflags + call for the user specified by CRED on locked node NP, to change + the flags to FLAGS. */ +error_t netfs_attempt_chflags (struct iouser *cred, struct node *np, + int flags) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a utimes + call for the user specified by CRED on locked node NP, to change + the atime to ATIME and the mtime to MTIME. If ATIME or MTIME is + null, then set to the current time. */ +error_t netfs_attempt_utimes (struct iouser *cred, struct node *np, + struct timespec *atime, struct timespec *mtime) +{ + return EROFS; +} + +/* The user must define this function. This should attempt to set the + size of the locked file NP (for user CRED) to SIZE bytes long. */ +error_t netfs_attempt_set_size (struct iouser *cred, struct node *np, + loff_t size) +{ + return EROFS; +} + +/* The user must define this function. This should attempt to fetch + filesystem status information for the remote filesystem, for the + user CRED. NP is locked. */ +error_t netfs_attempt_statfs (struct iouser *cred, struct node *np, + fsys_statfsbuf_t *st) +{ + return ENOSYS; +} + +/* The user must define this function. This should sync the locked + file NP completely to disk, for the user CRED. If WAIT is set, + return only after the sync is completely finished. */ +error_t netfs_attempt_sync (struct iouser *cred, struct node *np, + int wait) +{ + return 0; +} + +/* The user must define this function. This should sync the entire + remote filesystem. If WAIT is set, return only after the sync is + completely finished. */ +error_t netfs_attempt_syncfs (struct iouser *cred, int wait) +{ + return 0; +} + +/* The user must define this function. Delete NAME in DIR (which is + locked) for USER. */ +error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, + char *name) +{ + return EROFS; +} + +/* The user must define this function. Attempt to rename the + directory FROMDIR to TODIR. Note that neither of the specific nodes + are locked. */ +error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, + char *fromname, struct node *todir, + char *toname, int excl) +{ + return EROFS; +} + +/* The user must define this function. Attempt to create a new + directory named NAME in DIR (which is locked) for USER with mode + MODE. */ +error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, + char *name, mode_t mode) +{ + return EROFS; +} + +/* The user must define this function. Attempt to remove directory + named NAME in DIR (which is locked) for USER. */ +error_t netfs_attempt_rmdir (struct iouser *user, + struct node *dir, char *name) +{ + return EROFS; +} + + +/* The user must define this function. Create a link in DIR with name + NAME to FILE for USER. Note that neither DIR nor FILE are + locked. If EXCL is set, do not delete the target. Return EEXIST if + NAME is already found in DIR. */ +error_t netfs_attempt_link (struct iouser *user, struct node *dir, + struct node *file, char *name, int excl) +{ + return EROFS; +} + +/* The user must define this function. Attempt to create an anonymous + file related to DIR (which is locked) for USER with MODE. Set *NP + to the returned file upon success. No matter what, unlock DIR. */ +error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, + mode_t mode, struct node **np) +{ + return EROFS; +} + +/* The user must define this function. Attempt to create a file named + NAME in DIR (which is locked) for USER with MODE. Set *NP to the + new node upon return. On any error, clear *NP. *NP should be + locked on success; no matter what, unlock DIR before returning. */ +error_t netfs_attempt_create_file (struct iouser *user, struct node *dir, + char *name, mode_t mode, struct node **np) +{ + return EROFS; +} + +/* The user must define this function. Write to the locked file NP + for user CRED starting at OFSET and continuing for up to *LEN bytes + from DATA. Set *LEN to the amount successfully written upon + return. */ +error_t netfs_attempt_write (struct iouser *cred, struct node *np, + loff_t offset, size_t *len, void *data) +{ + return EROFS; +} + + diff --git a/procfs.c b/procfs.c new file mode 100644 index 00000000..304befba --- /dev/null +++ b/procfs.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include "procfs.h" + +struct netnode +{ + const struct procfs_node_ops *ops; + void *hook; + + /* (cached) contents of the node */ + void *contents; + size_t contents_len; +}; + +struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) +{ + struct netnode *nn; + struct node *np; + + nn = malloc (sizeof *nn); + if (! nn) + return NULL; + + memset (nn, 0, sizeof *nn); + nn->ops = ops; + nn->hook = hook; + + np = netfs_make_node (nn); + if (! np) + { + free (nn); + return NULL; + } + + np->nn = nn; + memset (&np->nn_stat, 0, sizeof np->nn_stat); + np->nn_translated = 0; + + if (np->nn->ops->lookup) + np->nn_stat.st_mode = S_IFDIR | 0555; + else + np->nn_stat.st_mode = S_IFREG | 0444; + + return np; +} + +error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) +{ + if (! np->nn->contents && np->nn->ops->get_contents) + { + void *contents; + size_t contents_len; + error_t err; + + err = np->nn->ops->get_contents (np->nn->hook, &contents, &contents_len); + if (err) + return err; + + np->nn->contents = contents; + np->nn->contents_len = contents_len; + } + + *data = np->nn->contents; + *data_len = np->nn->contents_len; + return 0; +} + +error_t procfs_lookup (struct node *np, const char *name, struct node **npp) +{ + error_t err = ENOENT; + + if (np->nn->ops->lookup) + err = np->nn->ops->lookup (np->nn->hook, name, npp); + + return err; +} + +void procfs_cleanup (struct node *np) +{ + if (np->nn->contents && np->nn->ops->cleanup_contents) + np->nn->ops->cleanup_contents (np->nn->contents); + + if (np->nn->ops->cleanup) + np->nn->ops->cleanup (np->nn->hook); + + free (np->nn); +} diff --git a/procfs.h b/procfs.h new file mode 100644 index 00000000..0557b6d1 --- /dev/null +++ b/procfs.h @@ -0,0 +1,40 @@ +#include +#include + + +/* Interface for the procfs side. */ + +/* Any of these callback functions can be omitted, in which case + reasonable defaults will be used. The initial file mode and type + depend on whether a lookup function is provided, but can be + overridden in update_stat(). */ +struct procfs_node_ops +{ + /* Fetch the contents of a node. A pointer to the contents should be + returned in *CONTENTS and their length in *CONTENTS_LEN. The exact + nature of these data depends on whether the node is a regular file, + symlink or directory, as determined by the file mode in + netnode->nn_stat. For regular files and symlinks, they are what + you would expect; for directories, they are an argz vector of the + names of the entries. */ + error_t (*get_contents) (void *hook, void **contents, size_t *contents_len); + void (*cleanup_contents) (void *contents); + + /* Lookup NAME in this directory, and store the result in *np. The + returned node should be created by lookup() using procfs_make_node() + or a derived function. */ + error_t (*lookup) (void *hook, const char *name, struct node **np); + + /* Destroy this node. */ + void (*cleanup) (void *hook); +}; + +struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); + + +/* Interface for the libnetfs side. */ + +error_t procfs_get_contents (struct node *np, void **data, size_t *data_len); +error_t procfs_lookup (struct node *np, const char *name, struct node **npp); +void procfs_cleanup (struct node *np); + -- cgit v1.2.3 From faf709e3898de748f4c7ea02110010b018a995a6 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 10:10:22 +0000 Subject: Add a helper module for simple regular files * procfs_file.h: New file, declares procfs_file_make_node. * procfs_file.c: New file, implements procfs_file_make_node. * main.c: Use them. * Makefile: Add the procfs_file module. --- main.c | 13 ++----------- procfs_file.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ procfs_file.h | 6 ++++++ 3 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 procfs_file.c create mode 100644 procfs_file.h diff --git a/main.c b/main.c index cafd0c9a..457cf6a7 100644 --- a/main.c +++ b/main.c @@ -3,14 +3,7 @@ #include #include #include "procfs.h" - -static error_t get_contents (void *hook, void **contents, size_t *contents_len) -{ - static const char hello[] = "Hello, World!\n"; - *contents = (void *) hello; - *contents_len = sizeof hello - 1; - return 0; -} +#include "procfs_file.h" static error_t get_entries (void *hook, void **contents, size_t *contents_len) { @@ -22,12 +15,10 @@ static error_t get_entries (void *hook, void **contents, size_t *contents_len) static error_t lookup (void *hook, const char *name, struct node **np) { - static const struct procfs_node_ops ops = { .get_contents = get_contents }; - if (strcmp (name, "hello")) return ENOENT; - *np = procfs_make_node (&ops, NULL); + *np = procfs_file_make_node ("Hello, World!\n", -1, NULL); if (! *np) return ENOMEM; diff --git a/procfs_file.c b/procfs_file.c new file mode 100644 index 00000000..62419ee5 --- /dev/null +++ b/procfs_file.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include "procfs.h" +#include "procfs_file.h" + +struct procfs_file +{ + void *contents; + size_t len; + void (*cleanup)(void *contents); +}; + +error_t +procfs_file_getcontents (void *hook, void **contents, size_t *contents_len) +{ + struct procfs_file *f = hook; + + *contents = f->contents; + *contents_len = f->len; + return 0; +} + +void +procfs_file_cleanup (void *hook) +{ + struct procfs_file *f = hook; + + if (f->cleanup) + f->cleanup (f->contents); + + free (f); +} + +struct node * +procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)) +{ + static const struct procfs_node_ops ops = { + .get_contents = procfs_file_getcontents, + .cleanup = procfs_file_cleanup, + }; + struct procfs_file *f; + struct node *np; + + f = malloc (sizeof *f); + if (! f) + return NULL; + + f->contents = contents; + f->len = (len >= 0) ? len : strlen (f->contents); + f->cleanup = cleanup; + + np = procfs_make_node (&ops, f); + if (! np) + free (f); + + return np; +} + diff --git a/procfs_file.h b/procfs_file.h new file mode 100644 index 00000000..b615db93 --- /dev/null +++ b/procfs_file.h @@ -0,0 +1,6 @@ +/* Create a new regular file with the given CONTENTS. If LEN is negative, + CONTENTS is considered as a string and the file stops at the first + nul char. If CLEANUP is non-NULL, it is passed CONTENTS when the + node is destroyed. */ +struct node * +procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)); -- cgit v1.2.3 From e4f03466e3a31a8929e974ded8e6f6f451b3980a Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 10:26:12 +0000 Subject: Implement simple directories * procfs_dir.h: New file; declare the procfs_dir_make_node function, based on the procfs_dir_entry structure. * procfs_dir.c: New file; implement simple directories. * Makefile: Add the procfs_dir module. * main.c: Use it. --- main.c | 29 ++++++---------------- procfs_dir.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ procfs_dir.h | 15 ++++++++++++ 3 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 procfs_dir.c create mode 100644 procfs_dir.h diff --git a/main.c b/main.c index 457cf6a7..62e440d4 100644 --- a/main.c +++ b/main.c @@ -4,32 +4,19 @@ #include #include "procfs.h" #include "procfs_file.h" +#include "procfs_dir.h" -static error_t get_entries (void *hook, void **contents, size_t *contents_len) +static struct node *make_file (void *dir_hook, void *ent_hook) { - static const char entries[] = "hello"; - *contents = (void *) entries; - *contents_len = sizeof entries; - return 0; -} - -static error_t lookup (void *hook, const char *name, struct node **np) -{ - if (strcmp (name, "hello")) - return ENOENT; - - *np = procfs_file_make_node ("Hello, World!\n", -1, NULL); - if (! *np) - return ENOMEM; - - return 0; + return procfs_file_make_node (ent_hook, -1, NULL); } int main (int argc, char **argv) { - static const struct procfs_node_ops ops = { - .get_contents = get_entries, - .lookup = lookup, + static const struct procfs_dir_entry entries[] = { + { "hello", make_file, "Hello, World!\n" }, + { "goodbye", make_file, "Goodbye, cruel World!\n" }, + { } }; mach_port_t bootstrap; @@ -40,7 +27,7 @@ int main (int argc, char **argv) error (1, 0, "Must be started as a translator"); netfs_init (); - netfs_root_node = procfs_make_node (&ops, NULL); + netfs_root_node = procfs_dir_make_node (entries, NULL); netfs_startup (bootstrap, 0); for (;;) diff --git a/procfs_dir.c b/procfs_dir.c new file mode 100644 index 00000000..4d4faa28 --- /dev/null +++ b/procfs_dir.c @@ -0,0 +1,79 @@ +#include +#include +#include "procfs.h" +#include "procfs_dir.h" + +struct procfs_dir_node +{ + const struct procfs_dir_entry *entries; + void *hook; +}; + +static error_t +procfs_dir_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct procfs_dir_node *dn = hook; + const struct procfs_dir_entry *ent; + char *pos; + + *contents_len = 0; + for (ent = dn->entries; ent->name; ent++) + *contents_len += strlen (ent->name) + 1; + + *contents = malloc (*contents_len); + if (! *contents) + return ENOMEM; + + pos = *contents; + for (ent = dn->entries; ent->name; ent++) + { + strcpy (pos, ent->name); + pos += strlen (ent->name) + 1; + } + + return 0; +} + +static error_t +procfs_dir_lookup (void *hook, const char *name, struct node **np) +{ + struct procfs_dir_node *dn = hook; + const struct procfs_dir_entry *ent; + + for (ent = dn->entries; ent->name && strcmp (name, ent->name); ent++); + if (! ent->name) + return ENOENT; + + *np = ent->make_node (dn->hook, ent->hook); + if (! *np) + return ENOMEM; + + return 0; +} + +struct node * +procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook) +{ + static const struct procfs_node_ops ops = { + .get_contents = procfs_dir_get_contents, + .lookup = procfs_dir_lookup, + .cleanup_contents = free, + .cleanup = free, + }; + struct procfs_dir_node *dn; + struct node *np; + + dn = malloc (sizeof *dn); + if (! dn) + return NULL; + + dn->entries = entries; + dn->hook = dir_hook; + + np = procfs_make_node (&ops, dn); + if (! np) + free (dn); + + return np; +} + diff --git a/procfs_dir.h b/procfs_dir.h new file mode 100644 index 00000000..1ba45ad0 --- /dev/null +++ b/procfs_dir.h @@ -0,0 +1,15 @@ + +/* Each entry associates a name with a callback function for creating new + nodes corresponding to that entry. */ +struct procfs_dir_entry +{ + const char *name; + struct node *(*make_node)(void *dir_hook, void *entry_hook); + void *hook; +}; + +/* A simple directory is built from a table of entries. The table is + terminated by a null NAME pointer. */ +struct node * +procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook); + -- cgit v1.2.3 From 1db5f258c1ce92d92aa1589762865d96cbb20971 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 12:49:33 +0000 Subject: Add the list of processes as a directory * proclist.h, proclist.c: New files. * main.c: Add a proclist directory based on them. * Makefile: Include the proclist module. --- main.c | 8 +++++++ proclist.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ proclist.h | 2 ++ 3 files changed, 91 insertions(+) create mode 100644 proclist.c create mode 100644 proclist.h diff --git a/main.c b/main.c index 62e440d4..bc5c865c 100644 --- a/main.c +++ b/main.c @@ -1,21 +1,29 @@ #include +#include #include #include #include #include "procfs.h" #include "procfs_file.h" #include "procfs_dir.h" +#include "proclist.h" static struct node *make_file (void *dir_hook, void *ent_hook) { return procfs_file_make_node (ent_hook, -1, NULL); } +static struct node *make_proclist (void *dir_hook, void *ent_hook) +{ + return proclist_make_node (getproc ()); +} + int main (int argc, char **argv) { static const struct procfs_dir_entry entries[] = { { "hello", make_file, "Hello, World!\n" }, { "goodbye", make_file, "Goodbye, cruel World!\n" }, + { "proclist", make_proclist, }, { } }; mach_port_t bootstrap; diff --git a/proclist.c b/proclist.c new file mode 100644 index 00000000..4dd6ab31 --- /dev/null +++ b/proclist.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include "procfs.h" +#include "procfs_file.h" +#include "procfs_dir.h" + +#define PID_STR_SIZE (3 * sizeof (pid_t) + 1) + +struct proclist_node +{ + process_t process; +}; + +static error_t +proclist_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct proclist_node *pl = hook; + pidarray_t pids; + mach_msg_type_number_t num_pids; + error_t err; + int i; + + num_pids = 0; + err = proc_getallpids (pl->process, &pids, &num_pids); + if (err) + return EIO; + + *contents = malloc (num_pids * PID_STR_SIZE); + if (*contents) + { + *contents_len = 0; + for (i=0; i < num_pids; i++) + { + int n = sprintf (*contents + *contents_len, "%d", pids[i]); + assert (n >= 0); + *contents_len += (n + 1); + } + } + else + err = ENOMEM; + + vm_deallocate (mach_task_self (), (vm_address_t) pids, num_pids * sizeof pids[0]); + return err; +} + +static error_t +proclist_lookup (void *hook, const char *name, struct node **np) +{ + *np = procfs_file_make_node ("Ceci n'est pas un processus\n", -1, NULL); + return *np ? 0 : ENOMEM; +} + +struct node * +proclist_make_node (process_t process) +{ + static const struct procfs_node_ops ops = { + .get_contents = proclist_get_contents, + .lookup = proclist_lookup, + .cleanup_contents = free, + .cleanup = free, + }; + struct proclist_node *pl; + struct node *np; + + pl = malloc (sizeof *pl); + if (! pl) + return NULL; + + memset (pl, 0, sizeof *pl); + pl->process = process; + + np = procfs_make_node (&ops, pl); + if (! np) + free (pl); + + return np; +} + diff --git a/proclist.h b/proclist.h new file mode 100644 index 00000000..a766d50e --- /dev/null +++ b/proclist.h @@ -0,0 +1,2 @@ +#include +struct node *proclist_make_node (process_t process); -- cgit v1.2.3 From ef3adf6d159d566d83335cfe55a72206d492d838 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 16:48:55 +0000 Subject: Fix the failure semantics of procfs_make_node * procfs.c (procfs_make_node): Invoke the cleanup callback on failure, so that callers don't have to. * procfs.h: Document the change. * procfs_dir.c (procfs_dir_make_node), procfs_file.c (procfs_file_make_node), proclist.c (proclist_make_node): Update to reflect the change. --- procfs.c | 14 +++++++++----- procfs.h | 2 ++ procfs_dir.c | 7 +------ procfs_file.c | 7 +------ proclist.c | 7 +------ 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/procfs.c b/procfs.c index 304befba..0c57686b 100644 --- a/procfs.c +++ b/procfs.c @@ -22,7 +22,7 @@ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) nn = malloc (sizeof *nn); if (! nn) - return NULL; + goto fail; memset (nn, 0, sizeof *nn); nn->ops = ops; @@ -30,10 +30,7 @@ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) np = netfs_make_node (nn); if (! np) - { - free (nn); - return NULL; - } + goto fail; np->nn = nn; memset (&np->nn_stat, 0, sizeof np->nn_stat); @@ -45,6 +42,13 @@ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) np->nn_stat.st_mode = S_IFREG | 0444; return np; + +fail: + if (ops->cleanup) + ops->cleanup (hook); + + free (nn); + return NULL; } error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) diff --git a/procfs.h b/procfs.h index 0557b6d1..21b0f93d 100644 --- a/procfs.h +++ b/procfs.h @@ -29,6 +29,8 @@ struct procfs_node_ops void (*cleanup) (void *hook); }; +/* Create a new node and return it. Returns NULL if it fails to allocate + enough memory. In this case, ops->cleanup will be invoked. */ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); diff --git a/procfs_dir.c b/procfs_dir.c index 4d4faa28..62a45b1b 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -61,7 +61,6 @@ procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook) .cleanup = free, }; struct procfs_dir_node *dn; - struct node *np; dn = malloc (sizeof *dn); if (! dn) @@ -70,10 +69,6 @@ procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook) dn->entries = entries; dn->hook = dir_hook; - np = procfs_make_node (&ops, dn); - if (! np) - free (dn); - - return np; + return procfs_make_node (&ops, dn); } diff --git a/procfs_file.c b/procfs_file.c index 62419ee5..cb0488e9 100644 --- a/procfs_file.c +++ b/procfs_file.c @@ -40,7 +40,6 @@ procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)) .cleanup = procfs_file_cleanup, }; struct procfs_file *f; - struct node *np; f = malloc (sizeof *f); if (! f) @@ -50,10 +49,6 @@ procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)) f->len = (len >= 0) ? len : strlen (f->contents); f->cleanup = cleanup; - np = procfs_make_node (&ops, f); - if (! np) - free (f); - - return np; + return procfs_make_node (&ops, f); } diff --git a/proclist.c b/proclist.c index 4dd6ab31..16cef9d6 100644 --- a/proclist.c +++ b/proclist.c @@ -63,7 +63,6 @@ proclist_make_node (process_t process) .cleanup = free, }; struct proclist_node *pl; - struct node *np; pl = malloc (sizeof *pl); if (! pl) @@ -72,10 +71,6 @@ proclist_make_node (process_t process) memset (pl, 0, sizeof *pl); pl->process = process; - np = procfs_make_node (&ops, pl); - if (! np) - free (pl); - - return np; + return procfs_make_node (&ops, pl); } -- cgit v1.2.3 From 09b121d42e9ba25e103b103bf1f53e1350e084a1 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 17:27:54 +0000 Subject: More cleanup possibilities * procfs.c, procfs.h: Extend the signature of the cleanup_contents callback in the procfs_node_ops structure to include the hook and contents_len. (cleanup_contents_with_free, cleanup_contents_with_vm_deallocate): New functions, can be used as a cleanup_contents callback for simple cases. * procfs_dir.c, procfs_dir.h (procfs_dir_make_node): Update, add a cleanup callback, make sure the cleanup callback is invoked if there is an error. * proclist.c (proclist_make_node), main.c (main): Update to match the new interfaces. --- main.c | 2 +- procfs.c | 15 ++++++++++++++- procfs.h | 6 +++++- procfs_dir.c | 27 +++++++++++++++++++++++---- procfs_dir.h | 9 +++++++-- proclist.c | 2 +- 6 files changed, 51 insertions(+), 10 deletions(-) diff --git a/main.c b/main.c index bc5c865c..4350eff5 100644 --- a/main.c +++ b/main.c @@ -35,7 +35,7 @@ int main (int argc, char **argv) error (1, 0, "Must be started as a translator"); netfs_init (); - netfs_root_node = procfs_dir_make_node (entries, NULL); + netfs_root_node = procfs_dir_make_node (entries, NULL, NULL); netfs_startup (bootstrap, 0); for (;;) diff --git a/procfs.c b/procfs.c index 0c57686b..755e0519 100644 --- a/procfs.c +++ b/procfs.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include "procfs.h" @@ -15,6 +16,18 @@ struct netnode size_t contents_len; }; +void +procfs_cleanup_contents_with_free (void *hook, void *cont, size_t len) +{ + free (cont); +} + +void +procfs_cleanup_contents_with_vm_deallocate (void *hook, void *cont, size_t len) +{ + vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); +} + struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) { struct netnode *nn; @@ -85,7 +98,7 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp) void procfs_cleanup (struct node *np) { if (np->nn->contents && np->nn->ops->cleanup_contents) - np->nn->ops->cleanup_contents (np->nn->contents); + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); if (np->nn->ops->cleanup) np->nn->ops->cleanup (np->nn->hook); diff --git a/procfs.h b/procfs.h index 21b0f93d..3cb3223d 100644 --- a/procfs.h +++ b/procfs.h @@ -18,7 +18,7 @@ struct procfs_node_ops you would expect; for directories, they are an argz vector of the names of the entries. */ error_t (*get_contents) (void *hook, void **contents, size_t *contents_len); - void (*cleanup_contents) (void *contents); + void (*cleanup_contents) (void *hook, void *contents, size_t contents_len); /* Lookup NAME in this directory, and store the result in *np. The returned node should be created by lookup() using procfs_make_node() @@ -29,6 +29,10 @@ struct procfs_node_ops void (*cleanup) (void *hook); }; +/* These helper functions can be used as procfs_node_ops.cleanup_contents. */ +void procfs_cleanup_contents_with_free (void *, void *, size_t); +void procfs_cleanup_contents_with_vm_deallocate (void *, void *, size_t); + /* Create a new node and return it. Returns NULL if it fails to allocate enough memory. In this case, ops->cleanup will be invoked. */ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); diff --git a/procfs_dir.c b/procfs_dir.c index 62a45b1b..b7fb28fa 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -7,6 +7,7 @@ struct procfs_dir_node { const struct procfs_dir_entry *entries; void *hook; + void (*cleanup) (void *hook); }; static error_t @@ -51,23 +52,41 @@ procfs_dir_lookup (void *hook, const char *name, struct node **np) return 0; } +static void +procfs_dir_cleanup (void *hook) +{ + struct procfs_dir_node *dn = hook; + + if (dn->cleanup) + dn->cleanup (dn->hook); + + free (dn); +} + struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook) +procfs_dir_make_node (const struct procfs_dir_entry *entries, + void *dir_hook, void (*cleanup) (void *dir_hook)) { static const struct procfs_node_ops ops = { .get_contents = procfs_dir_get_contents, .lookup = procfs_dir_lookup, - .cleanup_contents = free, - .cleanup = free, + .cleanup_contents = procfs_cleanup_contents_with_free, + .cleanup = procfs_dir_cleanup, }; struct procfs_dir_node *dn; dn = malloc (sizeof *dn); if (! dn) - return NULL; + { + if (cleanup) + cleanup (dir_hook); + + return NULL; + } dn->entries = entries; dn->hook = dir_hook; + dn->cleanup = cleanup; return procfs_make_node (&ops, dn); } diff --git a/procfs_dir.h b/procfs_dir.h index 1ba45ad0..4eb934e0 100644 --- a/procfs_dir.h +++ b/procfs_dir.h @@ -9,7 +9,12 @@ struct procfs_dir_entry }; /* A simple directory is built from a table of entries. The table is - terminated by a null NAME pointer. */ + terminated by a null NAME pointer. The DIR_HOOK is passed the + MAKE_NODE callback function of looked up procfs_dir_entries, and to + the provided CLEANUP function when the directory is destroyed. + Returns the new directory node. If not enough memory can be + allocated, CLEANUP is invoked immediately and NULL is returned. */ struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, void *dir_hook); +procfs_dir_make_node (const struct procfs_dir_entry *entries, + void *dir_hook, void (*cleanup) (void *dir_hook)); diff --git a/proclist.c b/proclist.c index 16cef9d6..e009ebdd 100644 --- a/proclist.c +++ b/proclist.c @@ -59,7 +59,7 @@ proclist_make_node (process_t process) static const struct procfs_node_ops ops = { .get_contents = proclist_get_contents, .lookup = proclist_lookup, - .cleanup_contents = free, + .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = free, }; struct proclist_node *pl; -- cgit v1.2.3 From 931c02a6bd8197b0b6334622795984463c05200b Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 20:34:58 +0000 Subject: Add real process nodes * process.c, process.h: New files, implement a process directory with cmdline and environ files. * Makefile: Add the process module. * proclist.c: Replace stub pid files with the real thing. --- process.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ process.h | 2 ++ proclist.c | 13 ++++++++--- 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 process.c create mode 100644 process.h diff --git a/process.c b/process.c new file mode 100644 index 00000000..90ea511b --- /dev/null +++ b/process.c @@ -0,0 +1,79 @@ +#include +#include +#include "procfs.h" +#include "procfs_dir.h" +#include "process.h" + +struct process_node { + process_t procserv; + pid_t pid; +}; + + +/* The proc_getprocargs() and proc_getprocenv() calls have the same + prototype and we use them in the same way; namely, publish the data + they return as-is. We take advantage of this to have common code and + use a function pointer as the procfs_dir "entry hook" to choose the + call to use on a file by file basis. */ + +struct process_argz_node +{ + struct process_node pn; + error_t (*getargz) (process_t, pid_t, void **, mach_msg_type_number_t *); +}; + +static error_t +process_argz_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct process_argz_node *pz = hook; + error_t err; + + *contents_len = 0; + err = pz->getargz (pz->pn.procserv, pz->pn.pid, contents, contents_len); + if (err) + return EIO; + + return 0; +} + +static struct node * +process_argz_make_node (void *dir_hook, void *entry_hook) +{ + static const struct procfs_node_ops ops = { + .get_contents = process_argz_get_contents, + .cleanup_contents = procfs_cleanup_contents_with_vm_deallocate, + .cleanup = free, + }; + struct process_argz_node *zn; + + zn = malloc (sizeof *zn); + if (! zn) + return NULL; + + memcpy (&zn->pn, dir_hook, sizeof zn->pn); + zn->getargz = entry_hook; + + return procfs_make_node (&ops, zn); +} + + +struct node * +process_make_node (process_t procserv, pid_t pid) +{ + static const struct procfs_dir_entry entries[] = { + { "cmdline", process_argz_make_node, proc_getprocargs, }, + { "environ", process_argz_make_node, proc_getprocenv, }, + { NULL, } + }; + struct process_node *pn; + + pn = malloc (sizeof *pn); + if (! pn) + return NULL; + + pn->procserv = procserv; + pn->pid = pid; + + return procfs_dir_make_node (entries, pn, free); +} + diff --git a/process.h b/process.h new file mode 100644 index 00000000..8ca7c851 --- /dev/null +++ b/process.h @@ -0,0 +1,2 @@ +struct node * +process_make_node (process_t procserv, pid_t pid); diff --git a/proclist.c b/proclist.c index e009ebdd..148e4bc3 100644 --- a/proclist.c +++ b/proclist.c @@ -4,8 +4,7 @@ #include #include #include "procfs.h" -#include "procfs_file.h" -#include "procfs_dir.h" +#include "process.h" #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) @@ -49,7 +48,15 @@ proclist_get_contents (void *hook, void **contents, size_t *contents_len) static error_t proclist_lookup (void *hook, const char *name, struct node **np) { - *np = procfs_file_make_node ("Ceci n'est pas un processus\n", -1, NULL); + struct proclist_node *pl = hook; + char *endp; + pid_t pid; + + pid = strtol (name, &endp, 10); + if (name[0] == '0' || !name[0] || *endp) + return ENOENT; + + *np = process_make_node (pl->process, pid); return *np ? 0 : ENOMEM; } -- cgit v1.2.3 From 85feec46e7d8884a9a34276c7cad8133c5fbb02e Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Tue, 17 Aug 2010 22:20:32 +0000 Subject: Fetch process information and reject the non-existing ones * process.c, process.h (process_make_node): Make static, include a procinfo structure into the node information. (process_lookup_pid): New function, replaces process_make_node as the outer interface, returns an error for non-existing processes. * proclist.c (proclist_lookup): Convert to the new interface. --- process.c | 34 +++++++++++++++++++++++++++++++--- process.h | 10 ++++++++-- proclist.c | 12 +++++++++--- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/process.c b/process.c index 90ea511b..612ed493 100644 --- a/process.c +++ b/process.c @@ -7,6 +7,7 @@ struct process_node { process_t procserv; pid_t pid; + struct procinfo info; }; @@ -57,8 +58,8 @@ process_argz_make_node (void *dir_hook, void *entry_hook) } -struct node * -process_make_node (process_t procserv, pid_t pid) +static struct node * +process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) { static const struct procfs_dir_entry entries[] = { { "cmdline", process_argz_make_node, proc_getprocargs, }, @@ -73,7 +74,34 @@ process_make_node (process_t procserv, pid_t pid) pn->procserv = procserv; pn->pid = pid; + memcpy (&pn->info, info, sizeof pn->info); - return procfs_dir_make_node (entries, pn, free); + return procfs_dir_make_node (entries, pn, process_cleanup); } +error_t +process_lookup_pid (process_t procserv, pid_t pid, struct node **np) +{ + procinfo_t info; + size_t info_sz; + data_t tw; + size_t tw_sz; + int flags; + error_t err; + + tw_sz = info_sz = 0, flags = 0; + err = proc_getprocinfo (procserv, pid, &flags, &info, &info_sz, &tw, &tw_sz); + if (err == ESRCH) + return ENOENT; + if (err) + return EIO; + + assert (info_sz * sizeof *info >= sizeof (struct procinfo)); + *np = process_make_node (procserv, pid, (struct procinfo *) info); + vm_deallocate (mach_task_self (), (vm_address_t) info, info_sz); + + if (! *np) + return ENOMEM; + + return 0; +} diff --git a/process.h b/process.h index 8ca7c851..abdaaa3b 100644 --- a/process.h +++ b/process.h @@ -1,2 +1,8 @@ -struct node * -process_make_node (process_t procserv, pid_t pid); +#include + +/* Create a node for a directory representing information available at + the proc server PROC for the given PID. On success, returns the + newly created node in *NP. */ +error_t +process_lookup_pid (process_t proc, pid_t pid, struct node **np); + diff --git a/proclist.c b/proclist.c index 148e4bc3..75b61a2e 100644 --- a/proclist.c +++ b/proclist.c @@ -52,12 +52,18 @@ proclist_lookup (void *hook, const char *name, struct node **np) char *endp; pid_t pid; + /* Self-lookups should not end up here. */ + assert (name[0]); + + /* No leading zeros allowed */ + if (name[0] == '0' && name[1]) + return ENOENT; + pid = strtol (name, &endp, 10); - if (name[0] == '0' || !name[0] || *endp) + if (*endp) return ENOENT; - *np = process_make_node (pl->process, pid); - return *np ? 0 : ENOMEM; + return process_lookup_pid (pl->process, pid, np); } struct node * -- cgit v1.2.3 From f89f2ccd6f4dde2dc6c6ffabd0f784ecf2a46617 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 18 Aug 2010 20:44:54 +0000 Subject: Fuse the proclist into the root node * dircat.c, dircat.h: New files, merge directories. * Makefile: Add the dircat module. * main.c: Use dircat to merge the proclist into the root directory, instead of having it as a stand-alone one. * procfs.h, procfs.c: Add a "refresh hack" to have the contents of the root directory recreated on each request. * proclist.c (proclist_make_node): Enable the hack in question. --- dircat.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dircat.h | 9 ++++++ main.c | 41 +++++++++++++++++++------- procfs.c | 8 +++++ procfs.h | 8 +++++ proclist.c | 1 + 6 files changed, 156 insertions(+), 10 deletions(-) create mode 100644 dircat.c create mode 100644 dircat.h diff --git a/dircat.c b/dircat.c new file mode 100644 index 00000000..857ba72b --- /dev/null +++ b/dircat.c @@ -0,0 +1,99 @@ +#include +#include +#include "procfs.h" + +struct dircat_node +{ + struct node **dirs; +}; + +static error_t +dircat_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct dircat_node *dcn = hook; + int i, sz, pos; + error_t err; + + pos = 0; + *contents = malloc (sz = 512); + + for (i=0; dcn->dirs[i]; i++) + { + void *subcon; + size_t sublen; + + err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); + if (err) + { + free (*contents); + *contents = NULL; + return err; + } + + while (pos + sublen > sz) + *contents = realloc (*contents, sz *= 2); + + memcpy (*contents + pos, subcon, sublen); + pos += sublen; + } + + *contents_len = pos; + return 0; +} + +static error_t +dircat_lookup (void *hook, const char *name, struct node **np) +{ + struct dircat_node *dcn = hook; + error_t err; + int i; + + err = ENOENT; + for (i=0; err && dcn->dirs[i]; i++) + err = procfs_lookup (dcn->dirs[i], name, np); + + return err; +} + +static void +dircat_release_dirs (struct node **dirs) +{ + int i; + + for (i=0; dirs[i]; i++) + netfs_nrele (dirs[i]); +} + +static void +dircat_cleanup (void *hook) +{ + struct dircat_node *dcn = hook; + + dircat_release_dirs (dcn->dirs); + free (dcn); +} + +struct node * +dircat_make_node (struct node **dirs) +{ + static struct procfs_node_ops ops = { + .get_contents = dircat_get_contents, + .cleanup_contents = procfs_cleanup_contents_with_free, + .lookup = dircat_lookup, + .cleanup = dircat_cleanup, + /* necessary so that it propagates to proclist */ + .enable_refresh_hack_and_break_readdir = 1, + }; + struct dircat_node *dcn; + + dcn = malloc (sizeof *dcn); + if (! dcn) + { + dircat_release_dirs (dirs); + return NULL; + } + + dcn->dirs = dirs; + return procfs_make_node (&ops, dcn); +} + diff --git a/dircat.h b/dircat.h new file mode 100644 index 00000000..cb228526 --- /dev/null +++ b/dircat.h @@ -0,0 +1,9 @@ +/* Append the contents of multiple directories. DIRS is a + NULL-terminated array of directory nodes. One reference is consumed + for each of them, even on ENOMEM, in which case NULL is returned. + DIRS has to be static data for now, or at list remain available and + unchanged for the duration of the created node's life. Strange + things will happen if they have entries with the same name or if one + of them is not a directory. */ +struct node * +dircat_make_node (struct node **dirs); diff --git a/main.c b/main.c index 4350eff5..e08bbdb7 100644 --- a/main.c +++ b/main.c @@ -7,25 +7,46 @@ #include "procfs_file.h" #include "procfs_dir.h" #include "proclist.h" +#include "dircat.h" -static struct node *make_file (void *dir_hook, void *ent_hook) +static struct node * +make_file (void *dir_hook, void *ent_hook) { return procfs_file_make_node (ent_hook, -1, NULL); } -static struct node *make_proclist (void *dir_hook, void *ent_hook) +error_t +root_make_node (struct node **np) { - return proclist_make_node (getproc ()); + static const struct procfs_dir_entry static_entries[] = { + { "hello", make_file, "Hello, World!\n" }, + { "goodbye", make_file, "Goodbye, cruel World!\n" }, + }; + /* We never have two root nodes alive simultaneously, so it's ok to + have this as static data. */ + static struct node *root_dirs[3]; + + root_dirs[0] = procfs_dir_make_node (static_entries, NULL, NULL); + if (! root_dirs[0]) + return ENOMEM; + + root_dirs[1] = proclist_make_node (getproc ()); + if (! root_dirs[1]) + { + netfs_nrele (root_dirs[0]); + return ENOMEM; + } + + root_dirs[2] = NULL; + *np = dircat_make_node (root_dirs); + if (! *np) + return ENOMEM; + + return 0; } int main (int argc, char **argv) { - static const struct procfs_dir_entry entries[] = { - { "hello", make_file, "Hello, World!\n" }, - { "goodbye", make_file, "Goodbye, cruel World!\n" }, - { "proclist", make_proclist, }, - { } - }; mach_port_t bootstrap; argp_parse (&netfs_std_startup_argp, argc, argv, 0, 0, 0); @@ -35,7 +56,7 @@ int main (int argc, char **argv) error (1, 0, "Must be started as a translator"); netfs_init (); - netfs_root_node = procfs_dir_make_node (entries, NULL, NULL); + root_make_node (&netfs_root_node); netfs_startup (bootstrap, 0); for (;;) diff --git a/procfs.c b/procfs.c index 755e0519..573bb72f 100644 --- a/procfs.c +++ b/procfs.c @@ -66,6 +66,14 @@ fail: error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) { + if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) + { + if (np->nn->ops->cleanup_contents) + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, + np->nn->contents_len); + np->nn->contents = NULL; + } + if (! np->nn->contents && np->nn->ops->get_contents) { void *contents; diff --git a/procfs.h b/procfs.h index 3cb3223d..b44db6e3 100644 --- a/procfs.h +++ b/procfs.h @@ -27,6 +27,14 @@ struct procfs_node_ops /* Destroy this node. */ void (*cleanup) (void *hook); + + /* FIXME: This is needed because the root node is persistent, and we + want the list of processes to be updated. However, this means that + readdir() on the root node runs the risk of returning incoherent + results if done in multiple runs and processes are added/removed in + the meantime. The right way to fix this is probably to add a + getroot() user hook function to libnetfs. */ + int enable_refresh_hack_and_break_readdir; }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ diff --git a/proclist.c b/proclist.c index 75b61a2e..94a7a04d 100644 --- a/proclist.c +++ b/proclist.c @@ -74,6 +74,7 @@ proclist_make_node (process_t process) .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = free, + .enable_refresh_hack_and_break_readdir = 1, }; struct proclist_node *pl; -- cgit v1.2.3 From 89b154b710010b09d731d74dc94e4bc6ce795006 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 18 Aug 2010 21:06:08 +0000 Subject: Set the owner of process directories. * process.c (process_make_node): Use the owner_uid from the procinfo structure to set the owner of the created directory. --- process.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/process.c b/process.c index 612ed493..411f4c4a 100644 --- a/process.c +++ b/process.c @@ -67,6 +67,7 @@ process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) { NULL, } }; struct process_node *pn; + struct node *np; pn = malloc (sizeof *pn); if (! pn) @@ -76,7 +77,10 @@ process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) pn->pid = pid; memcpy (&pn->info, info, sizeof pn->info); - return procfs_dir_make_node (entries, pn, process_cleanup); + np = procfs_dir_make_node (entries, pn, process_cleanup); + np->nn_stat.st_uid = pn->info.owner; + + return np; } error_t -- cgit v1.2.3 From 1f9c094faa066aff3e02f00f997bfc37756cdd1f Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Thu, 19 Aug 2010 03:12:27 +0000 Subject: Add a basic [pid]/stat file * process.c: Add a basic stat file. --- process.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/process.c b/process.c index 411f4c4a..2b89ef81 100644 --- a/process.c +++ b/process.c @@ -1,3 +1,4 @@ +#include #include #include #include "procfs.h" @@ -57,6 +58,113 @@ process_argz_make_node (void *dir_hook, void *entry_hook) return procfs_make_node (&ops, zn); } +/* The other files don't need any information besides the data in struct + process_node. Furthermore, their contents don't have any nul byte. + Consequently, we use a simple "multiplexer" based on the information + below. */ + +struct process_file_node +{ + struct process_node pn; + error_t (*get_contents) (struct process_node *pn, char **contents); +}; + +static char mapstate (int hurd_state) +{ + return '?'; +} + +static error_t +process_file_gc_stat (struct process_node *pn, char **contents) +{ + char *argz; + size_t argz_len; + int len; + + argz = NULL, argz_len = 0; + proc_getprocargs(pn->procserv, pn->pid, &argz, &argz_len); + + len = asprintf (contents, + "%d (%s) %c " /* pid, command, state */ + "%d %d %d " /* ppid, pgid, session */ + "%d %d " /* controling tty stuff */ + "%u " /* flags, as defined by */ + "%lu %lu %lu %lu " /* page fault counts */ + "%lu %lu %ld %ld " /* user/sys times, in sysconf(_SC_CLK_TCK) */ + "%ld %ld " /* scheduler params (priority, nice) */ + "%ld %ld " /* number of threads, [obsolete] */ + "%llu " /* start time since boot (jiffies) */ + "%lu %ld %lu " /* virtual size, rss, rss limit */ + "%lu %lu %lu %lu %lu " /* some vm addresses (code, stack, sp, pc) */ + "%lu %lu %lu %lu " /* pending, blocked, ignored and caught sigs */ + "%lu " /* wait channel */ + "%lu %lu " /* swap usage (not maintained in Linux) */ + "%d " /* exit signal, to be sent to the parent */ + "%d " /* last processor used */ + "%u %u " /* RT priority and policy */ + "%llu " /* aggregated block I/O delay */ + "\n", + pn->pid, argz ?: "", mapstate (pn->info.state), + pn->info.ppid, pn->info.pgrp, pn->info.session, + 0, 0, + 0, + 0L, 0L, 0L, 0L, + 0L, 0L, 0L, 0L, + 0L, 0L, + 0L, 0L, + 0LL, + 0L, 0L, 0L, + 0L, 0L, 0L, 0L, 0L, + 0L, 0L, 0L, 0L, + 0L, + 0L, 0L, + 0, + 0, + 0, 0, + 0LL); + + vm_deallocate (mach_task_self (), (vm_address_t) argz, argz_len); + + if (len < 0) + return ENOMEM; + + return 0; +} + +static error_t +process_file_get_contents (void *hook, void **contents, size_t *contents_len) +{ + struct process_file_node *fn = hook; + error_t err; + + err = fn->get_contents (&fn->pn, (char **) contents); + if (err) + return err; + + *contents_len = strlen (*contents); + return 0; +} + +static struct node * +process_file_make_node (void *dir_hook, void *entry_hook) +{ + static const struct procfs_node_ops ops = { + .get_contents = process_file_get_contents, + .cleanup_contents = procfs_cleanup_contents_with_free, + .cleanup = free, + }; + struct process_file_node *fn; + + fn = malloc (sizeof *fn); + if (! fn) + return NULL; + + memcpy (&fn->pn, dir_hook, sizeof fn->pn); + fn->get_contents = entry_hook; + + return procfs_make_node (&ops, fn); +} + static struct node * process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) @@ -64,6 +172,7 @@ process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) static const struct procfs_dir_entry entries[] = { { "cmdline", process_argz_make_node, proc_getprocargs, }, { "environ", process_argz_make_node, proc_getprocenv, }, + { "stat", process_file_make_node, process_file_gc_stat, }, { NULL, } }; struct process_node *pn; -- cgit v1.2.3 From e9b239bbec8cae14a9a4d510bae7496d733e5812 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Thu, 19 Aug 2010 04:52:17 +0000 Subject: Add the dot entries to directories * procfs_dir.c (procfs_dir_get_contents): Prepend the . and .. entries to the ones from the given table. --- procfs_dir.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/procfs_dir.c b/procfs_dir.c index b7fb28fa..431fea3e 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -13,11 +13,12 @@ struct procfs_dir_node static error_t procfs_dir_get_contents (void *hook, void **contents, size_t *contents_len) { + static const char dot_dotdot[] = ".\0.."; struct procfs_dir_node *dn = hook; const struct procfs_dir_entry *ent; char *pos; - *contents_len = 0; + *contents_len = sizeof dot_dotdot; for (ent = dn->entries; ent->name; ent++) *contents_len += strlen (ent->name) + 1; @@ -25,7 +26,8 @@ procfs_dir_get_contents (void *hook, void **contents, size_t *contents_len) if (! *contents) return ENOMEM; - pos = *contents; + memcpy (*contents, dot_dotdot, sizeof dot_dotdot); + pos = *contents + sizeof dot_dotdot; for (ent = dn->entries; ent->name; ent++) { strcpy (pos, ent->name); -- cgit v1.2.3 From 87fbcc7a89559aa529eeb12472053ff869f66de9 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Thu, 19 Aug 2010 07:48:30 +0000 Subject: Implement lookup for . and .. * procfs.c (procfs_lookup): Keep track of the parent directory, implement the lookup of the dot-directories. (procfs_cleanup): Release the reference to the parent node, if applicable. * procfs.h: Add a comment about the parent reference. * netfs.c (netfs_attempt_lookup): Lock the looked up node after the directory has been unlocked, in case they are the same. --- netfs.c | 3 ++- procfs.c | 26 ++++++++++++++++++++++++-- procfs.h | 5 ++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/netfs.c b/netfs.c index 58665085..6b105f91 100644 --- a/netfs.c +++ b/netfs.c @@ -151,10 +151,11 @@ error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, error_t err; err = procfs_lookup (dir, name, np); + mutex_unlock (&dir->lock); + if (! err) mutex_lock (&(*np)->lock); - mutex_unlock (&dir->lock); return err; } diff --git a/procfs.c b/procfs.c index 573bb72f..c5f19497 100644 --- a/procfs.c +++ b/procfs.c @@ -14,6 +14,9 @@ struct netnode /* (cached) contents of the node */ void *contents; size_t contents_len; + + /* parent directory, if applicable */ + struct node *parent; }; void @@ -97,8 +100,24 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp) { error_t err = ENOENT; - if (np->nn->ops->lookup) - err = np->nn->ops->lookup (np->nn->hook, name, npp); + if (err && ! strcmp (name, ".")) + { + netfs_nref(*npp = np); + err = 0; + } + + if (err && np->nn->parent && ! strcmp (name, "..")) + { + netfs_nref(*npp = np->nn->parent); + err = 0; + } + + if (err && np->nn->ops->lookup) + { + err = np->nn->ops->lookup (np->nn->hook, name, npp); + if (! err) + netfs_nref ((*npp)->nn->parent = np); + } return err; } @@ -111,5 +130,8 @@ void procfs_cleanup (struct node *np) if (np->nn->ops->cleanup) np->nn->ops->cleanup (np->nn->hook); + if (np->nn->parent) + netfs_nrele (np->nn->parent); + free (np->nn); } diff --git a/procfs.h b/procfs.h index b44db6e3..42eed0e2 100644 --- a/procfs.h +++ b/procfs.h @@ -22,7 +22,10 @@ struct procfs_node_ops /* Lookup NAME in this directory, and store the result in *np. The returned node should be created by lookup() using procfs_make_node() - or a derived function. */ + or a derived function. Note that the parent will be kept alive as + long as the child exists, so you can safely reference the parent's + data from the child. You may want to consider locking if there's + any mutation going on, though. */ error_t (*lookup) (void *hook, const char *name, struct node **np); /* Destroy this node. */ -- cgit v1.2.3 From 5baed27bd3b7a7d20ecb77068546b158d131fc1c Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Thu, 19 Aug 2010 23:10:11 +0000 Subject: Invent path-based inode numbers * procfs.h, procfs.c (procfs_make_ino): New function, invents an inode number by hashing the parent's and the name of an entry. (procfs_lookup): Use it to assign an inode number to child nodes at lookup time. * main.c (root_make_node): Assign an arbitrary inode number to the root directory. --- main.c | 4 ++++ procfs.c | 28 +++++++++++++++++++++++++++- procfs.h | 5 +++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index e08bbdb7..15602819 100644 --- a/main.c +++ b/main.c @@ -42,6 +42,10 @@ root_make_node (struct node **np) if (! *np) return ENOMEM; + /* Since this one is not created through proc_lookup(), we have to affect an + inode number to it. */ + (*np)->nn_stat.st_ino = * (uint32_t *) "PROC"; + return 0; } diff --git a/procfs.c b/procfs.c index c5f19497..4cce46b9 100644 --- a/procfs.c +++ b/procfs.c @@ -67,6 +67,29 @@ fail: return NULL; } +/* FIXME: possibly not the fastest hash function... */ +ino64_t +procfs_make_ino (struct node *np, const char *filename) +{ + unsigned short x[3]; + + if (! strcmp (filename, ".")) + return np->nn_stat.st_ino; + if (! strcmp (filename, "..")) + return np->nn->parent ? np->nn->parent->nn_stat.st_ino : /* FIXME: */ 42; + + assert (sizeof np->nn_stat.st_ino > sizeof x); + memcpy (x, &np->nn_stat.st_ino, sizeof x); + + while (*filename) + { + x[0] ^= *(filename++); + jrand48 (x); + } + + return jrand48 (x); +} + error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) { if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) @@ -116,7 +139,10 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp) { err = np->nn->ops->lookup (np->nn->hook, name, npp); if (! err) - netfs_nref ((*npp)->nn->parent = np); + { + (*npp)->nn_stat.st_ino = procfs_make_ino (np, name); + netfs_nref ((*npp)->nn->parent = np); + } } return err; diff --git a/procfs.h b/procfs.h index 42eed0e2..4c9d828b 100644 --- a/procfs.h +++ b/procfs.h @@ -51,6 +51,11 @@ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); /* Interface for the libnetfs side. */ +/* Get the inode number which will be given to a child of NP named FILENAME. + This allows us to retreive them for readdir() without creating the + corresponding child nodes. */ +ino64_t procfs_make_ino (struct node *np, const char *filename); + error_t procfs_get_contents (struct node *np, void **data, size_t *data_len); error_t procfs_lookup (struct node *np, const char *name, struct node **npp); void procfs_cleanup (struct node *np); -- cgit v1.2.3 From 7eff83acaac2167ffdc7a297a0ed6a78354aa062 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 09:25:27 +0000 Subject: Handle the ref counter spinlock on cleanup * netfs.c (netfs_node_norefs): Handle the reference counters spinlock so as to avoid deadlocking on reentry. --- netfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netfs.c b/netfs.c index 6b105f91..e98af752 100644 --- a/netfs.c +++ b/netfs.c @@ -163,8 +163,12 @@ error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, free all its associated storage. */ void netfs_node_norefs (struct node *np) { + spin_unlock (&netfs_node_refcnt_lock); + procfs_cleanup (np); free (np); + + spin_lock (&netfs_node_refcnt_lock); } -- cgit v1.2.3 From 41e9b70f37295ec16d403d7efd1e49027ab867a8 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 09:26:09 +0000 Subject: Use libps and enhance [pid]/stat * Makefile: Add libps to the $(LIBS). * proclist.c, proclist.h: Embed the proc server port in a ps_context structure. (proclist_make_node): Change to prototype to allow for the possibility of error. Rename to proclist_create_node to reflect the change and non-triviality. * process.c, process.h: Revamp. Use a full-blown procstat structure instead of just the procinfo fetched from the process server. Use the additional data to complement [pid]/stat. (process_lookup_pid): Get a ps_context structure instead of a port to the process server. * main.c (root_make_node): Convert to the new interface for proclist_create_node. --- main.c | 7 +- process.c | 267 ++++++++++++++++++++++++++++++++----------------------------- process.h | 8 +- procfs.c | 2 +- proclist.c | 35 ++++---- proclist.h | 2 +- 6 files changed, 163 insertions(+), 158 deletions(-) diff --git a/main.c b/main.c index 15602819..75e1cda3 100644 --- a/main.c +++ b/main.c @@ -25,16 +25,17 @@ root_make_node (struct node **np) /* We never have two root nodes alive simultaneously, so it's ok to have this as static data. */ static struct node *root_dirs[3]; + error_t err; root_dirs[0] = procfs_dir_make_node (static_entries, NULL, NULL); if (! root_dirs[0]) return ENOMEM; - root_dirs[1] = proclist_make_node (getproc ()); - if (! root_dirs[1]) + err = proclist_create_node (getproc (), &root_dirs[1]); + if (err) { netfs_nrele (root_dirs[0]); - return ENOMEM; + return err; } root_dirs[2] = NULL; diff --git a/process.c b/process.c index 2b89ef81..a1cc0f61 100644 --- a/process.c +++ b/process.c @@ -1,100 +1,75 @@ #include #include +#include #include +#include +#include +#include #include "procfs.h" #include "procfs_dir.h" #include "process.h" + +/* Implementations for the process_file_desc.get_contents callback. */ -struct process_node { - process_t procserv; - pid_t pid; - struct procinfo info; -}; - - -/* The proc_getprocargs() and proc_getprocenv() calls have the same - prototype and we use them in the same way; namely, publish the data - they return as-is. We take advantage of this to have common code and - use a function pointer as the procfs_dir "entry hook" to choose the - call to use on a file by file basis. */ - -struct process_argz_node +static char * +process_file_gc_cmdline (struct proc_stat *ps, size_t *len) { - struct process_node pn; - error_t (*getargz) (process_t, pid_t, void **, mach_msg_type_number_t *); -}; + *len = proc_stat_args_len(ps); + return proc_stat_args(ps); +} -static error_t -process_argz_get_contents (void *hook, void **contents, size_t *contents_len) +static char * +process_file_gc_environ (struct proc_stat *ps, size_t *len) { - struct process_argz_node *pz = hook; - error_t err; - - *contents_len = 0; - err = pz->getargz (pz->pn.procserv, pz->pn.pid, contents, contents_len); - if (err) - return EIO; - - return 0; + *len = proc_stat_args_len(ps); + return proc_stat_args(ps); } -static struct node * -process_argz_make_node (void *dir_hook, void *entry_hook) +static char state_char (struct proc_stat *ps) { - static const struct procfs_node_ops ops = { - .get_contents = process_argz_get_contents, - .cleanup_contents = procfs_cleanup_contents_with_vm_deallocate, - .cleanup = free, - }; - struct process_argz_node *zn; - - zn = malloc (sizeof *zn); - if (! zn) - return NULL; + int i; - memcpy (&zn->pn, dir_hook, sizeof zn->pn); - zn->getargz = entry_hook; + for (i = 0; (1 << i) & (PSTAT_STATE_P_STATES | PSTAT_STATE_T_STATES); i++) + if (proc_stat_state (ps) & (1 << i)) + return proc_stat_state_tags[i]; - return procfs_make_node (&ops, zn); + return '?'; } -/* The other files don't need any information besides the data in struct - process_node. Furthermore, their contents don't have any nul byte. - Consequently, we use a simple "multiplexer" based on the information - below. */ - -struct process_file_node +static long int sc_tv (time_value_t tv) { - struct process_node pn; - error_t (*get_contents) (struct process_node *pn, char **contents); -}; + double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; + return usecs * sysconf(_SC_CLK_TCK) / 1000000; +} -static char mapstate (int hurd_state) +static long long int jiff_tv (time_value_t tv) { - return '?'; + double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; + /* Let's say a jiffy is 1/100 of a second.. */ + return usecs * 100 / 1000000; } -static error_t -process_file_gc_stat (struct process_node *pn, char **contents) +static char * +process_file_gc_stat (struct proc_stat *ps, size_t *len) { - char *argz; - size_t argz_len; - int len; - - argz = NULL, argz_len = 0; - proc_getprocargs(pn->procserv, pn->pid, &argz, &argz_len); - - len = asprintf (contents, + struct procinfo *pi = proc_stat_proc_info (ps); + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); + char *contents; + + /* See proc(5) for more information about the contents of each field for the + Linux procfs. */ + *len = asprintf (&contents, "%d (%s) %c " /* pid, command, state */ "%d %d %d " /* ppid, pgid, session */ "%d %d " /* controling tty stuff */ "%u " /* flags, as defined by */ "%lu %lu %lu %lu " /* page fault counts */ "%lu %lu %ld %ld " /* user/sys times, in sysconf(_SC_CLK_TCK) */ - "%ld %ld " /* scheduler params (priority, nice) */ - "%ld %ld " /* number of threads, [obsolete] */ + "%d %d " /* scheduler params (priority, nice) */ + "%d %ld " /* number of threads, [obsolete] */ "%llu " /* start time since boot (jiffies) */ - "%lu %ld %lu " /* virtual size, rss, rss limit */ + "%lu %ld %lu " /* virtual size (bytes), rss (pages), rss lim */ "%lu %lu %lu %lu %lu " /* some vm addresses (code, stack, sp, pc) */ "%lu %lu %lu %lu " /* pending, blocked, ignored and caught sigs */ "%lu " /* wait channel */ @@ -104,44 +79,71 @@ process_file_gc_stat (struct process_node *pn, char **contents) "%u %u " /* RT priority and policy */ "%llu " /* aggregated block I/O delay */ "\n", - pn->pid, argz ?: "", mapstate (pn->info.state), - pn->info.ppid, pn->info.pgrp, pn->info.session, - 0, 0, - 0, - 0L, 0L, 0L, 0L, - 0L, 0L, 0L, 0L, - 0L, 0L, - 0L, 0L, - 0LL, - 0L, 0L, 0L, + proc_stat_pid (ps), proc_stat_args (ps), state_char (ps), + pi->ppid, pi->pgrp, pi->session, + 0, 0, /* no such thing as a major:minor for ctty */ + 0, /* no such thing as CLONE_* flags on Hurd */ + 0L, 0L, 0L, 0L, /* TASK_EVENTS_INFO is unavailable on GNU Mach */ + sc_tv (thbi->user_time), sc_tv (thbi->system_time), + 0L, 0L, /* cumulative time for children */ + MACH_PRIORITY_TO_NICE(thbi->base_priority) + 20, + MACH_PRIORITY_TO_NICE(thbi->base_priority), + pi->nthreads, 0L, + jiff_tv (thbi->creation_time), /* FIXME: ... since boot */ + (long unsigned int) tbi->virtual_size, + (long unsigned int) tbi->resident_size / PAGE_SIZE, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, - 0L, + (long unsigned int) proc_stat_thread_rpc (ps), /* close enough */ 0L, 0L, 0, 0, 0, 0, 0LL); - vm_deallocate (mach_task_self (), (vm_address_t) argz, argz_len); + return len >= 0 ? contents : NULL; +} - if (len < 0) - return ENOMEM; - return 0; -} +/* Describes a file in a process directory. This is used as an "entry hook" + * for our procfs_dir entry table, passed to process_file_make_node. */ +struct process_file_desc +{ + /* The proc_stat information required to get the contents of this file. */ + ps_flags_t needs; + + /* Once we have acquired the necessary information, there can be only + memory allocation errors, hence this simplified signature. */ + char *(*get_contents) (struct proc_stat *ps, size_t *len); + + /* The cmdline and environ contents don't need any cleaning since they are + part of a proc_stat structure. */ + int no_cleanup; +}; + +/* Information associated to an actual file node. */ +struct process_file_node +{ + const struct process_file_desc *desc; + struct proc_stat *ps; +}; static error_t process_file_get_contents (void *hook, void **contents, size_t *contents_len) { - struct process_file_node *fn = hook; + struct process_file_node *file = hook; error_t err; - err = fn->get_contents (&fn->pn, (char **) contents); + err = proc_stat_set_flags (file->ps, file->desc->needs); if (err) - return err; + return EIO; + if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) + return EIO; + + *contents = file->desc->get_contents (file->ps, contents_len); + if (! *contents) + return ENOMEM; - *contents_len = strlen (*contents); return 0; } @@ -153,68 +155,75 @@ process_file_make_node (void *dir_hook, void *entry_hook) .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = free, }; - struct process_file_node *fn; + static const struct procfs_node_ops ops_no_cleanup = { + .get_contents = process_file_get_contents, + .cleanup = free, + }; + struct process_file_node *f; - fn = malloc (sizeof *fn); - if (! fn) + f = malloc (sizeof *f); + if (! f) return NULL; - memcpy (&fn->pn, dir_hook, sizeof fn->pn); - fn->get_contents = entry_hook; + f->desc = entry_hook; + f->ps = dir_hook; - return procfs_make_node (&ops, fn); + return procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); } -static struct node * -process_make_node (process_t procserv, pid_t pid, const struct procinfo *info) -{ - static const struct procfs_dir_entry entries[] = { - { "cmdline", process_argz_make_node, proc_getprocargs, }, - { "environ", process_argz_make_node, proc_getprocenv, }, - { "stat", process_file_make_node, process_file_gc_stat, }, - { NULL, } - }; - struct process_node *pn; - struct node *np; - - pn = malloc (sizeof *pn); - if (! pn) - return NULL; - - pn->procserv = procserv; - pn->pid = pid; - memcpy (&pn->info, info, sizeof pn->info); - - np = procfs_dir_make_node (entries, pn, process_cleanup); - np->nn_stat.st_uid = pn->info.owner; - - return np; -} +static struct procfs_dir_entry entries[] = { + { + .name = "cmdline", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_cmdline, + .needs = PSTAT_ARGS, + .no_cleanup = 1, + }, + }, + { + .name = "environ", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_environ, + .needs = PSTAT_ENV, + .no_cleanup = 1, + }, + }, + { + .name = "stat", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_stat, + .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO + | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC + | PSTAT_THREAD_WAIT, + }, + }, + {} +}; error_t -process_lookup_pid (process_t procserv, pid_t pid, struct node **np) +process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) { - procinfo_t info; - size_t info_sz; - data_t tw; - size_t tw_sz; - int flags; + struct proc_stat *ps; error_t err; - tw_sz = info_sz = 0, flags = 0; - err = proc_getprocinfo (procserv, pid, &flags, &info, &info_sz, &tw, &tw_sz); + err = _proc_stat_create (pid, pc, &ps); if (err == ESRCH) return ENOENT; if (err) return EIO; - assert (info_sz * sizeof *info >= sizeof (struct procinfo)); - *np = process_make_node (procserv, pid, (struct procinfo *) info); - vm_deallocate (mach_task_self (), (vm_address_t) info, info_sz); + err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); + if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) + return EIO; + *np = procfs_dir_make_node (entries, ps, (void (*)(void *)) _proc_stat_free); if (! *np) return ENOMEM; + (*np)->nn_stat.st_uid = proc_stat_owner_uid (ps); return 0; } diff --git a/process.h b/process.h index abdaaa3b..8c2ee636 100644 --- a/process.h +++ b/process.h @@ -1,8 +1,8 @@ -#include +#include -/* Create a node for a directory representing information available at - the proc server PROC for the given PID. On success, returns the +/* Create a node for a directory representing the given PID, as published by + the proc server refrenced by the libps context PC. On success, returns the newly created node in *NP. */ error_t -process_lookup_pid (process_t proc, pid_t pid, struct node **np); +process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np); diff --git a/procfs.c b/procfs.c index 4cce46b9..0a235a76 100644 --- a/procfs.c +++ b/procfs.c @@ -87,7 +87,7 @@ procfs_make_ino (struct node *np, const char *filename) jrand48 (x); } - return jrand48 (x); + return (unsigned long) jrand48 (x); } error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) diff --git a/proclist.c b/proclist.c index 94a7a04d..56a3fdf9 100644 --- a/proclist.c +++ b/proclist.c @@ -3,27 +3,23 @@ #include #include #include +#include #include "procfs.h" #include "process.h" #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) -struct proclist_node -{ - process_t process; -}; - static error_t proclist_get_contents (void *hook, void **contents, size_t *contents_len) { - struct proclist_node *pl = hook; + struct ps_context *pc = hook; pidarray_t pids; mach_msg_type_number_t num_pids; error_t err; int i; num_pids = 0; - err = proc_getallpids (pl->process, &pids, &num_pids); + err = proc_getallpids (pc->server, &pids, &num_pids); if (err) return EIO; @@ -48,7 +44,7 @@ proclist_get_contents (void *hook, void **contents, size_t *contents_len) static error_t proclist_lookup (void *hook, const char *name, struct node **np) { - struct proclist_node *pl = hook; + struct ps_context *pc = hook; char *endp; pid_t pid; @@ -63,28 +59,27 @@ proclist_lookup (void *hook, const char *name, struct node **np) if (*endp) return ENOENT; - return process_lookup_pid (pl->process, pid, np); + return process_lookup_pid (pc, pid, np); } -struct node * -proclist_make_node (process_t process) +error_t +proclist_create_node (process_t procserv, struct node **np) { static const struct procfs_node_ops ops = { .get_contents = proclist_get_contents, .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = free, + .cleanup = (void (*)(void *)) ps_context_free, .enable_refresh_hack_and_break_readdir = 1, }; - struct proclist_node *pl; - - pl = malloc (sizeof *pl); - if (! pl) - return NULL; + struct ps_context *pc; + error_t err; - memset (pl, 0, sizeof *pl); - pl->process = process; + err = ps_context_create (procserv, &pc); + if (err) + return err; - return procfs_make_node (&ops, pl); + *np = procfs_make_node (&ops, pc); + return 0; } diff --git a/proclist.h b/proclist.h index a766d50e..1c7ab084 100644 --- a/proclist.h +++ b/proclist.h @@ -1,2 +1,2 @@ #include -struct node *proclist_make_node (process_t process); +error_t proclist_create_node (process_t procserv, struct node **np); -- cgit v1.2.3 From f3d54d87f2abd6ff2be77e1e396bb45a2f0953a6 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 11:09:36 +0000 Subject: Implement symlinks * netfs.c (netfs_validate_stat): For symlinks, fetch the contents and propagate their length into the nn_stat.st_size field. (netfs_attempt_readlink): Implement using procfs_get_contents. --- netfs.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/netfs.c b/netfs.c index e98af752..a47861e5 100644 --- a/netfs.c +++ b/netfs.c @@ -24,6 +24,28 @@ char *netfs_server_version = PROCFS_SERVER_VERSION; /* Maximum number of symlinks to follow before returning ELOOP. */ int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; +/* The user must define this function. Make sure that NP->nn_stat is + filled with the most current information. CRED identifies the user + responsible for the operation. NP is locked. */ +error_t netfs_validate_stat (struct node *np, struct iouser *cred) +{ + void *contents; + size_t contents_len; + error_t err; + + /* Only symlinks need to have their size filled, before a read is + attempted. */ + if (! S_ISLNK (np->nn_stat.st_mode)) + return 0; + + err = procfs_get_contents (np, &contents, &contents_len); + if (err) + return err; + + np->nn_stat.st_size = contents_len; + return 0; +} + /* The user must define this function. Read from the locked file NP for user CRED starting at OFFSET and continuing for up to *LEN bytes. Put the data at DATA. Set *LEN to the amount successfully @@ -56,7 +78,17 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, error_t netfs_attempt_readlink (struct iouser *user, struct node *np, char *buf) { - return EIO; + char *contents; + size_t contents_len; + error_t err; + + err = procfs_get_contents (np, (void **) &contents, &contents_len); + if (err) + return err; + + assert (contents_len == np->nn_stat.st_size); + memcpy (buf, contents, contents_len); + return 0; } /* Helper function for netfs_get_dirents() below. CONTENTS is an argz @@ -210,14 +242,6 @@ error_t netfs_report_access (struct iouser *cred, struct node *np, /* Trivial or unsupported libnetfs callbacks. */ -/* The user must define this function. Make sure that NP->nn_stat is - filled with the most current information. CRED identifies the user - responsible for the operation. NP is locked. */ -error_t netfs_validate_stat (struct node *np, struct iouser *cred) -{ - return 0; -} - /* The user must define this function. This should attempt a chmod call for the user specified by CRED on locked node NP, to change the owner to UID and the group to GID. */ -- cgit v1.2.3 From bebb88600bc0fc7aa3abb86712652c0ff5c38122 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 11:21:59 +0000 Subject: Encapsulate access to node->nn_stat * procfs.c, procfs.h (procfs_node_chown, procfs_node_chmod, procfs_node_chtype): New functions, encapsulate access to some nn_stat fields. * process.c (process_lookup_pid): Use procfs_node_chown instead of direct access. --- process.c | 2 +- procfs.c | 19 +++++++++++++++++++ procfs.h | 13 +++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/process.c b/process.c index a1cc0f61..779a2e18 100644 --- a/process.c +++ b/process.c @@ -224,6 +224,6 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (! *np) return ENOMEM; - (*np)->nn_stat.st_uid = proc_stat_owner_uid (ps); + procfs_node_chown (*np, proc_stat_owner_uid (ps)); return 0; } diff --git a/procfs.c b/procfs.c index 0a235a76..5396ecf7 100644 --- a/procfs.c +++ b/procfs.c @@ -67,6 +67,25 @@ fail: return NULL; } +void procfs_node_chown (struct node *np, uid_t owner) +{ + np->nn_stat.st_uid = owner; +} + +void procfs_node_chmod (struct node *np, mode_t mode) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & S_IFMT) | mode; + np->nn_translated = np->nn_stat.st_mode; +} + +void procfs_node_chtype (struct node *np, mode_t type) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & ~S_IFMT) | type; + np->nn_translated = np->nn_stat.st_mode; + if (type == S_IFLNK) + procfs_node_chmod (np, 0777); +} + /* FIXME: possibly not the fastest hash function... */ ino64_t procfs_make_ino (struct node *np, const char *filename) diff --git a/procfs.h b/procfs.h index 4c9d828b..4ab3b567 100644 --- a/procfs.h +++ b/procfs.h @@ -48,6 +48,19 @@ void procfs_cleanup_contents_with_vm_deallocate (void *, void *, size_t); enough memory. In this case, ops->cleanup will be invoked. */ struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); +/* Set the owner of the node NP. Must be called right after the node + has been created. */ +void procfs_node_chown (struct node *np, uid_t owner); + +/* Set the permission bits of the node NP. Must be called right after + the node has been created. */ +void procfs_node_chmod (struct node *np, mode_t mode); + +/* Set the type of the node NP. If type is S_IFLNK, appropriate + permission bits will be set as well. Must be called right after the + node has been created. */ +void procfs_node_chtype (struct node *np, mode_t type); + /* Interface for the libnetfs side. */ -- cgit v1.2.3 From eac768767aef12d1b0b98468eacf5a12db1bf124 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 18:06:16 +0000 Subject: Set a restrictive mode on some sensitive files * process.c (process_file_make_node, entries): Set the environ and stat files as readable only by the owner of the process. --- process.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/process.c b/process.c index 779a2e18..8955cf40 100644 --- a/process.c +++ b/process.c @@ -119,6 +119,9 @@ struct process_file_desc /* The cmdline and environ contents don't need any cleaning since they are part of a proc_stat structure. */ int no_cleanup; + + /* If specified, the file mode to be set with procfs_node_chmod(). */ + mode_t mode; }; /* Information associated to an actual file node. */ @@ -160,6 +163,7 @@ process_file_make_node (void *dir_hook, void *entry_hook) .cleanup = free, }; struct process_file_node *f; + struct node *np; f = malloc (sizeof *f); if (! f) @@ -168,7 +172,15 @@ process_file_make_node (void *dir_hook, void *entry_hook) f->desc = entry_hook; f->ps = dir_hook; - return procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); + np = procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); + if (! np) + return NULL; + + procfs_node_chown (np, proc_stat_owner_uid (f->ps)); + if (f->desc->mode) + procfs_node_chmod (np, f->desc->mode); + + return np; } @@ -189,6 +201,7 @@ static struct procfs_dir_entry entries[] = { .get_contents = process_file_gc_environ, .needs = PSTAT_ENV, .no_cleanup = 1, + .mode = 0400, }, }, { @@ -199,6 +212,7 @@ static struct procfs_dir_entry entries[] = { .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC | PSTAT_THREAD_WAIT, + .mode = 0400, }, }, {} -- cgit v1.2.3 From 90a5e8f072ba3e06508d2fe82195058d1578e345 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 18:08:17 +0000 Subject: New root files: version, uptime, stat * rootdir.c, rootdir.h: New files. * main.c: Use rootdir_create_node. * Makefile: Add the rootdir module. --- main.c | 21 ++------- rootdir.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rootdir.h | 2 + 3 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 rootdir.c create mode 100644 rootdir.h diff --git a/main.c b/main.c index 75e1cda3..15ad60f4 100644 --- a/main.c +++ b/main.c @@ -4,34 +4,23 @@ #include #include #include "procfs.h" -#include "procfs_file.h" -#include "procfs_dir.h" #include "proclist.h" +#include "rootdir.h" #include "dircat.h" -static struct node * -make_file (void *dir_hook, void *ent_hook) -{ - return procfs_file_make_node (ent_hook, -1, NULL); -} - error_t root_make_node (struct node **np) { - static const struct procfs_dir_entry static_entries[] = { - { "hello", make_file, "Hello, World!\n" }, - { "goodbye", make_file, "Goodbye, cruel World!\n" }, - }; /* We never have two root nodes alive simultaneously, so it's ok to have this as static data. */ static struct node *root_dirs[3]; error_t err; - root_dirs[0] = procfs_dir_make_node (static_entries, NULL, NULL); - if (! root_dirs[0]) - return ENOMEM; + err = proclist_create_node (getproc (), &root_dirs[0]); + if (err) + return err; - err = proclist_create_node (getproc (), &root_dirs[1]); + err = rootdir_create_node (&root_dirs[1]); if (err) { netfs_nrele (root_dirs[0]); diff --git a/rootdir.c b/rootdir.c new file mode 100644 index 00000000..fb48b932 --- /dev/null +++ b/rootdir.c @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include "procfs.h" +#include "procfs_dir.h" + +/* This implements a directory node with the static files in /proc */ + +#define INIT_PID 1 + +static error_t +get_boottime (struct ps_context *pc, struct timeval *tv) +{ + struct proc_stat *ps; + error_t err; + + err = _proc_stat_create (INIT_PID, pc, &ps); + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (err || !(proc_stat_flags (ps) & PSTAT_TASK_BASIC)) + err = EIO; + + if (! err) + { + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + tv->tv_sec = tbi->creation_time.seconds; + tv->tv_usec = tbi->creation_time.microseconds; + } + + _proc_stat_free (ps); + return err; +} + +static error_t +rootdir_gc_version (void *hook, void **contents, size_t *contents_len) +{ + struct utsname uts; + int r; + + r = uname (&uts); + if (r < 0) + return errno; + + *contents_len = asprintf ((char **) contents, + "Linux version 2.6.1 (%s %s %s %s)\n", + uts.sysname, uts.release, uts.version, uts.machine); + + return *contents_len >= 0 ? 0 : ENOMEM; +} + +/* Uptime -- we use the start time of init to deduce it. This is probably a bit + fragile, as any clock update will make the result inaccurate. */ +static error_t +rootdir_gc_uptime (void *hook, void **contents, size_t *contents_len) +{ + struct timeval time, boottime; + double up_secs; + error_t err; + + err = gettimeofday (&time, NULL); + if (err < 0) + return errno; + + err = get_boottime (hook, &boottime); + if (err) + return err; + + timersub (&time, &boottime, &time); + up_secs = time.tv_sec + time.tv_usec / 1000000.; + + /* The second field is the total idle time. As far as I know we don't + keep track of it. */ + *contents_len = asprintf ((char **) contents, "%.2lf %.2lf\n", up_secs, 0.); + + return *contents_len >= 0 ? 0 : ENOMEM; +} + +static error_t +rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) +{ + struct timeval boottime; + struct vm_statistics vmstats; + error_t err; + + err = get_boottime (hook, &boottime); + if (err) + return err; + + err = vm_statistics (mach_task_self (), &vmstats); + if (err) + return EIO; + + *contents_len = asprintf ((char **) contents, + /* Does Mach keeps track of any of this? */ + "cpu 0 0 0 0 0 0 0 0 0\n" + "cpu0 0 0 0 0 0 0 0 0 0\n" + "intr 0\n" + /* This we know. */ + "page %d %d\n" + "btime %lu\n", + vmstats.pageins, vmstats.pageouts, + boottime.tv_sec); + + return *contents_len >= 0 ? 0 : ENOMEM; +} + +static struct node * +rootdir_file_make_node (void *dir_hook, void *entry_hook) +{ + return procfs_make_node (entry_hook, dir_hook); +} + +static struct procfs_dir_entry rootdir_entries[] = { + { + .name = "version", + .make_node = rootdir_file_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_version, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "uptime", + .make_node = rootdir_file_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_uptime, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "stat", + .make_node = rootdir_file_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_stat, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + {} +}; + +error_t +rootdir_create_node (struct node **np) +{ + struct ps_context *pc; + error_t err; + + err = ps_context_create (getproc (), &pc); + if (err) + return err; + + *np = procfs_dir_make_node (rootdir_entries, pc, + (void (*)(void *)) ps_context_free); + return 0; +} + diff --git a/rootdir.h b/rootdir.h new file mode 100644 index 00000000..a764b0fd --- /dev/null +++ b/rootdir.h @@ -0,0 +1,2 @@ +error_t +rootdir_create_node (struct node **np); -- cgit v1.2.3 From 880f120da999a3217079af65ce7273087e0e0eda Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sat, 21 Aug 2010 19:18:59 +0000 Subject: Add loadavg * rootdir.c: Add the root file "loadavg". --- rootdir.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/rootdir.c b/rootdir.c index fb48b932..0985b63b 100644 --- a/rootdir.c +++ b/rootdir.c @@ -108,6 +108,28 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) return *contents_len >= 0 ? 0 : ENOMEM; } +static error_t +rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) +{ + host_load_info_data_t hli; + mach_msg_type_number_t cnt; + error_t err; + + cnt = HOST_LOAD_INFO_COUNT; + err = host_info (mach_host_self (), HOST_LOAD_INFO, (host_info_t) &hli, &cnt); + if (err) + return err; + + assert (cnt == HOST_LOAD_INFO_COUNT); + *contents_len = asprintf ((char **) contents, + "%.2f %.2f %.2f 1/0 0\n", + hli.avenrun[0] / (double) LOAD_SCALE, + hli.avenrun[1] / (double) LOAD_SCALE, + hli.avenrun[2] / (double) LOAD_SCALE); + + return *contents_len >= 0 ? 0 : ENOMEM; +} + static struct node * rootdir_file_make_node (void *dir_hook, void *entry_hook) { @@ -139,6 +161,14 @@ static struct procfs_dir_entry rootdir_entries[] = { .cleanup_contents = procfs_cleanup_contents_with_free, }, }, + { + .name = "loadavg", + .make_node = rootdir_file_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_loadavg, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, {} }; -- cgit v1.2.3 From 6e84b8c1182013691d3629bfc08e49f81b662a2d Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 00:55:11 +0000 Subject: Add a fake "self" symlink * rootdir.c: Add a fake "self" symlink which always points to init. --- rootdir.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/rootdir.c b/rootdir.c index 0985b63b..79928446 100644 --- a/rootdir.c +++ b/rootdir.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "procfs.h" #include "procfs_dir.h" @@ -130,12 +131,30 @@ rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) return *contents_len >= 0 ? 0 : ENOMEM; } +static error_t +rootdir_gc_fakeself (void *hook, void **contents, size_t *contents_len) +{ + *contents = "1"; + *contents_len = strlen (*contents); + return 0; +} + + static struct node * rootdir_file_make_node (void *dir_hook, void *entry_hook) { return procfs_make_node (entry_hook, dir_hook); } +static struct node * +rootdir_symlink_make_node (void *dir_hook, void *entry_hook) +{ + struct node *np = procfs_make_node (entry_hook, dir_hook); + if (np) + procfs_node_chtype (np, S_IFLNK); + return np; +} + static struct procfs_dir_entry rootdir_entries[] = { { .name = "version", @@ -169,6 +188,13 @@ static struct procfs_dir_entry rootdir_entries[] = { .cleanup_contents = procfs_cleanup_contents_with_free, }, }, + { + .name = "self", + .make_node = rootdir_symlink_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_fakeself, + }, + }, {} }; -- cgit v1.2.3 From 5dc5292664522e85ea4ede00f2edbfeed929eb5e Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 00:55:29 +0000 Subject: Add an empty meminfo root file * rootdir.c: Add "meminfo", empty for now. --- rootdir.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rootdir.c b/rootdir.c index 79928446..17fdb93a 100644 --- a/rootdir.c +++ b/rootdir.c @@ -131,6 +131,13 @@ rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) return *contents_len >= 0 ? 0 : ENOMEM; } +static error_t +rootdir_gc_empty (void *hook, void **contents, size_t *contents_len) +{ + *contents_len = 0; + return 0; +} + static error_t rootdir_gc_fakeself (void *hook, void **contents, size_t *contents_len) { @@ -188,6 +195,13 @@ static struct procfs_dir_entry rootdir_entries[] = { .cleanup_contents = procfs_cleanup_contents_with_free, }, }, + { + .name = "meminfo", + .make_node = rootdir_file_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_empty, + }, + }, { .name = "self", .make_node = rootdir_symlink_make_node, -- cgit v1.2.3 From 24fa47890c0d180b807de8abb1a284755cba9c96 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sun, 22 Aug 2010 19:33:43 +0000 Subject: Play nice with the procps old_Hertz_hack * rootdir.c (rootdir_gc_uptime, rootdir_gc_stat): assume a completely idle rather than completely busy system, so that the idle seconds can be meaningfully divided by the idle jiffies by procps. --- rootdir.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/rootdir.c b/rootdir.c index 17fdb93a..50f6e071 100644 --- a/rootdir.c +++ b/rootdir.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -74,8 +75,11 @@ rootdir_gc_uptime (void *hook, void **contents, size_t *contents_len) up_secs = time.tv_sec + time.tv_usec / 1000000.; /* The second field is the total idle time. As far as I know we don't - keep track of it. */ - *contents_len = asprintf ((char **) contents, "%.2lf %.2lf\n", up_secs, 0.); + keep track of it. However, procps uses it to compute "USER_HZ", and + proc(5) specifies that it should be equal to USER_HZ times the idle value + in ticks from /proc/stat. So we assume a completely idle system both here + and there to make that work. */ + *contents_len = asprintf ((char **) contents, "%.2lf %.2lf\n", up_secs, up_secs); return *contents_len >= 0 ? 0 : ENOMEM; } @@ -83,10 +87,15 @@ rootdir_gc_uptime (void *hook, void **contents, size_t *contents_len) static error_t rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) { - struct timeval boottime; + struct timeval boottime, time; struct vm_statistics vmstats; + unsigned long up_ticks; error_t err; + err = gettimeofday (&time, NULL); + if (err < 0) + return errno; + err = get_boottime (hook, &boottime); if (err) return err; @@ -95,14 +104,19 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) if (err) return EIO; + timersub (&time, &boottime, &time); + up_ticks = sysconf(_SC_CLK_TCK) * (time.tv_sec + time.tv_usec / 1000000.); + *contents_len = asprintf ((char **) contents, /* Does Mach keeps track of any of this? */ - "cpu 0 0 0 0 0 0 0 0 0\n" - "cpu0 0 0 0 0 0 0 0 0 0\n" + "cpu 0 0 0 %lu 0 0 0 0 0\n" + "cpu0 0 0 0 %lu 0 0 0 0 0\n" "intr 0\n" /* This we know. */ "page %d %d\n" "btime %lu\n", + up_ticks, + up_ticks, vmstats.pageins, vmstats.pageouts, boottime.tv_sec); -- cgit v1.2.3 From 9ab114b6a7e0723135555ed202886f47c032f511 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sun, 22 Aug 2010 20:17:54 +0000 Subject: Add --clk-tck to set the clock unit * main.c (argp_parser, main): Add and parse the --clk-tck option. * main.h: Publish opt_clk_tck. * process.c (sc_tc): Use the user-provided clock frequency. * rootdir.c (rootdir_gc_stat): Likewise. --- main.c | 40 +++++++++++++++++++++++++++++++++++++++- main.h | 2 ++ process.c | 3 ++- rootdir.c | 3 ++- 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 main.h diff --git a/main.c b/main.c index 15ad60f4..a59ab47f 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,6 +8,42 @@ #include "proclist.h" #include "rootdir.h" #include "dircat.h" +#include "main.h" + +/* Command-line options */ +int opt_clk_tck; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + char *endp; + + switch (key) + { + case 'h': + opt_clk_tck = strtol (arg, &endp, 0); + if (*endp || ! *arg || opt_clk_tck <= 0) + error (1, 0, "--clk-tck: HZ should be a positive integer"); + break; + } + + return 0; +} + +struct argp argp = { + .options = (struct argp_option []) { + { "clk-tck", 'h', "HZ", 0, + "Unit used for the values expressed in system clock ticks " + "(default: sysconf(_SC_CLK_TCK))" }, + {} + }, + .parser = argp_parser, + .doc = "A virtual filesystem emulating the Linux procfs.", + .children = (struct argp_child []) { + { &netfs_std_startup_argp, }, + {} + }, +}; error_t root_make_node (struct node **np) @@ -43,7 +80,8 @@ int main (int argc, char **argv) { mach_port_t bootstrap; - argp_parse (&netfs_std_startup_argp, argc, argv, 0, 0, 0); + opt_clk_tck = sysconf(_SC_CLK_TCK); + argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); if (bootstrap == MACH_PORT_NULL) diff --git a/main.h b/main.h new file mode 100644 index 00000000..4b2ef9a1 --- /dev/null +++ b/main.h @@ -0,0 +1,2 @@ +/* Startup options */ +extern int opt_clk_tck; diff --git a/process.c b/process.c index 8955cf40..65f0e503 100644 --- a/process.c +++ b/process.c @@ -8,6 +8,7 @@ #include "procfs.h" #include "procfs_dir.h" #include "process.h" +#include "main.h" /* Implementations for the process_file_desc.get_contents callback. */ @@ -39,7 +40,7 @@ static char state_char (struct proc_stat *ps) static long int sc_tv (time_value_t tv) { double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; - return usecs * sysconf(_SC_CLK_TCK) / 1000000; + return usecs * opt_clk_tck / 1000000; } static long long int jiff_tv (time_value_t tv) diff --git a/rootdir.c b/rootdir.c index 50f6e071..1d9c083c 100644 --- a/rootdir.c +++ b/rootdir.c @@ -7,6 +7,7 @@ #include #include "procfs.h" #include "procfs_dir.h" +#include "main.h" /* This implements a directory node with the static files in /proc */ @@ -105,7 +106,7 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) return EIO; timersub (&time, &boottime, &time); - up_ticks = sysconf(_SC_CLK_TCK) * (time.tv_sec + time.tv_usec / 1000000.); + up_ticks = opt_clk_tck * (time.tv_sec + time.tv_usec / 1000000.); *contents_len = asprintf ((char **) contents, /* Does Mach keeps track of any of this? */ -- cgit v1.2.3 From a22115eca05fd87748aed2ffde8caeb5b71f1c6d Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sun, 22 Aug 2010 20:46:54 +0000 Subject: Add --stat-mode to override the perms for [pid]/stat * main.c (argp_parser, main): Add the --stat-mode option. * process.c (process_lookup_pid): Use it. --- main.c | 14 ++++++++++++++ main.h | 1 + process.c | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/main.c b/main.c index a59ab47f..09cffc76 100644 --- a/main.c +++ b/main.c @@ -12,6 +12,7 @@ /* Command-line options */ int opt_clk_tck; +mode_t opt_stat_mode; static error_t argp_parser (int key, char *arg, struct argp_state *state) @@ -25,6 +26,12 @@ argp_parser (int key, char *arg, struct argp_state *state) if (*endp || ! *arg || opt_clk_tck <= 0) error (1, 0, "--clk-tck: HZ should be a positive integer"); break; + + case 's': + opt_stat_mode = strtol (arg, &endp, 8); + if (*endp || ! *arg || opt_stat_mode & ~07777) + error (1, 0, "--stat-mode: MODE should be an octal mode"); + break; } return 0; @@ -35,6 +42,12 @@ struct argp argp = { { "clk-tck", 'h', "HZ", 0, "Unit used for the values expressed in system clock ticks " "(default: sysconf(_SC_CLK_TCK))" }, + { "stat-mode", 's', "MODE", 0, + "The [pid]/stat file publishes information which on Hurd is only " + "available to the process owner. " + "You can use this option to override its mode to be more permissive " + "for compatibility purposes. " + "(default: 0400)" }, {} }, .parser = argp_parser, @@ -81,6 +94,7 @@ int main (int argc, char **argv) mach_port_t bootstrap; opt_clk_tck = sysconf(_SC_CLK_TCK); + opt_stat_mode = 0400; argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); diff --git a/main.h b/main.h index 4b2ef9a1..6669d321 100644 --- a/main.h +++ b/main.h @@ -1,2 +1,3 @@ /* Startup options */ extern int opt_clk_tck; +extern mode_t opt_stat_mode; diff --git a/process.c b/process.c index 65f0e503..f7a7a577 100644 --- a/process.c +++ b/process.c @@ -206,6 +206,7 @@ static struct procfs_dir_entry entries[] = { }, }, { + /* Beware of the hack below, which requires this to be entries[2]. */ .name = "stat", .make_node = process_file_make_node, .hook = & (struct process_file_desc) { @@ -235,6 +236,10 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) return EIO; + /* FIXME: have a separate proc_desc structure for each file, so this can be + accessed in a more robust and straightforward way. */ + ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + *np = procfs_dir_make_node (entries, ps, (void (*)(void *)) _proc_stat_free); if (! *np) return ENOMEM; -- cgit v1.2.3 From 8b8965bcc85053857b84efd5a0ca63976870de14 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Sun, 22 Aug 2010 21:23:36 +0000 Subject: Add a fake-self option to control the self symlink * main.c (argp_parse, main): Add the --fake-self option. * main.h: Publish it. * rootdir.c (rootdir_gc_fakeself, rootdir_entries, rootdir_create_node): Use it. --- main.c | 17 +++++++++++++++++ main.h | 1 + rootdir.c | 30 +++++++++++++++++------------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/main.c b/main.c index 09cffc76..26f5248f 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,7 @@ /* Command-line options */ int opt_clk_tck; mode_t opt_stat_mode; +pid_t opt_fake_self; static error_t argp_parser (int key, char *arg, struct argp_state *state) @@ -32,6 +33,17 @@ argp_parser (int key, char *arg, struct argp_state *state) if (*endp || ! *arg || opt_stat_mode & ~07777) error (1, 0, "--stat-mode: MODE should be an octal mode"); break; + + case 'S': + if (arg) + { + opt_fake_self = strtol (arg, &endp, 0); + if (*endp || ! *arg) + error (1, 0, "--fake-self: PID must be an integer"); + } + else + opt_fake_self = 1; + break; } return 0; @@ -48,6 +60,10 @@ struct argp argp = { "You can use this option to override its mode to be more permissive " "for compatibility purposes. " "(default: 0400)" }, + { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL, + "Provide a fake \"self\" symlink to the given PID, for compatibility " + "purposes. If PID is omitted, \"self\" will point to init. " + "(default: no self link)" }, {} }, .parser = argp_parser, @@ -95,6 +111,7 @@ int main (int argc, char **argv) opt_clk_tck = sysconf(_SC_CLK_TCK); opt_stat_mode = 0400; + opt_fake_self = -1; argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); diff --git a/main.h b/main.h index 6669d321..361380b3 100644 --- a/main.h +++ b/main.h @@ -1,3 +1,4 @@ /* Startup options */ extern int opt_clk_tck; extern mode_t opt_stat_mode; +extern pid_t opt_fake_self; diff --git a/rootdir.c b/rootdir.c index 1d9c083c..833fc150 100644 --- a/rootdir.c +++ b/rootdir.c @@ -156,9 +156,8 @@ rootdir_gc_empty (void *hook, void **contents, size_t *contents_len) static error_t rootdir_gc_fakeself (void *hook, void **contents, size_t *contents_len) { - *contents = "1"; - *contents_len = strlen (*contents); - return 0; + *contents_len = asprintf ((char **) contents, "%d", opt_fake_self); + return *contents_len >= 0 ? 0 : ENOMEM; } @@ -177,7 +176,15 @@ rootdir_symlink_make_node (void *dir_hook, void *entry_hook) return np; } -static struct procfs_dir_entry rootdir_entries[] = { +static const struct procfs_dir_entry rootdir_entries[] = { + { + .name = "self", + .make_node = rootdir_symlink_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_fakeself, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, { .name = "version", .make_node = rootdir_file_make_node, @@ -217,13 +224,6 @@ static struct procfs_dir_entry rootdir_entries[] = { .get_contents = rootdir_gc_empty, }, }, - { - .name = "self", - .make_node = rootdir_symlink_make_node, - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_fakeself, - }, - }, {} }; @@ -231,14 +231,18 @@ error_t rootdir_create_node (struct node **np) { struct ps_context *pc; + const struct procfs_dir_entry *entries; error_t err; err = ps_context_create (getproc (), &pc); if (err) return err; - *np = procfs_dir_make_node (rootdir_entries, pc, - (void (*)(void *)) ps_context_free); + entries = rootdir_entries; + if (opt_fake_self < 0) + entries++; + + *np = procfs_dir_make_node (entries, pc, (void (*)(void *)) ps_context_free); return 0; } -- cgit v1.2.3 From c8d73b6e554d6bf1492b10a063e8e35a9cb002c2 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 00:52:24 +0000 Subject: Add meminfo and vmstat * rootdir.c: Add a (non-empty) meminfo and a vmstat file. --- rootdir.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/rootdir.c b/rootdir.c index 833fc150..f5b43ff0 100644 --- a/rootdir.c +++ b/rootdir.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -9,7 +10,10 @@ #include "procfs_dir.h" #include "main.h" -/* This implements a directory node with the static files in /proc */ +/* This implements a directory node with the static files in /proc. + NB: the libps functions for host information return static storage; + using them would require locking and as a consequence it would be + more complicated, not simpler. */ #define INIT_PID 1 @@ -147,10 +151,83 @@ rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_empty (void *hook, void **contents, size_t *contents_len) +rootdir_gc_meminfo (void *hook, void **contents, size_t *contents_len) { - *contents_len = 0; - return 0; + host_basic_info_data_t hbi; + mach_msg_type_number_t cnt; + struct vm_statistics vmstats; + error_t err; + + err = vm_statistics (mach_task_self (), &vmstats); + if (err) + return EIO; + + cnt = HOST_BASIC_INFO_COUNT; + err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); + if (err) + return err; + + assert (cnt == HOST_BASIC_INFO_COUNT); + *contents_len = asprintf ((char **) contents, + "MemTotal: %14lu kB\n" + "MemFree: %14lu kB\n" + "Active: %14lu kB\n" + "Inactive: %14lu kB\n" + "Mlocked: %14lu kB\n" + , + /* TODO: check that these are really 1024-bytes kBs. */ + (long unsigned) hbi.memory_size / 1024, + (long unsigned) vmstats.free_count * PAGE_SIZE / 1024, + (long unsigned) vmstats.active_count * PAGE_SIZE / 1024, + (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, + (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024); + + return *contents_len >= 0 ? 0 : ENOMEM; +} + +static error_t +rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) +{ + host_basic_info_data_t hbi; + mach_msg_type_number_t cnt; + struct vm_statistics vmstats; + error_t err; + + err = vm_statistics (mach_task_self (), &vmstats); + if (err) + return EIO; + + cnt = HOST_BASIC_INFO_COUNT; + err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); + if (err) + return err; + + assert (cnt == HOST_BASIC_INFO_COUNT); + *contents_len = asprintf ((char **) contents, + "nr_free_pages %lu\n" + "nr_inactive_anon %lu\n" + "nr_active_anon %lu\n" + "nr_inactive_file %lu\n" + "nr_active_file %lu\n" + "nr_unevictable %lu\n" + "nr_mlock %lu\n" + "pgpgin %lu\n" + "pgpgout %lu\n" + "pgfault %lu\n", + (long unsigned) vmstats.free_count, + /* FIXME: how can we distinguish the anon/file pages? Maybe we can + ask the default pager how many it manages? */ + (long unsigned) vmstats.inactive_count, + (long unsigned) vmstats.active_count, + (long unsigned) 0, + (long unsigned) 0, + (long unsigned) vmstats.wire_count, + (long unsigned) vmstats.wire_count, + (long unsigned) vmstats.pageins, + (long unsigned) vmstats.pageouts, + (long unsigned) vmstats.faults); + + return *contents_len >= 0 ? 0 : ENOMEM; } static error_t @@ -221,7 +298,16 @@ static const struct procfs_dir_entry rootdir_entries[] = { .name = "meminfo", .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_empty, + .get_contents = rootdir_gc_meminfo, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "vmstat", + .make_node = rootdir_file_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_vmstat, + .cleanup_contents = procfs_cleanup_contents_with_free, }, }, {} -- cgit v1.2.3 From d87eae321df3f434ea9b6cf96c2437c8b9a7b23d Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 05:19:19 +0000 Subject: Add a global cmdline file * main.c (argp_parser, main): Add the --kernel-pid option. * main.h: Publish it. * rootdir.c (rootdir_gc_cmdline): New function. --- main.c | 11 +++++++++++ main.h | 1 + rootdir.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/main.c b/main.c index 26f5248f..fee4867c 100644 --- a/main.c +++ b/main.c @@ -14,6 +14,7 @@ int opt_clk_tck; mode_t opt_stat_mode; pid_t opt_fake_self; +pid_t opt_kernel_pid; static error_t argp_parser (int key, char *arg, struct argp_state *state) @@ -44,6 +45,12 @@ argp_parser (int key, char *arg, struct argp_state *state) else opt_fake_self = 1; break; + + case 'k': + opt_kernel_pid = strtol (arg, &endp, 0); + if (*endp || ! *arg || (signed) opt_kernel_pid < 0) + error (1, 0, "--kernel-process: PID must be a positive integer"); + break; } return 0; @@ -64,6 +71,9 @@ struct argp argp = { "Provide a fake \"self\" symlink to the given PID, for compatibility " "purposes. If PID is omitted, \"self\" will point to init. " "(default: no self link)" }, + { "kernel-process", 'k', "PID", 0, + "Process identifier for the kernel, used to retreive its command line " + "(default: 2)" }, {} }, .parser = argp_parser, @@ -112,6 +122,7 @@ int main (int argc, char **argv) opt_clk_tck = sysconf(_SC_CLK_TCK); opt_stat_mode = 0400; opt_fake_self = -1; + opt_kernel_pid = 2; argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); diff --git a/main.h b/main.h index 361380b3..6ada229a 100644 --- a/main.h +++ b/main.h @@ -2,3 +2,4 @@ extern int opt_clk_tck; extern mode_t opt_stat_mode; extern pid_t opt_fake_self; +extern pid_t opt_kernel_pid; diff --git a/rootdir.c b/rootdir.c index f5b43ff0..865342ce 100644 --- a/rootdir.c +++ b/rootdir.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "procfs.h" #include "procfs_dir.h" @@ -230,6 +231,41 @@ rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) return *contents_len >= 0 ? 0 : ENOMEM; } +static error_t +rootdir_gc_cmdline (void *hook, void **contents, size_t *contents_len) +{ + struct ps_context *pc = hook; + struct proc_stat *ps; + error_t err; + + err = _proc_stat_create (opt_kernel_pid, pc, &ps); + if (err) + return EIO; + + err = proc_stat_set_flags (ps, PSTAT_ARGS); + if (err || ! (proc_stat_flags (ps) & PSTAT_ARGS)) + { + err = EIO; + goto out; + } + + *contents_len = proc_stat_args_len (ps); + *contents = malloc (*contents_len); + if (! *contents) + { + err = ENOMEM; + goto out; + } + + memcpy (*contents, proc_stat_args (ps), *contents_len); + argz_stringify (*contents, *contents_len, ' '); + ((char *) *contents)[*contents_len - 1] = '\n'; + +out: + _proc_stat_free (ps); + return err; +} + static error_t rootdir_gc_fakeself (void *hook, void **contents, size_t *contents_len) { @@ -310,6 +346,14 @@ static const struct procfs_dir_entry rootdir_entries[] = { .cleanup_contents = procfs_cleanup_contents_with_free, }, }, + { + .name = "cmdline", + .make_node = rootdir_file_make_node, + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_cmdline, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, {} }; -- cgit v1.2.3 From 166becc7157e51c54a51a7cb78602704256969d0 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 05:44:37 +0000 Subject: Add statm to process directories * process.c: Add the statm file. --- process.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/process.c b/process.c index f7a7a577..4404d084 100644 --- a/process.c +++ b/process.c @@ -105,6 +105,20 @@ process_file_gc_stat (struct proc_stat *ps, size_t *len) return len >= 0 ? contents : NULL; } +static char * +process_file_gc_statm (struct proc_stat *ps, size_t *len) +{ + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + char *contents; + + *len = asprintf (&contents, + "%lu %lu 0 0 0 0 0\n", + tbi->virtual_size / sysconf(_SC_PAGE_SIZE), + tbi->resident_size / sysconf(_SC_PAGE_SIZE)); + + return len >= 0 ? contents : NULL; +} + /* Describes a file in a process directory. This is used as an "entry hook" * for our procfs_dir entry table, passed to process_file_make_node. */ @@ -217,6 +231,15 @@ static struct procfs_dir_entry entries[] = { .mode = 0400, }, }, + { + .name = "statm", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_statm, + .needs = PSTAT_TASK_BASIC, + .mode = 0444, + }, + }, {} }; -- cgit v1.2.3 From 41c86b73e275b632e10fc81e2c4823472dedb89f Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 07:14:45 +0000 Subject: Add a status file to process directories * process.c: Add a status file. --- process.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/process.c b/process.c index 4404d084..b2b098ff 100644 --- a/process.c +++ b/process.c @@ -37,6 +37,27 @@ static char state_char (struct proc_stat *ps) return '?'; } +static const char *state_string (struct proc_stat *ps) +{ + static const char *const state_strings[] = { + "T (stopped)", + "Z (zombie)", + "R (running)", + "H (halted)", + "D (disk sleep)", + "S (sleeping)", + "I (idle)", + NULL + }; + int i; + + for (i = 0; state_strings[i]; i++) + if (proc_stat_state (ps) & (1 << i)) + return state_strings[i]; + + return "? (unknown)"; +} + static long int sc_tv (time_value_t tv) { double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; @@ -119,6 +140,42 @@ process_file_gc_statm (struct proc_stat *ps, size_t *len) return len >= 0 ? contents : NULL; } +static char * +process_file_gc_status (struct proc_stat *ps, size_t *len) +{ + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + char *contents; + + *len = asprintf (&contents, + "Name:\t%s\n" + "State:\t%s\n" + "Tgid:\t%u\n" + "Pid:\t%u\n" + "PPid:\t%u\n" + "Uid:\t%u\t%u\t%u\t%u\n" + "VmSize:\t%8u kB\n" + "VmPeak:\t%8u kB\n" + "VmRSS:\t%8u kB\n" + "VmHWM:\t%8u kB\n" /* ie. resident peak */ + "Threads:\t%u\n", + proc_stat_args (ps), + state_string (ps), + proc_stat_pid (ps), /* XXX will need more work for threads */ + proc_stat_pid (ps), + proc_stat_proc_info (ps)->ppid, + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + tbi->virtual_size / 1024, + tbi->virtual_size / 1024, + tbi->resident_size / 1024, + tbi->resident_size / 1024, + proc_stat_num_threads (ps)); + + return len >= 0 ? contents : NULL; +} + /* Describes a file in a process directory. This is used as an "entry hook" * for our procfs_dir entry table, passed to process_file_make_node. */ @@ -240,6 +297,16 @@ static struct procfs_dir_entry entries[] = { .mode = 0444, }, }, + { + .name = "status", + .make_node = process_file_make_node, + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_status, + .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO + | PSTAT_TASK_BASIC | PSTAT_OWNER_UID | PSTAT_NUM_THREADS, + .mode = 0444, + }, + }, {} }; -- cgit v1.2.3 From c0e9dd6d3bcad339d8a263712997f0aaa89f236e Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 07:35:59 +0000 Subject: Add a --compatible option * main.c (argp_parser): Add --compatible, which sets the options required for compatibility with the procps tools. --- main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main.c b/main.c index fee4867c..35d05c65 100644 --- a/main.c +++ b/main.c @@ -51,6 +51,12 @@ argp_parser (int key, char *arg, struct argp_state *state) if (*endp || ! *arg || (signed) opt_kernel_pid < 0) error (1, 0, "--kernel-process: PID must be a positive integer"); break; + + case 'c': + opt_clk_tck = 100; + opt_stat_mode = 0444; + opt_fake_self = 1; + break; } return 0; @@ -74,6 +80,9 @@ struct argp argp = { { "kernel-process", 'k', "PID", 0, "Process identifier for the kernel, used to retreive its command line " "(default: 2)" }, + { "compatible", 'c', NULL, 0, + "Try to be compatible with the Linux procps utilities. " + "Currently equivalent to -h 100 -s 0444 -S 1." }, {} }, .parser = argp_parser, -- cgit v1.2.3 From 3e4b6453f821646ff7c81cd770c4f4f1f781b3a6 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 08:24:43 +0000 Subject: Handle errors in main * main.c (main): Handle errors from argp_parse and root_make_node. --- main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 35d05c65..a1db4753 100644 --- a/main.c +++ b/main.c @@ -127,19 +127,24 @@ root_make_node (struct node **np) int main (int argc, char **argv) { mach_port_t bootstrap; + error_t err; opt_clk_tck = sysconf(_SC_CLK_TCK); opt_stat_mode = 0400; opt_fake_self = -1; opt_kernel_pid = 2; - argp_parse (&argp, argc, argv, 0, 0, 0); + err = argp_parse (&argp, argc, argv, 0, 0, 0); + if (err) + error (1, err, "Could not parse command line"); task_get_bootstrap_port (mach_task_self (), &bootstrap); if (bootstrap == MACH_PORT_NULL) error (1, 0, "Must be started as a translator"); netfs_init (); - root_make_node (&netfs_root_node); + err = root_make_node (&netfs_root_node); + if (err) + error (1, err, "Could not create the root node"); netfs_startup (bootstrap, 0); for (;;) -- cgit v1.2.3 From 60f604f96c8f78320d415d92b325d0de80949043 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 08:25:07 +0000 Subject: netfs_server_loop never returns * main.c: Don't call netfs_server_loop repeatedly; it should never return. --- main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index a1db4753..4be506fb 100644 --- a/main.c +++ b/main.c @@ -147,7 +147,8 @@ int main (int argc, char **argv) error (1, err, "Could not create the root node"); netfs_startup (bootstrap, 0); - for (;;) - netfs_server_loop (); + netfs_server_loop (); + + assert (0 /* netfs_server_loop returned after all */); } -- cgit v1.2.3 From 687c9658628eb044be75df8074c5983e865b6394 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 09:06:01 +0000 Subject: Use a global ps_context * proclist.c, proclist.h (proclist_create_node): Use a ps_context passed by the caller; errors are no longer possible, rename to proclist_make_node and change the signature accordingly. * rootdir.c, rootdir.h (rootdir_create_node): Likewise. * main.c (main): Create the ps_context here and pass it to root_make_node. (root_make_node): Pass it to proclist_make_node and rootdir_make_node. --- main.c | 35 ++++++++++++++++++++++------------- proclist.c | 15 +++------------ proclist.h | 6 ++++-- rootdir.c | 13 +++---------- rootdir.h | 6 ++++-- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/main.c b/main.c index 4be506fb..91156485 100644 --- a/main.c +++ b/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "procfs.h" #include "proclist.h" #include "rootdir.h" @@ -94,38 +95,42 @@ struct argp argp = { }; error_t -root_make_node (struct node **np) +root_make_node (struct ps_context *pc, struct node **np) { /* We never have two root nodes alive simultaneously, so it's ok to have this as static data. */ static struct node *root_dirs[3]; - error_t err; - err = proclist_create_node (getproc (), &root_dirs[0]); - if (err) - return err; + root_dirs[0] = proclist_make_node (pc); + if (! root_dirs[0]) + goto nomem; - err = rootdir_create_node (&root_dirs[1]); - if (err) - { - netfs_nrele (root_dirs[0]); - return err; - } + root_dirs[1] = rootdir_make_node (pc); + if (! root_dirs[1]) + goto nomem; root_dirs[2] = NULL; *np = dircat_make_node (root_dirs); if (! *np) - return ENOMEM; + goto nomem; /* Since this one is not created through proc_lookup(), we have to affect an inode number to it. */ (*np)->nn_stat.st_ino = * (uint32_t *) "PROC"; return 0; + +nomem: + if (root_dirs[1]) + netfs_nrele (root_dirs[1]); + if (root_dirs[0]) + netfs_nrele (root_dirs[0]); + return ENOMEM; } int main (int argc, char **argv) { + struct ps_context *pc; mach_port_t bootstrap; error_t err; @@ -137,12 +142,16 @@ int main (int argc, char **argv) if (err) error (1, err, "Could not parse command line"); + err = ps_context_create (getproc (), &pc); + if (err) + error (1, err, "Could not create libps context"); + task_get_bootstrap_port (mach_task_self (), &bootstrap); if (bootstrap == MACH_PORT_NULL) error (1, 0, "Must be started as a translator"); netfs_init (); - err = root_make_node (&netfs_root_node); + err = root_make_node (pc, &netfs_root_node); if (err) error (1, err, "Could not create the root node"); diff --git a/proclist.c b/proclist.c index 56a3fdf9..35422a81 100644 --- a/proclist.c +++ b/proclist.c @@ -62,24 +62,15 @@ proclist_lookup (void *hook, const char *name, struct node **np) return process_lookup_pid (pc, pid, np); } -error_t -proclist_create_node (process_t procserv, struct node **np) +struct node * +proclist_make_node (struct ps_context *pc) { static const struct procfs_node_ops ops = { .get_contents = proclist_get_contents, .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = (void (*)(void *)) ps_context_free, .enable_refresh_hack_and_break_readdir = 1, }; - struct ps_context *pc; - error_t err; - - err = ps_context_create (procserv, &pc); - if (err) - return err; - - *np = procfs_make_node (&ops, pc); - return 0; + return procfs_make_node (&ops, pc); } diff --git a/proclist.h b/proclist.h index 1c7ab084..ce69dde3 100644 --- a/proclist.h +++ b/proclist.h @@ -1,2 +1,4 @@ -#include -error_t proclist_create_node (process_t procserv, struct node **np); +#include + +struct node * +proclist_make_node (struct ps_context *pc); diff --git a/rootdir.c b/rootdir.c index 865342ce..8062f0d3 100644 --- a/rootdir.c +++ b/rootdir.c @@ -357,22 +357,15 @@ static const struct procfs_dir_entry rootdir_entries[] = { {} }; -error_t -rootdir_create_node (struct node **np) +struct node +*rootdir_make_node (struct ps_context *pc) { - struct ps_context *pc; const struct procfs_dir_entry *entries; - error_t err; - - err = ps_context_create (getproc (), &pc); - if (err) - return err; entries = rootdir_entries; if (opt_fake_self < 0) entries++; - *np = procfs_dir_make_node (entries, pc, (void (*)(void *)) ps_context_free); - return 0; + return procfs_dir_make_node (entries, pc, NULL); } diff --git a/rootdir.h b/rootdir.h index a764b0fd..0caee258 100644 --- a/rootdir.h +++ b/rootdir.h @@ -1,2 +1,4 @@ -error_t -rootdir_create_node (struct node **np); +#include + +struct node * +rootdir_make_node (struct ps_context *pc); -- cgit v1.2.3 From fa82e6672499e2fb5a4191c567c6a418d1f88405 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:02:13 +0000 Subject: Fix the handling of processes without an owner * main.c (argp_parser): New option --anonymous-owner. * main.h: Publish it. * process.c (process_lookup_pid): Use it to set the file owner uid of non-owned processes. --- main.c | 22 ++++++++++++++++++++++ main.h | 1 + process.c | 4 +++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 91156485..06c1da04 100644 --- a/main.c +++ b/main.c @@ -16,10 +16,12 @@ int opt_clk_tck; mode_t opt_stat_mode; pid_t opt_fake_self; pid_t opt_kernel_pid; +uid_t opt_anon_owner; static error_t argp_parser (int key, char *arg, struct argp_state *state) { + struct passwd *pw; char *endp; switch (key) @@ -58,6 +60,20 @@ argp_parser (int key, char *arg, struct argp_state *state) opt_stat_mode = 0444; opt_fake_self = 1; break; + + case 'a': + pw = getpwnam (arg); + if (pw) + { + opt_anon_owner = pw->pw_uid; + break; + } + + opt_anon_owner = strtol (arg, &endp, 0); + if (*endp || ! *arg || (signed) opt_anon_owner < 0) + error(1, 0, "--anonymous-owner: USER should be the a user name " + "or a numeric UID."); + break; } return 0; @@ -84,6 +100,11 @@ struct argp argp = { { "compatible", 'c', NULL, 0, "Try to be compatible with the Linux procps utilities. " "Currently equivalent to -h 100 -s 0444 -S 1." }, + { "anonymous-owner", 'a', "USER", 0, + "Make USER the owner of files related to processes without one. " + "Be aware that USER will be granted access to the environment and " + "other sensitive information about the processes in question. " + "(default: use uid 0)" }, {} }, .parser = argp_parser, @@ -138,6 +159,7 @@ int main (int argc, char **argv) opt_stat_mode = 0400; opt_fake_self = -1; opt_kernel_pid = 2; + opt_anon_owner = 0; err = argp_parse (&argp, argc, argv, 0, 0, 0); if (err) error (1, err, "Could not parse command line"); diff --git a/main.h b/main.h index 6ada229a..28d1b023 100644 --- a/main.h +++ b/main.h @@ -3,3 +3,4 @@ extern int opt_clk_tck; extern mode_t opt_stat_mode; extern pid_t opt_fake_self; extern pid_t opt_kernel_pid; +extern uid_t opt_anon_owner; diff --git a/process.c b/process.c index b2b098ff..7f5646ae 100644 --- a/process.c +++ b/process.c @@ -314,6 +314,7 @@ error_t process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) { struct proc_stat *ps; + int owner; error_t err; err = _proc_stat_create (pid, pc, &ps); @@ -334,6 +335,7 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) if (! *np) return ENOMEM; - procfs_node_chown (*np, proc_stat_owner_uid (ps)); + owner = proc_stat_owner_uid (ps); + procfs_node_chown (*np, owner >= 0 ? owner : opt_anon_owner); return 0; } -- cgit v1.2.3 From bff8f1d6895d32ded381e68cd647e437b28e22bf Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:02:48 +0000 Subject: Remove the unused procfs_file module * procfs_file.c, procfs_file.h: Remove. * Makefile: Remove procfs_file. --- procfs_file.c | 54 ------------------------------------------------------ procfs_file.h | 6 ------ 2 files changed, 60 deletions(-) delete mode 100644 procfs_file.c delete mode 100644 procfs_file.h diff --git a/procfs_file.c b/procfs_file.c deleted file mode 100644 index cb0488e9..00000000 --- a/procfs_file.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include "procfs.h" -#include "procfs_file.h" - -struct procfs_file -{ - void *contents; - size_t len; - void (*cleanup)(void *contents); -}; - -error_t -procfs_file_getcontents (void *hook, void **contents, size_t *contents_len) -{ - struct procfs_file *f = hook; - - *contents = f->contents; - *contents_len = f->len; - return 0; -} - -void -procfs_file_cleanup (void *hook) -{ - struct procfs_file *f = hook; - - if (f->cleanup) - f->cleanup (f->contents); - - free (f); -} - -struct node * -procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)) -{ - static const struct procfs_node_ops ops = { - .get_contents = procfs_file_getcontents, - .cleanup = procfs_file_cleanup, - }; - struct procfs_file *f; - - f = malloc (sizeof *f); - if (! f) - return NULL; - - f->contents = contents; - f->len = (len >= 0) ? len : strlen (f->contents); - f->cleanup = cleanup; - - return procfs_make_node (&ops, f); -} - diff --git a/procfs_file.h b/procfs_file.h deleted file mode 100644 index b615db93..00000000 --- a/procfs_file.h +++ /dev/null @@ -1,6 +0,0 @@ -/* Create a new regular file with the given CONTENTS. If LEN is negative, - CONTENTS is considered as a string and the file stops at the first - nul char. If CLEANUP is non-NULL, it is passed CONTENTS when the - node is destroyed. */ -struct node * -procfs_file_make_node (void *contents, ssize_t len, void (*cleanup)(void *)); -- cgit v1.2.3 From 0277bc261796743148769a3f76f9cae51c61e0a4 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:24:29 +0000 Subject: Make contents a char* to avoid typecasts all over the place * procfs.h (procfs_cleanup_contents_with_free, procfs_cleanup_contents_with_vm_deallocate, procfs_get_contents, struct procfs_ops): Change CONTENTS from a void pointer to a char one. * dircat.c, netfs.c, process.c, procfs.c, procfs_dir.c, proclist.c, rootdir.c: Update. --- dircat.c | 4 ++-- netfs.c | 10 +++++----- process.c | 2 +- procfs.c | 10 +++++----- procfs.h | 10 +++++----- procfs_dir.c | 2 +- proclist.c | 2 +- rootdir.c | 32 ++++++++++++++++---------------- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/dircat.c b/dircat.c index 857ba72b..93bb2fed 100644 --- a/dircat.c +++ b/dircat.c @@ -8,7 +8,7 @@ struct dircat_node }; static error_t -dircat_get_contents (void *hook, void **contents, size_t *contents_len) +dircat_get_contents (void *hook, char **contents, size_t *contents_len) { struct dircat_node *dcn = hook; int i, sz, pos; @@ -19,7 +19,7 @@ dircat_get_contents (void *hook, void **contents, size_t *contents_len) for (i=0; dcn->dirs[i]; i++) { - void *subcon; + char *subcon; size_t sublen; err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); diff --git a/netfs.c b/netfs.c index a47861e5..6fd82a00 100644 --- a/netfs.c +++ b/netfs.c @@ -29,7 +29,7 @@ int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; responsible for the operation. NP is locked. */ error_t netfs_validate_stat (struct node *np, struct iouser *cred) { - void *contents; + char *contents; size_t contents_len; error_t err; @@ -57,7 +57,7 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, size_t contents_len; error_t err; - err = procfs_get_contents (np, (void **) &contents, &contents_len); + err = procfs_get_contents (np, &contents, &contents_len); if (err) return err; @@ -82,7 +82,7 @@ error_t netfs_attempt_readlink (struct iouser *user, struct node *np, size_t contents_len; error_t err; - err = procfs_get_contents (np, (void **) &contents, &contents_len); + err = procfs_get_contents (np, &contents, &contents_len); if (err) return err; @@ -140,7 +140,7 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, size_t contents_len; error_t err; - err = procfs_get_contents (dir, (void **) &contents, &contents_len); + err = procfs_get_contents (dir, &contents, &contents_len); if (err) return err; @@ -159,7 +159,7 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, putentries (contents, contents_len, nentries, NULL, datacnt); if (bufsize < *datacnt) { - void *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); + char *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); if (n == MAP_FAILED) return ENOMEM; diff --git a/process.c b/process.c index 7f5646ae..fa795522 100644 --- a/process.c +++ b/process.c @@ -204,7 +204,7 @@ struct process_file_node }; static error_t -process_file_get_contents (void *hook, void **contents, size_t *contents_len) +process_file_get_contents (void *hook, char **contents, size_t *contents_len) { struct process_file_node *file = hook; error_t err; diff --git a/procfs.c b/procfs.c index 5396ecf7..a5f52b50 100644 --- a/procfs.c +++ b/procfs.c @@ -12,7 +12,7 @@ struct netnode void *hook; /* (cached) contents of the node */ - void *contents; + char *contents; size_t contents_len; /* parent directory, if applicable */ @@ -20,13 +20,13 @@ struct netnode }; void -procfs_cleanup_contents_with_free (void *hook, void *cont, size_t len) +procfs_cleanup_contents_with_free (void *hook, char *cont, size_t len) { free (cont); } void -procfs_cleanup_contents_with_vm_deallocate (void *hook, void *cont, size_t len) +procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, size_t len) { vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); } @@ -109,7 +109,7 @@ procfs_make_ino (struct node *np, const char *filename) return (unsigned long) jrand48 (x); } -error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) +error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) { if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) { @@ -121,7 +121,7 @@ error_t procfs_get_contents (struct node *np, void **data, size_t *data_len) if (! np->nn->contents && np->nn->ops->get_contents) { - void *contents; + char *contents; size_t contents_len; error_t err; diff --git a/procfs.h b/procfs.h index 4ab3b567..8336ee85 100644 --- a/procfs.h +++ b/procfs.h @@ -17,8 +17,8 @@ struct procfs_node_ops netnode->nn_stat. For regular files and symlinks, they are what you would expect; for directories, they are an argz vector of the names of the entries. */ - error_t (*get_contents) (void *hook, void **contents, size_t *contents_len); - void (*cleanup_contents) (void *hook, void *contents, size_t contents_len); + error_t (*get_contents) (void *hook, char **contents, size_t *contents_len); + void (*cleanup_contents) (void *hook, char *contents, size_t contents_len); /* Lookup NAME in this directory, and store the result in *np. The returned node should be created by lookup() using procfs_make_node() @@ -41,8 +41,8 @@ struct procfs_node_ops }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ -void procfs_cleanup_contents_with_free (void *, void *, size_t); -void procfs_cleanup_contents_with_vm_deallocate (void *, void *, size_t); +void procfs_cleanup_contents_with_free (void *, char *, size_t); +void procfs_cleanup_contents_with_vm_deallocate (void *, char *, size_t); /* Create a new node and return it. Returns NULL if it fails to allocate enough memory. In this case, ops->cleanup will be invoked. */ @@ -69,7 +69,7 @@ void procfs_node_chtype (struct node *np, mode_t type); corresponding child nodes. */ ino64_t procfs_make_ino (struct node *np, const char *filename); -error_t procfs_get_contents (struct node *np, void **data, size_t *data_len); +error_t procfs_get_contents (struct node *np, char **data, size_t *data_len); error_t procfs_lookup (struct node *np, const char *name, struct node **npp); void procfs_cleanup (struct node *np); diff --git a/procfs_dir.c b/procfs_dir.c index 431fea3e..4df46695 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -11,7 +11,7 @@ struct procfs_dir_node }; static error_t -procfs_dir_get_contents (void *hook, void **contents, size_t *contents_len) +procfs_dir_get_contents (void *hook, char **contents, size_t *contents_len) { static const char dot_dotdot[] = ".\0.."; struct procfs_dir_node *dn = hook; diff --git a/proclist.c b/proclist.c index 35422a81..b5acb26c 100644 --- a/proclist.c +++ b/proclist.c @@ -10,7 +10,7 @@ #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) static error_t -proclist_get_contents (void *hook, void **contents, size_t *contents_len) +proclist_get_contents (void *hook, char **contents, size_t *contents_len) { struct ps_context *pc = hook; pidarray_t pids; diff --git a/rootdir.c b/rootdir.c index 8062f0d3..cd8949bf 100644 --- a/rootdir.c +++ b/rootdir.c @@ -44,7 +44,7 @@ get_boottime (struct ps_context *pc, struct timeval *tv) } static error_t -rootdir_gc_version (void *hook, void **contents, size_t *contents_len) +rootdir_gc_version (void *hook, char **contents, size_t *contents_len) { struct utsname uts; int r; @@ -53,7 +53,7 @@ rootdir_gc_version (void *hook, void **contents, size_t *contents_len) if (r < 0) return errno; - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "Linux version 2.6.1 (%s %s %s %s)\n", uts.sysname, uts.release, uts.version, uts.machine); @@ -63,7 +63,7 @@ rootdir_gc_version (void *hook, void **contents, size_t *contents_len) /* Uptime -- we use the start time of init to deduce it. This is probably a bit fragile, as any clock update will make the result inaccurate. */ static error_t -rootdir_gc_uptime (void *hook, void **contents, size_t *contents_len) +rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) { struct timeval time, boottime; double up_secs; @@ -85,13 +85,13 @@ rootdir_gc_uptime (void *hook, void **contents, size_t *contents_len) proc(5) specifies that it should be equal to USER_HZ times the idle value in ticks from /proc/stat. So we assume a completely idle system both here and there to make that work. */ - *contents_len = asprintf ((char **) contents, "%.2lf %.2lf\n", up_secs, up_secs); + *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, up_secs); return *contents_len >= 0 ? 0 : ENOMEM; } static error_t -rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) +rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) { struct timeval boottime, time; struct vm_statistics vmstats; @@ -113,7 +113,7 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) timersub (&time, &boottime, &time); up_ticks = opt_clk_tck * (time.tv_sec + time.tv_usec / 1000000.); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, /* Does Mach keeps track of any of this? */ "cpu 0 0 0 %lu 0 0 0 0 0\n" "cpu0 0 0 0 %lu 0 0 0 0 0\n" @@ -130,7 +130,7 @@ rootdir_gc_stat (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) +rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) { host_load_info_data_t hli; mach_msg_type_number_t cnt; @@ -142,7 +142,7 @@ rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) return err; assert (cnt == HOST_LOAD_INFO_COUNT); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "%.2f %.2f %.2f 1/0 0\n", hli.avenrun[0] / (double) LOAD_SCALE, hli.avenrun[1] / (double) LOAD_SCALE, @@ -152,7 +152,7 @@ rootdir_gc_loadavg (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_meminfo (void *hook, void **contents, size_t *contents_len) +rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -169,7 +169,7 @@ rootdir_gc_meminfo (void *hook, void **contents, size_t *contents_len) return err; assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "MemTotal: %14lu kB\n" "MemFree: %14lu kB\n" "Active: %14lu kB\n" @@ -187,7 +187,7 @@ rootdir_gc_meminfo (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) +rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -204,7 +204,7 @@ rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) return err; assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf ((char **) contents, + *contents_len = asprintf (contents, "nr_free_pages %lu\n" "nr_inactive_anon %lu\n" "nr_active_anon %lu\n" @@ -232,7 +232,7 @@ rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len) } static error_t -rootdir_gc_cmdline (void *hook, void **contents, size_t *contents_len) +rootdir_gc_cmdline (void *hook, char **contents, size_t *contents_len) { struct ps_context *pc = hook; struct proc_stat *ps; @@ -259,7 +259,7 @@ rootdir_gc_cmdline (void *hook, void **contents, size_t *contents_len) memcpy (*contents, proc_stat_args (ps), *contents_len); argz_stringify (*contents, *contents_len, ' '); - ((char *) *contents)[*contents_len - 1] = '\n'; + (*contents)[*contents_len - 1] = '\n'; out: _proc_stat_free (ps); @@ -267,9 +267,9 @@ out: } static error_t -rootdir_gc_fakeself (void *hook, void **contents, size_t *contents_len) +rootdir_gc_fakeself (void *hook, char **contents, size_t *contents_len) { - *contents_len = asprintf ((char **) contents, "%d", opt_fake_self); + *contents_len = asprintf (contents, "%d", opt_fake_self); return *contents_len >= 0 ? 0 : ENOMEM; } -- cgit v1.2.3 From 2f30d52e2753c4fc854753ee2d0efb895a317c9f Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:33:22 +0000 Subject: Detect asprintf's ENOMEM in procfs.c rather than everywhere * procfs.h: Make CONTENTS_LEN an ssize_t rather than a size_t, and document the change. * procfs.c (procfs_get_contents): Initialize CONTENTS_LEN to a negative value, and fail with ENOMEM if it's still negative after the callback returns. (everywhere): Update to ssize_t. * dircat.c, netfs.c, process.c, procfs_dir.c, proclist.c, rootdir.c: Update to ssize_t and the new GET_CONTENTS semantics. --- dircat.c | 4 ++-- netfs.c | 8 ++++---- process.c | 54 ++++++++++++++++++++---------------------------------- procfs.c | 13 ++++++++----- procfs.h | 14 ++++++++------ procfs_dir.c | 2 +- proclist.c | 2 +- rootdir.c | 30 +++++++++++++++--------------- 8 files changed, 59 insertions(+), 68 deletions(-) diff --git a/dircat.c b/dircat.c index 93bb2fed..bb66508a 100644 --- a/dircat.c +++ b/dircat.c @@ -8,7 +8,7 @@ struct dircat_node }; static error_t -dircat_get_contents (void *hook, char **contents, size_t *contents_len) +dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct dircat_node *dcn = hook; int i, sz, pos; @@ -20,7 +20,7 @@ dircat_get_contents (void *hook, char **contents, size_t *contents_len) for (i=0; dcn->dirs[i]; i++) { char *subcon; - size_t sublen; + ssize_t sublen; err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); if (err) diff --git a/netfs.c b/netfs.c index 6fd82a00..e41e0623 100644 --- a/netfs.c +++ b/netfs.c @@ -30,7 +30,7 @@ int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; error_t netfs_validate_stat (struct node *np, struct iouser *cred) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; /* Only symlinks need to have their size filled, before a read is @@ -54,7 +54,7 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, loff_t offset, size_t *len, void *data) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (np, &contents, &contents_len); @@ -79,7 +79,7 @@ error_t netfs_attempt_readlink (struct iouser *user, struct node *np, char *buf) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (np, &contents, &contents_len); @@ -137,7 +137,7 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, vm_size_t bufsize, int *amt) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; err = procfs_get_contents (dir, &contents, &contents_len); diff --git a/process.c b/process.c index fa795522..624f79e7 100644 --- a/process.c +++ b/process.c @@ -12,18 +12,18 @@ /* Implementations for the process_file_desc.get_contents callback. */ -static char * -process_file_gc_cmdline (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_cmdline (struct proc_stat *ps, char **contents) { - *len = proc_stat_args_len(ps); - return proc_stat_args(ps); + *contents = proc_stat_args(ps); + return proc_stat_args_len(ps); } -static char * -process_file_gc_environ (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_environ (struct proc_stat *ps, char **contents) { - *len = proc_stat_args_len(ps); - return proc_stat_args(ps); + *contents = proc_stat_env(ps); + return proc_stat_env_len(ps); } static char state_char (struct proc_stat *ps) @@ -71,17 +71,16 @@ static long long int jiff_tv (time_value_t tv) return usecs * 100 / 1000000; } -static char * -process_file_gc_stat (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_stat (struct proc_stat *ps, char **contents) { struct procinfo *pi = proc_stat_proc_info (ps); task_basic_info_t tbi = proc_stat_task_basic_info (ps); thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); - char *contents; /* See proc(5) for more information about the contents of each field for the Linux procfs. */ - *len = asprintf (&contents, + return asprintf (contents, "%d (%s) %c " /* pid, command, state */ "%d %d %d " /* ppid, pgid, session */ "%d %d " /* controling tty stuff */ @@ -122,31 +121,23 @@ process_file_gc_stat (struct proc_stat *ps, size_t *len) 0, 0, 0, 0LL); - - return len >= 0 ? contents : NULL; } -static char * -process_file_gc_statm (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_statm (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); - char *contents; - - *len = asprintf (&contents, + return asprintf (contents, "%lu %lu 0 0 0 0 0\n", tbi->virtual_size / sysconf(_SC_PAGE_SIZE), tbi->resident_size / sysconf(_SC_PAGE_SIZE)); - - return len >= 0 ? contents : NULL; } -static char * -process_file_gc_status (struct proc_stat *ps, size_t *len) +static ssize_t +process_file_gc_status (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); - char *contents; - - *len = asprintf (&contents, + return asprintf (contents, "Name:\t%s\n" "State:\t%s\n" "Tgid:\t%u\n" @@ -172,8 +163,6 @@ process_file_gc_status (struct proc_stat *ps, size_t *len) tbi->resident_size / 1024, tbi->resident_size / 1024, proc_stat_num_threads (ps)); - - return len >= 0 ? contents : NULL; } @@ -186,7 +175,7 @@ struct process_file_desc /* Once we have acquired the necessary information, there can be only memory allocation errors, hence this simplified signature. */ - char *(*get_contents) (struct proc_stat *ps, size_t *len); + ssize_t (*get_contents) (struct proc_stat *ps, char **contents); /* The cmdline and environ contents don't need any cleaning since they are part of a proc_stat structure. */ @@ -204,7 +193,7 @@ struct process_file_node }; static error_t -process_file_get_contents (void *hook, char **contents, size_t *contents_len) +process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct process_file_node *file = hook; error_t err; @@ -215,10 +204,7 @@ process_file_get_contents (void *hook, char **contents, size_t *contents_len) if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) return EIO; - *contents = file->desc->get_contents (file->ps, contents_len); - if (! *contents) - return ENOMEM; - + *contents_len = file->desc->get_contents (file->ps, contents); return 0; } diff --git a/procfs.c b/procfs.c index a5f52b50..6d15e4fd 100644 --- a/procfs.c +++ b/procfs.c @@ -13,20 +13,20 @@ struct netnode /* (cached) contents of the node */ char *contents; - size_t contents_len; + ssize_t contents_len; /* parent directory, if applicable */ struct node *parent; }; void -procfs_cleanup_contents_with_free (void *hook, char *cont, size_t len) +procfs_cleanup_contents_with_free (void *hook, char *cont, ssize_t len) { free (cont); } void -procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, size_t len) +procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, ssize_t len) { vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); } @@ -109,7 +109,7 @@ procfs_make_ino (struct node *np, const char *filename) return (unsigned long) jrand48 (x); } -error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) { if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) { @@ -122,12 +122,15 @@ error_t procfs_get_contents (struct node *np, char **data, size_t *data_len) if (! np->nn->contents && np->nn->ops->get_contents) { char *contents; - size_t contents_len; + ssize_t contents_len; error_t err; + contents_len = -1; err = np->nn->ops->get_contents (np->nn->hook, &contents, &contents_len); if (err) return err; + if (contents_len < 0) + return ENOMEM; np->nn->contents = contents; np->nn->contents_len = contents_len; diff --git a/procfs.h b/procfs.h index 8336ee85..e8ef18b3 100644 --- a/procfs.h +++ b/procfs.h @@ -16,9 +16,11 @@ struct procfs_node_ops symlink or directory, as determined by the file mode in netnode->nn_stat. For regular files and symlinks, they are what you would expect; for directories, they are an argz vector of the - names of the entries. */ - error_t (*get_contents) (void *hook, char **contents, size_t *contents_len); - void (*cleanup_contents) (void *hook, char *contents, size_t contents_len); + names of the entries. If upon return, *CONTENTS_LEN is negative or + unchanged, the call is considered to have failed because of a memory + allocation error. */ + error_t (*get_contents) (void *hook, char **contents, ssize_t *contents_len); + void (*cleanup_contents) (void *hook, char *contents, ssize_t contents_len); /* Lookup NAME in this directory, and store the result in *np. The returned node should be created by lookup() using procfs_make_node() @@ -41,8 +43,8 @@ struct procfs_node_ops }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ -void procfs_cleanup_contents_with_free (void *, char *, size_t); -void procfs_cleanup_contents_with_vm_deallocate (void *, char *, size_t); +void procfs_cleanup_contents_with_free (void *, char *, ssize_t); +void procfs_cleanup_contents_with_vm_deallocate (void *, char *, ssize_t); /* Create a new node and return it. Returns NULL if it fails to allocate enough memory. In this case, ops->cleanup will be invoked. */ @@ -69,7 +71,7 @@ void procfs_node_chtype (struct node *np, mode_t type); corresponding child nodes. */ ino64_t procfs_make_ino (struct node *np, const char *filename); -error_t procfs_get_contents (struct node *np, char **data, size_t *data_len); +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len); error_t procfs_lookup (struct node *np, const char *name, struct node **npp); void procfs_cleanup (struct node *np); diff --git a/procfs_dir.c b/procfs_dir.c index 4df46695..8ec3f7a5 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -11,7 +11,7 @@ struct procfs_dir_node }; static error_t -procfs_dir_get_contents (void *hook, char **contents, size_t *contents_len) +procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) { static const char dot_dotdot[] = ".\0.."; struct procfs_dir_node *dn = hook; diff --git a/proclist.c b/proclist.c index b5acb26c..38368feb 100644 --- a/proclist.c +++ b/proclist.c @@ -10,7 +10,7 @@ #define PID_STR_SIZE (3 * sizeof (pid_t) + 1) static error_t -proclist_get_contents (void *hook, char **contents, size_t *contents_len) +proclist_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct ps_context *pc = hook; pidarray_t pids; diff --git a/rootdir.c b/rootdir.c index cd8949bf..364b0731 100644 --- a/rootdir.c +++ b/rootdir.c @@ -44,7 +44,7 @@ get_boottime (struct ps_context *pc, struct timeval *tv) } static error_t -rootdir_gc_version (void *hook, char **contents, size_t *contents_len) +rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) { struct utsname uts; int r; @@ -57,13 +57,13 @@ rootdir_gc_version (void *hook, char **contents, size_t *contents_len) "Linux version 2.6.1 (%s %s %s %s)\n", uts.sysname, uts.release, uts.version, uts.machine); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } /* Uptime -- we use the start time of init to deduce it. This is probably a bit fragile, as any clock update will make the result inaccurate. */ static error_t -rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) +rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) { struct timeval time, boottime; double up_secs; @@ -87,11 +87,11 @@ rootdir_gc_uptime (void *hook, char **contents, size_t *contents_len) and there to make that work. */ *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, up_secs); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) +rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) { struct timeval boottime, time; struct vm_statistics vmstats; @@ -126,11 +126,11 @@ rootdir_gc_stat (void *hook, char **contents, size_t *contents_len) vmstats.pageins, vmstats.pageouts, boottime.tv_sec); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) +rootdir_gc_loadavg (void *hook, char **contents, ssize_t *contents_len) { host_load_info_data_t hli; mach_msg_type_number_t cnt; @@ -148,11 +148,11 @@ rootdir_gc_loadavg (void *hook, char **contents, size_t *contents_len) hli.avenrun[1] / (double) LOAD_SCALE, hli.avenrun[2] / (double) LOAD_SCALE); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) +rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -183,11 +183,11 @@ rootdir_gc_meminfo (void *hook, char **contents, size_t *contents_len) (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) +rootdir_gc_vmstat (void *hook, char **contents, ssize_t *contents_len) { host_basic_info_data_t hbi; mach_msg_type_number_t cnt; @@ -228,11 +228,11 @@ rootdir_gc_vmstat (void *hook, char **contents, size_t *contents_len) (long unsigned) vmstats.pageouts, (long unsigned) vmstats.faults); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } static error_t -rootdir_gc_cmdline (void *hook, char **contents, size_t *contents_len) +rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) { struct ps_context *pc = hook; struct proc_stat *ps; @@ -267,10 +267,10 @@ out: } static error_t -rootdir_gc_fakeself (void *hook, char **contents, size_t *contents_len) +rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) { *contents_len = asprintf (contents, "%d", opt_fake_self); - return *contents_len >= 0 ? 0 : ENOMEM; + return 0; } -- cgit v1.2.3 From e7563c6a79a163b727027c676e96b99b7ae2624e Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 11:54:10 +0000 Subject: Improve the interface for dircat_make_node * dircat.c, dircat.h (dircat_make_node): Use an explicit array size for DIRS, fail with ENOMEM is any of them is NULL, and release the reference on the non-NULL nodes on any error. * main.c (root_make_node): Use the new interface. --- dircat.c | 37 +++++++++++++++++++++++-------------- dircat.h | 17 +++++++++-------- main.c | 27 ++++++--------------------- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/dircat.c b/dircat.c index bb66508a..d043486d 100644 --- a/dircat.c +++ b/dircat.c @@ -4,7 +4,8 @@ struct dircat_node { - struct node **dirs; + int num_dirs; + struct node *dirs[0]; }; static error_t @@ -17,7 +18,7 @@ dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) pos = 0; *contents = malloc (sz = 512); - for (i=0; dcn->dirs[i]; i++) + for (i=0; i < dcn->num_dirs; i++) { char *subcon; ssize_t sublen; @@ -49,19 +50,20 @@ dircat_lookup (void *hook, const char *name, struct node **np) int i; err = ENOENT; - for (i=0; err && dcn->dirs[i]; i++) + for (i=0; err && i < dcn->num_dirs; i++) err = procfs_lookup (dcn->dirs[i], name, np); return err; } static void -dircat_release_dirs (struct node **dirs) +dircat_release_dirs (struct node *const *dirs, int num_dirs) { int i; - for (i=0; dirs[i]; i++) - netfs_nrele (dirs[i]); + for (i=0; i < num_dirs; i++) + if (dirs[i]) + netfs_nrele (dirs[i]); } static void @@ -69,12 +71,12 @@ dircat_cleanup (void *hook) { struct dircat_node *dcn = hook; - dircat_release_dirs (dcn->dirs); + dircat_release_dirs (dcn->dirs, dcn->num_dirs); free (dcn); } struct node * -dircat_make_node (struct node **dirs) +dircat_make_node (struct node *const *dirs, int num_dirs) { static struct procfs_node_ops ops = { .get_contents = dircat_get_contents, @@ -85,15 +87,22 @@ dircat_make_node (struct node **dirs) .enable_refresh_hack_and_break_readdir = 1, }; struct dircat_node *dcn; + int i; + + for (i=0; i < num_dirs; i++) + if (! dirs[i]) + goto fail; - dcn = malloc (sizeof *dcn); + dcn = malloc (sizeof *dcn + num_dirs * sizeof dcn->dirs[0]); if (! dcn) - { - dircat_release_dirs (dirs); - return NULL; - } + goto fail; - dcn->dirs = dirs; + dcn->num_dirs = num_dirs; + memcpy (dcn->dirs, dirs, num_dirs * sizeof dcn->dirs[0]); return procfs_make_node (&ops, dcn); + +fail: + dircat_release_dirs (dirs, num_dirs); + return NULL; } diff --git a/dircat.h b/dircat.h index cb228526..951d2021 100644 --- a/dircat.h +++ b/dircat.h @@ -1,9 +1,10 @@ -/* Append the contents of multiple directories. DIRS is a - NULL-terminated array of directory nodes. One reference is consumed - for each of them, even on ENOMEM, in which case NULL is returned. - DIRS has to be static data for now, or at list remain available and - unchanged for the duration of the created node's life. Strange - things will happen if they have entries with the same name or if one - of them is not a directory. */ +/* Append the contents of NUM_DIRS directories. DIRS is an array of + directory nodes. One reference is consumed for each of them. If a + memory allocation error occurs, or if one of the directories is a + NULL pointer, the references are dropped immediately and NULL is + returned. The given DIRS array is duplicated and can therefore be + allocated on the caller's stack. Strange things will happen if some + elements of DIRS have entries with the same name or if one of them is + not a directory. */ struct node * -dircat_make_node (struct node **dirs); +dircat_make_node (struct node *const *dirs, int num_dirs); diff --git a/main.c b/main.c index 06c1da04..eaab9867 100644 --- a/main.c +++ b/main.c @@ -118,35 +118,20 @@ struct argp argp = { error_t root_make_node (struct ps_context *pc, struct node **np) { - /* We never have two root nodes alive simultaneously, so it's ok to - have this as static data. */ - static struct node *root_dirs[3]; + struct node *root_dirs[] = { + proclist_make_node (pc), + rootdir_make_node (pc), + }; - root_dirs[0] = proclist_make_node (pc); - if (! root_dirs[0]) - goto nomem; - - root_dirs[1] = rootdir_make_node (pc); - if (! root_dirs[1]) - goto nomem; - - root_dirs[2] = NULL; - *np = dircat_make_node (root_dirs); + *np = dircat_make_node (root_dirs, sizeof root_dirs / sizeof root_dirs[0]); if (! *np) - goto nomem; + return ENOMEM; /* Since this one is not created through proc_lookup(), we have to affect an inode number to it. */ (*np)->nn_stat.st_ino = * (uint32_t *) "PROC"; return 0; - -nomem: - if (root_dirs[1]) - netfs_nrele (root_dirs[1]); - if (root_dirs[0]) - netfs_nrele (root_dirs[0]); - return ENOMEM; } int main (int argc, char **argv) -- cgit v1.2.3 From 6a887dbb2c998e250df612f7c28c00d3e7ba8b38 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 14:15:54 +0000 Subject: Revamp procfs_dir * procfs_dir.c, procfs_dir.h: Revamp the interface to make the more complicated use cases somewhat less hackish. * process.c: Update, specify a default make_node function. * rootdir.c: Likewise; make this optional "self" link use case somewhat less hackish. --- process.c | 16 +++++++------ procfs_dir.c | 78 ++++++++++++++++++++++++++++++++++++++---------------------- procfs_dir.h | 48 +++++++++++++++++++++++++++---------- rootdir.c | 36 +++++++++++++++------------- 4 files changed, 113 insertions(+), 65 deletions(-) diff --git a/process.c b/process.c index 624f79e7..61688f7e 100644 --- a/process.c +++ b/process.c @@ -209,7 +209,7 @@ process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) } static struct node * -process_file_make_node (void *dir_hook, void *entry_hook) +process_file_make_node (void *dir_hook, const void *entry_hook) { static const struct procfs_node_ops ops = { .get_contents = process_file_get_contents, @@ -245,7 +245,6 @@ process_file_make_node (void *dir_hook, void *entry_hook) static struct procfs_dir_entry entries[] = { { .name = "cmdline", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_cmdline, .needs = PSTAT_ARGS, @@ -254,7 +253,6 @@ static struct procfs_dir_entry entries[] = { }, { .name = "environ", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_environ, .needs = PSTAT_ENV, @@ -265,7 +263,6 @@ static struct procfs_dir_entry entries[] = { { /* Beware of the hack below, which requires this to be entries[2]. */ .name = "stat", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_stat, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO @@ -276,7 +273,6 @@ static struct procfs_dir_entry entries[] = { }, { .name = "statm", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_statm, .needs = PSTAT_TASK_BASIC, @@ -285,7 +281,6 @@ static struct procfs_dir_entry entries[] = { }, { .name = "status", - .make_node = process_file_make_node, .hook = & (struct process_file_desc) { .get_contents = process_file_gc_status, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO @@ -299,6 +294,13 @@ static struct procfs_dir_entry entries[] = { error_t process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) { + static const struct procfs_dir_ops dir_ops = { + .entries = entries, + .cleanup = (void (*)(void *)) _proc_stat_free, + .entry_ops = { + .make_node = process_file_make_node, + }, + }; struct proc_stat *ps; int owner; error_t err; @@ -317,7 +319,7 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) accessed in a more robust and straightforward way. */ ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; - *np = procfs_dir_make_node (entries, ps, (void (*)(void *)) _proc_stat_free); + *np = procfs_dir_make_node (&dir_ops, ps); if (! *np) return ENOMEM; diff --git a/procfs_dir.c b/procfs_dir.c index 8ec3f7a5..dfe30a26 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -5,49 +5,71 @@ struct procfs_dir_node { - const struct procfs_dir_entry *entries; + const struct procfs_dir_ops *ops; void *hook; - void (*cleanup) (void *hook); }; +static int +entry_exists (struct procfs_dir_node *dir, const struct procfs_dir_entry *ent) +{ + if (ent->ops.exists) + return ent->ops.exists (dir->hook, ent->hook); + if (dir->ops->entry_ops.exists) + return dir->ops->entry_ops.exists (dir->hook, ent->hook); + + return 1; +} + static error_t procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) { static const char dot_dotdot[] = ".\0.."; - struct procfs_dir_node *dn = hook; + struct procfs_dir_node *dir = hook; const struct procfs_dir_entry *ent; - char *pos; + int pos; - *contents_len = sizeof dot_dotdot; - for (ent = dn->entries; ent->name; ent++) - *contents_len += strlen (ent->name) + 1; + /* Evaluate how much space is needed. Note that we include the hidden + entries, just in case their status changes between now and then. */ + pos = sizeof dot_dotdot; + for (ent = dir->ops->entries; ent->name; ent++) + pos += strlen (ent->name) + 1; - *contents = malloc (*contents_len); + *contents = malloc (pos); if (! *contents) return ENOMEM; memcpy (*contents, dot_dotdot, sizeof dot_dotdot); - pos = *contents + sizeof dot_dotdot; - for (ent = dn->entries; ent->name; ent++) + pos = sizeof dot_dotdot; + for (ent = dir->ops->entries; ent->name; ent++) { - strcpy (pos, ent->name); + if (! entry_exists (dir, ent)) + continue; + + strcpy (*contents + pos, ent->name); pos += strlen (ent->name) + 1; } + *contents_len = pos; return 0; } static error_t procfs_dir_lookup (void *hook, const char *name, struct node **np) { - struct procfs_dir_node *dn = hook; + struct procfs_dir_node *dir = hook; const struct procfs_dir_entry *ent; - for (ent = dn->entries; ent->name && strcmp (name, ent->name); ent++); + for (ent = dir->ops->entries; ent->name && strcmp (name, ent->name); ent++); if (! ent->name) return ENOENT; - *np = ent->make_node (dn->hook, ent->hook); + if (ent->ops.make_node) + *np = ent->ops.make_node (dir->hook, ent->hook); + else if (dir->ops->entry_ops.make_node) + *np = dir->ops->entry_ops.make_node (dir->hook, ent->hook); + else + return EGRATUITOUS; + if (! *np) return ENOMEM; @@ -57,17 +79,16 @@ procfs_dir_lookup (void *hook, const char *name, struct node **np) static void procfs_dir_cleanup (void *hook) { - struct procfs_dir_node *dn = hook; + struct procfs_dir_node *dir = hook; - if (dn->cleanup) - dn->cleanup (dn->hook); + if (dir->ops->cleanup) + dir->ops->cleanup (dir->hook); - free (dn); + free (dir); } struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, - void *dir_hook, void (*cleanup) (void *dir_hook)) +procfs_dir_make_node (const struct procfs_dir_ops *dir_ops, void *dir_hook) { static const struct procfs_node_ops ops = { .get_contents = procfs_dir_get_contents, @@ -75,21 +96,20 @@ procfs_dir_make_node (const struct procfs_dir_entry *entries, .cleanup_contents = procfs_cleanup_contents_with_free, .cleanup = procfs_dir_cleanup, }; - struct procfs_dir_node *dn; + struct procfs_dir_node *dir; - dn = malloc (sizeof *dn); - if (! dn) + dir = malloc (sizeof *dir); + if (! dir) { - if (cleanup) - cleanup (dir_hook); + if (dir_ops->cleanup) + dir_ops->cleanup (dir_hook); return NULL; } - dn->entries = entries; - dn->hook = dir_hook; - dn->cleanup = cleanup; + dir->ops = dir_ops; + dir->hook = dir_hook; - return procfs_make_node (&ops, dn); + return procfs_make_node (&ops, dir); } diff --git a/procfs_dir.h b/procfs_dir.h index 4eb934e0..12e99d2a 100644 --- a/procfs_dir.h +++ b/procfs_dir.h @@ -1,20 +1,44 @@ +/* This module provides an abstraction layer for implementing simple + directories with (mostly) static contents. The user defines the + contents of the directory by providing a table of entries and various + optional callback functions. */ -/* Each entry associates a name with a callback function for creating new - nodes corresponding to that entry. */ +/* These operations define how a given entry will behave. Either can be + omitted, both from the entry-specific operations and from the + directory-wide defaults. */ +struct procfs_dir_entry_ops +{ + /* Called when this entry is looked up to create a corresponding node. */ + struct node *(*make_node)(void *dir_hook, const void *entry_hook); + /* If this is provided and returns 0, this entry will be hidden. */ + int (*exists)(void *dir_hook, const void *entry_hook); +}; + +/* Describes an individual directory entry, associating a NAME with + * arbitrary HOOK data and node-specific OPS. */ struct procfs_dir_entry { const char *name; - struct node *(*make_node)(void *dir_hook, void *entry_hook); - void *hook; + const void *hook; + struct procfs_dir_entry_ops ops; +}; + +/* Describes a complete directory. ENTRIES is a table terminated by a + null NAME field. ENTRY_OPS provides default operations for the + entries which don't specify them. The optional CLEANUP function + should release all the resources associated with the directory hook. */ +struct procfs_dir_ops +{ + const struct procfs_dir_entry *entries; + void (*cleanup)(void *dir_hook); + struct procfs_dir_entry_ops entry_ops; }; -/* A simple directory is built from a table of entries. The table is - terminated by a null NAME pointer. The DIR_HOOK is passed the - MAKE_NODE callback function of looked up procfs_dir_entries, and to - the provided CLEANUP function when the directory is destroyed. - Returns the new directory node. If not enough memory can be - allocated, CLEANUP is invoked immediately and NULL is returned. */ +/* Create and return a new node for the directory described in OPS. + The DIR_HOOK is passed the MAKE_NODE callback function of looked up + entries, as well as to the CLEANUP callback when the node is + destroyed. If not enough memory can be allocated, OPS->CLEANUP is + invoked immediately and NULL is returned. */ struct node * -procfs_dir_make_node (const struct procfs_dir_entry *entries, - void *dir_hook, void (*cleanup) (void *dir_hook)); +procfs_dir_make_node (const struct procfs_dir_ops *ops, void *dir_hook); diff --git a/rootdir.c b/rootdir.c index 364b0731..dcee9a54 100644 --- a/rootdir.c +++ b/rootdir.c @@ -266,6 +266,12 @@ out: return err; } +static int +rootdir_fakeself_exists () +{ + return opt_fake_self >= 0; +} + static error_t rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) { @@ -275,13 +281,13 @@ rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) static struct node * -rootdir_file_make_node (void *dir_hook, void *entry_hook) +rootdir_file_make_node (void *dir_hook, const void *entry_hook) { return procfs_make_node (entry_hook, dir_hook); } static struct node * -rootdir_symlink_make_node (void *dir_hook, void *entry_hook) +rootdir_symlink_make_node (void *dir_hook, const void *entry_hook) { struct node *np = procfs_make_node (entry_hook, dir_hook); if (np) @@ -292,15 +298,17 @@ rootdir_symlink_make_node (void *dir_hook, void *entry_hook) static const struct procfs_dir_entry rootdir_entries[] = { { .name = "self", - .make_node = rootdir_symlink_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_fakeself, .cleanup_contents = procfs_cleanup_contents_with_free, }, + .ops = { + .make_node = rootdir_symlink_make_node, + .exists = rootdir_fakeself_exists, + } }, { .name = "version", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_version, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -308,7 +316,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "uptime", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_uptime, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -316,7 +323,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "stat", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_stat, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -324,7 +330,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "loadavg", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_loadavg, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -332,7 +337,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "meminfo", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_meminfo, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -340,7 +344,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "vmstat", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_vmstat, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -348,7 +351,6 @@ static const struct procfs_dir_entry rootdir_entries[] = { }, { .name = "cmdline", - .make_node = rootdir_file_make_node, .hook = & (struct procfs_node_ops) { .get_contents = rootdir_gc_cmdline, .cleanup_contents = procfs_cleanup_contents_with_free, @@ -360,12 +362,12 @@ static const struct procfs_dir_entry rootdir_entries[] = { struct node *rootdir_make_node (struct ps_context *pc) { - const struct procfs_dir_entry *entries; - - entries = rootdir_entries; - if (opt_fake_self < 0) - entries++; - - return procfs_dir_make_node (entries, pc, NULL); + static const struct procfs_dir_ops ops = { + .entries = rootdir_entries, + .entry_ops = { + .make_node = rootdir_file_make_node, + }, + }; + return procfs_dir_make_node (&ops, pc); } -- cgit v1.2.3 From 49ffe9e1dc9b12fa1c87c103326e0207d0cf45d8 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 16:46:04 +0000 Subject: Cleanup pass on process.c * process.c: Reorder some of the code. Improve comments. Jiffies and clock tick are the same thing, right? Replace the stat mode and cleanup hacks by more straightforward solutions. --- process.c | 122 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 79 insertions(+), 43 deletions(-) diff --git a/process.c b/process.c index 61688f7e..1f9d5781 100644 --- a/process.c +++ b/process.c @@ -9,22 +9,20 @@ #include "procfs_dir.h" #include "process.h" #include "main.h" - -/* Implementations for the process_file_desc.get_contents callback. */ -static ssize_t -process_file_gc_cmdline (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_args(ps); - return proc_stat_args_len(ps); -} +/* This module implements the process directories and the files they + contain. A libps proc_stat structure is created for each process + node, and is used by the individual file content generators as a + source of information. Each possible file (cmdline, environ, ...) is + decribed in a process_file_desc structure, which specifies which bits + of information (ie. libps flags) it needs, and what function should + be used to generate the file's contents. -static ssize_t -process_file_gc_environ (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_env(ps); - return proc_stat_env_len(ps); -} + The content generators are defined first, followed by glue logic and + entry table. */ + + +/* Helper functions */ static char state_char (struct proc_stat *ps) { @@ -58,17 +56,26 @@ static const char *state_string (struct proc_stat *ps) return "? (unknown)"; } -static long int sc_tv (time_value_t tv) +static long long int timeval_jiffies (time_value_t tv) { - double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; - return usecs * opt_clk_tck / 1000000; + double secs = tv.seconds + tv.microseconds / 1000000.; + return secs * opt_clk_tck; } -static long long int jiff_tv (time_value_t tv) +/* Actual content generators */ + +static ssize_t +process_file_gc_cmdline (struct proc_stat *ps, char **contents) { - double usecs = ((double) tv.seconds) * 1000000 + tv.microseconds; - /* Let's say a jiffy is 1/100 of a second.. */ - return usecs * 100 / 1000000; + *contents = proc_stat_args(ps); + return proc_stat_args_len(ps); +} + +static ssize_t +process_file_gc_environ (struct proc_stat *ps, char **contents) +{ + *contents = proc_stat_env(ps); + return proc_stat_env_len(ps); } static ssize_t @@ -105,17 +112,18 @@ process_file_gc_stat (struct proc_stat *ps, char **contents) 0, 0, /* no such thing as a major:minor for ctty */ 0, /* no such thing as CLONE_* flags on Hurd */ 0L, 0L, 0L, 0L, /* TASK_EVENTS_INFO is unavailable on GNU Mach */ - sc_tv (thbi->user_time), sc_tv (thbi->system_time), + (long unsigned) timeval_jiffies (thbi->user_time), + (long unsigned) timeval_jiffies (thbi->system_time), 0L, 0L, /* cumulative time for children */ MACH_PRIORITY_TO_NICE(thbi->base_priority) + 20, MACH_PRIORITY_TO_NICE(thbi->base_priority), pi->nthreads, 0L, - jiff_tv (thbi->creation_time), /* FIXME: ... since boot */ - (long unsigned int) tbi->virtual_size, - (long unsigned int) tbi->resident_size / PAGE_SIZE, 0L, + timeval_jiffies (thbi->creation_time), /* FIXME: ... since boot */ + (long unsigned) tbi->virtual_size, + (long unsigned) tbi->resident_size / PAGE_SIZE, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, - (long unsigned int) proc_stat_thread_rpc (ps), /* close enough */ + (long unsigned) proc_stat_thread_rpc (ps), /* close enough */ 0L, 0L, 0, 0, @@ -127,6 +135,7 @@ static ssize_t process_file_gc_statm (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); + return asprintf (contents, "%lu %lu 0 0 0 0 0\n", tbi->virtual_size / sysconf(_SC_PAGE_SIZE), @@ -137,6 +146,7 @@ static ssize_t process_file_gc_status (struct proc_stat *ps, char **contents) { task_basic_info_t tbi = proc_stat_task_basic_info (ps); + return asprintf (contents, "Name:\t%s\n" "State:\t%s\n" @@ -165,59 +175,70 @@ process_file_gc_status (struct proc_stat *ps, char **contents) proc_stat_num_threads (ps)); } + +/* Implementation of the file nodes. */ -/* Describes a file in a process directory. This is used as an "entry hook" - * for our procfs_dir entry table, passed to process_file_make_node. */ +/* Describes a file in the process directories. This structure is + filled in as an "entry hook" in our procfs_dir entry table and is + passed to the process_file_make_node function defined below. */ struct process_file_desc { /* The proc_stat information required to get the contents of this file. */ ps_flags_t needs; - /* Once we have acquired the necessary information, there can be only - memory allocation errors, hence this simplified signature. */ + /* Content generator to use for this file. Once we have acquired the + necessary information, there can be only memory allocation errors, + hence this simplified signature. */ ssize_t (*get_contents) (struct proc_stat *ps, char **contents); - /* The cmdline and environ contents don't need any cleaning since they are - part of a proc_stat structure. */ + /* The cmdline and environ contents don't need any cleaning since they + point directly into the proc_stat structure. */ int no_cleanup; /* If specified, the file mode to be set with procfs_node_chmod(). */ mode_t mode; }; -/* Information associated to an actual file node. */ struct process_file_node { const struct process_file_desc *desc; struct proc_stat *ps; }; +/* FIXME: lock the parent! */ static error_t process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) { struct process_file_node *file = hook; error_t err; + /* Fetch the required information. */ err = proc_stat_set_flags (file->ps, file->desc->needs); if (err) return EIO; if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) return EIO; + /* Call the actual content generator (see the definitions below). */ *contents_len = file->desc->get_contents (file->ps, contents); return 0; } +static void +process_file_cleanup_contents (void *hook, char *contents, ssize_t len) +{ + struct process_file_node *file = hook; + + if (! file->desc->no_cleanup) + free (contents); +} + static struct node * process_file_make_node (void *dir_hook, const void *entry_hook) { static const struct procfs_node_ops ops = { .get_contents = process_file_get_contents, - .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = free, - }; - static const struct procfs_node_ops ops_no_cleanup = { - .get_contents = process_file_get_contents, + .cleanup_contents = process_file_cleanup_contents, .cleanup = free, }; struct process_file_node *f; @@ -230,7 +251,7 @@ process_file_make_node (void *dir_hook, const void *entry_hook) f->desc = entry_hook; f->ps = dir_hook; - np = procfs_make_node (f->desc->no_cleanup ? &ops_no_cleanup : &ops, f); + np = procfs_make_node (&ops, f); if (! np) return NULL; @@ -241,6 +262,18 @@ process_file_make_node (void *dir_hook, const void *entry_hook) return np; } +/* Stat needs its own constructor in oreder to set its mode according to + the --stat-mode command-line option. */ +static struct node * +process_stat_make_node (void *dir_hook, const void *entry_hook) +{ + struct node *np = process_file_make_node (dir_hook, entry_hook); + if (np) procfs_node_chmod (np, opt_stat_mode); + return np; +} + + +/* Implementation of the process directory per se. */ static struct procfs_dir_entry entries[] = { { @@ -261,22 +294,22 @@ static struct procfs_dir_entry entries[] = { }, }, { - /* Beware of the hack below, which requires this to be entries[2]. */ .name = "stat", .hook = & (struct process_file_desc) { .get_contents = process_file_gc_stat, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC | PSTAT_THREAD_WAIT, - .mode = 0400, }, + .ops = { + .make_node = process_stat_make_node, + } }, { .name = "statm", .hook = & (struct process_file_desc) { .get_contents = process_file_gc_statm, .needs = PSTAT_TASK_BASIC, - .mode = 0444, }, }, { @@ -285,7 +318,6 @@ static struct procfs_dir_entry entries[] = { .get_contents = process_file_gc_status, .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO | PSTAT_TASK_BASIC | PSTAT_OWNER_UID | PSTAT_NUM_THREADS, - .mode = 0444, }, }, {} @@ -319,6 +351,10 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) accessed in a more robust and straightforward way. */ ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + /* FIXME: have a separate proc_desc structure for each file, so this can be + accessed in a more robust and straightforward way. */ + ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + *np = procfs_dir_make_node (&dir_ops, ps); if (! *np) return ENOMEM; -- cgit v1.2.3 From f3bac2c0691d9bd5c89de206faa809cd34d86c35 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 19:04:48 +0000 Subject: Fix the global idle time * rootdir.c: Replace INIT_PID by KERNEL_PID, for boot time and idle time purposes. (get_idletime): New function, queries the kernel's idle thread. (rootdir_gc_uptime, rootdir_gc_stat): Use the new function and provide the real idle time. --- rootdir.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/rootdir.c b/rootdir.c index dcee9a54..728008e5 100644 --- a/rootdir.c +++ b/rootdir.c @@ -16,15 +16,16 @@ using them would require locking and as a consequence it would be more complicated, not simpler. */ -#define INIT_PID 1 +#define KERNEL_PID 2 +/* We get the boot time by using that of the kernel process. */ static error_t get_boottime (struct ps_context *pc, struct timeval *tv) { struct proc_stat *ps; error_t err; - err = _proc_stat_create (INIT_PID, pc, &ps); + err = _proc_stat_create (KERNEL_PID, pc, &ps); if (err) return err; @@ -43,6 +44,63 @@ get_boottime (struct ps_context *pc, struct timeval *tv) return err; } +/* We get the idle time by querying the kernel's idle thread. */ +static error_t +get_idletime (struct ps_context *pc, struct timeval *tv) +{ + struct proc_stat *ps, *pst; + thread_basic_info_t tbi; + error_t err; + int i; + + err = _proc_stat_create (KERNEL_PID, pc, &ps); + if (err) + return err; + + pst = NULL, tbi = NULL; + + err = proc_stat_set_flags (ps, PSTAT_NUM_THREADS); + if (err || !(proc_stat_flags (ps) & PSTAT_NUM_THREADS)) + { + err = EIO; + goto out; + } + + /* Look for the idle thread */ + for (i=0; !tbi || !(tbi->flags & TH_FLAGS_IDLE); i++) + { + if (pst) + _proc_stat_free (pst); + + pst = NULL, tbi = NULL; + if (i >= proc_stat_num_threads (ps)) + { + err = ESRCH; + goto out; + } + + err = proc_stat_thread_create (ps, i, &pst); + if (err) + continue; + + err = proc_stat_set_flags (pst, PSTAT_THREAD_BASIC); + if (err || ! (proc_stat_flags (pst) & PSTAT_THREAD_BASIC)) + continue; + + tbi = proc_stat_thread_basic_info (pst); + } + + /* We found it! */ + tv->tv_sec = tbi->system_time.seconds; + tv->tv_usec = tbi->system_time.microseconds; + err = 0; + +out: + if (pst) _proc_stat_free (pst); + _proc_stat_free (ps); + return err; +} + static error_t rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) { @@ -65,8 +123,8 @@ rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) static error_t rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) { - struct timeval time, boottime; - double up_secs; + struct timeval time, boottime, idletime; + double up_secs, idle_secs; error_t err; err = gettimeofday (&time, NULL); @@ -77,15 +135,20 @@ rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) if (err) return err; + err = get_idletime (hook, &idletime); + if (err) + return err; + timersub (&time, &boottime, &time); up_secs = time.tv_sec + time.tv_usec / 1000000.; + idle_secs = idletime.tv_sec + idletime.tv_usec / 1000000.; /* The second field is the total idle time. As far as I know we don't keep track of it. However, procps uses it to compute "USER_HZ", and proc(5) specifies that it should be equal to USER_HZ times the idle value in ticks from /proc/stat. So we assume a completely idle system both here and there to make that work. */ - *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, up_secs); + *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, idle_secs); return 0; } @@ -93,9 +156,9 @@ rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) static error_t rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) { - struct timeval boottime, time; + struct timeval boottime, time, idletime; struct vm_statistics vmstats; - unsigned long up_ticks; + unsigned long up_ticks, idle_ticks; error_t err; err = gettimeofday (&time, NULL); @@ -106,23 +169,26 @@ rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) if (err) return err; + err = get_idletime (hook, &idletime); + if (err) + return err; + err = vm_statistics (mach_task_self (), &vmstats); if (err) return EIO; timersub (&time, &boottime, &time); up_ticks = opt_clk_tck * (time.tv_sec + time.tv_usec / 1000000.); + idle_ticks = opt_clk_tck * (idletime.tv_sec + idletime.tv_usec / 1000000.); *contents_len = asprintf (contents, - /* Does Mach keeps track of any of this? */ - "cpu 0 0 0 %lu 0 0 0 0 0\n" - "cpu0 0 0 0 %lu 0 0 0 0 0\n" + "cpu %lu 0 0 %lu 0 0 0 0 0\n" + "cpu0 %lu 0 0 %lu 0 0 0 0 0\n" "intr 0\n" - /* This we know. */ "page %d %d\n" "btime %lu\n", - up_ticks, - up_ticks, + up_ticks - idle_ticks, idle_ticks, + up_ticks - idle_ticks, idle_ticks, vmstats.pageins, vmstats.pageouts, boottime.tv_sec); -- cgit v1.2.3 From 59b3864bbd09e81df1a5934a02d8af7f4eec0b28 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 20:21:52 +0000 Subject: Make sure the clock never runs backwards. * process.c, rootdir.c: When converting timeval structures into seconds or jiffies, make sure that floating point rounding errors don't make the clock the result jump backwards on second boundaries. --- process.c | 4 ++-- rootdir.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/process.c b/process.c index 1f9d5781..68e7bc1d 100644 --- a/process.c +++ b/process.c @@ -58,8 +58,8 @@ static const char *state_string (struct proc_stat *ps) static long long int timeval_jiffies (time_value_t tv) { - double secs = tv.seconds + tv.microseconds / 1000000.; - return secs * opt_clk_tck; + double secs = tv.seconds * 1000000. + tv.microseconds; + return secs * opt_clk_tck / 1000000.; } /* Actual content generators */ diff --git a/rootdir.c b/rootdir.c index 728008e5..c6ddd87c 100644 --- a/rootdir.c +++ b/rootdir.c @@ -140,8 +140,8 @@ rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) return err; timersub (&time, &boottime, &time); - up_secs = time.tv_sec + time.tv_usec / 1000000.; - idle_secs = idletime.tv_sec + idletime.tv_usec / 1000000.; + up_secs = (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; + idle_secs = (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; /* The second field is the total idle time. As far as I know we don't keep track of it. However, procps uses it to compute "USER_HZ", and @@ -178,8 +178,8 @@ rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) return EIO; timersub (&time, &boottime, &time); - up_ticks = opt_clk_tck * (time.tv_sec + time.tv_usec / 1000000.); - idle_ticks = opt_clk_tck * (idletime.tv_sec + idletime.tv_usec / 1000000.); + up_ticks = opt_clk_tck * (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; + idle_ticks = opt_clk_tck * (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; *contents_len = asprintf (contents, "cpu %lu 0 0 %lu 0 0 0 0 0\n" -- cgit v1.2.3 From c9bfe14f2e5e09b1692ae4a120de1df2cf835d05 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Mon, 23 Aug 2010 20:43:16 +0000 Subject: Refresh nodes when they're read from the start. This is necessary for top, for instance, which keeps some files open and re-reads them regularly. As an extra bonus we can drop the refresh hack. * procfs.c, procfs.h: Remove the refresh hack. (procfs_refresh): New function, invalidates the cached contents. * netfs.c (netfs_attempt_read, netfs_get_dirents): Call procfs_refresh when the read is from offset 0. * proclist.c (proclist_make_node): Remove the refresh hack. * dircat.c (dircat_make_node): Likewise. (dircat_get_contents): Use procfs_refresh to avoid keeping old data from the component nodes. --- dircat.c | 5 +++-- netfs.c | 6 ++++++ procfs.c | 19 +++++++++---------- procfs.h | 13 +++++-------- proclist.c | 1 - 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/dircat.c b/dircat.c index d043486d..d24e8345 100644 --- a/dircat.c +++ b/dircat.c @@ -23,6 +23,9 @@ dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) char *subcon; ssize_t sublen; + /* Make sure we're not getting some old stuff. */ + procfs_refresh (dcn->dirs[i]); + err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); if (err) { @@ -83,8 +86,6 @@ dircat_make_node (struct node *const *dirs, int num_dirs) .cleanup_contents = procfs_cleanup_contents_with_free, .lookup = dircat_lookup, .cleanup = dircat_cleanup, - /* necessary so that it propagates to proclist */ - .enable_refresh_hack_and_break_readdir = 1, }; struct dircat_node *dcn; int i; diff --git a/netfs.c b/netfs.c index e41e0623..02a4bf54 100644 --- a/netfs.c +++ b/netfs.c @@ -57,6 +57,9 @@ error_t netfs_attempt_read (struct iouser *cred, struct node *np, ssize_t contents_len; error_t err; + if (offset == 0) + procfs_refresh (np); + err = procfs_get_contents (np, &contents, &contents_len); if (err) return err; @@ -139,6 +142,9 @@ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, char *contents; ssize_t contents_len; error_t err; + + if (entry == 0) + procfs_refresh (dir); err = procfs_get_contents (dir, &contents, &contents_len); if (err) diff --git a/procfs.c b/procfs.c index 6d15e4fd..f7b28347 100644 --- a/procfs.c +++ b/procfs.c @@ -111,14 +111,6 @@ procfs_make_ino (struct node *np, const char *filename) error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) { - if (np->nn->ops->enable_refresh_hack_and_break_readdir && np->nn->contents) - { - if (np->nn->ops->cleanup_contents) - np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, - np->nn->contents_len); - np->nn->contents = NULL; - } - if (! np->nn->contents && np->nn->ops->get_contents) { char *contents; @@ -141,6 +133,14 @@ error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) return 0; } +void procfs_refresh (struct node *np) +{ + if (np->nn->contents && np->nn->ops->cleanup_contents) + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); + + np->nn->contents = NULL; +} + error_t procfs_lookup (struct node *np, const char *name, struct node **npp) { error_t err = ENOENT; @@ -172,8 +172,7 @@ error_t procfs_lookup (struct node *np, const char *name, struct node **npp) void procfs_cleanup (struct node *np) { - if (np->nn->contents && np->nn->ops->cleanup_contents) - np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); + procfs_refresh (np); if (np->nn->ops->cleanup) np->nn->ops->cleanup (np->nn->hook); diff --git a/procfs.h b/procfs.h index e8ef18b3..a9665f97 100644 --- a/procfs.h +++ b/procfs.h @@ -32,14 +32,6 @@ struct procfs_node_ops /* Destroy this node. */ void (*cleanup) (void *hook); - - /* FIXME: This is needed because the root node is persistent, and we - want the list of processes to be updated. However, this means that - readdir() on the root node runs the risk of returning incoherent - results if done in multiple runs and processes are added/removed in - the meantime. The right way to fix this is probably to add a - getroot() user hook function to libnetfs. */ - int enable_refresh_hack_and_break_readdir; }; /* These helper functions can be used as procfs_node_ops.cleanup_contents. */ @@ -71,6 +63,11 @@ void procfs_node_chtype (struct node *np, mode_t type); corresponding child nodes. */ ino64_t procfs_make_ino (struct node *np, const char *filename); +/* Forget the current cached contents for the node. This is done before reads + from offset 0, to ensure that the data are recent even for utilities such as + top which keep some nodes open. */ +void procfs_refresh (struct node *np); + error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len); error_t procfs_lookup (struct node *np, const char *name, struct node **npp); void procfs_cleanup (struct node *np); diff --git a/proclist.c b/proclist.c index 38368feb..fe5d0cff 100644 --- a/proclist.c +++ b/proclist.c @@ -69,7 +69,6 @@ proclist_make_node (struct ps_context *pc) .get_contents = proclist_get_contents, .lookup = proclist_lookup, .cleanup_contents = procfs_cleanup_contents_with_free, - .enable_refresh_hack_and_break_readdir = 1, }; return procfs_make_node (&ops, pc); } -- cgit v1.2.3 From 2ceddf5449bb99683e096b39120a602a5de6a6ec Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 25 Aug 2010 05:46:49 +0000 Subject: Fix leak in error case * process.c (process_lookup_pid): Fix leak in error case. --- process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/process.c b/process.c index 68e7bc1d..47e34708 100644 --- a/process.c +++ b/process.c @@ -345,7 +345,10 @@ process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) - return EIO; + { + _proc_stat_free (ps); + return EIO; + } /* FIXME: have a separate proc_desc structure for each file, so this can be accessed in a more robust and straightforward way. */ -- cgit v1.2.3 From f708dd1262df8033d4709dbba1da026e8b92f669 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 25 Aug 2010 05:47:08 +0000 Subject: Add a PROFILE mode * Makefile: Change FOOFLAGS defaults to appropriate values when $(PROFILE) is defined. * rootdir.c: Add an "exit" file, which causes exit to be called when looked up, so that profiling data can be written to disk. --- rootdir.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rootdir.c b/rootdir.c index c6ddd87c..204bc02b 100644 --- a/rootdir.c +++ b/rootdir.c @@ -422,6 +422,15 @@ static const struct procfs_dir_entry rootdir_entries[] = { .cleanup_contents = procfs_cleanup_contents_with_free, }, }, +#ifdef PROFILE + /* In order to get a usable gmon.out file, we must apparently use exit(). */ + { + .name = "exit", + .ops = { + .make_node = exit, + }, + }, +#endif {} }; -- cgit v1.2.3 From cc1b191e53042a9938daf92ce84e869dda592868 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 25 Aug 2010 12:03:16 +0000 Subject: Add swap information to the top-level stat file * rootdir.c (rootdir_gc_meminfo): Add swap information. * TODO: Update. --- rootdir.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/rootdir.c b/rootdir.c index 204bc02b..419f774e 100644 --- a/rootdir.c +++ b/rootdir.c @@ -1,7 +1,10 @@ #include #include +#include +#include #include #include +#include #include #include #include @@ -101,6 +104,22 @@ out: return err; } +static error_t +get_swapinfo (default_pager_info_t *info) +{ + mach_port_t defpager; + error_t err; + + defpager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); + if (defpager == MACH_PORT_NULL) + return errno; + + err = default_pager_info (defpager, info); + mach_port_deallocate (mach_task_self (), defpager); + + return err; +} + static error_t rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) { @@ -223,6 +242,7 @@ rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) host_basic_info_data_t hbi; mach_msg_type_number_t cnt; struct vm_statistics vmstats; + default_pager_info_t swap; error_t err; err = vm_statistics (mach_task_self (), &vmstats); @@ -234,6 +254,10 @@ rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) if (err) return err; + err = get_swapinfo (&swap); + if (err) + return err; + assert (cnt == HOST_BASIC_INFO_COUNT); *contents_len = asprintf (contents, "MemTotal: %14lu kB\n" @@ -241,13 +265,17 @@ rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) "Active: %14lu kB\n" "Inactive: %14lu kB\n" "Mlocked: %14lu kB\n" + "SwapTotal:%14lu kB\n" + "SwapFree: %14lu kB\n" , /* TODO: check that these are really 1024-bytes kBs. */ (long unsigned) hbi.memory_size / 1024, (long unsigned) vmstats.free_count * PAGE_SIZE / 1024, (long unsigned) vmstats.active_count * PAGE_SIZE / 1024, (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, - (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024); + (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024, + (long unsigned) swap.dpi_total_space / 1024, + (long unsigned) swap.dpi_free_space / 1024); return 0; } -- cgit v1.2.3 From 3a19c9fb17d79c83e30bf0739246956aea80f168 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 25 Aug 2010 19:04:24 +0000 Subject: Add some comments in rootdir.c * rootdir.c: Add page breaks to separate sections and add header comments for them. --- rootdir.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/rootdir.c b/rootdir.c index 419f774e..2a2ab5a5 100644 --- a/rootdir.c +++ b/rootdir.c @@ -21,6 +21,9 @@ #define KERNEL_PID 2 + +/* Helper functions */ + /* We get the boot time by using that of the kernel process. */ static error_t get_boottime (struct ps_context *pc, struct timeval *tv) @@ -120,6 +123,9 @@ get_swapinfo (default_pager_info_t *info) return err; } + +/* Content generators */ + static error_t rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) { @@ -137,8 +143,6 @@ rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) return 0; } -/* Uptime -- we use the start time of init to deduce it. This is probably a bit - fragile, as any clock update will make the result inaccurate. */ static error_t rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) { @@ -373,10 +377,16 @@ rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) return 0; } + +/* Glue logic and entries table */ static struct node * rootdir_file_make_node (void *dir_hook, const void *entry_hook) { + /* The entry hook we use is actually a procfs_node_ops for the file to be + created. The hook associated to these newly created files (and passed + to the generators above as a consequence) is always the same global + ps_context, which we get from rootdir_make_node as the directory hook. */ return procfs_make_node (entry_hook, dir_hook); } -- cgit v1.2.3 From 5d8a8c2b664e36006eea5698709b98849b0ad129 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 1 Sep 2010 23:36:14 +0200 Subject: Prevent pthread.h from exposing assert() * sysdeps/generic/bits/cancelation.h: Do not include (__pthread_cleanup_pop): Do not call `assert'. --- sysdeps/generic/bits/cancelation.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/sysdeps/generic/bits/cancelation.h b/sysdeps/generic/bits/cancelation.h index db9169a9..46486f5e 100644 --- a/sysdeps/generic/bits/cancelation.h +++ b/sysdeps/generic/bits/cancelation.h @@ -20,8 +20,6 @@ #ifndef _BITS_CANCELATION_H #define _BITS_CANCELATION_H 1 -#include - struct __pthread_cancelation_handler { void (*handler)(void *); @@ -47,7 +45,6 @@ struct __pthread_cancelation_handler **__pthread_get_cleanup_stack (void); #define __pthread_cleanup_pop(execute) \ if (execute) \ __handler.handler (__handler.arg); \ - assert (*__handlers == &__handler); \ *__handlers = __handler.next; \ } -- cgit v1.2.3 From 59ce2f2ebf8eb60b34fec056d8e6ccc9ad5ef6f8 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 2 Sep 2010 03:59:40 +0200 Subject: Use __sched_param instead of sched_param to avoid exposing inclusion of and exposure of sched_param from * sysdeps/generic/bits/thread-attr.h: Define __need_schedparam and include instead of including (__pthread_attr): Use `__sched_param' instead of `sched_param'. --- sysdeps/generic/bits/thread-attr.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sysdeps/generic/bits/thread-attr.h b/sysdeps/generic/bits/thread-attr.h index c3a93fde..f2e55f2b 100644 --- a/sysdeps/generic/bits/thread-attr.h +++ b/sysdeps/generic/bits/thread-attr.h @@ -20,7 +20,8 @@ #ifndef _BITS_THREAD_ATTR_H #define _BITS_THREAD_ATTR_H 1 -#include +#define __need_schedparam +#include enum __pthread_detachstate; enum __pthread_inheritsched; @@ -30,7 +31,7 @@ enum __pthread_contentionscope; that not all of them are supported on all systems. */ struct __pthread_attr { - struct sched_param schedparam; + struct __sched_param schedparam; void *stackaddr; size_t stacksize; size_t guardsize; -- cgit v1.2.3 From ba5c9d57be1a4e8167747dfdf4d94c2e03b9e24d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 3 Sep 2010 00:20:42 +0200 Subject: Fix __sched_param / sched_param conversion * sysdeps/generic/pt-attr-getschedparam.c (pthread_attr_getschedparam): memcpy from `attr->schedparam' to `param' to convert from __sched_param to sched_param. * sysdeps/generic/pt-attr-setschedparam.c (pthread_attr_setschedparam): memcpy from `param' to `attr->schedparam' to convert from sched_param to __sched_param. --- sysdeps/generic/pt-attr-getschedparam.c | 2 +- sysdeps/generic/pt-attr-setschedparam.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sysdeps/generic/pt-attr-getschedparam.c b/sysdeps/generic/pt-attr-getschedparam.c index 25afebd0..6c3f15be 100644 --- a/sysdeps/generic/pt-attr-getschedparam.c +++ b/sysdeps/generic/pt-attr-getschedparam.c @@ -26,6 +26,6 @@ int pthread_attr_getschedparam (const pthread_attr_t *attr, struct sched_param *param) { - *param = attr->schedparam; + memcpy (param, &attr->schedparam, sizeof *param); return 0; } diff --git a/sysdeps/generic/pt-attr-setschedparam.c b/sysdeps/generic/pt-attr-setschedparam.c index 18a575ec..5459f108 100644 --- a/sysdeps/generic/pt-attr-setschedparam.c +++ b/sysdeps/generic/pt-attr-setschedparam.c @@ -30,7 +30,7 @@ pthread_attr_setschedparam (pthread_attr_t *attr, if (memcmp (param, &__pthread_default_attr.schedparam, sizeof *param) == 0) { - attr->schedparam = *param; + memcpy (&attr->schedparam, param, sizeof *param); return 0; } -- cgit v1.2.3 From 33210c5802462b93f0e6bc16d7dccb042ec76798 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Thu, 26 Aug 2010 23:03:40 +0000 Subject: Add copyright notices * dircat.c, dircat.h, main.c, main.h, netfs.c, process.c, process.h, procfs.c, procfs.h, procfs_dir.c, procfs_dir.h, proclist.c, proclist.h, rootdir.c, rootdir.h: Add copyright notices. --- dircat.c | 19 +++++++++++++++++++ dircat.h | 19 +++++++++++++++++++ main.c | 19 +++++++++++++++++++ main.h | 19 +++++++++++++++++++ netfs.c | 19 +++++++++++++++++++ process.c | 19 +++++++++++++++++++ process.h | 19 +++++++++++++++++++ procfs.c | 19 +++++++++++++++++++ procfs.h | 19 +++++++++++++++++++ procfs_dir.c | 19 +++++++++++++++++++ procfs_dir.h | 19 +++++++++++++++++++ proclist.c | 19 +++++++++++++++++++ proclist.h | 19 +++++++++++++++++++ rootdir.c | 19 +++++++++++++++++++ rootdir.h | 19 +++++++++++++++++++ 15 files changed, 285 insertions(+) diff --git a/dircat.c b/dircat.c index d24e8345..5a60899a 100644 --- a/dircat.c +++ b/dircat.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, concatenation of two directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include "procfs.h" diff --git a/dircat.h b/dircat.h index 951d2021..4177b384 100644 --- a/dircat.h +++ b/dircat.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, concatenation of two directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Append the contents of NUM_DIRS directories. DIRS is an array of directory nodes. One reference is consumed for each of them. If a memory allocation error occurs, or if one of the directories is a diff --git a/main.c b/main.c index eaab9867..94fc227d 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, main program. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/main.h b/main.h index 28d1b023..4e28b7eb 100644 --- a/main.h +++ b/main.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, command-line options set by main.c. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Startup options */ extern int opt_clk_tck; extern mode_t opt_stat_mode; diff --git a/netfs.c b/netfs.c index 02a4bf54..24a6603f 100644 --- a/netfs.c +++ b/netfs.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, interface with libnetfs. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/process.c b/process.c index 47e34708..6652a4e9 100644 --- a/process.c +++ b/process.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, implementation of process directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/process.h b/process.h index 8c2ee636..b230a281 100644 --- a/process.h +++ b/process.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, implementation of process directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include /* Create a node for a directory representing the given PID, as published by diff --git a/procfs.c b/procfs.c index f7b28347..ee52de7a 100644 --- a/procfs.c +++ b/procfs.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, basic infrastructure. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/procfs.h b/procfs.h index a9665f97..64782ec4 100644 --- a/procfs.h +++ b/procfs.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, basic infrastructure. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include diff --git a/procfs_dir.c b/procfs_dir.c index dfe30a26..c250aa48 100644 --- a/procfs_dir.c +++ b/procfs_dir.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, infrastructure for directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include "procfs.h" diff --git a/procfs_dir.h b/procfs_dir.h index 12e99d2a..94c5b019 100644 --- a/procfs_dir.h +++ b/procfs_dir.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, infrastructure for directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* This module provides an abstraction layer for implementing simple directories with (mostly) static contents. The user defines the contents of the directory by providing a table of entries and various diff --git a/proclist.c b/proclist.c index fe5d0cff..58b942dc 100644 --- a/proclist.c +++ b/proclist.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, list of processes as a directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/proclist.h b/proclist.h index ce69dde3..bfe95b3d 100644 --- a/proclist.h +++ b/proclist.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, list of processes as a directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include struct node * diff --git a/rootdir.c b/rootdir.c index 2a2ab5a5..da068cf4 100644 --- a/rootdir.c +++ b/rootdir.c @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, permanent files of the root directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include diff --git a/rootdir.h b/rootdir.h index 0caee258..6980da8f 100644 --- a/rootdir.h +++ b/rootdir.h @@ -1,3 +1,22 @@ +/* Hurd /proc filesystem, permanent files of the root directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include struct node * -- cgit v1.2.3 From 86935e7331b64d1ef3234a01ddca08be336162fb Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 1 Sep 2010 10:19:49 +0000 Subject: Use the user-provided kernel PID for uptime * rootdir.c (get_boottime, get_idletime): replace KERNEL_PID with the opt_kernel_pid command-line option. * main.c (argp): Document the change. --- main.c | 3 ++- rootdir.c | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index 94fc227d..3a976ccc 100644 --- a/main.c +++ b/main.c @@ -114,7 +114,8 @@ struct argp argp = { "purposes. If PID is omitted, \"self\" will point to init. " "(default: no self link)" }, { "kernel-process", 'k', "PID", 0, - "Process identifier for the kernel, used to retreive its command line " + "Process identifier for the kernel, used to retreive its command " + "line, as well as the global up and idle times. " "(default: 2)" }, { "compatible", 'c', NULL, 0, "Try to be compatible with the Linux procps utilities. " diff --git a/rootdir.c b/rootdir.c index da068cf4..15ef8bce 100644 --- a/rootdir.c +++ b/rootdir.c @@ -38,8 +38,6 @@ using them would require locking and as a consequence it would be more complicated, not simpler. */ -#define KERNEL_PID 2 - /* Helper functions */ @@ -50,7 +48,7 @@ get_boottime (struct ps_context *pc, struct timeval *tv) struct proc_stat *ps; error_t err; - err = _proc_stat_create (KERNEL_PID, pc, &ps); + err = _proc_stat_create (opt_kernel_pid, pc, &ps); if (err) return err; @@ -78,7 +76,7 @@ get_idletime (struct ps_context *pc, struct timeval *tv) error_t err; int i; - err = _proc_stat_create (KERNEL_PID, pc, &ps); + err = _proc_stat_create (opt_kernel_pid, pc, &ps); if (err) return err; -- cgit v1.2.3 From ff7be39f3df8234e9f64b9098c76493cf0977439 Mon Sep 17 00:00:00 2001 From: Jeremie Koenig Date: Wed, 1 Sep 2010 10:49:11 +0000 Subject: Use 2 instead of 42 as the parent inode number * procfs.c (procfs_make_ino): Use 2 rather than 42 as a temporary hack, since 2 is the root's inode with ext2fs. --- procfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/procfs.c b/procfs.c index ee52de7a..ae5a6769 100644 --- a/procfs.c +++ b/procfs.c @@ -114,7 +114,7 @@ procfs_make_ino (struct node *np, const char *filename) if (! strcmp (filename, ".")) return np->nn_stat.st_ino; if (! strcmp (filename, "..")) - return np->nn->parent ? np->nn->parent->nn_stat.st_ino : /* FIXME: */ 42; + return np->nn->parent ? np->nn->parent->nn_stat.st_ino : /* FIXME: */ 2; assert (sizeof np->nn_stat.st_ino > sizeof x); memcpy (x, &np->nn_stat.st_ino, sizeof x); -- cgit v1.2.3 From 494db38b7df523f566957ef5aa56b9b3d2af6764 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 26 Sep 2010 21:12:48 +0000 Subject: Move files to procfs to merge along hurd --- dircat.c | 128 ------------- dircat.h | 29 --- main.c | 190 -------------------- main.h | 25 --- netfs.c | 445 ---------------------------------------------- process.c | 387 ---------------------------------------- process.h | 27 --- procfs.c | 203 --------------------- procfs.h | 93 ---------- procfs/Makefile | 26 +++ procfs/TODO | 24 +++ procfs/dircat.c | 128 +++++++++++++ procfs/dircat.h | 29 +++ procfs/main.c | 190 ++++++++++++++++++++ procfs/main.h | 25 +++ procfs/netfs.c | 445 ++++++++++++++++++++++++++++++++++++++++++++++ procfs/process.c | 387 ++++++++++++++++++++++++++++++++++++++++ procfs/process.h | 27 +++ procfs/procfs.c | 203 +++++++++++++++++++++ procfs/procfs.h | 93 ++++++++++ procfs/procfs_dir.c | 134 ++++++++++++++ procfs/procfs_dir.h | 63 +++++++ procfs/proclist.c | 94 ++++++++++ procfs/proclist.h | 23 +++ procfs/rootdir.c | 503 ++++++++++++++++++++++++++++++++++++++++++++++++++++ procfs/rootdir.h | 23 +++ procfs_dir.c | 134 -------------- procfs_dir.h | 63 ------- proclist.c | 94 ---------- proclist.h | 23 --- rootdir.c | 503 ---------------------------------------------------- rootdir.h | 23 --- 32 files changed, 2417 insertions(+), 2367 deletions(-) delete mode 100644 dircat.c delete mode 100644 dircat.h delete mode 100644 main.c delete mode 100644 main.h delete mode 100644 netfs.c delete mode 100644 process.c delete mode 100644 process.h delete mode 100644 procfs.c delete mode 100644 procfs.h create mode 100644 procfs/Makefile create mode 100644 procfs/TODO create mode 100644 procfs/dircat.c create mode 100644 procfs/dircat.h create mode 100644 procfs/main.c create mode 100644 procfs/main.h create mode 100644 procfs/netfs.c create mode 100644 procfs/process.c create mode 100644 procfs/process.h create mode 100644 procfs/procfs.c create mode 100644 procfs/procfs.h create mode 100644 procfs/procfs_dir.c create mode 100644 procfs/procfs_dir.h create mode 100644 procfs/proclist.c create mode 100644 procfs/proclist.h create mode 100644 procfs/rootdir.c create mode 100644 procfs/rootdir.h delete mode 100644 procfs_dir.c delete mode 100644 procfs_dir.h delete mode 100644 proclist.c delete mode 100644 proclist.h delete mode 100644 rootdir.c delete mode 100644 rootdir.h diff --git a/dircat.c b/dircat.c deleted file mode 100644 index 5a60899a..00000000 --- a/dircat.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Hurd /proc filesystem, concatenation of two directories. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include "procfs.h" - -struct dircat_node -{ - int num_dirs; - struct node *dirs[0]; -}; - -static error_t -dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - struct dircat_node *dcn = hook; - int i, sz, pos; - error_t err; - - pos = 0; - *contents = malloc (sz = 512); - - for (i=0; i < dcn->num_dirs; i++) - { - char *subcon; - ssize_t sublen; - - /* Make sure we're not getting some old stuff. */ - procfs_refresh (dcn->dirs[i]); - - err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); - if (err) - { - free (*contents); - *contents = NULL; - return err; - } - - while (pos + sublen > sz) - *contents = realloc (*contents, sz *= 2); - - memcpy (*contents + pos, subcon, sublen); - pos += sublen; - } - - *contents_len = pos; - return 0; -} - -static error_t -dircat_lookup (void *hook, const char *name, struct node **np) -{ - struct dircat_node *dcn = hook; - error_t err; - int i; - - err = ENOENT; - for (i=0; err && i < dcn->num_dirs; i++) - err = procfs_lookup (dcn->dirs[i], name, np); - - return err; -} - -static void -dircat_release_dirs (struct node *const *dirs, int num_dirs) -{ - int i; - - for (i=0; i < num_dirs; i++) - if (dirs[i]) - netfs_nrele (dirs[i]); -} - -static void -dircat_cleanup (void *hook) -{ - struct dircat_node *dcn = hook; - - dircat_release_dirs (dcn->dirs, dcn->num_dirs); - free (dcn); -} - -struct node * -dircat_make_node (struct node *const *dirs, int num_dirs) -{ - static struct procfs_node_ops ops = { - .get_contents = dircat_get_contents, - .cleanup_contents = procfs_cleanup_contents_with_free, - .lookup = dircat_lookup, - .cleanup = dircat_cleanup, - }; - struct dircat_node *dcn; - int i; - - for (i=0; i < num_dirs; i++) - if (! dirs[i]) - goto fail; - - dcn = malloc (sizeof *dcn + num_dirs * sizeof dcn->dirs[0]); - if (! dcn) - goto fail; - - dcn->num_dirs = num_dirs; - memcpy (dcn->dirs, dirs, num_dirs * sizeof dcn->dirs[0]); - return procfs_make_node (&ops, dcn); - -fail: - dircat_release_dirs (dirs, num_dirs); - return NULL; -} - diff --git a/dircat.h b/dircat.h deleted file mode 100644 index 4177b384..00000000 --- a/dircat.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Hurd /proc filesystem, concatenation of two directories. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* Append the contents of NUM_DIRS directories. DIRS is an array of - directory nodes. One reference is consumed for each of them. If a - memory allocation error occurs, or if one of the directories is a - NULL pointer, the references are dropped immediately and NULL is - returned. The given DIRS array is duplicated and can therefore be - allocated on the caller's stack. Strange things will happen if some - elements of DIRS have entries with the same name or if one of them is - not a directory. */ -struct node * -dircat_make_node (struct node *const *dirs, int num_dirs); diff --git a/main.c b/main.c deleted file mode 100644 index 3a976ccc..00000000 --- a/main.c +++ /dev/null @@ -1,190 +0,0 @@ -/* Hurd /proc filesystem, main program. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include -#include "procfs.h" -#include "proclist.h" -#include "rootdir.h" -#include "dircat.h" -#include "main.h" - -/* Command-line options */ -int opt_clk_tck; -mode_t opt_stat_mode; -pid_t opt_fake_self; -pid_t opt_kernel_pid; -uid_t opt_anon_owner; - -static error_t -argp_parser (int key, char *arg, struct argp_state *state) -{ - struct passwd *pw; - char *endp; - - switch (key) - { - case 'h': - opt_clk_tck = strtol (arg, &endp, 0); - if (*endp || ! *arg || opt_clk_tck <= 0) - error (1, 0, "--clk-tck: HZ should be a positive integer"); - break; - - case 's': - opt_stat_mode = strtol (arg, &endp, 8); - if (*endp || ! *arg || opt_stat_mode & ~07777) - error (1, 0, "--stat-mode: MODE should be an octal mode"); - break; - - case 'S': - if (arg) - { - opt_fake_self = strtol (arg, &endp, 0); - if (*endp || ! *arg) - error (1, 0, "--fake-self: PID must be an integer"); - } - else - opt_fake_self = 1; - break; - - case 'k': - opt_kernel_pid = strtol (arg, &endp, 0); - if (*endp || ! *arg || (signed) opt_kernel_pid < 0) - error (1, 0, "--kernel-process: PID must be a positive integer"); - break; - - case 'c': - opt_clk_tck = 100; - opt_stat_mode = 0444; - opt_fake_self = 1; - break; - - case 'a': - pw = getpwnam (arg); - if (pw) - { - opt_anon_owner = pw->pw_uid; - break; - } - - opt_anon_owner = strtol (arg, &endp, 0); - if (*endp || ! *arg || (signed) opt_anon_owner < 0) - error(1, 0, "--anonymous-owner: USER should be the a user name " - "or a numeric UID."); - break; - } - - return 0; -} - -struct argp argp = { - .options = (struct argp_option []) { - { "clk-tck", 'h', "HZ", 0, - "Unit used for the values expressed in system clock ticks " - "(default: sysconf(_SC_CLK_TCK))" }, - { "stat-mode", 's', "MODE", 0, - "The [pid]/stat file publishes information which on Hurd is only " - "available to the process owner. " - "You can use this option to override its mode to be more permissive " - "for compatibility purposes. " - "(default: 0400)" }, - { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL, - "Provide a fake \"self\" symlink to the given PID, for compatibility " - "purposes. If PID is omitted, \"self\" will point to init. " - "(default: no self link)" }, - { "kernel-process", 'k', "PID", 0, - "Process identifier for the kernel, used to retreive its command " - "line, as well as the global up and idle times. " - "(default: 2)" }, - { "compatible", 'c', NULL, 0, - "Try to be compatible with the Linux procps utilities. " - "Currently equivalent to -h 100 -s 0444 -S 1." }, - { "anonymous-owner", 'a', "USER", 0, - "Make USER the owner of files related to processes without one. " - "Be aware that USER will be granted access to the environment and " - "other sensitive information about the processes in question. " - "(default: use uid 0)" }, - {} - }, - .parser = argp_parser, - .doc = "A virtual filesystem emulating the Linux procfs.", - .children = (struct argp_child []) { - { &netfs_std_startup_argp, }, - {} - }, -}; - -error_t -root_make_node (struct ps_context *pc, struct node **np) -{ - struct node *root_dirs[] = { - proclist_make_node (pc), - rootdir_make_node (pc), - }; - - *np = dircat_make_node (root_dirs, sizeof root_dirs / sizeof root_dirs[0]); - if (! *np) - return ENOMEM; - - /* Since this one is not created through proc_lookup(), we have to affect an - inode number to it. */ - (*np)->nn_stat.st_ino = * (uint32_t *) "PROC"; - - return 0; -} - -int main (int argc, char **argv) -{ - struct ps_context *pc; - mach_port_t bootstrap; - error_t err; - - opt_clk_tck = sysconf(_SC_CLK_TCK); - opt_stat_mode = 0400; - opt_fake_self = -1; - opt_kernel_pid = 2; - opt_anon_owner = 0; - err = argp_parse (&argp, argc, argv, 0, 0, 0); - if (err) - error (1, err, "Could not parse command line"); - - err = ps_context_create (getproc (), &pc); - if (err) - error (1, err, "Could not create libps context"); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "Must be started as a translator"); - - netfs_init (); - err = root_make_node (pc, &netfs_root_node); - if (err) - error (1, err, "Could not create the root node"); - - netfs_startup (bootstrap, 0); - netfs_server_loop (); - - assert (0 /* netfs_server_loop returned after all */); -} - diff --git a/main.h b/main.h deleted file mode 100644 index 4e28b7eb..00000000 --- a/main.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Hurd /proc filesystem, command-line options set by main.c. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* Startup options */ -extern int opt_clk_tck; -extern mode_t opt_stat_mode; -extern pid_t opt_fake_self; -extern pid_t opt_kernel_pid; -extern uid_t opt_anon_owner; diff --git a/netfs.c b/netfs.c deleted file mode 100644 index 24a6603f..00000000 --- a/netfs.c +++ /dev/null @@ -1,445 +0,0 @@ -/* Hurd /proc filesystem, interface with libnetfs. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include "procfs.h" - -#define PROCFS_SERVER_NAME "procfs" -#define PROCFS_SERVER_VERSION "0.1.0" -#define PROCFS_MAXSYMLINKS 16 - - -/* Interesting libnetfs callback functions. */ - -/* The user must define this variable. Set this to the name of the - filesystem server. */ -char *netfs_server_name = PROCFS_SERVER_NAME; - -/* The user must define this variables. Set this to be the server - version number. */ -char *netfs_server_version = PROCFS_SERVER_VERSION; - -/* Maximum number of symlinks to follow before returning ELOOP. */ -int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; - -/* The user must define this function. Make sure that NP->nn_stat is - filled with the most current information. CRED identifies the user - responsible for the operation. NP is locked. */ -error_t netfs_validate_stat (struct node *np, struct iouser *cred) -{ - char *contents; - ssize_t contents_len; - error_t err; - - /* Only symlinks need to have their size filled, before a read is - attempted. */ - if (! S_ISLNK (np->nn_stat.st_mode)) - return 0; - - err = procfs_get_contents (np, &contents, &contents_len); - if (err) - return err; - - np->nn_stat.st_size = contents_len; - return 0; -} - -/* The user must define this function. Read from the locked file NP - for user CRED starting at OFFSET and continuing for up to *LEN - bytes. Put the data at DATA. Set *LEN to the amount successfully - read upon return. */ -error_t netfs_attempt_read (struct iouser *cred, struct node *np, - loff_t offset, size_t *len, void *data) -{ - char *contents; - ssize_t contents_len; - error_t err; - - if (offset == 0) - procfs_refresh (np); - - err = procfs_get_contents (np, &contents, &contents_len); - if (err) - return err; - - contents += offset; - contents_len -= offset; - - if (*len > contents_len) - *len = contents_len; - if (*len < 0) - *len = 0; - - memcpy (data, contents, *len); - return 0; -} - -/* The user must define this function. Read the contents of locked - node NP (a symlink), for USER, into BUF. */ -error_t netfs_attempt_readlink (struct iouser *user, struct node *np, - char *buf) -{ - char *contents; - ssize_t contents_len; - error_t err; - - err = procfs_get_contents (np, &contents, &contents_len); - if (err) - return err; - - assert (contents_len == np->nn_stat.st_size); - memcpy (buf, contents, contents_len); - return 0; -} - -/* Helper function for netfs_get_dirents() below. CONTENTS is an argz - vector of directory entry names, as returned by procfs_get_contents(). - Convert at most NENTRIES of them to dirent structures, put them in - DATA (if not NULL), write the number of entries processed in *AMT and - return the required/used space in DATACNT. */ -static int putentries (char *contents, size_t contents_len, int nentries, - char *data, mach_msg_type_number_t *datacnt) -{ - int i; - - *datacnt = 0; - for (i = 0; contents_len && (nentries < 0 || i < nentries); i++) - { - int namlen = strlen (contents); - int reclen = sizeof (struct dirent) + namlen; - - if (data) - { - struct dirent *d = (struct dirent *) (data + *datacnt); - d->d_fileno = 42; /* XXX */ - d->d_namlen = namlen; - d->d_reclen = reclen; - d->d_type = DT_UNKNOWN; - strcpy (d->d_name, contents); - } - - *datacnt += reclen; - contents += namlen + 1; - contents_len -= namlen + 1; - } - - return i; -} - -/* The user must define this function. Fill the array *DATA of size - BUFSIZE with up to NENTRIES dirents from DIR (which is locked) - starting with entry ENTRY for user CRED. The number of entries in - the array is stored in *AMT and the number of bytes in *DATACNT. - If the supplied buffer is not large enough to hold the data, it - should be grown. */ -error_t netfs_get_dirents (struct iouser *cred, struct node *dir, - int entry, int nentries, char **data, - mach_msg_type_number_t *datacnt, - vm_size_t bufsize, int *amt) -{ - char *contents; - ssize_t contents_len; - error_t err; - - if (entry == 0) - procfs_refresh (dir); - - err = procfs_get_contents (dir, &contents, &contents_len); - if (err) - return err; - - /* We depend on the fact that CONTENTS is terminated. */ - assert (contents_len == 0 || contents[contents_len - 1] == '\0'); - - /* Skip to the first requested entry. */ - while (contents_len && entry--) - { - int ofs = strlen (contents) + 1; - contents += ofs; - contents_len -= ofs; - } - - /* Allocate a buffer if necessary. */ - putentries (contents, contents_len, nentries, NULL, datacnt); - if (bufsize < *datacnt) - { - char *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); - if (n == MAP_FAILED) - return ENOMEM; - - *data = n; - } - - /* Do the actual conversion. */ - *amt = putentries (contents, contents_len, nentries, *data, datacnt); - - return 0; -} - -/* The user must define this function. Lookup NAME in DIR (which is - locked) for USER; set *NP to the found name upon return. If the - name was not found, then return ENOENT. On any error, clear *NP. - (*NP, if found, should be locked and a reference to it generated. - This call should unlock DIR no matter what.) */ -error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, - char *name, struct node **np) -{ - error_t err; - - err = procfs_lookup (dir, name, np); - mutex_unlock (&dir->lock); - - if (! err) - mutex_lock (&(*np)->lock); - - return err; -} - -/* The user must define this function. Node NP has no more references; - free all its associated storage. */ -void netfs_node_norefs (struct node *np) -{ - spin_unlock (&netfs_node_refcnt_lock); - - procfs_cleanup (np); - free (np); - - spin_lock (&netfs_node_refcnt_lock); -} - - -/* Libnetfs callbacks managed with libfshelp. */ - -/* The user must define this function. Locked node NP is being opened - by USER, with FLAGS. NEWNODE is nonzero if we just created this - node. Return an error if we should not permit the open to complete - because of a permission restriction. */ -error_t netfs_check_open_permissions (struct iouser *user, struct node *np, - int flags, int newnode) -{ - error_t err = 0; - if (!err && (flags & O_READ)) - err = fshelp_access (&np->nn_stat, S_IREAD, user); - if (!err && (flags & O_WRITE)) - err = fshelp_access (&np->nn_stat, S_IWRITE, user); - if (!err && (flags & O_EXEC)) - err = fshelp_access (&np->nn_stat, S_IEXEC, user); - return err; -} - -/* The user must define this function. Return the valid access - types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for - locked file NP and user CRED. */ -error_t netfs_report_access (struct iouser *cred, struct node *np, - int *types) -{ - *types = 0; - if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - return 0; -} - - -/* Trivial or unsupported libnetfs callbacks. */ - -/* The user must define this function. This should attempt a chmod - call for the user specified by CRED on locked node NP, to change - the owner to UID and the group to GID. */ -error_t netfs_attempt_chown (struct iouser *cred, struct node *np, - uid_t uid, uid_t gid) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a chauthor - call for the user specified by CRED on locked node NP, thereby - changing the author to AUTHOR. */ -error_t netfs_attempt_chauthor (struct iouser *cred, struct node *np, - uid_t author) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a chmod - call for the user specified by CRED on locked node NODE, to change - the mode to MODE. Unlike the normal Unix and Hurd meaning of - chmod, this function is also used to attempt to change files into - other types. If such a transition is attempted which is - impossible, then return EOPNOTSUPP. */ -error_t netfs_attempt_chmod (struct iouser *cred, struct node *np, - mode_t mode) -{ - return EROFS; -} - -/* The user must define this function. Attempt to turn locked node NP - (user CRED) into a symlink with target NAME. */ -error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *np, - char *name) -{ - return EROFS; -} - -/* The user must define this function. Attempt to turn NODE (user - CRED) into a device. TYPE is either S_IFBLK or S_IFCHR. NP is - locked. */ -error_t netfs_attempt_mkdev (struct iouser *cred, struct node *np, - mode_t type, dev_t indexes) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a chflags - call for the user specified by CRED on locked node NP, to change - the flags to FLAGS. */ -error_t netfs_attempt_chflags (struct iouser *cred, struct node *np, - int flags) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a utimes - call for the user specified by CRED on locked node NP, to change - the atime to ATIME and the mtime to MTIME. If ATIME or MTIME is - null, then set to the current time. */ -error_t netfs_attempt_utimes (struct iouser *cred, struct node *np, - struct timespec *atime, struct timespec *mtime) -{ - return EROFS; -} - -/* The user must define this function. This should attempt to set the - size of the locked file NP (for user CRED) to SIZE bytes long. */ -error_t netfs_attempt_set_size (struct iouser *cred, struct node *np, - loff_t size) -{ - return EROFS; -} - -/* The user must define this function. This should attempt to fetch - filesystem status information for the remote filesystem, for the - user CRED. NP is locked. */ -error_t netfs_attempt_statfs (struct iouser *cred, struct node *np, - fsys_statfsbuf_t *st) -{ - return ENOSYS; -} - -/* The user must define this function. This should sync the locked - file NP completely to disk, for the user CRED. If WAIT is set, - return only after the sync is completely finished. */ -error_t netfs_attempt_sync (struct iouser *cred, struct node *np, - int wait) -{ - return 0; -} - -/* The user must define this function. This should sync the entire - remote filesystem. If WAIT is set, return only after the sync is - completely finished. */ -error_t netfs_attempt_syncfs (struct iouser *cred, int wait) -{ - return 0; -} - -/* The user must define this function. Delete NAME in DIR (which is - locked) for USER. */ -error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) -{ - return EROFS; -} - -/* The user must define this function. Attempt to rename the - directory FROMDIR to TODIR. Note that neither of the specific nodes - are locked. */ -error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, - char *fromname, struct node *todir, - char *toname, int excl) -{ - return EROFS; -} - -/* The user must define this function. Attempt to create a new - directory named NAME in DIR (which is locked) for USER with mode - MODE. */ -error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, - char *name, mode_t mode) -{ - return EROFS; -} - -/* The user must define this function. Attempt to remove directory - named NAME in DIR (which is locked) for USER. */ -error_t netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - return EROFS; -} - - -/* The user must define this function. Create a link in DIR with name - NAME to FILE for USER. Note that neither DIR nor FILE are - locked. If EXCL is set, do not delete the target. Return EEXIST if - NAME is already found in DIR. */ -error_t netfs_attempt_link (struct iouser *user, struct node *dir, - struct node *file, char *name, int excl) -{ - return EROFS; -} - -/* The user must define this function. Attempt to create an anonymous - file related to DIR (which is locked) for USER with MODE. Set *NP - to the returned file upon success. No matter what, unlock DIR. */ -error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, - mode_t mode, struct node **np) -{ - return EROFS; -} - -/* The user must define this function. Attempt to create a file named - NAME in DIR (which is locked) for USER with MODE. Set *NP to the - new node upon return. On any error, clear *NP. *NP should be - locked on success; no matter what, unlock DIR before returning. */ -error_t netfs_attempt_create_file (struct iouser *user, struct node *dir, - char *name, mode_t mode, struct node **np) -{ - return EROFS; -} - -/* The user must define this function. Write to the locked file NP - for user CRED starting at OFSET and continuing for up to *LEN bytes - from DATA. Set *LEN to the amount successfully written upon - return. */ -error_t netfs_attempt_write (struct iouser *cred, struct node *np, - loff_t offset, size_t *len, void *data) -{ - return EROFS; -} - - diff --git a/process.c b/process.c deleted file mode 100644 index 6652a4e9..00000000 --- a/process.c +++ /dev/null @@ -1,387 +0,0 @@ -/* Hurd /proc filesystem, implementation of process directories. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include -#include "procfs.h" -#include "procfs_dir.h" -#include "process.h" -#include "main.h" - -/* This module implements the process directories and the files they - contain. A libps proc_stat structure is created for each process - node, and is used by the individual file content generators as a - source of information. Each possible file (cmdline, environ, ...) is - decribed in a process_file_desc structure, which specifies which bits - of information (ie. libps flags) it needs, and what function should - be used to generate the file's contents. - - The content generators are defined first, followed by glue logic and - entry table. */ - - -/* Helper functions */ - -static char state_char (struct proc_stat *ps) -{ - int i; - - for (i = 0; (1 << i) & (PSTAT_STATE_P_STATES | PSTAT_STATE_T_STATES); i++) - if (proc_stat_state (ps) & (1 << i)) - return proc_stat_state_tags[i]; - - return '?'; -} - -static const char *state_string (struct proc_stat *ps) -{ - static const char *const state_strings[] = { - "T (stopped)", - "Z (zombie)", - "R (running)", - "H (halted)", - "D (disk sleep)", - "S (sleeping)", - "I (idle)", - NULL - }; - int i; - - for (i = 0; state_strings[i]; i++) - if (proc_stat_state (ps) & (1 << i)) - return state_strings[i]; - - return "? (unknown)"; -} - -static long long int timeval_jiffies (time_value_t tv) -{ - double secs = tv.seconds * 1000000. + tv.microseconds; - return secs * opt_clk_tck / 1000000.; -} - -/* Actual content generators */ - -static ssize_t -process_file_gc_cmdline (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_args(ps); - return proc_stat_args_len(ps); -} - -static ssize_t -process_file_gc_environ (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_env(ps); - return proc_stat_env_len(ps); -} - -static ssize_t -process_file_gc_stat (struct proc_stat *ps, char **contents) -{ - struct procinfo *pi = proc_stat_proc_info (ps); - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); - - /* See proc(5) for more information about the contents of each field for the - Linux procfs. */ - return asprintf (contents, - "%d (%s) %c " /* pid, command, state */ - "%d %d %d " /* ppid, pgid, session */ - "%d %d " /* controling tty stuff */ - "%u " /* flags, as defined by */ - "%lu %lu %lu %lu " /* page fault counts */ - "%lu %lu %ld %ld " /* user/sys times, in sysconf(_SC_CLK_TCK) */ - "%d %d " /* scheduler params (priority, nice) */ - "%d %ld " /* number of threads, [obsolete] */ - "%llu " /* start time since boot (jiffies) */ - "%lu %ld %lu " /* virtual size (bytes), rss (pages), rss lim */ - "%lu %lu %lu %lu %lu " /* some vm addresses (code, stack, sp, pc) */ - "%lu %lu %lu %lu " /* pending, blocked, ignored and caught sigs */ - "%lu " /* wait channel */ - "%lu %lu " /* swap usage (not maintained in Linux) */ - "%d " /* exit signal, to be sent to the parent */ - "%d " /* last processor used */ - "%u %u " /* RT priority and policy */ - "%llu " /* aggregated block I/O delay */ - "\n", - proc_stat_pid (ps), proc_stat_args (ps), state_char (ps), - pi->ppid, pi->pgrp, pi->session, - 0, 0, /* no such thing as a major:minor for ctty */ - 0, /* no such thing as CLONE_* flags on Hurd */ - 0L, 0L, 0L, 0L, /* TASK_EVENTS_INFO is unavailable on GNU Mach */ - (long unsigned) timeval_jiffies (thbi->user_time), - (long unsigned) timeval_jiffies (thbi->system_time), - 0L, 0L, /* cumulative time for children */ - MACH_PRIORITY_TO_NICE(thbi->base_priority) + 20, - MACH_PRIORITY_TO_NICE(thbi->base_priority), - pi->nthreads, 0L, - timeval_jiffies (thbi->creation_time), /* FIXME: ... since boot */ - (long unsigned) tbi->virtual_size, - (long unsigned) tbi->resident_size / PAGE_SIZE, 0L, - 0L, 0L, 0L, 0L, 0L, - 0L, 0L, 0L, 0L, - (long unsigned) proc_stat_thread_rpc (ps), /* close enough */ - 0L, 0L, - 0, - 0, - 0, 0, - 0LL); -} - -static ssize_t -process_file_gc_statm (struct proc_stat *ps, char **contents) -{ - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - - return asprintf (contents, - "%lu %lu 0 0 0 0 0\n", - tbi->virtual_size / sysconf(_SC_PAGE_SIZE), - tbi->resident_size / sysconf(_SC_PAGE_SIZE)); -} - -static ssize_t -process_file_gc_status (struct proc_stat *ps, char **contents) -{ - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - - return asprintf (contents, - "Name:\t%s\n" - "State:\t%s\n" - "Tgid:\t%u\n" - "Pid:\t%u\n" - "PPid:\t%u\n" - "Uid:\t%u\t%u\t%u\t%u\n" - "VmSize:\t%8u kB\n" - "VmPeak:\t%8u kB\n" - "VmRSS:\t%8u kB\n" - "VmHWM:\t%8u kB\n" /* ie. resident peak */ - "Threads:\t%u\n", - proc_stat_args (ps), - state_string (ps), - proc_stat_pid (ps), /* XXX will need more work for threads */ - proc_stat_pid (ps), - proc_stat_proc_info (ps)->ppid, - proc_stat_owner_uid (ps), - proc_stat_owner_uid (ps), - proc_stat_owner_uid (ps), - proc_stat_owner_uid (ps), - tbi->virtual_size / 1024, - tbi->virtual_size / 1024, - tbi->resident_size / 1024, - tbi->resident_size / 1024, - proc_stat_num_threads (ps)); -} - - -/* Implementation of the file nodes. */ - -/* Describes a file in the process directories. This structure is - filled in as an "entry hook" in our procfs_dir entry table and is - passed to the process_file_make_node function defined below. */ -struct process_file_desc -{ - /* The proc_stat information required to get the contents of this file. */ - ps_flags_t needs; - - /* Content generator to use for this file. Once we have acquired the - necessary information, there can be only memory allocation errors, - hence this simplified signature. */ - ssize_t (*get_contents) (struct proc_stat *ps, char **contents); - - /* The cmdline and environ contents don't need any cleaning since they - point directly into the proc_stat structure. */ - int no_cleanup; - - /* If specified, the file mode to be set with procfs_node_chmod(). */ - mode_t mode; -}; - -struct process_file_node -{ - const struct process_file_desc *desc; - struct proc_stat *ps; -}; - -/* FIXME: lock the parent! */ -static error_t -process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - struct process_file_node *file = hook; - error_t err; - - /* Fetch the required information. */ - err = proc_stat_set_flags (file->ps, file->desc->needs); - if (err) - return EIO; - if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) - return EIO; - - /* Call the actual content generator (see the definitions below). */ - *contents_len = file->desc->get_contents (file->ps, contents); - return 0; -} - -static void -process_file_cleanup_contents (void *hook, char *contents, ssize_t len) -{ - struct process_file_node *file = hook; - - if (! file->desc->no_cleanup) - free (contents); -} - -static struct node * -process_file_make_node (void *dir_hook, const void *entry_hook) -{ - static const struct procfs_node_ops ops = { - .get_contents = process_file_get_contents, - .cleanup_contents = process_file_cleanup_contents, - .cleanup = free, - }; - struct process_file_node *f; - struct node *np; - - f = malloc (sizeof *f); - if (! f) - return NULL; - - f->desc = entry_hook; - f->ps = dir_hook; - - np = procfs_make_node (&ops, f); - if (! np) - return NULL; - - procfs_node_chown (np, proc_stat_owner_uid (f->ps)); - if (f->desc->mode) - procfs_node_chmod (np, f->desc->mode); - - return np; -} - -/* Stat needs its own constructor in oreder to set its mode according to - the --stat-mode command-line option. */ -static struct node * -process_stat_make_node (void *dir_hook, const void *entry_hook) -{ - struct node *np = process_file_make_node (dir_hook, entry_hook); - if (np) procfs_node_chmod (np, opt_stat_mode); - return np; -} - - -/* Implementation of the process directory per se. */ - -static struct procfs_dir_entry entries[] = { - { - .name = "cmdline", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_cmdline, - .needs = PSTAT_ARGS, - .no_cleanup = 1, - }, - }, - { - .name = "environ", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_environ, - .needs = PSTAT_ENV, - .no_cleanup = 1, - .mode = 0400, - }, - }, - { - .name = "stat", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_stat, - .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO - | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC - | PSTAT_THREAD_WAIT, - }, - .ops = { - .make_node = process_stat_make_node, - } - }, - { - .name = "statm", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_statm, - .needs = PSTAT_TASK_BASIC, - }, - }, - { - .name = "status", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_status, - .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO - | PSTAT_TASK_BASIC | PSTAT_OWNER_UID | PSTAT_NUM_THREADS, - }, - }, - {} -}; - -error_t -process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) -{ - static const struct procfs_dir_ops dir_ops = { - .entries = entries, - .cleanup = (void (*)(void *)) _proc_stat_free, - .entry_ops = { - .make_node = process_file_make_node, - }, - }; - struct proc_stat *ps; - int owner; - error_t err; - - err = _proc_stat_create (pid, pc, &ps); - if (err == ESRCH) - return ENOENT; - if (err) - return EIO; - - err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); - if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) - { - _proc_stat_free (ps); - return EIO; - } - - /* FIXME: have a separate proc_desc structure for each file, so this can be - accessed in a more robust and straightforward way. */ - ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; - - /* FIXME: have a separate proc_desc structure for each file, so this can be - accessed in a more robust and straightforward way. */ - ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; - - *np = procfs_dir_make_node (&dir_ops, ps); - if (! *np) - return ENOMEM; - - owner = proc_stat_owner_uid (ps); - procfs_node_chown (*np, owner >= 0 ? owner : opt_anon_owner); - return 0; -} diff --git a/process.h b/process.h deleted file mode 100644 index b230a281..00000000 --- a/process.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Hurd /proc filesystem, implementation of process directories. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include - -/* Create a node for a directory representing the given PID, as published by - the proc server refrenced by the libps context PC. On success, returns the - newly created node in *NP. */ -error_t -process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np); - diff --git a/procfs.c b/procfs.c deleted file mode 100644 index ae5a6769..00000000 --- a/procfs.c +++ /dev/null @@ -1,203 +0,0 @@ -/* Hurd /proc filesystem, basic infrastructure. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include "procfs.h" - -struct netnode -{ - const struct procfs_node_ops *ops; - void *hook; - - /* (cached) contents of the node */ - char *contents; - ssize_t contents_len; - - /* parent directory, if applicable */ - struct node *parent; -}; - -void -procfs_cleanup_contents_with_free (void *hook, char *cont, ssize_t len) -{ - free (cont); -} - -void -procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, ssize_t len) -{ - vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); -} - -struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) -{ - struct netnode *nn; - struct node *np; - - nn = malloc (sizeof *nn); - if (! nn) - goto fail; - - memset (nn, 0, sizeof *nn); - nn->ops = ops; - nn->hook = hook; - - np = netfs_make_node (nn); - if (! np) - goto fail; - - np->nn = nn; - memset (&np->nn_stat, 0, sizeof np->nn_stat); - np->nn_translated = 0; - - if (np->nn->ops->lookup) - np->nn_stat.st_mode = S_IFDIR | 0555; - else - np->nn_stat.st_mode = S_IFREG | 0444; - - return np; - -fail: - if (ops->cleanup) - ops->cleanup (hook); - - free (nn); - return NULL; -} - -void procfs_node_chown (struct node *np, uid_t owner) -{ - np->nn_stat.st_uid = owner; -} - -void procfs_node_chmod (struct node *np, mode_t mode) -{ - np->nn_stat.st_mode = (np->nn_stat.st_mode & S_IFMT) | mode; - np->nn_translated = np->nn_stat.st_mode; -} - -void procfs_node_chtype (struct node *np, mode_t type) -{ - np->nn_stat.st_mode = (np->nn_stat.st_mode & ~S_IFMT) | type; - np->nn_translated = np->nn_stat.st_mode; - if (type == S_IFLNK) - procfs_node_chmod (np, 0777); -} - -/* FIXME: possibly not the fastest hash function... */ -ino64_t -procfs_make_ino (struct node *np, const char *filename) -{ - unsigned short x[3]; - - if (! strcmp (filename, ".")) - return np->nn_stat.st_ino; - if (! strcmp (filename, "..")) - return np->nn->parent ? np->nn->parent->nn_stat.st_ino : /* FIXME: */ 2; - - assert (sizeof np->nn_stat.st_ino > sizeof x); - memcpy (x, &np->nn_stat.st_ino, sizeof x); - - while (*filename) - { - x[0] ^= *(filename++); - jrand48 (x); - } - - return (unsigned long) jrand48 (x); -} - -error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) -{ - if (! np->nn->contents && np->nn->ops->get_contents) - { - char *contents; - ssize_t contents_len; - error_t err; - - contents_len = -1; - err = np->nn->ops->get_contents (np->nn->hook, &contents, &contents_len); - if (err) - return err; - if (contents_len < 0) - return ENOMEM; - - np->nn->contents = contents; - np->nn->contents_len = contents_len; - } - - *data = np->nn->contents; - *data_len = np->nn->contents_len; - return 0; -} - -void procfs_refresh (struct node *np) -{ - if (np->nn->contents && np->nn->ops->cleanup_contents) - np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); - - np->nn->contents = NULL; -} - -error_t procfs_lookup (struct node *np, const char *name, struct node **npp) -{ - error_t err = ENOENT; - - if (err && ! strcmp (name, ".")) - { - netfs_nref(*npp = np); - err = 0; - } - - if (err && np->nn->parent && ! strcmp (name, "..")) - { - netfs_nref(*npp = np->nn->parent); - err = 0; - } - - if (err && np->nn->ops->lookup) - { - err = np->nn->ops->lookup (np->nn->hook, name, npp); - if (! err) - { - (*npp)->nn_stat.st_ino = procfs_make_ino (np, name); - netfs_nref ((*npp)->nn->parent = np); - } - } - - return err; -} - -void procfs_cleanup (struct node *np) -{ - procfs_refresh (np); - - if (np->nn->ops->cleanup) - np->nn->ops->cleanup (np->nn->hook); - - if (np->nn->parent) - netfs_nrele (np->nn->parent); - - free (np->nn); -} diff --git a/procfs.h b/procfs.h deleted file mode 100644 index 64782ec4..00000000 --- a/procfs.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Hurd /proc filesystem, basic infrastructure. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include - - -/* Interface for the procfs side. */ - -/* Any of these callback functions can be omitted, in which case - reasonable defaults will be used. The initial file mode and type - depend on whether a lookup function is provided, but can be - overridden in update_stat(). */ -struct procfs_node_ops -{ - /* Fetch the contents of a node. A pointer to the contents should be - returned in *CONTENTS and their length in *CONTENTS_LEN. The exact - nature of these data depends on whether the node is a regular file, - symlink or directory, as determined by the file mode in - netnode->nn_stat. For regular files and symlinks, they are what - you would expect; for directories, they are an argz vector of the - names of the entries. If upon return, *CONTENTS_LEN is negative or - unchanged, the call is considered to have failed because of a memory - allocation error. */ - error_t (*get_contents) (void *hook, char **contents, ssize_t *contents_len); - void (*cleanup_contents) (void *hook, char *contents, ssize_t contents_len); - - /* Lookup NAME in this directory, and store the result in *np. The - returned node should be created by lookup() using procfs_make_node() - or a derived function. Note that the parent will be kept alive as - long as the child exists, so you can safely reference the parent's - data from the child. You may want to consider locking if there's - any mutation going on, though. */ - error_t (*lookup) (void *hook, const char *name, struct node **np); - - /* Destroy this node. */ - void (*cleanup) (void *hook); -}; - -/* These helper functions can be used as procfs_node_ops.cleanup_contents. */ -void procfs_cleanup_contents_with_free (void *, char *, ssize_t); -void procfs_cleanup_contents_with_vm_deallocate (void *, char *, ssize_t); - -/* Create a new node and return it. Returns NULL if it fails to allocate - enough memory. In this case, ops->cleanup will be invoked. */ -struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); - -/* Set the owner of the node NP. Must be called right after the node - has been created. */ -void procfs_node_chown (struct node *np, uid_t owner); - -/* Set the permission bits of the node NP. Must be called right after - the node has been created. */ -void procfs_node_chmod (struct node *np, mode_t mode); - -/* Set the type of the node NP. If type is S_IFLNK, appropriate - permission bits will be set as well. Must be called right after the - node has been created. */ -void procfs_node_chtype (struct node *np, mode_t type); - - -/* Interface for the libnetfs side. */ - -/* Get the inode number which will be given to a child of NP named FILENAME. - This allows us to retreive them for readdir() without creating the - corresponding child nodes. */ -ino64_t procfs_make_ino (struct node *np, const char *filename); - -/* Forget the current cached contents for the node. This is done before reads - from offset 0, to ensure that the data are recent even for utilities such as - top which keep some nodes open. */ -void procfs_refresh (struct node *np); - -error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len); -error_t procfs_lookup (struct node *np, const char *name, struct node **npp); -void procfs_cleanup (struct node *np); - diff --git a/procfs/Makefile b/procfs/Makefile new file mode 100644 index 00000000..a397522f --- /dev/null +++ b/procfs/Makefile @@ -0,0 +1,26 @@ +TARGET = procfs +OBJS = procfs.o netfs.o procfs_dir.o \ + process.o proclist.o rootdir.o dircat.o main.o +LIBS = -lnetfs -lps + +CC = gcc +CFLAGS = -Wall -g +CPPFLAGS = +LDFLAGS = + +ifdef PROFILE +CFLAGS= -g -pg +CPPFLAGS= -DPROFILE +LDFLAGS= -static +LIBS= -lnetfs -lfshelp -liohelp -lps -lports -lthreads -lihash -lshouldbeinlibc +endif + +CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + $(RM) $(TARGET) $(OBJS) diff --git a/procfs/TODO b/procfs/TODO new file mode 100644 index 00000000..952d67bc --- /dev/null +++ b/procfs/TODO @@ -0,0 +1,24 @@ +Known bugs to be fixed +---------------------- + +* The non-owned processes sometimes show up with INT_MAX as their owner, + instead of opt_anon_uid. This is likely to be a libps problem. + +Improvements and new features +----------------------------- + +* There is a lot of dynamic memory allocation going on and it comes with a + cost in performance. We could try to limit such allocation, as long as it + keeps the inner interface simple and preserves the read/readdir semantics + (performance is probably not critical for a proc filesystem.) + One way would be to add an (optional) "needed_length" field to + procfs_node_ops, and arrange to pass a sufficent buffer in (*contents, + *contents_len) when get_contents is called. Then the user-provided buffer + might be used directly under some circumstances. + +* Add thread directories as [pid]/task/[n]. This shouldn't be too hard if we + use "process" nodes for threads, and provide an "exists" hook for the "task" + entry itself so that it's disabled in thread nodes. It might prove necessary + to have "optional" libps flags for some content generators, though, since + some of them might be missing for threads. + diff --git a/procfs/dircat.c b/procfs/dircat.c new file mode 100644 index 00000000..5a60899a --- /dev/null +++ b/procfs/dircat.c @@ -0,0 +1,128 @@ +/* Hurd /proc filesystem, concatenation of two directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include "procfs.h" + +struct dircat_node +{ + int num_dirs; + struct node *dirs[0]; +}; + +static error_t +dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) +{ + struct dircat_node *dcn = hook; + int i, sz, pos; + error_t err; + + pos = 0; + *contents = malloc (sz = 512); + + for (i=0; i < dcn->num_dirs; i++) + { + char *subcon; + ssize_t sublen; + + /* Make sure we're not getting some old stuff. */ + procfs_refresh (dcn->dirs[i]); + + err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); + if (err) + { + free (*contents); + *contents = NULL; + return err; + } + + while (pos + sublen > sz) + *contents = realloc (*contents, sz *= 2); + + memcpy (*contents + pos, subcon, sublen); + pos += sublen; + } + + *contents_len = pos; + return 0; +} + +static error_t +dircat_lookup (void *hook, const char *name, struct node **np) +{ + struct dircat_node *dcn = hook; + error_t err; + int i; + + err = ENOENT; + for (i=0; err && i < dcn->num_dirs; i++) + err = procfs_lookup (dcn->dirs[i], name, np); + + return err; +} + +static void +dircat_release_dirs (struct node *const *dirs, int num_dirs) +{ + int i; + + for (i=0; i < num_dirs; i++) + if (dirs[i]) + netfs_nrele (dirs[i]); +} + +static void +dircat_cleanup (void *hook) +{ + struct dircat_node *dcn = hook; + + dircat_release_dirs (dcn->dirs, dcn->num_dirs); + free (dcn); +} + +struct node * +dircat_make_node (struct node *const *dirs, int num_dirs) +{ + static struct procfs_node_ops ops = { + .get_contents = dircat_get_contents, + .cleanup_contents = procfs_cleanup_contents_with_free, + .lookup = dircat_lookup, + .cleanup = dircat_cleanup, + }; + struct dircat_node *dcn; + int i; + + for (i=0; i < num_dirs; i++) + if (! dirs[i]) + goto fail; + + dcn = malloc (sizeof *dcn + num_dirs * sizeof dcn->dirs[0]); + if (! dcn) + goto fail; + + dcn->num_dirs = num_dirs; + memcpy (dcn->dirs, dirs, num_dirs * sizeof dcn->dirs[0]); + return procfs_make_node (&ops, dcn); + +fail: + dircat_release_dirs (dirs, num_dirs); + return NULL; +} + diff --git a/procfs/dircat.h b/procfs/dircat.h new file mode 100644 index 00000000..4177b384 --- /dev/null +++ b/procfs/dircat.h @@ -0,0 +1,29 @@ +/* Hurd /proc filesystem, concatenation of two directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Append the contents of NUM_DIRS directories. DIRS is an array of + directory nodes. One reference is consumed for each of them. If a + memory allocation error occurs, or if one of the directories is a + NULL pointer, the references are dropped immediately and NULL is + returned. The given DIRS array is duplicated and can therefore be + allocated on the caller's stack. Strange things will happen if some + elements of DIRS have entries with the same name or if one of them is + not a directory. */ +struct node * +dircat_make_node (struct node *const *dirs, int num_dirs); diff --git a/procfs/main.c b/procfs/main.c new file mode 100644 index 00000000..3a976ccc --- /dev/null +++ b/procfs/main.c @@ -0,0 +1,190 @@ +/* Hurd /proc filesystem, main program. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include "procfs.h" +#include "proclist.h" +#include "rootdir.h" +#include "dircat.h" +#include "main.h" + +/* Command-line options */ +int opt_clk_tck; +mode_t opt_stat_mode; +pid_t opt_fake_self; +pid_t opt_kernel_pid; +uid_t opt_anon_owner; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + struct passwd *pw; + char *endp; + + switch (key) + { + case 'h': + opt_clk_tck = strtol (arg, &endp, 0); + if (*endp || ! *arg || opt_clk_tck <= 0) + error (1, 0, "--clk-tck: HZ should be a positive integer"); + break; + + case 's': + opt_stat_mode = strtol (arg, &endp, 8); + if (*endp || ! *arg || opt_stat_mode & ~07777) + error (1, 0, "--stat-mode: MODE should be an octal mode"); + break; + + case 'S': + if (arg) + { + opt_fake_self = strtol (arg, &endp, 0); + if (*endp || ! *arg) + error (1, 0, "--fake-self: PID must be an integer"); + } + else + opt_fake_self = 1; + break; + + case 'k': + opt_kernel_pid = strtol (arg, &endp, 0); + if (*endp || ! *arg || (signed) opt_kernel_pid < 0) + error (1, 0, "--kernel-process: PID must be a positive integer"); + break; + + case 'c': + opt_clk_tck = 100; + opt_stat_mode = 0444; + opt_fake_self = 1; + break; + + case 'a': + pw = getpwnam (arg); + if (pw) + { + opt_anon_owner = pw->pw_uid; + break; + } + + opt_anon_owner = strtol (arg, &endp, 0); + if (*endp || ! *arg || (signed) opt_anon_owner < 0) + error(1, 0, "--anonymous-owner: USER should be the a user name " + "or a numeric UID."); + break; + } + + return 0; +} + +struct argp argp = { + .options = (struct argp_option []) { + { "clk-tck", 'h', "HZ", 0, + "Unit used for the values expressed in system clock ticks " + "(default: sysconf(_SC_CLK_TCK))" }, + { "stat-mode", 's', "MODE", 0, + "The [pid]/stat file publishes information which on Hurd is only " + "available to the process owner. " + "You can use this option to override its mode to be more permissive " + "for compatibility purposes. " + "(default: 0400)" }, + { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL, + "Provide a fake \"self\" symlink to the given PID, for compatibility " + "purposes. If PID is omitted, \"self\" will point to init. " + "(default: no self link)" }, + { "kernel-process", 'k', "PID", 0, + "Process identifier for the kernel, used to retreive its command " + "line, as well as the global up and idle times. " + "(default: 2)" }, + { "compatible", 'c', NULL, 0, + "Try to be compatible with the Linux procps utilities. " + "Currently equivalent to -h 100 -s 0444 -S 1." }, + { "anonymous-owner", 'a', "USER", 0, + "Make USER the owner of files related to processes without one. " + "Be aware that USER will be granted access to the environment and " + "other sensitive information about the processes in question. " + "(default: use uid 0)" }, + {} + }, + .parser = argp_parser, + .doc = "A virtual filesystem emulating the Linux procfs.", + .children = (struct argp_child []) { + { &netfs_std_startup_argp, }, + {} + }, +}; + +error_t +root_make_node (struct ps_context *pc, struct node **np) +{ + struct node *root_dirs[] = { + proclist_make_node (pc), + rootdir_make_node (pc), + }; + + *np = dircat_make_node (root_dirs, sizeof root_dirs / sizeof root_dirs[0]); + if (! *np) + return ENOMEM; + + /* Since this one is not created through proc_lookup(), we have to affect an + inode number to it. */ + (*np)->nn_stat.st_ino = * (uint32_t *) "PROC"; + + return 0; +} + +int main (int argc, char **argv) +{ + struct ps_context *pc; + mach_port_t bootstrap; + error_t err; + + opt_clk_tck = sysconf(_SC_CLK_TCK); + opt_stat_mode = 0400; + opt_fake_self = -1; + opt_kernel_pid = 2; + opt_anon_owner = 0; + err = argp_parse (&argp, argc, argv, 0, 0, 0); + if (err) + error (1, err, "Could not parse command line"); + + err = ps_context_create (getproc (), &pc); + if (err) + error (1, err, "Could not create libps context"); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "Must be started as a translator"); + + netfs_init (); + err = root_make_node (pc, &netfs_root_node); + if (err) + error (1, err, "Could not create the root node"); + + netfs_startup (bootstrap, 0); + netfs_server_loop (); + + assert (0 /* netfs_server_loop returned after all */); +} + diff --git a/procfs/main.h b/procfs/main.h new file mode 100644 index 00000000..4e28b7eb --- /dev/null +++ b/procfs/main.h @@ -0,0 +1,25 @@ +/* Hurd /proc filesystem, command-line options set by main.c. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Startup options */ +extern int opt_clk_tck; +extern mode_t opt_stat_mode; +extern pid_t opt_fake_self; +extern pid_t opt_kernel_pid; +extern uid_t opt_anon_owner; diff --git a/procfs/netfs.c b/procfs/netfs.c new file mode 100644 index 00000000..24a6603f --- /dev/null +++ b/procfs/netfs.c @@ -0,0 +1,445 @@ +/* Hurd /proc filesystem, interface with libnetfs. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include "procfs.h" + +#define PROCFS_SERVER_NAME "procfs" +#define PROCFS_SERVER_VERSION "0.1.0" +#define PROCFS_MAXSYMLINKS 16 + + +/* Interesting libnetfs callback functions. */ + +/* The user must define this variable. Set this to the name of the + filesystem server. */ +char *netfs_server_name = PROCFS_SERVER_NAME; + +/* The user must define this variables. Set this to be the server + version number. */ +char *netfs_server_version = PROCFS_SERVER_VERSION; + +/* Maximum number of symlinks to follow before returning ELOOP. */ +int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; + +/* The user must define this function. Make sure that NP->nn_stat is + filled with the most current information. CRED identifies the user + responsible for the operation. NP is locked. */ +error_t netfs_validate_stat (struct node *np, struct iouser *cred) +{ + char *contents; + ssize_t contents_len; + error_t err; + + /* Only symlinks need to have their size filled, before a read is + attempted. */ + if (! S_ISLNK (np->nn_stat.st_mode)) + return 0; + + err = procfs_get_contents (np, &contents, &contents_len); + if (err) + return err; + + np->nn_stat.st_size = contents_len; + return 0; +} + +/* The user must define this function. Read from the locked file NP + for user CRED starting at OFFSET and continuing for up to *LEN + bytes. Put the data at DATA. Set *LEN to the amount successfully + read upon return. */ +error_t netfs_attempt_read (struct iouser *cred, struct node *np, + loff_t offset, size_t *len, void *data) +{ + char *contents; + ssize_t contents_len; + error_t err; + + if (offset == 0) + procfs_refresh (np); + + err = procfs_get_contents (np, &contents, &contents_len); + if (err) + return err; + + contents += offset; + contents_len -= offset; + + if (*len > contents_len) + *len = contents_len; + if (*len < 0) + *len = 0; + + memcpy (data, contents, *len); + return 0; +} + +/* The user must define this function. Read the contents of locked + node NP (a symlink), for USER, into BUF. */ +error_t netfs_attempt_readlink (struct iouser *user, struct node *np, + char *buf) +{ + char *contents; + ssize_t contents_len; + error_t err; + + err = procfs_get_contents (np, &contents, &contents_len); + if (err) + return err; + + assert (contents_len == np->nn_stat.st_size); + memcpy (buf, contents, contents_len); + return 0; +} + +/* Helper function for netfs_get_dirents() below. CONTENTS is an argz + vector of directory entry names, as returned by procfs_get_contents(). + Convert at most NENTRIES of them to dirent structures, put them in + DATA (if not NULL), write the number of entries processed in *AMT and + return the required/used space in DATACNT. */ +static int putentries (char *contents, size_t contents_len, int nentries, + char *data, mach_msg_type_number_t *datacnt) +{ + int i; + + *datacnt = 0; + for (i = 0; contents_len && (nentries < 0 || i < nentries); i++) + { + int namlen = strlen (contents); + int reclen = sizeof (struct dirent) + namlen; + + if (data) + { + struct dirent *d = (struct dirent *) (data + *datacnt); + d->d_fileno = 42; /* XXX */ + d->d_namlen = namlen; + d->d_reclen = reclen; + d->d_type = DT_UNKNOWN; + strcpy (d->d_name, contents); + } + + *datacnt += reclen; + contents += namlen + 1; + contents_len -= namlen + 1; + } + + return i; +} + +/* The user must define this function. Fill the array *DATA of size + BUFSIZE with up to NENTRIES dirents from DIR (which is locked) + starting with entry ENTRY for user CRED. The number of entries in + the array is stored in *AMT and the number of bytes in *DATACNT. + If the supplied buffer is not large enough to hold the data, it + should be grown. */ +error_t netfs_get_dirents (struct iouser *cred, struct node *dir, + int entry, int nentries, char **data, + mach_msg_type_number_t *datacnt, + vm_size_t bufsize, int *amt) +{ + char *contents; + ssize_t contents_len; + error_t err; + + if (entry == 0) + procfs_refresh (dir); + + err = procfs_get_contents (dir, &contents, &contents_len); + if (err) + return err; + + /* We depend on the fact that CONTENTS is terminated. */ + assert (contents_len == 0 || contents[contents_len - 1] == '\0'); + + /* Skip to the first requested entry. */ + while (contents_len && entry--) + { + int ofs = strlen (contents) + 1; + contents += ofs; + contents_len -= ofs; + } + + /* Allocate a buffer if necessary. */ + putentries (contents, contents_len, nentries, NULL, datacnt); + if (bufsize < *datacnt) + { + char *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); + if (n == MAP_FAILED) + return ENOMEM; + + *data = n; + } + + /* Do the actual conversion. */ + *amt = putentries (contents, contents_len, nentries, *data, datacnt); + + return 0; +} + +/* The user must define this function. Lookup NAME in DIR (which is + locked) for USER; set *NP to the found name upon return. If the + name was not found, then return ENOENT. On any error, clear *NP. + (*NP, if found, should be locked and a reference to it generated. + This call should unlock DIR no matter what.) */ +error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, + char *name, struct node **np) +{ + error_t err; + + err = procfs_lookup (dir, name, np); + mutex_unlock (&dir->lock); + + if (! err) + mutex_lock (&(*np)->lock); + + return err; +} + +/* The user must define this function. Node NP has no more references; + free all its associated storage. */ +void netfs_node_norefs (struct node *np) +{ + spin_unlock (&netfs_node_refcnt_lock); + + procfs_cleanup (np); + free (np); + + spin_lock (&netfs_node_refcnt_lock); +} + + +/* Libnetfs callbacks managed with libfshelp. */ + +/* The user must define this function. Locked node NP is being opened + by USER, with FLAGS. NEWNODE is nonzero if we just created this + node. Return an error if we should not permit the open to complete + because of a permission restriction. */ +error_t netfs_check_open_permissions (struct iouser *user, struct node *np, + int flags, int newnode) +{ + error_t err = 0; + if (!err && (flags & O_READ)) + err = fshelp_access (&np->nn_stat, S_IREAD, user); + if (!err && (flags & O_WRITE)) + err = fshelp_access (&np->nn_stat, S_IWRITE, user); + if (!err && (flags & O_EXEC)) + err = fshelp_access (&np->nn_stat, S_IEXEC, user); + return err; +} + +/* The user must define this function. Return the valid access + types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for + locked file NP and user CRED. */ +error_t netfs_report_access (struct iouser *cred, struct node *np, + int *types) +{ + *types = 0; + if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + return 0; +} + + +/* Trivial or unsupported libnetfs callbacks. */ + +/* The user must define this function. This should attempt a chmod + call for the user specified by CRED on locked node NP, to change + the owner to UID and the group to GID. */ +error_t netfs_attempt_chown (struct iouser *cred, struct node *np, + uid_t uid, uid_t gid) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a chauthor + call for the user specified by CRED on locked node NP, thereby + changing the author to AUTHOR. */ +error_t netfs_attempt_chauthor (struct iouser *cred, struct node *np, + uid_t author) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a chmod + call for the user specified by CRED on locked node NODE, to change + the mode to MODE. Unlike the normal Unix and Hurd meaning of + chmod, this function is also used to attempt to change files into + other types. If such a transition is attempted which is + impossible, then return EOPNOTSUPP. */ +error_t netfs_attempt_chmod (struct iouser *cred, struct node *np, + mode_t mode) +{ + return EROFS; +} + +/* The user must define this function. Attempt to turn locked node NP + (user CRED) into a symlink with target NAME. */ +error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *np, + char *name) +{ + return EROFS; +} + +/* The user must define this function. Attempt to turn NODE (user + CRED) into a device. TYPE is either S_IFBLK or S_IFCHR. NP is + locked. */ +error_t netfs_attempt_mkdev (struct iouser *cred, struct node *np, + mode_t type, dev_t indexes) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a chflags + call for the user specified by CRED on locked node NP, to change + the flags to FLAGS. */ +error_t netfs_attempt_chflags (struct iouser *cred, struct node *np, + int flags) +{ + return EROFS; +} + +/* The user must define this function. This should attempt a utimes + call for the user specified by CRED on locked node NP, to change + the atime to ATIME and the mtime to MTIME. If ATIME or MTIME is + null, then set to the current time. */ +error_t netfs_attempt_utimes (struct iouser *cred, struct node *np, + struct timespec *atime, struct timespec *mtime) +{ + return EROFS; +} + +/* The user must define this function. This should attempt to set the + size of the locked file NP (for user CRED) to SIZE bytes long. */ +error_t netfs_attempt_set_size (struct iouser *cred, struct node *np, + loff_t size) +{ + return EROFS; +} + +/* The user must define this function. This should attempt to fetch + filesystem status information for the remote filesystem, for the + user CRED. NP is locked. */ +error_t netfs_attempt_statfs (struct iouser *cred, struct node *np, + fsys_statfsbuf_t *st) +{ + return ENOSYS; +} + +/* The user must define this function. This should sync the locked + file NP completely to disk, for the user CRED. If WAIT is set, + return only after the sync is completely finished. */ +error_t netfs_attempt_sync (struct iouser *cred, struct node *np, + int wait) +{ + return 0; +} + +/* The user must define this function. This should sync the entire + remote filesystem. If WAIT is set, return only after the sync is + completely finished. */ +error_t netfs_attempt_syncfs (struct iouser *cred, int wait) +{ + return 0; +} + +/* The user must define this function. Delete NAME in DIR (which is + locked) for USER. */ +error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, + char *name) +{ + return EROFS; +} + +/* The user must define this function. Attempt to rename the + directory FROMDIR to TODIR. Note that neither of the specific nodes + are locked. */ +error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, + char *fromname, struct node *todir, + char *toname, int excl) +{ + return EROFS; +} + +/* The user must define this function. Attempt to create a new + directory named NAME in DIR (which is locked) for USER with mode + MODE. */ +error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, + char *name, mode_t mode) +{ + return EROFS; +} + +/* The user must define this function. Attempt to remove directory + named NAME in DIR (which is locked) for USER. */ +error_t netfs_attempt_rmdir (struct iouser *user, + struct node *dir, char *name) +{ + return EROFS; +} + + +/* The user must define this function. Create a link in DIR with name + NAME to FILE for USER. Note that neither DIR nor FILE are + locked. If EXCL is set, do not delete the target. Return EEXIST if + NAME is already found in DIR. */ +error_t netfs_attempt_link (struct iouser *user, struct node *dir, + struct node *file, char *name, int excl) +{ + return EROFS; +} + +/* The user must define this function. Attempt to create an anonymous + file related to DIR (which is locked) for USER with MODE. Set *NP + to the returned file upon success. No matter what, unlock DIR. */ +error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, + mode_t mode, struct node **np) +{ + return EROFS; +} + +/* The user must define this function. Attempt to create a file named + NAME in DIR (which is locked) for USER with MODE. Set *NP to the + new node upon return. On any error, clear *NP. *NP should be + locked on success; no matter what, unlock DIR before returning. */ +error_t netfs_attempt_create_file (struct iouser *user, struct node *dir, + char *name, mode_t mode, struct node **np) +{ + return EROFS; +} + +/* The user must define this function. Write to the locked file NP + for user CRED starting at OFSET and continuing for up to *LEN bytes + from DATA. Set *LEN to the amount successfully written upon + return. */ +error_t netfs_attempt_write (struct iouser *cred, struct node *np, + loff_t offset, size_t *len, void *data) +{ + return EROFS; +} + + diff --git a/procfs/process.c b/procfs/process.c new file mode 100644 index 00000000..6652a4e9 --- /dev/null +++ b/procfs/process.c @@ -0,0 +1,387 @@ +/* Hurd /proc filesystem, implementation of process directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include "procfs.h" +#include "procfs_dir.h" +#include "process.h" +#include "main.h" + +/* This module implements the process directories and the files they + contain. A libps proc_stat structure is created for each process + node, and is used by the individual file content generators as a + source of information. Each possible file (cmdline, environ, ...) is + decribed in a process_file_desc structure, which specifies which bits + of information (ie. libps flags) it needs, and what function should + be used to generate the file's contents. + + The content generators are defined first, followed by glue logic and + entry table. */ + + +/* Helper functions */ + +static char state_char (struct proc_stat *ps) +{ + int i; + + for (i = 0; (1 << i) & (PSTAT_STATE_P_STATES | PSTAT_STATE_T_STATES); i++) + if (proc_stat_state (ps) & (1 << i)) + return proc_stat_state_tags[i]; + + return '?'; +} + +static const char *state_string (struct proc_stat *ps) +{ + static const char *const state_strings[] = { + "T (stopped)", + "Z (zombie)", + "R (running)", + "H (halted)", + "D (disk sleep)", + "S (sleeping)", + "I (idle)", + NULL + }; + int i; + + for (i = 0; state_strings[i]; i++) + if (proc_stat_state (ps) & (1 << i)) + return state_strings[i]; + + return "? (unknown)"; +} + +static long long int timeval_jiffies (time_value_t tv) +{ + double secs = tv.seconds * 1000000. + tv.microseconds; + return secs * opt_clk_tck / 1000000.; +} + +/* Actual content generators */ + +static ssize_t +process_file_gc_cmdline (struct proc_stat *ps, char **contents) +{ + *contents = proc_stat_args(ps); + return proc_stat_args_len(ps); +} + +static ssize_t +process_file_gc_environ (struct proc_stat *ps, char **contents) +{ + *contents = proc_stat_env(ps); + return proc_stat_env_len(ps); +} + +static ssize_t +process_file_gc_stat (struct proc_stat *ps, char **contents) +{ + struct procinfo *pi = proc_stat_proc_info (ps); + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); + + /* See proc(5) for more information about the contents of each field for the + Linux procfs. */ + return asprintf (contents, + "%d (%s) %c " /* pid, command, state */ + "%d %d %d " /* ppid, pgid, session */ + "%d %d " /* controling tty stuff */ + "%u " /* flags, as defined by */ + "%lu %lu %lu %lu " /* page fault counts */ + "%lu %lu %ld %ld " /* user/sys times, in sysconf(_SC_CLK_TCK) */ + "%d %d " /* scheduler params (priority, nice) */ + "%d %ld " /* number of threads, [obsolete] */ + "%llu " /* start time since boot (jiffies) */ + "%lu %ld %lu " /* virtual size (bytes), rss (pages), rss lim */ + "%lu %lu %lu %lu %lu " /* some vm addresses (code, stack, sp, pc) */ + "%lu %lu %lu %lu " /* pending, blocked, ignored and caught sigs */ + "%lu " /* wait channel */ + "%lu %lu " /* swap usage (not maintained in Linux) */ + "%d " /* exit signal, to be sent to the parent */ + "%d " /* last processor used */ + "%u %u " /* RT priority and policy */ + "%llu " /* aggregated block I/O delay */ + "\n", + proc_stat_pid (ps), proc_stat_args (ps), state_char (ps), + pi->ppid, pi->pgrp, pi->session, + 0, 0, /* no such thing as a major:minor for ctty */ + 0, /* no such thing as CLONE_* flags on Hurd */ + 0L, 0L, 0L, 0L, /* TASK_EVENTS_INFO is unavailable on GNU Mach */ + (long unsigned) timeval_jiffies (thbi->user_time), + (long unsigned) timeval_jiffies (thbi->system_time), + 0L, 0L, /* cumulative time for children */ + MACH_PRIORITY_TO_NICE(thbi->base_priority) + 20, + MACH_PRIORITY_TO_NICE(thbi->base_priority), + pi->nthreads, 0L, + timeval_jiffies (thbi->creation_time), /* FIXME: ... since boot */ + (long unsigned) tbi->virtual_size, + (long unsigned) tbi->resident_size / PAGE_SIZE, 0L, + 0L, 0L, 0L, 0L, 0L, + 0L, 0L, 0L, 0L, + (long unsigned) proc_stat_thread_rpc (ps), /* close enough */ + 0L, 0L, + 0, + 0, + 0, 0, + 0LL); +} + +static ssize_t +process_file_gc_statm (struct proc_stat *ps, char **contents) +{ + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + + return asprintf (contents, + "%lu %lu 0 0 0 0 0\n", + tbi->virtual_size / sysconf(_SC_PAGE_SIZE), + tbi->resident_size / sysconf(_SC_PAGE_SIZE)); +} + +static ssize_t +process_file_gc_status (struct proc_stat *ps, char **contents) +{ + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + + return asprintf (contents, + "Name:\t%s\n" + "State:\t%s\n" + "Tgid:\t%u\n" + "Pid:\t%u\n" + "PPid:\t%u\n" + "Uid:\t%u\t%u\t%u\t%u\n" + "VmSize:\t%8u kB\n" + "VmPeak:\t%8u kB\n" + "VmRSS:\t%8u kB\n" + "VmHWM:\t%8u kB\n" /* ie. resident peak */ + "Threads:\t%u\n", + proc_stat_args (ps), + state_string (ps), + proc_stat_pid (ps), /* XXX will need more work for threads */ + proc_stat_pid (ps), + proc_stat_proc_info (ps)->ppid, + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + proc_stat_owner_uid (ps), + tbi->virtual_size / 1024, + tbi->virtual_size / 1024, + tbi->resident_size / 1024, + tbi->resident_size / 1024, + proc_stat_num_threads (ps)); +} + + +/* Implementation of the file nodes. */ + +/* Describes a file in the process directories. This structure is + filled in as an "entry hook" in our procfs_dir entry table and is + passed to the process_file_make_node function defined below. */ +struct process_file_desc +{ + /* The proc_stat information required to get the contents of this file. */ + ps_flags_t needs; + + /* Content generator to use for this file. Once we have acquired the + necessary information, there can be only memory allocation errors, + hence this simplified signature. */ + ssize_t (*get_contents) (struct proc_stat *ps, char **contents); + + /* The cmdline and environ contents don't need any cleaning since they + point directly into the proc_stat structure. */ + int no_cleanup; + + /* If specified, the file mode to be set with procfs_node_chmod(). */ + mode_t mode; +}; + +struct process_file_node +{ + const struct process_file_desc *desc; + struct proc_stat *ps; +}; + +/* FIXME: lock the parent! */ +static error_t +process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) +{ + struct process_file_node *file = hook; + error_t err; + + /* Fetch the required information. */ + err = proc_stat_set_flags (file->ps, file->desc->needs); + if (err) + return EIO; + if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) + return EIO; + + /* Call the actual content generator (see the definitions below). */ + *contents_len = file->desc->get_contents (file->ps, contents); + return 0; +} + +static void +process_file_cleanup_contents (void *hook, char *contents, ssize_t len) +{ + struct process_file_node *file = hook; + + if (! file->desc->no_cleanup) + free (contents); +} + +static struct node * +process_file_make_node (void *dir_hook, const void *entry_hook) +{ + static const struct procfs_node_ops ops = { + .get_contents = process_file_get_contents, + .cleanup_contents = process_file_cleanup_contents, + .cleanup = free, + }; + struct process_file_node *f; + struct node *np; + + f = malloc (sizeof *f); + if (! f) + return NULL; + + f->desc = entry_hook; + f->ps = dir_hook; + + np = procfs_make_node (&ops, f); + if (! np) + return NULL; + + procfs_node_chown (np, proc_stat_owner_uid (f->ps)); + if (f->desc->mode) + procfs_node_chmod (np, f->desc->mode); + + return np; +} + +/* Stat needs its own constructor in oreder to set its mode according to + the --stat-mode command-line option. */ +static struct node * +process_stat_make_node (void *dir_hook, const void *entry_hook) +{ + struct node *np = process_file_make_node (dir_hook, entry_hook); + if (np) procfs_node_chmod (np, opt_stat_mode); + return np; +} + + +/* Implementation of the process directory per se. */ + +static struct procfs_dir_entry entries[] = { + { + .name = "cmdline", + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_cmdline, + .needs = PSTAT_ARGS, + .no_cleanup = 1, + }, + }, + { + .name = "environ", + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_environ, + .needs = PSTAT_ENV, + .no_cleanup = 1, + .mode = 0400, + }, + }, + { + .name = "stat", + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_stat, + .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO + | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC + | PSTAT_THREAD_WAIT, + }, + .ops = { + .make_node = process_stat_make_node, + } + }, + { + .name = "statm", + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_statm, + .needs = PSTAT_TASK_BASIC, + }, + }, + { + .name = "status", + .hook = & (struct process_file_desc) { + .get_contents = process_file_gc_status, + .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO + | PSTAT_TASK_BASIC | PSTAT_OWNER_UID | PSTAT_NUM_THREADS, + }, + }, + {} +}; + +error_t +process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) +{ + static const struct procfs_dir_ops dir_ops = { + .entries = entries, + .cleanup = (void (*)(void *)) _proc_stat_free, + .entry_ops = { + .make_node = process_file_make_node, + }, + }; + struct proc_stat *ps; + int owner; + error_t err; + + err = _proc_stat_create (pid, pc, &ps); + if (err == ESRCH) + return ENOENT; + if (err) + return EIO; + + err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); + if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) + { + _proc_stat_free (ps); + return EIO; + } + + /* FIXME: have a separate proc_desc structure for each file, so this can be + accessed in a more robust and straightforward way. */ + ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + + /* FIXME: have a separate proc_desc structure for each file, so this can be + accessed in a more robust and straightforward way. */ + ((struct process_file_desc *) entries[2].hook)->mode = opt_stat_mode; + + *np = procfs_dir_make_node (&dir_ops, ps); + if (! *np) + return ENOMEM; + + owner = proc_stat_owner_uid (ps); + procfs_node_chown (*np, owner >= 0 ? owner : opt_anon_owner); + return 0; +} diff --git a/procfs/process.h b/procfs/process.h new file mode 100644 index 00000000..b230a281 --- /dev/null +++ b/procfs/process.h @@ -0,0 +1,27 @@ +/* Hurd /proc filesystem, implementation of process directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include + +/* Create a node for a directory representing the given PID, as published by + the proc server refrenced by the libps context PC. On success, returns the + newly created node in *NP. */ +error_t +process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np); + diff --git a/procfs/procfs.c b/procfs/procfs.c new file mode 100644 index 00000000..ae5a6769 --- /dev/null +++ b/procfs/procfs.c @@ -0,0 +1,203 @@ +/* Hurd /proc filesystem, basic infrastructure. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include "procfs.h" + +struct netnode +{ + const struct procfs_node_ops *ops; + void *hook; + + /* (cached) contents of the node */ + char *contents; + ssize_t contents_len; + + /* parent directory, if applicable */ + struct node *parent; +}; + +void +procfs_cleanup_contents_with_free (void *hook, char *cont, ssize_t len) +{ + free (cont); +} + +void +procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, ssize_t len) +{ + vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); +} + +struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) +{ + struct netnode *nn; + struct node *np; + + nn = malloc (sizeof *nn); + if (! nn) + goto fail; + + memset (nn, 0, sizeof *nn); + nn->ops = ops; + nn->hook = hook; + + np = netfs_make_node (nn); + if (! np) + goto fail; + + np->nn = nn; + memset (&np->nn_stat, 0, sizeof np->nn_stat); + np->nn_translated = 0; + + if (np->nn->ops->lookup) + np->nn_stat.st_mode = S_IFDIR | 0555; + else + np->nn_stat.st_mode = S_IFREG | 0444; + + return np; + +fail: + if (ops->cleanup) + ops->cleanup (hook); + + free (nn); + return NULL; +} + +void procfs_node_chown (struct node *np, uid_t owner) +{ + np->nn_stat.st_uid = owner; +} + +void procfs_node_chmod (struct node *np, mode_t mode) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & S_IFMT) | mode; + np->nn_translated = np->nn_stat.st_mode; +} + +void procfs_node_chtype (struct node *np, mode_t type) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & ~S_IFMT) | type; + np->nn_translated = np->nn_stat.st_mode; + if (type == S_IFLNK) + procfs_node_chmod (np, 0777); +} + +/* FIXME: possibly not the fastest hash function... */ +ino64_t +procfs_make_ino (struct node *np, const char *filename) +{ + unsigned short x[3]; + + if (! strcmp (filename, ".")) + return np->nn_stat.st_ino; + if (! strcmp (filename, "..")) + return np->nn->parent ? np->nn->parent->nn_stat.st_ino : /* FIXME: */ 2; + + assert (sizeof np->nn_stat.st_ino > sizeof x); + memcpy (x, &np->nn_stat.st_ino, sizeof x); + + while (*filename) + { + x[0] ^= *(filename++); + jrand48 (x); + } + + return (unsigned long) jrand48 (x); +} + +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) +{ + if (! np->nn->contents && np->nn->ops->get_contents) + { + char *contents; + ssize_t contents_len; + error_t err; + + contents_len = -1; + err = np->nn->ops->get_contents (np->nn->hook, &contents, &contents_len); + if (err) + return err; + if (contents_len < 0) + return ENOMEM; + + np->nn->contents = contents; + np->nn->contents_len = contents_len; + } + + *data = np->nn->contents; + *data_len = np->nn->contents_len; + return 0; +} + +void procfs_refresh (struct node *np) +{ + if (np->nn->contents && np->nn->ops->cleanup_contents) + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); + + np->nn->contents = NULL; +} + +error_t procfs_lookup (struct node *np, const char *name, struct node **npp) +{ + error_t err = ENOENT; + + if (err && ! strcmp (name, ".")) + { + netfs_nref(*npp = np); + err = 0; + } + + if (err && np->nn->parent && ! strcmp (name, "..")) + { + netfs_nref(*npp = np->nn->parent); + err = 0; + } + + if (err && np->nn->ops->lookup) + { + err = np->nn->ops->lookup (np->nn->hook, name, npp); + if (! err) + { + (*npp)->nn_stat.st_ino = procfs_make_ino (np, name); + netfs_nref ((*npp)->nn->parent = np); + } + } + + return err; +} + +void procfs_cleanup (struct node *np) +{ + procfs_refresh (np); + + if (np->nn->ops->cleanup) + np->nn->ops->cleanup (np->nn->hook); + + if (np->nn->parent) + netfs_nrele (np->nn->parent); + + free (np->nn); +} diff --git a/procfs/procfs.h b/procfs/procfs.h new file mode 100644 index 00000000..64782ec4 --- /dev/null +++ b/procfs/procfs.h @@ -0,0 +1,93 @@ +/* Hurd /proc filesystem, basic infrastructure. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include + + +/* Interface for the procfs side. */ + +/* Any of these callback functions can be omitted, in which case + reasonable defaults will be used. The initial file mode and type + depend on whether a lookup function is provided, but can be + overridden in update_stat(). */ +struct procfs_node_ops +{ + /* Fetch the contents of a node. A pointer to the contents should be + returned in *CONTENTS and their length in *CONTENTS_LEN. The exact + nature of these data depends on whether the node is a regular file, + symlink or directory, as determined by the file mode in + netnode->nn_stat. For regular files and symlinks, they are what + you would expect; for directories, they are an argz vector of the + names of the entries. If upon return, *CONTENTS_LEN is negative or + unchanged, the call is considered to have failed because of a memory + allocation error. */ + error_t (*get_contents) (void *hook, char **contents, ssize_t *contents_len); + void (*cleanup_contents) (void *hook, char *contents, ssize_t contents_len); + + /* Lookup NAME in this directory, and store the result in *np. The + returned node should be created by lookup() using procfs_make_node() + or a derived function. Note that the parent will be kept alive as + long as the child exists, so you can safely reference the parent's + data from the child. You may want to consider locking if there's + any mutation going on, though. */ + error_t (*lookup) (void *hook, const char *name, struct node **np); + + /* Destroy this node. */ + void (*cleanup) (void *hook); +}; + +/* These helper functions can be used as procfs_node_ops.cleanup_contents. */ +void procfs_cleanup_contents_with_free (void *, char *, ssize_t); +void procfs_cleanup_contents_with_vm_deallocate (void *, char *, ssize_t); + +/* Create a new node and return it. Returns NULL if it fails to allocate + enough memory. In this case, ops->cleanup will be invoked. */ +struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); + +/* Set the owner of the node NP. Must be called right after the node + has been created. */ +void procfs_node_chown (struct node *np, uid_t owner); + +/* Set the permission bits of the node NP. Must be called right after + the node has been created. */ +void procfs_node_chmod (struct node *np, mode_t mode); + +/* Set the type of the node NP. If type is S_IFLNK, appropriate + permission bits will be set as well. Must be called right after the + node has been created. */ +void procfs_node_chtype (struct node *np, mode_t type); + + +/* Interface for the libnetfs side. */ + +/* Get the inode number which will be given to a child of NP named FILENAME. + This allows us to retreive them for readdir() without creating the + corresponding child nodes. */ +ino64_t procfs_make_ino (struct node *np, const char *filename); + +/* Forget the current cached contents for the node. This is done before reads + from offset 0, to ensure that the data are recent even for utilities such as + top which keep some nodes open. */ +void procfs_refresh (struct node *np); + +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len); +error_t procfs_lookup (struct node *np, const char *name, struct node **npp); +void procfs_cleanup (struct node *np); + diff --git a/procfs/procfs_dir.c b/procfs/procfs_dir.c new file mode 100644 index 00000000..c250aa48 --- /dev/null +++ b/procfs/procfs_dir.c @@ -0,0 +1,134 @@ +/* Hurd /proc filesystem, infrastructure for directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include "procfs.h" +#include "procfs_dir.h" + +struct procfs_dir_node +{ + const struct procfs_dir_ops *ops; + void *hook; +}; + +static int +entry_exists (struct procfs_dir_node *dir, const struct procfs_dir_entry *ent) +{ + if (ent->ops.exists) + return ent->ops.exists (dir->hook, ent->hook); + if (dir->ops->entry_ops.exists) + return dir->ops->entry_ops.exists (dir->hook, ent->hook); + + return 1; +} + +static error_t +procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) +{ + static const char dot_dotdot[] = ".\0.."; + struct procfs_dir_node *dir = hook; + const struct procfs_dir_entry *ent; + int pos; + + /* Evaluate how much space is needed. Note that we include the hidden + entries, just in case their status changes between now and then. */ + pos = sizeof dot_dotdot; + for (ent = dir->ops->entries; ent->name; ent++) + pos += strlen (ent->name) + 1; + + *contents = malloc (pos); + if (! *contents) + return ENOMEM; + + memcpy (*contents, dot_dotdot, sizeof dot_dotdot); + pos = sizeof dot_dotdot; + for (ent = dir->ops->entries; ent->name; ent++) + { + if (! entry_exists (dir, ent)) + continue; + + strcpy (*contents + pos, ent->name); + pos += strlen (ent->name) + 1; + } + + *contents_len = pos; + return 0; +} + +static error_t +procfs_dir_lookup (void *hook, const char *name, struct node **np) +{ + struct procfs_dir_node *dir = hook; + const struct procfs_dir_entry *ent; + + for (ent = dir->ops->entries; ent->name && strcmp (name, ent->name); ent++); + if (! ent->name) + return ENOENT; + + if (ent->ops.make_node) + *np = ent->ops.make_node (dir->hook, ent->hook); + else if (dir->ops->entry_ops.make_node) + *np = dir->ops->entry_ops.make_node (dir->hook, ent->hook); + else + return EGRATUITOUS; + + if (! *np) + return ENOMEM; + + return 0; +} + +static void +procfs_dir_cleanup (void *hook) +{ + struct procfs_dir_node *dir = hook; + + if (dir->ops->cleanup) + dir->ops->cleanup (dir->hook); + + free (dir); +} + +struct node * +procfs_dir_make_node (const struct procfs_dir_ops *dir_ops, void *dir_hook) +{ + static const struct procfs_node_ops ops = { + .get_contents = procfs_dir_get_contents, + .lookup = procfs_dir_lookup, + .cleanup_contents = procfs_cleanup_contents_with_free, + .cleanup = procfs_dir_cleanup, + }; + struct procfs_dir_node *dir; + + dir = malloc (sizeof *dir); + if (! dir) + { + if (dir_ops->cleanup) + dir_ops->cleanup (dir_hook); + + return NULL; + } + + dir->ops = dir_ops; + dir->hook = dir_hook; + + return procfs_make_node (&ops, dir); +} + diff --git a/procfs/procfs_dir.h b/procfs/procfs_dir.h new file mode 100644 index 00000000..94c5b019 --- /dev/null +++ b/procfs/procfs_dir.h @@ -0,0 +1,63 @@ +/* Hurd /proc filesystem, infrastructure for directories. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This module provides an abstraction layer for implementing simple + directories with (mostly) static contents. The user defines the + contents of the directory by providing a table of entries and various + optional callback functions. */ + +/* These operations define how a given entry will behave. Either can be + omitted, both from the entry-specific operations and from the + directory-wide defaults. */ +struct procfs_dir_entry_ops +{ + /* Called when this entry is looked up to create a corresponding node. */ + struct node *(*make_node)(void *dir_hook, const void *entry_hook); + /* If this is provided and returns 0, this entry will be hidden. */ + int (*exists)(void *dir_hook, const void *entry_hook); +}; + +/* Describes an individual directory entry, associating a NAME with + * arbitrary HOOK data and node-specific OPS. */ +struct procfs_dir_entry +{ + const char *name; + const void *hook; + struct procfs_dir_entry_ops ops; +}; + +/* Describes a complete directory. ENTRIES is a table terminated by a + null NAME field. ENTRY_OPS provides default operations for the + entries which don't specify them. The optional CLEANUP function + should release all the resources associated with the directory hook. */ +struct procfs_dir_ops +{ + const struct procfs_dir_entry *entries; + void (*cleanup)(void *dir_hook); + struct procfs_dir_entry_ops entry_ops; +}; + +/* Create and return a new node for the directory described in OPS. + The DIR_HOOK is passed the MAKE_NODE callback function of looked up + entries, as well as to the CLEANUP callback when the node is + destroyed. If not enough memory can be allocated, OPS->CLEANUP is + invoked immediately and NULL is returned. */ +struct node * +procfs_dir_make_node (const struct procfs_dir_ops *ops, void *dir_hook); + diff --git a/procfs/proclist.c b/procfs/proclist.c new file mode 100644 index 00000000..58b942dc --- /dev/null +++ b/procfs/proclist.c @@ -0,0 +1,94 @@ +/* Hurd /proc filesystem, list of processes as a directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include "procfs.h" +#include "process.h" + +#define PID_STR_SIZE (3 * sizeof (pid_t) + 1) + +static error_t +proclist_get_contents (void *hook, char **contents, ssize_t *contents_len) +{ + struct ps_context *pc = hook; + pidarray_t pids; + mach_msg_type_number_t num_pids; + error_t err; + int i; + + num_pids = 0; + err = proc_getallpids (pc->server, &pids, &num_pids); + if (err) + return EIO; + + *contents = malloc (num_pids * PID_STR_SIZE); + if (*contents) + { + *contents_len = 0; + for (i=0; i < num_pids; i++) + { + int n = sprintf (*contents + *contents_len, "%d", pids[i]); + assert (n >= 0); + *contents_len += (n + 1); + } + } + else + err = ENOMEM; + + vm_deallocate (mach_task_self (), (vm_address_t) pids, num_pids * sizeof pids[0]); + return err; +} + +static error_t +proclist_lookup (void *hook, const char *name, struct node **np) +{ + struct ps_context *pc = hook; + char *endp; + pid_t pid; + + /* Self-lookups should not end up here. */ + assert (name[0]); + + /* No leading zeros allowed */ + if (name[0] == '0' && name[1]) + return ENOENT; + + pid = strtol (name, &endp, 10); + if (*endp) + return ENOENT; + + return process_lookup_pid (pc, pid, np); +} + +struct node * +proclist_make_node (struct ps_context *pc) +{ + static const struct procfs_node_ops ops = { + .get_contents = proclist_get_contents, + .lookup = proclist_lookup, + .cleanup_contents = procfs_cleanup_contents_with_free, + }; + return procfs_make_node (&ops, pc); +} + diff --git a/procfs/proclist.h b/procfs/proclist.h new file mode 100644 index 00000000..bfe95b3d --- /dev/null +++ b/procfs/proclist.h @@ -0,0 +1,23 @@ +/* Hurd /proc filesystem, list of processes as a directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include + +struct node * +proclist_make_node (struct ps_context *pc); diff --git a/procfs/rootdir.c b/procfs/rootdir.c new file mode 100644 index 00000000..15ef8bce --- /dev/null +++ b/procfs/rootdir.c @@ -0,0 +1,503 @@ +/* Hurd /proc filesystem, permanent files of the root directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "procfs.h" +#include "procfs_dir.h" +#include "main.h" + +/* This implements a directory node with the static files in /proc. + NB: the libps functions for host information return static storage; + using them would require locking and as a consequence it would be + more complicated, not simpler. */ + + +/* Helper functions */ + +/* We get the boot time by using that of the kernel process. */ +static error_t +get_boottime (struct ps_context *pc, struct timeval *tv) +{ + struct proc_stat *ps; + error_t err; + + err = _proc_stat_create (opt_kernel_pid, pc, &ps); + if (err) + return err; + + err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); + if (err || !(proc_stat_flags (ps) & PSTAT_TASK_BASIC)) + err = EIO; + + if (! err) + { + task_basic_info_t tbi = proc_stat_task_basic_info (ps); + tv->tv_sec = tbi->creation_time.seconds; + tv->tv_usec = tbi->creation_time.microseconds; + } + + _proc_stat_free (ps); + return err; +} + +/* We get the idle time by querying the kernel's idle thread. */ +static error_t +get_idletime (struct ps_context *pc, struct timeval *tv) +{ + struct proc_stat *ps, *pst; + thread_basic_info_t tbi; + error_t err; + int i; + + err = _proc_stat_create (opt_kernel_pid, pc, &ps); + if (err) + return err; + + pst = NULL, tbi = NULL; + + err = proc_stat_set_flags (ps, PSTAT_NUM_THREADS); + if (err || !(proc_stat_flags (ps) & PSTAT_NUM_THREADS)) + { + err = EIO; + goto out; + } + + /* Look for the idle thread */ + for (i=0; !tbi || !(tbi->flags & TH_FLAGS_IDLE); i++) + { + if (pst) + _proc_stat_free (pst); + + pst = NULL, tbi = NULL; + if (i >= proc_stat_num_threads (ps)) + { + err = ESRCH; + goto out; + } + + err = proc_stat_thread_create (ps, i, &pst); + if (err) + continue; + + err = proc_stat_set_flags (pst, PSTAT_THREAD_BASIC); + if (err || ! (proc_stat_flags (pst) & PSTAT_THREAD_BASIC)) + continue; + + tbi = proc_stat_thread_basic_info (pst); + } + + /* We found it! */ + tv->tv_sec = tbi->system_time.seconds; + tv->tv_usec = tbi->system_time.microseconds; + err = 0; + +out: + if (pst) _proc_stat_free (pst); + _proc_stat_free (ps); + return err; +} + +static error_t +get_swapinfo (default_pager_info_t *info) +{ + mach_port_t defpager; + error_t err; + + defpager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); + if (defpager == MACH_PORT_NULL) + return errno; + + err = default_pager_info (defpager, info); + mach_port_deallocate (mach_task_self (), defpager); + + return err; +} + + +/* Content generators */ + +static error_t +rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) +{ + struct utsname uts; + int r; + + r = uname (&uts); + if (r < 0) + return errno; + + *contents_len = asprintf (contents, + "Linux version 2.6.1 (%s %s %s %s)\n", + uts.sysname, uts.release, uts.version, uts.machine); + + return 0; +} + +static error_t +rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) +{ + struct timeval time, boottime, idletime; + double up_secs, idle_secs; + error_t err; + + err = gettimeofday (&time, NULL); + if (err < 0) + return errno; + + err = get_boottime (hook, &boottime); + if (err) + return err; + + err = get_idletime (hook, &idletime); + if (err) + return err; + + timersub (&time, &boottime, &time); + up_secs = (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; + idle_secs = (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; + + /* The second field is the total idle time. As far as I know we don't + keep track of it. However, procps uses it to compute "USER_HZ", and + proc(5) specifies that it should be equal to USER_HZ times the idle value + in ticks from /proc/stat. So we assume a completely idle system both here + and there to make that work. */ + *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, idle_secs); + + return 0; +} + +static error_t +rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) +{ + struct timeval boottime, time, idletime; + struct vm_statistics vmstats; + unsigned long up_ticks, idle_ticks; + error_t err; + + err = gettimeofday (&time, NULL); + if (err < 0) + return errno; + + err = get_boottime (hook, &boottime); + if (err) + return err; + + err = get_idletime (hook, &idletime); + if (err) + return err; + + err = vm_statistics (mach_task_self (), &vmstats); + if (err) + return EIO; + + timersub (&time, &boottime, &time); + up_ticks = opt_clk_tck * (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; + idle_ticks = opt_clk_tck * (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; + + *contents_len = asprintf (contents, + "cpu %lu 0 0 %lu 0 0 0 0 0\n" + "cpu0 %lu 0 0 %lu 0 0 0 0 0\n" + "intr 0\n" + "page %d %d\n" + "btime %lu\n", + up_ticks - idle_ticks, idle_ticks, + up_ticks - idle_ticks, idle_ticks, + vmstats.pageins, vmstats.pageouts, + boottime.tv_sec); + + return 0; +} + +static error_t +rootdir_gc_loadavg (void *hook, char **contents, ssize_t *contents_len) +{ + host_load_info_data_t hli; + mach_msg_type_number_t cnt; + error_t err; + + cnt = HOST_LOAD_INFO_COUNT; + err = host_info (mach_host_self (), HOST_LOAD_INFO, (host_info_t) &hli, &cnt); + if (err) + return err; + + assert (cnt == HOST_LOAD_INFO_COUNT); + *contents_len = asprintf (contents, + "%.2f %.2f %.2f 1/0 0\n", + hli.avenrun[0] / (double) LOAD_SCALE, + hli.avenrun[1] / (double) LOAD_SCALE, + hli.avenrun[2] / (double) LOAD_SCALE); + + return 0; +} + +static error_t +rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) +{ + host_basic_info_data_t hbi; + mach_msg_type_number_t cnt; + struct vm_statistics vmstats; + default_pager_info_t swap; + error_t err; + + err = vm_statistics (mach_task_self (), &vmstats); + if (err) + return EIO; + + cnt = HOST_BASIC_INFO_COUNT; + err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); + if (err) + return err; + + err = get_swapinfo (&swap); + if (err) + return err; + + assert (cnt == HOST_BASIC_INFO_COUNT); + *contents_len = asprintf (contents, + "MemTotal: %14lu kB\n" + "MemFree: %14lu kB\n" + "Active: %14lu kB\n" + "Inactive: %14lu kB\n" + "Mlocked: %14lu kB\n" + "SwapTotal:%14lu kB\n" + "SwapFree: %14lu kB\n" + , + /* TODO: check that these are really 1024-bytes kBs. */ + (long unsigned) hbi.memory_size / 1024, + (long unsigned) vmstats.free_count * PAGE_SIZE / 1024, + (long unsigned) vmstats.active_count * PAGE_SIZE / 1024, + (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, + (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024, + (long unsigned) swap.dpi_total_space / 1024, + (long unsigned) swap.dpi_free_space / 1024); + + return 0; +} + +static error_t +rootdir_gc_vmstat (void *hook, char **contents, ssize_t *contents_len) +{ + host_basic_info_data_t hbi; + mach_msg_type_number_t cnt; + struct vm_statistics vmstats; + error_t err; + + err = vm_statistics (mach_task_self (), &vmstats); + if (err) + return EIO; + + cnt = HOST_BASIC_INFO_COUNT; + err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); + if (err) + return err; + + assert (cnt == HOST_BASIC_INFO_COUNT); + *contents_len = asprintf (contents, + "nr_free_pages %lu\n" + "nr_inactive_anon %lu\n" + "nr_active_anon %lu\n" + "nr_inactive_file %lu\n" + "nr_active_file %lu\n" + "nr_unevictable %lu\n" + "nr_mlock %lu\n" + "pgpgin %lu\n" + "pgpgout %lu\n" + "pgfault %lu\n", + (long unsigned) vmstats.free_count, + /* FIXME: how can we distinguish the anon/file pages? Maybe we can + ask the default pager how many it manages? */ + (long unsigned) vmstats.inactive_count, + (long unsigned) vmstats.active_count, + (long unsigned) 0, + (long unsigned) 0, + (long unsigned) vmstats.wire_count, + (long unsigned) vmstats.wire_count, + (long unsigned) vmstats.pageins, + (long unsigned) vmstats.pageouts, + (long unsigned) vmstats.faults); + + return 0; +} + +static error_t +rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) +{ + struct ps_context *pc = hook; + struct proc_stat *ps; + error_t err; + + err = _proc_stat_create (opt_kernel_pid, pc, &ps); + if (err) + return EIO; + + err = proc_stat_set_flags (ps, PSTAT_ARGS); + if (err || ! (proc_stat_flags (ps) & PSTAT_ARGS)) + { + err = EIO; + goto out; + } + + *contents_len = proc_stat_args_len (ps); + *contents = malloc (*contents_len); + if (! *contents) + { + err = ENOMEM; + goto out; + } + + memcpy (*contents, proc_stat_args (ps), *contents_len); + argz_stringify (*contents, *contents_len, ' '); + (*contents)[*contents_len - 1] = '\n'; + +out: + _proc_stat_free (ps); + return err; +} + +static int +rootdir_fakeself_exists () +{ + return opt_fake_self >= 0; +} + +static error_t +rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) +{ + *contents_len = asprintf (contents, "%d", opt_fake_self); + return 0; +} + + +/* Glue logic and entries table */ + +static struct node * +rootdir_file_make_node (void *dir_hook, const void *entry_hook) +{ + /* The entry hook we use is actually a procfs_node_ops for the file to be + created. The hook associated to these newly created files (and passed + to the generators above as a consequence) is always the same global + ps_context, which we get from rootdir_make_node as the directory hook. */ + return procfs_make_node (entry_hook, dir_hook); +} + +static struct node * +rootdir_symlink_make_node (void *dir_hook, const void *entry_hook) +{ + struct node *np = procfs_make_node (entry_hook, dir_hook); + if (np) + procfs_node_chtype (np, S_IFLNK); + return np; +} + +static const struct procfs_dir_entry rootdir_entries[] = { + { + .name = "self", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_fakeself, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + .ops = { + .make_node = rootdir_symlink_make_node, + .exists = rootdir_fakeself_exists, + } + }, + { + .name = "version", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_version, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "uptime", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_uptime, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "stat", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_stat, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "loadavg", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_loadavg, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "meminfo", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_meminfo, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "vmstat", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_vmstat, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, + { + .name = "cmdline", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_cmdline, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, +#ifdef PROFILE + /* In order to get a usable gmon.out file, we must apparently use exit(). */ + { + .name = "exit", + .ops = { + .make_node = exit, + }, + }, +#endif + {} +}; + +struct node +*rootdir_make_node (struct ps_context *pc) +{ + static const struct procfs_dir_ops ops = { + .entries = rootdir_entries, + .entry_ops = { + .make_node = rootdir_file_make_node, + }, + }; + return procfs_dir_make_node (&ops, pc); +} + diff --git a/procfs/rootdir.h b/procfs/rootdir.h new file mode 100644 index 00000000..6980da8f --- /dev/null +++ b/procfs/rootdir.h @@ -0,0 +1,23 @@ +/* Hurd /proc filesystem, permanent files of the root directory. + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include + +struct node * +rootdir_make_node (struct ps_context *pc); diff --git a/procfs_dir.c b/procfs_dir.c deleted file mode 100644 index c250aa48..00000000 --- a/procfs_dir.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Hurd /proc filesystem, infrastructure for directories. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include "procfs.h" -#include "procfs_dir.h" - -struct procfs_dir_node -{ - const struct procfs_dir_ops *ops; - void *hook; -}; - -static int -entry_exists (struct procfs_dir_node *dir, const struct procfs_dir_entry *ent) -{ - if (ent->ops.exists) - return ent->ops.exists (dir->hook, ent->hook); - if (dir->ops->entry_ops.exists) - return dir->ops->entry_ops.exists (dir->hook, ent->hook); - - return 1; -} - -static error_t -procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - static const char dot_dotdot[] = ".\0.."; - struct procfs_dir_node *dir = hook; - const struct procfs_dir_entry *ent; - int pos; - - /* Evaluate how much space is needed. Note that we include the hidden - entries, just in case their status changes between now and then. */ - pos = sizeof dot_dotdot; - for (ent = dir->ops->entries; ent->name; ent++) - pos += strlen (ent->name) + 1; - - *contents = malloc (pos); - if (! *contents) - return ENOMEM; - - memcpy (*contents, dot_dotdot, sizeof dot_dotdot); - pos = sizeof dot_dotdot; - for (ent = dir->ops->entries; ent->name; ent++) - { - if (! entry_exists (dir, ent)) - continue; - - strcpy (*contents + pos, ent->name); - pos += strlen (ent->name) + 1; - } - - *contents_len = pos; - return 0; -} - -static error_t -procfs_dir_lookup (void *hook, const char *name, struct node **np) -{ - struct procfs_dir_node *dir = hook; - const struct procfs_dir_entry *ent; - - for (ent = dir->ops->entries; ent->name && strcmp (name, ent->name); ent++); - if (! ent->name) - return ENOENT; - - if (ent->ops.make_node) - *np = ent->ops.make_node (dir->hook, ent->hook); - else if (dir->ops->entry_ops.make_node) - *np = dir->ops->entry_ops.make_node (dir->hook, ent->hook); - else - return EGRATUITOUS; - - if (! *np) - return ENOMEM; - - return 0; -} - -static void -procfs_dir_cleanup (void *hook) -{ - struct procfs_dir_node *dir = hook; - - if (dir->ops->cleanup) - dir->ops->cleanup (dir->hook); - - free (dir); -} - -struct node * -procfs_dir_make_node (const struct procfs_dir_ops *dir_ops, void *dir_hook) -{ - static const struct procfs_node_ops ops = { - .get_contents = procfs_dir_get_contents, - .lookup = procfs_dir_lookup, - .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = procfs_dir_cleanup, - }; - struct procfs_dir_node *dir; - - dir = malloc (sizeof *dir); - if (! dir) - { - if (dir_ops->cleanup) - dir_ops->cleanup (dir_hook); - - return NULL; - } - - dir->ops = dir_ops; - dir->hook = dir_hook; - - return procfs_make_node (&ops, dir); -} - diff --git a/procfs_dir.h b/procfs_dir.h deleted file mode 100644 index 94c5b019..00000000 --- a/procfs_dir.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Hurd /proc filesystem, infrastructure for directories. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* This module provides an abstraction layer for implementing simple - directories with (mostly) static contents. The user defines the - contents of the directory by providing a table of entries and various - optional callback functions. */ - -/* These operations define how a given entry will behave. Either can be - omitted, both from the entry-specific operations and from the - directory-wide defaults. */ -struct procfs_dir_entry_ops -{ - /* Called when this entry is looked up to create a corresponding node. */ - struct node *(*make_node)(void *dir_hook, const void *entry_hook); - /* If this is provided and returns 0, this entry will be hidden. */ - int (*exists)(void *dir_hook, const void *entry_hook); -}; - -/* Describes an individual directory entry, associating a NAME with - * arbitrary HOOK data and node-specific OPS. */ -struct procfs_dir_entry -{ - const char *name; - const void *hook; - struct procfs_dir_entry_ops ops; -}; - -/* Describes a complete directory. ENTRIES is a table terminated by a - null NAME field. ENTRY_OPS provides default operations for the - entries which don't specify them. The optional CLEANUP function - should release all the resources associated with the directory hook. */ -struct procfs_dir_ops -{ - const struct procfs_dir_entry *entries; - void (*cleanup)(void *dir_hook); - struct procfs_dir_entry_ops entry_ops; -}; - -/* Create and return a new node for the directory described in OPS. - The DIR_HOOK is passed the MAKE_NODE callback function of looked up - entries, as well as to the CLEANUP callback when the node is - destroyed. If not enough memory can be allocated, OPS->CLEANUP is - invoked immediately and NULL is returned. */ -struct node * -procfs_dir_make_node (const struct procfs_dir_ops *ops, void *dir_hook); - diff --git a/proclist.c b/proclist.c deleted file mode 100644 index 58b942dc..00000000 --- a/proclist.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Hurd /proc filesystem, list of processes as a directory. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include "procfs.h" -#include "process.h" - -#define PID_STR_SIZE (3 * sizeof (pid_t) + 1) - -static error_t -proclist_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - struct ps_context *pc = hook; - pidarray_t pids; - mach_msg_type_number_t num_pids; - error_t err; - int i; - - num_pids = 0; - err = proc_getallpids (pc->server, &pids, &num_pids); - if (err) - return EIO; - - *contents = malloc (num_pids * PID_STR_SIZE); - if (*contents) - { - *contents_len = 0; - for (i=0; i < num_pids; i++) - { - int n = sprintf (*contents + *contents_len, "%d", pids[i]); - assert (n >= 0); - *contents_len += (n + 1); - } - } - else - err = ENOMEM; - - vm_deallocate (mach_task_self (), (vm_address_t) pids, num_pids * sizeof pids[0]); - return err; -} - -static error_t -proclist_lookup (void *hook, const char *name, struct node **np) -{ - struct ps_context *pc = hook; - char *endp; - pid_t pid; - - /* Self-lookups should not end up here. */ - assert (name[0]); - - /* No leading zeros allowed */ - if (name[0] == '0' && name[1]) - return ENOENT; - - pid = strtol (name, &endp, 10); - if (*endp) - return ENOENT; - - return process_lookup_pid (pc, pid, np); -} - -struct node * -proclist_make_node (struct ps_context *pc) -{ - static const struct procfs_node_ops ops = { - .get_contents = proclist_get_contents, - .lookup = proclist_lookup, - .cleanup_contents = procfs_cleanup_contents_with_free, - }; - return procfs_make_node (&ops, pc); -} - diff --git a/proclist.h b/proclist.h deleted file mode 100644 index bfe95b3d..00000000 --- a/proclist.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Hurd /proc filesystem, list of processes as a directory. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include - -struct node * -proclist_make_node (struct ps_context *pc); diff --git a/rootdir.c b/rootdir.c deleted file mode 100644 index 15ef8bce..00000000 --- a/rootdir.c +++ /dev/null @@ -1,503 +0,0 @@ -/* Hurd /proc filesystem, permanent files of the root directory. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "procfs.h" -#include "procfs_dir.h" -#include "main.h" - -/* This implements a directory node with the static files in /proc. - NB: the libps functions for host information return static storage; - using them would require locking and as a consequence it would be - more complicated, not simpler. */ - - -/* Helper functions */ - -/* We get the boot time by using that of the kernel process. */ -static error_t -get_boottime (struct ps_context *pc, struct timeval *tv) -{ - struct proc_stat *ps; - error_t err; - - err = _proc_stat_create (opt_kernel_pid, pc, &ps); - if (err) - return err; - - err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); - if (err || !(proc_stat_flags (ps) & PSTAT_TASK_BASIC)) - err = EIO; - - if (! err) - { - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - tv->tv_sec = tbi->creation_time.seconds; - tv->tv_usec = tbi->creation_time.microseconds; - } - - _proc_stat_free (ps); - return err; -} - -/* We get the idle time by querying the kernel's idle thread. */ -static error_t -get_idletime (struct ps_context *pc, struct timeval *tv) -{ - struct proc_stat *ps, *pst; - thread_basic_info_t tbi; - error_t err; - int i; - - err = _proc_stat_create (opt_kernel_pid, pc, &ps); - if (err) - return err; - - pst = NULL, tbi = NULL; - - err = proc_stat_set_flags (ps, PSTAT_NUM_THREADS); - if (err || !(proc_stat_flags (ps) & PSTAT_NUM_THREADS)) - { - err = EIO; - goto out; - } - - /* Look for the idle thread */ - for (i=0; !tbi || !(tbi->flags & TH_FLAGS_IDLE); i++) - { - if (pst) - _proc_stat_free (pst); - - pst = NULL, tbi = NULL; - if (i >= proc_stat_num_threads (ps)) - { - err = ESRCH; - goto out; - } - - err = proc_stat_thread_create (ps, i, &pst); - if (err) - continue; - - err = proc_stat_set_flags (pst, PSTAT_THREAD_BASIC); - if (err || ! (proc_stat_flags (pst) & PSTAT_THREAD_BASIC)) - continue; - - tbi = proc_stat_thread_basic_info (pst); - } - - /* We found it! */ - tv->tv_sec = tbi->system_time.seconds; - tv->tv_usec = tbi->system_time.microseconds; - err = 0; - -out: - if (pst) _proc_stat_free (pst); - _proc_stat_free (ps); - return err; -} - -static error_t -get_swapinfo (default_pager_info_t *info) -{ - mach_port_t defpager; - error_t err; - - defpager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); - if (defpager == MACH_PORT_NULL) - return errno; - - err = default_pager_info (defpager, info); - mach_port_deallocate (mach_task_self (), defpager); - - return err; -} - - -/* Content generators */ - -static error_t -rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) -{ - struct utsname uts; - int r; - - r = uname (&uts); - if (r < 0) - return errno; - - *contents_len = asprintf (contents, - "Linux version 2.6.1 (%s %s %s %s)\n", - uts.sysname, uts.release, uts.version, uts.machine); - - return 0; -} - -static error_t -rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) -{ - struct timeval time, boottime, idletime; - double up_secs, idle_secs; - error_t err; - - err = gettimeofday (&time, NULL); - if (err < 0) - return errno; - - err = get_boottime (hook, &boottime); - if (err) - return err; - - err = get_idletime (hook, &idletime); - if (err) - return err; - - timersub (&time, &boottime, &time); - up_secs = (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; - idle_secs = (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; - - /* The second field is the total idle time. As far as I know we don't - keep track of it. However, procps uses it to compute "USER_HZ", and - proc(5) specifies that it should be equal to USER_HZ times the idle value - in ticks from /proc/stat. So we assume a completely idle system both here - and there to make that work. */ - *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, idle_secs); - - return 0; -} - -static error_t -rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) -{ - struct timeval boottime, time, idletime; - struct vm_statistics vmstats; - unsigned long up_ticks, idle_ticks; - error_t err; - - err = gettimeofday (&time, NULL); - if (err < 0) - return errno; - - err = get_boottime (hook, &boottime); - if (err) - return err; - - err = get_idletime (hook, &idletime); - if (err) - return err; - - err = vm_statistics (mach_task_self (), &vmstats); - if (err) - return EIO; - - timersub (&time, &boottime, &time); - up_ticks = opt_clk_tck * (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; - idle_ticks = opt_clk_tck * (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; - - *contents_len = asprintf (contents, - "cpu %lu 0 0 %lu 0 0 0 0 0\n" - "cpu0 %lu 0 0 %lu 0 0 0 0 0\n" - "intr 0\n" - "page %d %d\n" - "btime %lu\n", - up_ticks - idle_ticks, idle_ticks, - up_ticks - idle_ticks, idle_ticks, - vmstats.pageins, vmstats.pageouts, - boottime.tv_sec); - - return 0; -} - -static error_t -rootdir_gc_loadavg (void *hook, char **contents, ssize_t *contents_len) -{ - host_load_info_data_t hli; - mach_msg_type_number_t cnt; - error_t err; - - cnt = HOST_LOAD_INFO_COUNT; - err = host_info (mach_host_self (), HOST_LOAD_INFO, (host_info_t) &hli, &cnt); - if (err) - return err; - - assert (cnt == HOST_LOAD_INFO_COUNT); - *contents_len = asprintf (contents, - "%.2f %.2f %.2f 1/0 0\n", - hli.avenrun[0] / (double) LOAD_SCALE, - hli.avenrun[1] / (double) LOAD_SCALE, - hli.avenrun[2] / (double) LOAD_SCALE); - - return 0; -} - -static error_t -rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) -{ - host_basic_info_data_t hbi; - mach_msg_type_number_t cnt; - struct vm_statistics vmstats; - default_pager_info_t swap; - error_t err; - - err = vm_statistics (mach_task_self (), &vmstats); - if (err) - return EIO; - - cnt = HOST_BASIC_INFO_COUNT; - err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); - if (err) - return err; - - err = get_swapinfo (&swap); - if (err) - return err; - - assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf (contents, - "MemTotal: %14lu kB\n" - "MemFree: %14lu kB\n" - "Active: %14lu kB\n" - "Inactive: %14lu kB\n" - "Mlocked: %14lu kB\n" - "SwapTotal:%14lu kB\n" - "SwapFree: %14lu kB\n" - , - /* TODO: check that these are really 1024-bytes kBs. */ - (long unsigned) hbi.memory_size / 1024, - (long unsigned) vmstats.free_count * PAGE_SIZE / 1024, - (long unsigned) vmstats.active_count * PAGE_SIZE / 1024, - (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, - (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024, - (long unsigned) swap.dpi_total_space / 1024, - (long unsigned) swap.dpi_free_space / 1024); - - return 0; -} - -static error_t -rootdir_gc_vmstat (void *hook, char **contents, ssize_t *contents_len) -{ - host_basic_info_data_t hbi; - mach_msg_type_number_t cnt; - struct vm_statistics vmstats; - error_t err; - - err = vm_statistics (mach_task_self (), &vmstats); - if (err) - return EIO; - - cnt = HOST_BASIC_INFO_COUNT; - err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); - if (err) - return err; - - assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf (contents, - "nr_free_pages %lu\n" - "nr_inactive_anon %lu\n" - "nr_active_anon %lu\n" - "nr_inactive_file %lu\n" - "nr_active_file %lu\n" - "nr_unevictable %lu\n" - "nr_mlock %lu\n" - "pgpgin %lu\n" - "pgpgout %lu\n" - "pgfault %lu\n", - (long unsigned) vmstats.free_count, - /* FIXME: how can we distinguish the anon/file pages? Maybe we can - ask the default pager how many it manages? */ - (long unsigned) vmstats.inactive_count, - (long unsigned) vmstats.active_count, - (long unsigned) 0, - (long unsigned) 0, - (long unsigned) vmstats.wire_count, - (long unsigned) vmstats.wire_count, - (long unsigned) vmstats.pageins, - (long unsigned) vmstats.pageouts, - (long unsigned) vmstats.faults); - - return 0; -} - -static error_t -rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) -{ - struct ps_context *pc = hook; - struct proc_stat *ps; - error_t err; - - err = _proc_stat_create (opt_kernel_pid, pc, &ps); - if (err) - return EIO; - - err = proc_stat_set_flags (ps, PSTAT_ARGS); - if (err || ! (proc_stat_flags (ps) & PSTAT_ARGS)) - { - err = EIO; - goto out; - } - - *contents_len = proc_stat_args_len (ps); - *contents = malloc (*contents_len); - if (! *contents) - { - err = ENOMEM; - goto out; - } - - memcpy (*contents, proc_stat_args (ps), *contents_len); - argz_stringify (*contents, *contents_len, ' '); - (*contents)[*contents_len - 1] = '\n'; - -out: - _proc_stat_free (ps); - return err; -} - -static int -rootdir_fakeself_exists () -{ - return opt_fake_self >= 0; -} - -static error_t -rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) -{ - *contents_len = asprintf (contents, "%d", opt_fake_self); - return 0; -} - - -/* Glue logic and entries table */ - -static struct node * -rootdir_file_make_node (void *dir_hook, const void *entry_hook) -{ - /* The entry hook we use is actually a procfs_node_ops for the file to be - created. The hook associated to these newly created files (and passed - to the generators above as a consequence) is always the same global - ps_context, which we get from rootdir_make_node as the directory hook. */ - return procfs_make_node (entry_hook, dir_hook); -} - -static struct node * -rootdir_symlink_make_node (void *dir_hook, const void *entry_hook) -{ - struct node *np = procfs_make_node (entry_hook, dir_hook); - if (np) - procfs_node_chtype (np, S_IFLNK); - return np; -} - -static const struct procfs_dir_entry rootdir_entries[] = { - { - .name = "self", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_fakeself, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - .ops = { - .make_node = rootdir_symlink_make_node, - .exists = rootdir_fakeself_exists, - } - }, - { - .name = "version", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_version, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "uptime", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_uptime, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "stat", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_stat, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "loadavg", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_loadavg, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "meminfo", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_meminfo, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "vmstat", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_vmstat, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "cmdline", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_cmdline, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, -#ifdef PROFILE - /* In order to get a usable gmon.out file, we must apparently use exit(). */ - { - .name = "exit", - .ops = { - .make_node = exit, - }, - }, -#endif - {} -}; - -struct node -*rootdir_make_node (struct ps_context *pc) -{ - static const struct procfs_dir_ops ops = { - .entries = rootdir_entries, - .entry_ops = { - .make_node = rootdir_file_make_node, - }, - }; - return procfs_dir_make_node (&ops, pc); -} - diff --git a/rootdir.h b/rootdir.h deleted file mode 100644 index 6980da8f..00000000 --- a/rootdir.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Hurd /proc filesystem, permanent files of the root directory. - Copyright (C) 2010 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include - -struct node * -rootdir_make_node (struct ps_context *pc); -- cgit v1.2.3 From d59e7933fd54562dfd0c1ae4988580deb02feac2 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 22 Feb 2011 21:06:36 +0100 Subject: Add Buffers and Cached to /proc/meminfo * rootdir.c (rootdir_gc_meminfo): Add Buffers and Cached, set to 0. --- rootdir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rootdir.c b/rootdir.c index 15ef8bce..1fa71b03 100644 --- a/rootdir.c +++ b/rootdir.c @@ -283,15 +283,18 @@ rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) *contents_len = asprintf (contents, "MemTotal: %14lu kB\n" "MemFree: %14lu kB\n" + "Buffers: %14lu kB\n" + "Cached: %14lu kB\n" "Active: %14lu kB\n" "Inactive: %14lu kB\n" "Mlocked: %14lu kB\n" "SwapTotal:%14lu kB\n" "SwapFree: %14lu kB\n" , - /* TODO: check that these are really 1024-bytes kBs. */ (long unsigned) hbi.memory_size / 1024, (long unsigned) vmstats.free_count * PAGE_SIZE / 1024, + 0, + 0, (long unsigned) vmstats.active_count * PAGE_SIZE / 1024, (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024, -- cgit v1.2.3 From 8957f5f62c3b4d1e4b511e1241ca831fa5efb3cc Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 18 Aug 2011 02:37:17 +0200 Subject: Import version from Kilobug --- gnupg-bithelp.h | 41 +++ gnupg-glue.h | 40 +++ gnupg-random.c | 810 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gnupg-random.h | 47 ++++ gnupg-rmd.h | 38 +++ gnupg-rmd160.c | 656 +++++++++++++++++++++++++++++++++++++++++++++ random.c | 624 +++++++++++++++++++++++++++++++++++++++++++ random.h | 32 +++ 8 files changed, 2288 insertions(+) create mode 100644 gnupg-bithelp.h create mode 100644 gnupg-glue.h create mode 100644 gnupg-random.c create mode 100644 gnupg-random.h create mode 100644 gnupg-rmd.h create mode 100644 gnupg-rmd160.c create mode 100644 random.c create mode 100644 random.h diff --git a/gnupg-bithelp.h b/gnupg-bithelp.h new file mode 100644 index 00000000..188db168 --- /dev/null +++ b/gnupg-bithelp.h @@ -0,0 +1,41 @@ +/* bithelp.h - Some bit manipulation helpers + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ +#ifndef G10_BITHELP_H +#define G10_BITHELP_H + + +/**************** + * Rotate a 32 bit integer by n bytes + */ +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol( u32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else + #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + + +#endif /*G10_BITHELP_H*/ diff --git a/gnupg-glue.h b/gnupg-glue.h new file mode 100644 index 00000000..cbf0a103 --- /dev/null +++ b/gnupg-glue.h @@ -0,0 +1,40 @@ +#ifndef __GNUPG_GLUE_H__ +#define __GNUPG_GLUE_H__ + +#include +#include + +#define SIZEOF_UNSIGNED_LONG 4 +typedef unsigned int u32; +typedef unsigned char byte; + +/* GnuPG's config.h */ +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_GETRUSAGE 1 +#define HAVE_RAND 1 + +/* GnuPG's memory.h */ +#define m_alloc malloc +#define m_alloc_secure malloc +#define m_alloc_clear(x) calloc(x, 1) +#define m_alloc_secure_clear(x) calloc(x, 1) +#define m_free free +#define m_strdup strdup + +/* GnuPG's dynaload.h */ +#define dynload_getfnc_fast_random_poll() (0) +#define dynload_getfnc_gather_random() &gather_random +int +gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ); + +/* GnuPG's miscellaneous stuff. */ +#define BUG() assert(0) +#define _(x) x +#define make_timestamp() time(0) +#define tty_printf printf +#define log_info(format, args...) printf(format , ## args) +#define log_fatal(format, args...) { printf(format , ## args) ; exit(2); } +#define DIM(v) (sizeof(v)/sizeof((v)[0])) + +#endif /* __GNUPG_GLUE_H__ */ diff --git a/gnupg-random.c b/gnupg-random.c new file mode 100644 index 00000000..8f308621 --- /dev/null +++ b/gnupg-random.c @@ -0,0 +1,810 @@ +/* random.c - random number generator + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + + +/**************** + * This random number generator is modelled after the one described + * in Peter Gutmann's Paper: "Software Generation of Practically + * Strong Random Numbers". + */ + +#ifndef __HURD__ +#include +#else +#include "gnupg-glue.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_GETHRTIME + #include +#endif +#ifdef HAVE_GETTIMEOFDAY + #include +#endif +#ifdef HAVE_GETRUSAGE + #include +#endif +#ifdef __MINGW32__ + #include +#endif +#ifndef __HURD__ +#include "util.h" +#endif +#ifndef __HURD__ +#include "rmd.h" +#include "ttyio.h" +#include "i18n.h" +#include "random.h" +#include "rand-internal.h" +#include "dynload.h" +#else +#include "gnupg-rmd.h" +#include "gnupg-random.h" +#endif + +#ifndef RAND_MAX /* for SunOS */ + #define RAND_MAX 32767 +#endif + + +#if SIZEOF_UNSIGNED_LONG == 8 + #define ADD_VALUE 0xa5a5a5a5a5a5a5a5 +#elif SIZEOF_UNSIGNED_LONG == 4 + #define ADD_VALUE 0xa5a5a5a5 +#else + #error weird size for an unsigned long +#endif + +#define BLOCKLEN 64 /* hash this amount of bytes */ +#define DIGESTLEN 20 /* into a digest of this length (rmd160) */ +/* poolblocks is the number of digests which make up the pool + * and poolsize must be a multiple of the digest length + * to make the AND operations faster, the size should also be + * a multiple of ulong + */ +#define POOLBLOCKS 30 +#define POOLSIZE (POOLBLOCKS*DIGESTLEN) +#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) + #error Please make sure that poolsize is a multiple of ulong +#endif +#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) + + +static int is_initialized; +#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) +static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */ +static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */ +static size_t pool_readpos; +static size_t pool_writepos; +static int pool_filled; +static int pool_balance; +static int just_mixed; +static int did_initial_extra_seeding; +static char *seed_file_name; +static int allow_seed_file_update; + +static int secure_alloc; +static int quick_test; +static int faked_rng; + + +#ifndef __HURD__ +static void read_pool( byte *buffer, size_t length, int level ); +#else +int read_pool( byte *buffer, size_t length, int level ); +#endif +static void add_randomness( const void *buffer, size_t length, int source ); +static void random_poll(void); +#ifndef __HURD__ +static void read_random_source( int requester, size_t length, int level); +#else +static int read_random_source( int requester, size_t length, int level); +#endif +static int gather_faked( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ); + +static struct { + ulong mixrnd; + ulong mixkey; + ulong slowpolls; + ulong fastpolls; + ulong getbytes1; + ulong ngetbytes1; + ulong getbytes2; + ulong ngetbytes2; + ulong addbytes; + ulong naddbytes; +} rndstats; + +static void +initialize(void) +{ + /* The data buffer is allocated somewhat larger, so that + * we can use this extra space (which is allocated in secure memory) + * as a temporary hash buffer */ + rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) + : m_alloc_clear(POOLSIZE+BLOCKLEN); + keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) + : m_alloc_clear(POOLSIZE+BLOCKLEN); + is_initialized = 1; +#ifndef __HURD__ + cipher_modules_constructor(); +#endif +} + +static void +burn_stack (int bytes) +{ + char buf[128]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + +void +random_dump_stats() +{ + fprintf(stderr, + "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" + " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n", + POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, + rndstats.naddbytes, rndstats.addbytes, + rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, + rndstats.ngetbytes2, rndstats.getbytes2 ); +} + +void +secure_random_alloc() +{ + secure_alloc = 1; +} + + +int +quick_random_gen( int onoff ) +{ + int last; + + read_random_source(0,0,0); /* init */ + last = quick_test; + if( onoff != -1 ) + quick_test = onoff; + return faked_rng? 1 : last; +} + + +/**************** + * Fill the buffer with LENGTH bytes of cryptographically strong + * random bytes. level 0 is not very strong, 1 is strong enough + * for most usage, 2 is good for key generation stuff but may be very slow. + */ +void +randomize_buffer( byte *buffer, size_t length, int level ) +{ + char *p = get_random_bits( length*8, level, 1 ); + memcpy( buffer, p, length ); + m_free(p); +} + + +int +random_is_faked() +{ + if( !is_initialized ) + initialize(); + return faked_rng || quick_test; +} + +/**************** + * Return a pointer to a randomized buffer of level 0 and LENGTH bits + * caller must free the buffer. + * Note: The returned value is rounded up to bytes. + */ +byte * +get_random_bits( size_t nbits, int level, int secure ) +{ + byte *buf, *p; + size_t nbytes = (nbits+7)/8; + + if( quick_test && level > 1 ) + level = 1; + MASK_LEVEL(level); + if( level == 1 ) { + rndstats.getbytes1 += nbytes; + rndstats.ngetbytes1++; + } + else if( level >= 2 ) { + rndstats.getbytes2 += nbytes; + rndstats.ngetbytes2++; + } + + buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes ); + for( p = buf; nbytes > 0; ) { + size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes; +#ifdef __HURD__ + n = +#endif + read_pool( p, n, level ); + nbytes -= n; + p += n; + + } + return buf; +} + + +/**************** + * Mix the pool + */ +static void +mix_pool(byte *pool) +{ + char *hashbuf = pool + POOLSIZE; + char *p, *pend; + int i, n; + RMD160_CONTEXT md; + + rmd160_init( &md ); + #if DIGESTLEN != 20 + #error must have a digest length of 20 for ripe-md-160 + #endif + /* loop over the pool */ + pend = pool + POOLSIZE; + memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); + memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); + rmd160_mixblock( &md, hashbuf); + memcpy(pool, hashbuf, 20 ); + + p = pool; + for( n=1; n < POOLBLOCKS; n++ ) { + memcpy(hashbuf, p, DIGESTLEN ); + + p += DIGESTLEN; + if( p+DIGESTLEN+BLOCKLEN < pend ) + memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); + else { + char *pp = p+DIGESTLEN; + for(i=DIGESTLEN; i < BLOCKLEN; i++ ) { + if( pp >= pend ) + pp = pool; + hashbuf[i] = *pp++; + } + } + + rmd160_mixblock( &md, hashbuf); + memcpy(p, hashbuf, 20 ); + } + burn_stack (200); /* for the rmd160_mixblock() */ +} + + +void +set_random_seed_file( const char *name ) +{ + if( seed_file_name ) + BUG(); + seed_file_name = m_strdup( name ); +} + +/**************** + * Read in a seed form the random_seed file + * and return true if this was successful + */ +static int +read_seed_file() +{ + int fd; + struct stat sb; + unsigned char buffer[POOLSIZE]; + int n; + + if( !seed_file_name ) + return 0; + + #ifdef HAVE_DOSISH_SYSTEM + fd = open( seed_file_name, O_RDONLY | O_BINARY ); + #else + fd = open( seed_file_name, O_RDONLY ); + #endif + if( fd == -1 && errno == ENOENT) { + allow_seed_file_update = 1; + return 0; + } + + if( fd == -1 ) { + log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); + return 0; + } + if( fstat( fd, &sb ) ) { + log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); + close(fd); + return 0; + } + if( !S_ISREG(sb.st_mode) ) { + log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); + close(fd); + return 0; + } + if( !sb.st_size ) { + log_info(_("note: random_seed file is empty\n") ); + close(fd); + allow_seed_file_update = 1; + return 0; + } + if( sb.st_size != POOLSIZE ) { + log_info(_("warning: invalid size of random_seed file - not used\n") ); + close(fd); + return 0; + } + do { + n = read( fd, buffer, POOLSIZE ); + } while( n == -1 && errno == EINTR ); + if( n != POOLSIZE ) { + log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); + close(fd); + return 0; + } + + close(fd); + + add_randomness( buffer, POOLSIZE, 0 ); + /* add some minor entropy to the pool now (this will also force a mixing) */ + { pid_t x = getpid(); + add_randomness( &x, sizeof(x), 0 ); + } + { time_t x = time(NULL); + add_randomness( &x, sizeof(x), 0 ); + } + { clock_t x = clock(); + add_randomness( &x, sizeof(x), 0 ); + } + /* And read a few bytes from our entropy source. By using + * a level of 0 this will not block and might not return anything + * with some entropy drivers, however the rndlinux driver will use + * /dev/urandom and return some stuff - Do not read to much as we + * want to be friendly to the scare system entropy resource. */ + read_random_source( 0, 16, 0 ); + + allow_seed_file_update = 1; + return 1; +} + +void +update_random_seed_file() +{ + ulong *sp, *dp; + int fd, i; + + if( !seed_file_name || !is_initialized || !pool_filled ) + return; + if( !allow_seed_file_update ) { + log_info(_("note: random_seed file not updated\n")); + return; + } + + + /* copy the entropy pool to a scratch pool and mix both of them */ + for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; + i < POOLWORDS; i++, dp++, sp++ ) { + *dp = *sp + ADD_VALUE; + } + mix_pool(rndpool); rndstats.mixrnd++; + mix_pool(keypool); rndstats.mixkey++; + + #ifdef HAVE_DOSISH_SYSTEM + fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, + S_IRUSR|S_IWUSR ); + #else + fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); + #endif + if( fd == -1 ) { + log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); + return; + } + do { + i = write( fd, keypool, POOLSIZE ); + } while( i == -1 && errno == EINTR ); + if( i != POOLSIZE ) { + log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); + } + if( close(fd) ) + log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); +} + +#ifdef __HURD__ +int readable_pool( size_t length, int level ) +{ + size_t needed = 0; + size_t my_balance = pool_balance; + size_t available = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; + + if (length > POOLSIZE) + length = POOLSIZE; + + if (level < 2) + return length; + + if( !pool_filled ) { + if( read_seed_file() ) + pool_filled = 1; + } + + if (!did_initial_extra_seeding) + { + /* Take account for initial extra seeding. */ + needed = length; + if (needed < POOLSIZE/2) + needed = POOLSIZE/2; + my_balance = needed; + + if (!pool_filled && pool_writepos + needed < POOLSIZE) + { + /* If the pool is not filled yet, we couldn't read the seed + file. Too bad. We will now have to take account for so many + random_poll()s as fit into the remaining pool. */ + + needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); + } + } + else + { + if (!pool_filled) + needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); + } + + /* NEEDED contains the bytes needed for initialization, MY_BALANCE the resulting + available bytes. */ + if (available < needed) + return 0; + return available + my_balance - needed; +} +#endif + +#ifndef __HURD__ +static void +#else +int +#endif +read_pool( byte *buffer, size_t length, int level ) +{ + int i; + ulong *sp, *dp; + + if( length > POOLSIZE ) { +#ifndef __HURD__ + log_fatal(_("too many random bits requested; the limit is %d\n"), + POOLSIZE*8-1 ); +#else + length = POOLSIZE; +#endif + } + + if( !pool_filled ) { + if( read_seed_file() ) + pool_filled = 1; + } + + /* For level 2 quality (key generation) we alwas make + * sure that the pool has been seeded enough initially */ + if( level == 2 && !did_initial_extra_seeding ) { + size_t needed; + + pool_balance = 0; + needed = length - pool_balance; + if( needed < POOLSIZE/2 ) + needed = POOLSIZE/2; + else if( needed > POOLSIZE ) + BUG(); +#ifdef __HURD__ + needed = +#endif + read_random_source( 3, needed, 2 ); +#ifdef __HURD__ + if (! needed) + return 0; + /* XXX This will succeed with needed < POOLSIZE/2 even. But + erroring out will waste the random we already got. */ +#endif + pool_balance += needed; + did_initial_extra_seeding=1; + } + + /* for level 2 make sure that there is enough random in the pool */ + if( level == 2 && pool_balance < length ) { + size_t needed; + + if( pool_balance < 0 ) + pool_balance = 0; + needed = length - pool_balance; + if( needed > POOLSIZE ) + BUG(); +#ifdef __HURD__ + needed = +#endif + read_random_source( 3, needed, 2 ); + pool_balance += needed; + } + +#ifdef __HURD__ + /* XXX This makes level 0 and 1 worse than needed at first start up. */ + if (level == 2) +#endif + /* make sure the pool is filled */ + while( !pool_filled ) + random_poll(); + + /* do always a fast random poll */ + fast_random_poll(); + + if( !level ) { /* no need for cryptographic strong random */ + /* create a new pool */ + for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; + i < POOLWORDS; i++, dp++, sp++ ) + *dp = *sp + ADD_VALUE; + /* must mix both pools */ + mix_pool(rndpool); rndstats.mixrnd++; + mix_pool(keypool); rndstats.mixkey++; + memcpy( buffer, keypool, length ); + return length; + } + else { +#ifdef __HURD__ + int amount; +#endif + /* mix the pool (if add_randomness() didn't it) */ + if( !just_mixed ) { + mix_pool(rndpool); + rndstats.mixrnd++; + } + /* create a new pool */ + for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; + i < POOLWORDS; i++, dp++, sp++ ) + *dp = *sp + ADD_VALUE; + /* and mix both pools */ + mix_pool(rndpool); rndstats.mixrnd++; + mix_pool(keypool); rndstats.mixkey++; + /* read the required data + * we use a readpoiter to read from a different postion each + * time */ +#ifdef __HURD__ + if (level == 2 && length > pool_balance) + length = pool_balance; + amount = length; +#endif + while( length-- ) { + *buffer++ = keypool[pool_readpos++]; + if( pool_readpos >= POOLSIZE ) + pool_readpos = 0; + pool_balance--; + } + if( pool_balance < 0 ) + pool_balance = 0; + /* and clear the keypool */ + memset( keypool, 0, POOLSIZE ); +#ifdef __HURD__ + return amount; +#endif + } +} + + +/**************** + * Add LENGTH bytes of randomness from buffer to the pool. + * source may be used to specify the randomness source. + * Source is: + * 0 - used ony for initialization + * 1 - fast random poll function + * 2 - normal poll function + * 3 - used when level 2 random quality has been requested + * to do an extra pool seed. + */ +static void +add_randomness( const void *buffer, size_t length, int source ) +{ + const byte *p = buffer; + + if( !is_initialized ) + initialize(); + rndstats.addbytes += length; + rndstats.naddbytes++; + while( length-- ) { + rndpool[pool_writepos++] = *p++; + if( pool_writepos >= POOLSIZE ) { + if( source > 1 ) + pool_filled = 1; + pool_writepos = 0; + mix_pool(rndpool); rndstats.mixrnd++; + just_mixed = !length; + } + } +} + + + +static void +random_poll() +{ + rndstats.slowpolls++; + read_random_source( 2, POOLSIZE/5, 1 ); +} + + +void +fast_random_poll() +{ + static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL; + static int initialized = 0; + + rndstats.fastpolls++; + if( !initialized ) { + if( !is_initialized ) + initialize(); + initialized = 1; + fnc = dynload_getfnc_fast_random_poll(); + } + if( fnc ) { + (*fnc)( add_randomness, 1 ); + return; + } + + /* fall back to the generic function */ + #if HAVE_GETHRTIME + { hrtime_t tv; + tv = gethrtime(); + add_randomness( &tv, sizeof(tv), 1 ); + } + #elif HAVE_GETTIMEOFDAY + { struct timeval tv; + if( gettimeofday( &tv, NULL ) ) + BUG(); + add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); + add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); + } + #elif HAVE_CLOCK_GETTIME + { struct timespec tv; + if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) + BUG(); + add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); + add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); + } + #else /* use times */ + #ifndef HAVE_DOSISH_SYSTEM + { struct tms buf; + times( &buf ); + add_randomness( &buf, sizeof buf, 1 ); + } + #endif + #endif + #ifdef HAVE_GETRUSAGE + #ifndef RUSAGE_SELF + #ifdef __GCC__ + #warning There is no RUSAGE_SELF on this system + #endif + #else + { struct rusage buf; + /* QNX/Neutrino does return ENOSYS - so we just ignore it and + * add whatever is in buf. In a chroot environment it might not + * work at all (i.e. because /proc/ is not accessible), so we better + * ognore all error codes and hope for the best + */ + getrusage( RUSAGE_SELF, &buf ); + + add_randomness( &buf, sizeof buf, 1 ); + memset( &buf, 0, sizeof buf ); + } + #endif + #endif + /* time and clock are availabe on all systems - so + * we better do it just in case one of the above functions + * didn't work */ + { time_t x = time(NULL); + add_randomness( &x, sizeof(x), 1 ); + } + { clock_t x = clock(); + add_randomness( &x, sizeof(x), 1 ); + } +} + + +#ifndef __HURD__ +static void +#else +static int +#endif +read_random_source( int requester, size_t length, int level ) +{ + static int (*fnc)(void (*)(const void*, size_t, int), int, + size_t, int) = NULL; +#ifdef __HURD__ + int got; +#endif + if( !fnc ) { + if( !is_initialized ) + initialize(); + fnc = dynload_getfnc_gather_random(); + if( !fnc ) { + faked_rng = 1; + fnc = gather_faked; + } + if( !requester && !length && !level ) +#ifndef __HURD__ + return; /* init only */ +#else + return 0; +#endif + } +#ifndef __HURD__ + if( (*fnc)( add_randomness, requester, length, level ) < 0 ) + log_fatal("No way to gather entropy for the RNG\n"); +#else + got = (*fnc)( add_randomness, requester, length, level ); + if (got < 0) + log_fatal("No way to gather entropy for the RNG\n"); + return got; +#endif +} + + +static int +gather_faked( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) +{ + static int initialized=0; + size_t n; + char *buffer, *p; + + if( !initialized ) { + log_info(_("WARNING: using insecure random number generator!!\n")); + tty_printf(_("The random number generator is only a kludge to let\n" + "it run - it is in no way a strong RNG!\n\n" + "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); + initialized=1; + #ifdef HAVE_RAND + srand(make_timestamp()*getpid()); + #else + srandom(make_timestamp()*getpid()); + #endif + } + printf("WAITING FOR %i bytes.\n", length); + p = buffer = m_alloc( length ); + n = length; + #ifdef HAVE_RAND + while( n-- ) + *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); + #else + while( n-- ) + *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); + #endif + add_randomness( buffer, length, requester ); + m_free(buffer); + return 0; /* okay */ +} + diff --git a/gnupg-random.h b/gnupg-random.h new file mode 100644 index 00000000..ee18febc --- /dev/null +++ b/gnupg-random.h @@ -0,0 +1,47 @@ +/* random.h - random functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ +#ifndef G10_RANDOM_H +#define G10_RANDOM_H + +#ifndef __HURD__ +#include "types.h" +#else +#include "gnupg-glue.h" +int read_pool (byte *, size_t, int); +int readable_pool (size_t, int); +#endif + +/*-- random.c --*/ +void random_dump_stats(void); +void secure_random_alloc(void); +void set_random_seed_file(const char *); +void update_random_seed_file(void); +int quick_random_gen( int onoff ); +int random_is_faked(void); +void randomize_buffer( byte *buffer, size_t length, int level ); +byte *get_random_bits( size_t nbits, int level, int secure ); +void fast_random_poll( void ); + +/*-- rndw32.c --*/ +#ifdef USE_STATIC_RNDW32 +void rndw32_set_dll_name( const char *name ); +#endif + +#endif /*G10_RANDOM_H*/ diff --git a/gnupg-rmd.h b/gnupg-rmd.h new file mode 100644 index 00000000..2446fc7d --- /dev/null +++ b/gnupg-rmd.h @@ -0,0 +1,38 @@ +/* rmd.h - RIPE-MD hash functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ +#ifndef G10_RMD_H +#define G10_RMD_H + +#ifdef __HURD__ +#include "gnupg-glue.h" +#endif + +/* we need this here because random.c must have direct access */ +typedef struct { + u32 h0,h1,h2,h3,h4; + u32 nblocks; + byte buf[64]; + int count; +} RMD160_CONTEXT; + +void rmd160_init( RMD160_CONTEXT *hd ); +void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); + +#endif /*G10_RMD_H*/ diff --git a/gnupg-rmd160.c b/gnupg-rmd160.c new file mode 100644 index 00000000..66107685 --- /dev/null +++ b/gnupg-rmd160.c @@ -0,0 +1,656 @@ +/* rmd160.c - RIPE-MD160 + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + +#ifndef __HURD__ +#include +#endif +#include +#include +#include +#include +#ifndef __HURD__ +#include "util.h" +#include "memory.h" +#include "rmd.h" +#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ +#include "dynload.h" + +#include "bithelp.h" +#else +#include "gnupg-rmd.h" +#include "gnupg-bithelp.h" +#endif + + +/********************************* + * RIPEMD-160 is not patented, see (as of 25.10.97) + * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html + * Note that the code uses Little Endian byteorder, which is good for + * 386 etc, but we must add some conversion when used on a big endian box. + * + * + * Pseudo-code for RIPEMD-160 + * + * RIPEMD-160 is an iterative hash function that operates on 32-bit words. + * The round function takes as input a 5-word chaining variable and a 16-word + * message block and maps this to a new chaining variable. All operations are + * defined on 32-bit words. Padding is identical to that of MD4. + * + * + * RIPEMD-160: definitions + * + * + * nonlinear functions at bit level: exor, mux, -, mux, - + * + * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) + * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) + * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) + * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) + * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) + * + * + * added constants (hexadecimal) + * + * K(j) = 0x00000000 (0 <= j <= 15) + * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) + * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) + * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) + * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) + * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) + * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) + * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) + * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) + * K'(j) = 0x00000000 (64 <= j <= 79) + * + * + * selection of message word + * + * r(j) = j (0 <= j <= 15) + * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 + * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 + * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 + * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 + * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 + * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 + * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 + * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + * + * + * amount for rotate left (rol) + * + * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 + * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 + * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 + * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 + * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 + * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 + * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 + * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 + * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + * + * + * initial value (hexadecimal) + * + * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; + * h4 = 0xC3D2E1F0; + * + * + * RIPEMD-160: pseudo-code + * + * It is assumed that the message after padding consists of t 16-word blocks + * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. + * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left + * shift (rotate) over s positions. + * + * + * for i := 0 to t-1 { + * A := h0; B := h1; C := h2; D = h3; E = h4; + * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; + * for j := 0 to 79 { + * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; + * A := E; E := D; D := rol_10(C); C := B; B := T; + * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] + [+] K'(j)) [+] E'; + * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; + * } + * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; + * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; + * } + */ + +/* Some examples: + * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 + * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe + * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc + * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 + * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc + * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b + * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 + * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb + * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 + */ + +static void +burn_stack (int bytes) +{ + char buf[150]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + + + +void +rmd160_init( RMD160_CONTEXT *hd ) +{ + hd->h0 = 0x67452301; + hd->h1 = 0xEFCDAB89; + hd->h2 = 0x98BADCFE; + hd->h3 = 0x10325476; + hd->h4 = 0xC3D2E1F0; + hd->nblocks = 0; + hd->count = 0; +} + + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void +transform( RMD160_CONTEXT *hd, byte *data ) +{ + u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; + #ifdef BIG_ENDIAN_HOST + u32 x[16]; + { int i; + byte *p2, *p1; + for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } + #else + #if 0 + u32 *x =(u32*)data; + #else + /* this version is better because it is always aligned; + * The performance penalty on a 586-100 is about 6% which + * is acceptable - because the data is more local it might + * also be possible that this is faster on some machines. + * This function (when compiled with -02 on gcc 2.7.2) + * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; + * [measured with a 4MB data and "gpgm --print-md rmd160"] */ + u32 x[16]; + memcpy( x, data, 64 ); + #endif + #endif + + +#define K0 0x00000000 +#define K1 0x5A827999 +#define K2 0x6ED9EBA1 +#define K3 0x8F1BBCDC +#define K4 0xA953FD4E +#define KK0 0x50A28BE6 +#define KK1 0x5C4DD124 +#define KK2 0x6D703EF3 +#define KK3 0x7A6D76E9 +#define KK4 0x00000000 +#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) +#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) +#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) +#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) +#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) +#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ + a = rol(t,s) + e; \ + c = rol(c,10); \ + } while(0) + + /* left lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F0, K0, 0, 11 ); + R( e, a, b, c, d, F0, K0, 1, 14 ); + R( d, e, a, b, c, F0, K0, 2, 15 ); + R( c, d, e, a, b, F0, K0, 3, 12 ); + R( b, c, d, e, a, F0, K0, 4, 5 ); + R( a, b, c, d, e, F0, K0, 5, 8 ); + R( e, a, b, c, d, F0, K0, 6, 7 ); + R( d, e, a, b, c, F0, K0, 7, 9 ); + R( c, d, e, a, b, F0, K0, 8, 11 ); + R( b, c, d, e, a, F0, K0, 9, 13 ); + R( a, b, c, d, e, F0, K0, 10, 14 ); + R( e, a, b, c, d, F0, K0, 11, 15 ); + R( d, e, a, b, c, F0, K0, 12, 6 ); + R( c, d, e, a, b, F0, K0, 13, 7 ); + R( b, c, d, e, a, F0, K0, 14, 9 ); + R( a, b, c, d, e, F0, K0, 15, 8 ); + R( e, a, b, c, d, F1, K1, 7, 7 ); + R( d, e, a, b, c, F1, K1, 4, 6 ); + R( c, d, e, a, b, F1, K1, 13, 8 ); + R( b, c, d, e, a, F1, K1, 1, 13 ); + R( a, b, c, d, e, F1, K1, 10, 11 ); + R( e, a, b, c, d, F1, K1, 6, 9 ); + R( d, e, a, b, c, F1, K1, 15, 7 ); + R( c, d, e, a, b, F1, K1, 3, 15 ); + R( b, c, d, e, a, F1, K1, 12, 7 ); + R( a, b, c, d, e, F1, K1, 0, 12 ); + R( e, a, b, c, d, F1, K1, 9, 15 ); + R( d, e, a, b, c, F1, K1, 5, 9 ); + R( c, d, e, a, b, F1, K1, 2, 11 ); + R( b, c, d, e, a, F1, K1, 14, 7 ); + R( a, b, c, d, e, F1, K1, 11, 13 ); + R( e, a, b, c, d, F1, K1, 8, 12 ); + R( d, e, a, b, c, F2, K2, 3, 11 ); + R( c, d, e, a, b, F2, K2, 10, 13 ); + R( b, c, d, e, a, F2, K2, 14, 6 ); + R( a, b, c, d, e, F2, K2, 4, 7 ); + R( e, a, b, c, d, F2, K2, 9, 14 ); + R( d, e, a, b, c, F2, K2, 15, 9 ); + R( c, d, e, a, b, F2, K2, 8, 13 ); + R( b, c, d, e, a, F2, K2, 1, 15 ); + R( a, b, c, d, e, F2, K2, 2, 14 ); + R( e, a, b, c, d, F2, K2, 7, 8 ); + R( d, e, a, b, c, F2, K2, 0, 13 ); + R( c, d, e, a, b, F2, K2, 6, 6 ); + R( b, c, d, e, a, F2, K2, 13, 5 ); + R( a, b, c, d, e, F2, K2, 11, 12 ); + R( e, a, b, c, d, F2, K2, 5, 7 ); + R( d, e, a, b, c, F2, K2, 12, 5 ); + R( c, d, e, a, b, F3, K3, 1, 11 ); + R( b, c, d, e, a, F3, K3, 9, 12 ); + R( a, b, c, d, e, F3, K3, 11, 14 ); + R( e, a, b, c, d, F3, K3, 10, 15 ); + R( d, e, a, b, c, F3, K3, 0, 14 ); + R( c, d, e, a, b, F3, K3, 8, 15 ); + R( b, c, d, e, a, F3, K3, 12, 9 ); + R( a, b, c, d, e, F3, K3, 4, 8 ); + R( e, a, b, c, d, F3, K3, 13, 9 ); + R( d, e, a, b, c, F3, K3, 3, 14 ); + R( c, d, e, a, b, F3, K3, 7, 5 ); + R( b, c, d, e, a, F3, K3, 15, 6 ); + R( a, b, c, d, e, F3, K3, 14, 8 ); + R( e, a, b, c, d, F3, K3, 5, 6 ); + R( d, e, a, b, c, F3, K3, 6, 5 ); + R( c, d, e, a, b, F3, K3, 2, 12 ); + R( b, c, d, e, a, F4, K4, 4, 9 ); + R( a, b, c, d, e, F4, K4, 0, 15 ); + R( e, a, b, c, d, F4, K4, 5, 5 ); + R( d, e, a, b, c, F4, K4, 9, 11 ); + R( c, d, e, a, b, F4, K4, 7, 6 ); + R( b, c, d, e, a, F4, K4, 12, 8 ); + R( a, b, c, d, e, F4, K4, 2, 13 ); + R( e, a, b, c, d, F4, K4, 10, 12 ); + R( d, e, a, b, c, F4, K4, 14, 5 ); + R( c, d, e, a, b, F4, K4, 1, 12 ); + R( b, c, d, e, a, F4, K4, 3, 13 ); + R( a, b, c, d, e, F4, K4, 8, 14 ); + R( e, a, b, c, d, F4, K4, 11, 11 ); + R( d, e, a, b, c, F4, K4, 6, 8 ); + R( c, d, e, a, b, F4, K4, 15, 5 ); + R( b, c, d, e, a, F4, K4, 13, 6 ); + + aa = a; bb = b; cc = c; dd = d; ee = e; + + /* right lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F4, KK0, 5, 8); + R( e, a, b, c, d, F4, KK0, 14, 9); + R( d, e, a, b, c, F4, KK0, 7, 9); + R( c, d, e, a, b, F4, KK0, 0, 11); + R( b, c, d, e, a, F4, KK0, 9, 13); + R( a, b, c, d, e, F4, KK0, 2, 15); + R( e, a, b, c, d, F4, KK0, 11, 15); + R( d, e, a, b, c, F4, KK0, 4, 5); + R( c, d, e, a, b, F4, KK0, 13, 7); + R( b, c, d, e, a, F4, KK0, 6, 7); + R( a, b, c, d, e, F4, KK0, 15, 8); + R( e, a, b, c, d, F4, KK0, 8, 11); + R( d, e, a, b, c, F4, KK0, 1, 14); + R( c, d, e, a, b, F4, KK0, 10, 14); + R( b, c, d, e, a, F4, KK0, 3, 12); + R( a, b, c, d, e, F4, KK0, 12, 6); + R( e, a, b, c, d, F3, KK1, 6, 9); + R( d, e, a, b, c, F3, KK1, 11, 13); + R( c, d, e, a, b, F3, KK1, 3, 15); + R( b, c, d, e, a, F3, KK1, 7, 7); + R( a, b, c, d, e, F3, KK1, 0, 12); + R( e, a, b, c, d, F3, KK1, 13, 8); + R( d, e, a, b, c, F3, KK1, 5, 9); + R( c, d, e, a, b, F3, KK1, 10, 11); + R( b, c, d, e, a, F3, KK1, 14, 7); + R( a, b, c, d, e, F3, KK1, 15, 7); + R( e, a, b, c, d, F3, KK1, 8, 12); + R( d, e, a, b, c, F3, KK1, 12, 7); + R( c, d, e, a, b, F3, KK1, 4, 6); + R( b, c, d, e, a, F3, KK1, 9, 15); + R( a, b, c, d, e, F3, KK1, 1, 13); + R( e, a, b, c, d, F3, KK1, 2, 11); + R( d, e, a, b, c, F2, KK2, 15, 9); + R( c, d, e, a, b, F2, KK2, 5, 7); + R( b, c, d, e, a, F2, KK2, 1, 15); + R( a, b, c, d, e, F2, KK2, 3, 11); + R( e, a, b, c, d, F2, KK2, 7, 8); + R( d, e, a, b, c, F2, KK2, 14, 6); + R( c, d, e, a, b, F2, KK2, 6, 6); + R( b, c, d, e, a, F2, KK2, 9, 14); + R( a, b, c, d, e, F2, KK2, 11, 12); + R( e, a, b, c, d, F2, KK2, 8, 13); + R( d, e, a, b, c, F2, KK2, 12, 5); + R( c, d, e, a, b, F2, KK2, 2, 14); + R( b, c, d, e, a, F2, KK2, 10, 13); + R( a, b, c, d, e, F2, KK2, 0, 13); + R( e, a, b, c, d, F2, KK2, 4, 7); + R( d, e, a, b, c, F2, KK2, 13, 5); + R( c, d, e, a, b, F1, KK3, 8, 15); + R( b, c, d, e, a, F1, KK3, 6, 5); + R( a, b, c, d, e, F1, KK3, 4, 8); + R( e, a, b, c, d, F1, KK3, 1, 11); + R( d, e, a, b, c, F1, KK3, 3, 14); + R( c, d, e, a, b, F1, KK3, 11, 14); + R( b, c, d, e, a, F1, KK3, 15, 6); + R( a, b, c, d, e, F1, KK3, 0, 14); + R( e, a, b, c, d, F1, KK3, 5, 6); + R( d, e, a, b, c, F1, KK3, 12, 9); + R( c, d, e, a, b, F1, KK3, 2, 12); + R( b, c, d, e, a, F1, KK3, 13, 9); + R( a, b, c, d, e, F1, KK3, 9, 12); + R( e, a, b, c, d, F1, KK3, 7, 5); + R( d, e, a, b, c, F1, KK3, 10, 15); + R( c, d, e, a, b, F1, KK3, 14, 8); + R( b, c, d, e, a, F0, KK4, 12, 8); + R( a, b, c, d, e, F0, KK4, 15, 5); + R( e, a, b, c, d, F0, KK4, 10, 12); + R( d, e, a, b, c, F0, KK4, 4, 9); + R( c, d, e, a, b, F0, KK4, 1, 12); + R( b, c, d, e, a, F0, KK4, 5, 5); + R( a, b, c, d, e, F0, KK4, 8, 14); + R( e, a, b, c, d, F0, KK4, 7, 6); + R( d, e, a, b, c, F0, KK4, 6, 8); + R( c, d, e, a, b, F0, KK4, 2, 13); + R( b, c, d, e, a, F0, KK4, 13, 6); + R( a, b, c, d, e, F0, KK4, 14, 5); + R( e, a, b, c, d, F0, KK4, 0, 15); + R( d, e, a, b, c, F0, KK4, 3, 13); + R( c, d, e, a, b, F0, KK4, 9, 11); + R( b, c, d, e, a, F0, KK4, 11, 11); + + + t = hd->h1 + d + cc; + hd->h1 = hd->h2 + e + dd; + hd->h2 = hd->h3 + a + ee; + hd->h3 = hd->h4 + b + aa; + hd->h4 = hd->h0 + c + bb; + hd->h0 = t; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) +{ + if( hd->count == 64 ) { /* flush the buffer */ + transform( hd, hd->buf ); + burn_stack (108+5*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + rmd160_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + burn_stack (108+5*sizeof(void*)); + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + +/**************** + * Apply the rmd160 transform function on the buffer which must have + * a length 64 bytes. Do not use this function together with the + * other functions, use rmd160_init to initialize internal variables. + * Returns: 16 bytes in buffer with the mixed contentes of buffer. + */ +void +rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) +{ + char *p = buffer; + transform( hd, buffer ); + #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) + X(0); + X(1); + X(2); + X(3); + X(4); + #undef X +} + + +/* The routine terminates the computation + */ + +static void +rmd160_final( RMD160_CONTEXT *hd ) +{ + u32 t, msb, lsb; + byte *p; + + rmd160_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else { /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + rmd160_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + burn_stack (108+5*sizeof(void*)); + + p = hd->buf; + #ifdef BIG_ENDIAN_HOST + #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ + *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) + #else /* little endian */ + #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) + #endif + X(0); + X(1); + X(2); + X(3); + X(4); + #undef X +} + +static byte * +rmd160_read( RMD160_CONTEXT *hd ) +{ + return hd->buf; +} + + + +/**************** + * Shortcut functions which puts the hash value of the supplied buffer + * into outbuf which must have a size of 20 bytes. + */ +void +rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) +{ + RMD160_CONTEXT hd; + + rmd160_init( &hd ); + rmd160_write( &hd, (byte*)buffer, length ); + rmd160_final( &hd ); + memcpy( outbuf, hd.buf, 20 ); +} + + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +static const char * +rmd160_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + + if( algo != 3 ) + return NULL; + + *contextsize = sizeof(RMD160_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 20; + *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init; + *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; + *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; + *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; + + return "RIPEMD160"; +} + + +#ifndef IS_MODULE +static +#endif +const char * const gnupgext_version = "RMD160 ($Revision: 1.17.2.4 $)"; + +static struct { + int class; + int version; + int value; + void (*func)(void); +} func_table[] = { + { 10, 1, 0, (void(*)(void))rmd160_get_info }, + { 11, 1, 3 }, +}; + + +#ifndef IS_MODULE +static +#endif +void * +gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) +{ + void *ret; + int i = *sequence; + + do { + if( i >= DIM(func_table) || i < 0 ) { + return NULL; + } + *class = func_table[i].class; + *vers = func_table[i].version; + switch( *class ) { + case 11: + case 21: + case 31: + ret = &func_table[i].value; + break; + default: + ret = func_table[i].func; + break; + } + i++; + } while( what && what != *class ); + + *sequence = i; + return ret; +} + + + +#ifndef __HURD__ +#ifndef IS_MODULE +void +rmd160_constructor(void) +{ + register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); +} +#endif +#endif diff --git a/random.c b/random.c new file mode 100644 index 00000000..0ae31f5f --- /dev/null +++ b/random.c @@ -0,0 +1,624 @@ +/* random.c - A single-file translator providing random data + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, 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 + General Public License for more details. + + You should have received a copy of the GNU 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 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "random.h" +#include "gnupg-random.h" + +/* Our control port. */ +struct trivfs_control *fsys; + +int read_blocked; /* For read and select. */ +struct condition wait; /* For read and select. */ +struct condition select_alert; /* For read and select. */ + + +/* The quality of randomness we provide. + 0: Very weak randomness based on time() and getrusage(). + No external random data is used. + 1: Pseudo random numbers based on all available real random + numbers. + 2: Strong random numbers with a somewhat guaranteed entropy. +*/ +#define DEFAULT_LEVEL 2 +static int level = DEFAULT_LEVEL; + +/* Name of file to use as seed. */ +static char *seed_file; + +/* The random bytes we collected. */ +char gatherbuf[GATHERBUFSIZE]; + +/* The current positions in gatherbuf[]. */ +int gatherrpos; +int gatherwpos; + +/* XXX Yuk Yuk. */ +#define POOLSIZE 600 + +/* Take up to length bytes from gather_random if available. If + nothing is available, sleep until something becomes available. + Must be called with global_lock held. */ +int +gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) +{ + int avail = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; + int first = GATHERBUFSIZE - gatherrpos; + int second = length - first; + + /* If level is zero, we should not block and not add anything + to the pool. */ + if( !level ) + return 0; + + /* io_read() should guarantee that there is always data available. */ + if (level == 2) + assert (avail); + + if (length > avail) + length = avail; + + if (first > length) + first = length; + (*add) (&gatherbuf[gatherrpos], first, requester); + gatherrpos = (gatherrpos + first) % GATHERBUFSIZE; + if (second > 0) + { + (*add) (&gatherbuf[gatherrpos], second, requester); + gatherrpos += second; + } + return length; +} + + +const char *argp_program_version = STANDARD_HURD_VERSION (random); + +/* This lock protects the GnuPG code. */ +static struct mutex global_lock; + +/* Trivfs hooks. */ +int trivfs_fstype = FSTYPE_MISC; +int trivfs_fsid = 0; + +int trivfs_allow_open = O_READ | O_WRITE; + +int trivfs_support_read = 1; +int trivfs_support_write = 1; +int trivfs_support_exec = 0; + +void +trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) +{ + /* Mark the node as a read-only plain file. */ + st->st_mode &= ~S_IFMT; + st->st_mode |= (S_IFCHR); + st->st_size = 0; +} + +error_t +trivfs_goaway (struct trivfs_control *cntl, int flags) +{ + update_random_seed_file (); + exit (0); +} + +/* Read data from an IO object. If offset is -1, read from the object + maintained file pointer. If the object is not seekable, offset is + ignored. The amount desired to be read is in AMOUNT. */ +error_t +trivfs_S_io_read (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + data_t *data, mach_msg_type_number_t *data_len, + loff_t offs, mach_msg_type_number_t amount) +{ + /* Deny access if they have bad credentials. */ + if (! cred) + return EOPNOTSUPP; + else if (! (cred->po->openmodes & O_READ)) + return EBADF; + + mutex_lock (&global_lock); + + if (amount > 0) + { + while (readable_pool (amount, level) == 0) + { + if (cred->po->openmodes & O_NONBLOCK) + { + mutex_unlock (&global_lock); + return EWOULDBLOCK; + } + read_blocked = 1; + if (hurd_condition_wait (&wait, &global_lock)) + { + mutex_unlock (&global_lock); + return EINTR; + } + /* See term/users.c for possible race? */ + } + + /* Possibly allocate a new buffer. */ + if (*data_len < amount) + *data = mmap (0, amount, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + amount = read_pool ((byte *) *data, amount, level); + } + *data_len = amount; + + /* Set atime, see term/users.c */ + + mutex_unlock (&global_lock); + + return 0; +} + +/* Write data to an IO object. If offset is -1, write at the object + maintained file pointer. If the object is not seekable, offset is + ignored. The amount successfully written is returned in amount. A + given user should not have more than one outstanding io_write on an + object at a time; servers implement congestion control by delaying + responses to io_write. Servers may drop data (returning ENOBUFS) + if they receive more than one write when not prepared for it. */ +error_t +trivfs_S_io_write (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t replytype, + data_t data, + mach_msg_type_number_t datalen, + loff_t offset, + mach_msg_type_number_t *amount) +{ + int i = 0; + /* Deny access if they have bad credentials. */ + if (! cred) + return EOPNOTSUPP; + else if (! (cred->po->openmodes & O_WRITE)) + return EBADF; + + mutex_lock (&global_lock); + + while (i < datalen) + { + gatherbuf[gatherwpos] = data[i++]; + gatherwpos = (gatherwpos + 1) % GATHERBUFSIZE; + if (gatherrpos == gatherwpos) + /* Overrun. */ + gatherrpos = (gatherrpos + 1) % GATHERBUFSIZE; + } + *amount = datalen; + + if (datalen > 0 && read_blocked) + { + read_blocked = 0; + condition_broadcast (&wait); + } + + mutex_unlock (&global_lock); + return 0; +} + +/* Tell how much data can be read from the object without blocking for + a "long time" (this should be the same meaning of "long time" used + by the nonblocking flag. */ +kern_return_t +trivfs_S_io_readable (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t replytype, + mach_msg_type_number_t *amount) +{ + /* Deny access if they have bad credentials. */ + if (! cred) + return EOPNOTSUPP; + else if (! (cred->po->openmodes & O_READ)) + return EBADF; + + mutex_lock (&global_lock); + + /* XXX: Before initialization, the amount depends on the amount we + want to read. Assume some medium value. */ + *amount = readable_pool (POOLSIZE/2, level); + + mutex_unlock (&global_lock); + + return 0; +} + +/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG. + Block until one of the indicated types of i/o can be done "quickly", and + return the types that are then available. ID_TAG is returned as passed; it + is just for the convenience of the user in matching up reply messages with + specific requests sent. */ +error_t +trivfs_S_io_select (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + int *type) +{ + if (!cred) + return EOPNOTSUPP; + + /* We only deal with SELECT_READ and SELECT_WRITE here. */ + if (*type & ~(SELECT_READ | SELECT_WRITE)) + return EINVAL; + + if (*type == 0) + return 0; + + mutex_lock (&global_lock); + + while (1) + { + /* XXX Before initialization, readable_pool depends on length. */ + int avail = readable_pool (POOLSIZE/2, level); + + if (avail != 0 || *type & SELECT_WRITE) + { + *type = (avail ? SELECT_READ : 0) | (*type & SELECT_WRITE); + mutex_unlock (&global_lock); + return 0; + } + + ports_interrupt_self_on_port_death (cred, reply); + read_blocked = 1; + + if (hurd_condition_wait (&select_alert, &global_lock)) + { + *type = 0; + mutex_unlock (&global_lock); + return EINTR; + } + } +} + + +/* Change current read/write offset */ +error_t +trivfs_S_io_seek (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + loff_t offs, int whence, loff_t *new_offs) +{ + if (! cred) + return EOPNOTSUPP; + + /* Not seekable. */ + return ESPIPE; +} + +/* Change the size of the file. If the size increases, new blocks are + zero-filled. After successful return, it is safe to reference mapped + areas of the file up to NEW_SIZE. */ +error_t +trivfs_S_file_set_size (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + loff_t size) +{ + if (!cred) + return EOPNOTSUPP; + + return size == 0 ? 0 : EINVAL; +} + +/* These four routines modify the O_APPEND, O_ASYNC, O_FSYNC, and + O_NONBLOCK bits for the IO object. In addition, io_get_openmodes + will tell you which of O_READ, O_WRITE, and O_EXEC the object can + be used for. The O_ASYNC bit affects icky async I/O; good async + I/O is done through io_async which is orthogonal to these calls. */ +error_t +trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + int mode) +{ + if (!cred) + return EOPNOTSUPP; + + return 0; +} + +error_t +trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + int bits) +{ + if (!cred) + return EOPNOTSUPP; + + return 0; +} + +error_t +trivfs_S_io_get_owner (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + pid_t *owner) +{ + if (!cred) + return EOPNOTSUPP; + + *owner = 0; + return 0; +} + +error_t +trivfs_S_io_mod_owner (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + pid_t owner) +{ + if (!cred) + return EOPNOTSUPP; + + return EINVAL; +} + +/* Return objects mapping the data underlying this memory object. If + the object can be read then memobjrd will be provided; if the + object can be written then memobjwr will be provided. For objects + where read data and write data are the same, these objects will be + equal, otherwise they will be disjoint. Servers are permitted to + implement io_map but not io_map_cntl. Some objects do not provide + mapping; they will set none of the ports and return an error. Such + objects can still be accessed by io_read and io_write. */ +error_t +trivfs_S_io_map(struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + mach_port_t *rdobj, + mach_msg_type_name_t *rdtype, + mach_port_t *wrobj, + mach_msg_type_name_t *wrtype) +{ + if (!cred) + return EOPNOTSUPP; + + return EINVAL; +} + + +int +random_demuxer (mach_msg_header_t *inp, + mach_msg_header_t *outp) +{ + extern int startup_notify_server (mach_msg_header_t *, mach_msg_header_t *); + + return (trivfs_demuxer (inp, outp) + || startup_notify_server (inp, outp)); +} + + +/* Options processing. We accept the same options on the command line + and from fsys_set_options. */ + +static const struct argp_option options[] = +{ + {"weak", 'w', 0, 0, "Output weak pseudo random data"}, + {"fast", 'f', 0, 0, "Output cheap random data fast"}, + {"secure", 's', 0, 0, "Output cryptographically secure random"}, + {"seed-file", 'S', "FILE", 0, "Use FILE to remember the seed"}, + {0} +}; + +static error_t +parse_opt (int opt, char *arg, struct argp_state *state) +{ + switch (opt) + { + default: + return ARGP_ERR_UNKNOWN; + case ARGP_KEY_INIT: + case ARGP_KEY_SUCCESS: + case ARGP_KEY_ERROR: + break; + + case 'w': + { + level = 0; + break; + } + case 'f': + { + level = 1; + break; + } + case 's': + { + level = 2; + break; + } + case 'S': + { + seed_file = strdup (arg); + set_random_seed_file (arg); + } + } + return 0; +} + +/* This will be called from libtrivfs to help construct the answer + to an fsys_get_options RPC. */ +error_t +trivfs_append_args (struct trivfs_control *fsys, + char **argz, size_t *argz_len) +{ + error_t err = 0; + char *opt; + + mutex_lock (&global_lock); + switch (level) + { + case 0: + { + opt = "--weak"; + break; + } + case 1: + { + opt = "--fast"; + break; + } + default: + { + opt = "--secure"; + break; + } + } + if (level != DEFAULT_LEVEL) + err = argz_add (argz, argz_len, opt); + + if (!err && seed_file) + { + if (asprintf (&opt, "--seed-file=%s", seed_file) < 0) + err = ENOMEM; + else + { + err = argz_add (argz, argz_len, opt); + free (opt); + } + } + mutex_unlock (&global_lock); + + return err; +} + +static struct argp random_argp = +{ options, parse_opt, 0, + "A translator providing random output." }; + +/* Setting this variable makes libtrivfs use our argp to + parse options passed in an fsys_set_options RPC. */ +struct argp *trivfs_runtime_argp = &random_argp; + +struct port_class *shutdown_notify_class; + +/* The system is going down; destroy all the extant port rights. That + will cause net channels and such to close promptly. */ +error_t +S_startup_dosync (mach_port_t handle) +{ + struct port_info *inpi = ports_lookup_port (fsys->pi.bucket, handle, + shutdown_notify_class); + + if (!inpi) + return EOPNOTSUPP; + + update_random_seed_file (); + return 0; +} + +void +sigterm_handler (int signo) +{ + update_random_seed_file (); + signal (SIGTERM, SIG_DFL); + raise (SIGTERM); +} + +void +arrange_shutdown_notification () +{ + error_t err; + mach_port_t initport, notify; + process_t procserver; + struct port_info *pi; + + shutdown_notify_class = ports_create_class (0, 0); + + signal (SIGTERM, sigterm_handler); + + /* Arrange to get notified when the system goes down, + but if we fail for some reason, just silently give up. No big deal. */ + + err = ports_create_port (shutdown_notify_class, fsys->pi.bucket, + sizeof (struct port_info), &pi); + if (err) + return; + + procserver = getproc (); + if (!procserver) + return; + + err = proc_getmsgport (procserver, 1, &initport); + mach_port_deallocate (mach_task_self (), procserver); + if (err) + return; + + notify = ports_get_send_right (pi); + ports_port_deref (pi); + startup_request_notification (initport, notify, + MACH_MSG_TYPE_MAKE_SEND, + program_invocation_short_name); + mach_port_deallocate (mach_task_self (), notify); + mach_port_deallocate (mach_task_self (), initport); +} + + +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t bootstrap; + + /* Initialize the lock that will protect everything. + We must do this before argp_parse, because parse_opt (above) will + use the lock. */ + mutex_init (&global_lock); + + /* The conditions are used to implement proper read/select + behaviour. */ + condition_init (&wait); + condition_init (&select_alert); + condition_implies (&wait, &select_alert); + + /* We use the same argp for options available at startup + as for options we'll accept in an fsys_set_options RPC. */ + argp_parse (&random_argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "Must be started as a translator"); + + /* Reply to our parent */ + err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys); + mach_port_deallocate (mach_task_self (), bootstrap); + if (err) + error (3, err, "trivfs_startup"); + + arrange_shutdown_notification (); + + /* Launch. */ + ports_manage_port_operations_multithread (fsys->pi.bucket, random_demuxer, + 10 * 1000, /* idle thread */ + 10 * 60 * 1000, /* idle server */ + 0); + return 0; +} diff --git a/random.h b/random.h new file mode 100644 index 00000000..a38a4177 --- /dev/null +++ b/random.h @@ -0,0 +1,32 @@ +/* random.c - A single-file translator providing random data + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, 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 + General Public License for more details. + + You should have received a copy of the GNU 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 */ + +#ifndef __RANDOM_H__ +#define __RANDOM_H__ + +/* How many random bytes to gather at most. + XXX: Should be at least POOLSIZE. */ +#define GATHERBUFSIZE 32768 + +/* The random bytes we collected. */ +extern char gatherbuf[GATHERBUFSIZE]; + +/* The current positions in gatherbuf[]. */ +extern int gatherrpos; +extern int gatherwpos; + +#endif -- cgit v1.2.3 From 7141fe6e0335254895e5eb0f853e5d2b3ef05793 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 18 Aug 2011 02:41:01 +0200 Subject: Move files for integration with the rest of hurd. --- gnupg-bithelp.h | 41 --- gnupg-glue.h | 40 --- gnupg-random.c | 810 ------------------------------------------------- gnupg-random.h | 47 --- gnupg-rmd.h | 38 --- gnupg-rmd160.c | 656 --------------------------------------- random.c | 624 ------------------------------------- random.h | 32 -- random/Makefile | 29 ++ random/TODO | 11 + random/gnupg-bithelp.h | 41 +++ random/gnupg-glue.h | 40 +++ random/gnupg-random.c | 810 +++++++++++++++++++++++++++++++++++++++++++++++++ random/gnupg-random.h | 47 +++ random/gnupg-rmd.h | 38 +++ random/gnupg-rmd160.c | 656 +++++++++++++++++++++++++++++++++++++++ random/random.c | 624 +++++++++++++++++++++++++++++++++++++ random/random.h | 32 ++ 18 files changed, 2328 insertions(+), 2288 deletions(-) delete mode 100644 gnupg-bithelp.h delete mode 100644 gnupg-glue.h delete mode 100644 gnupg-random.c delete mode 100644 gnupg-random.h delete mode 100644 gnupg-rmd.h delete mode 100644 gnupg-rmd160.c delete mode 100644 random.c delete mode 100644 random.h create mode 100644 random/Makefile create mode 100644 random/TODO create mode 100644 random/gnupg-bithelp.h create mode 100644 random/gnupg-glue.h create mode 100644 random/gnupg-random.c create mode 100644 random/gnupg-random.h create mode 100644 random/gnupg-rmd.h create mode 100644 random/gnupg-rmd160.c create mode 100644 random/random.c create mode 100644 random/random.h diff --git a/gnupg-bithelp.h b/gnupg-bithelp.h deleted file mode 100644 index 188db168..00000000 --- a/gnupg-bithelp.h +++ /dev/null @@ -1,41 +0,0 @@ -/* bithelp.h - Some bit manipulation helpers - * Copyright (C) 1999 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG 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 General Public License for more details. - * - * You should have received a copy of the GNU 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 - */ -#ifndef G10_BITHELP_H -#define G10_BITHELP_H - - -/**************** - * Rotate a 32 bit integer by n bytes - */ -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -rol( u32 x, int n) -{ - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n)); - return x; -} -#else - #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif - - -#endif /*G10_BITHELP_H*/ diff --git a/gnupg-glue.h b/gnupg-glue.h deleted file mode 100644 index cbf0a103..00000000 --- a/gnupg-glue.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __GNUPG_GLUE_H__ -#define __GNUPG_GLUE_H__ - -#include -#include - -#define SIZEOF_UNSIGNED_LONG 4 -typedef unsigned int u32; -typedef unsigned char byte; - -/* GnuPG's config.h */ -#define HAVE_GETTIMEOFDAY 1 -#define HAVE_GETRUSAGE 1 -#define HAVE_RAND 1 - -/* GnuPG's memory.h */ -#define m_alloc malloc -#define m_alloc_secure malloc -#define m_alloc_clear(x) calloc(x, 1) -#define m_alloc_secure_clear(x) calloc(x, 1) -#define m_free free -#define m_strdup strdup - -/* GnuPG's dynaload.h */ -#define dynload_getfnc_fast_random_poll() (0) -#define dynload_getfnc_gather_random() &gather_random -int -gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ); - -/* GnuPG's miscellaneous stuff. */ -#define BUG() assert(0) -#define _(x) x -#define make_timestamp() time(0) -#define tty_printf printf -#define log_info(format, args...) printf(format , ## args) -#define log_fatal(format, args...) { printf(format , ## args) ; exit(2); } -#define DIM(v) (sizeof(v)/sizeof((v)[0])) - -#endif /* __GNUPG_GLUE_H__ */ diff --git a/gnupg-random.c b/gnupg-random.c deleted file mode 100644 index 8f308621..00000000 --- a/gnupg-random.c +++ /dev/null @@ -1,810 +0,0 @@ -/* random.c - random number generator - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG 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 General Public License for more details. - * - * You should have received a copy of the GNU 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 - */ - - -/**************** - * This random number generator is modelled after the one described - * in Peter Gutmann's Paper: "Software Generation of Practically - * Strong Random Numbers". - */ - -#ifndef __HURD__ -#include -#else -#include "gnupg-glue.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_GETHRTIME - #include -#endif -#ifdef HAVE_GETTIMEOFDAY - #include -#endif -#ifdef HAVE_GETRUSAGE - #include -#endif -#ifdef __MINGW32__ - #include -#endif -#ifndef __HURD__ -#include "util.h" -#endif -#ifndef __HURD__ -#include "rmd.h" -#include "ttyio.h" -#include "i18n.h" -#include "random.h" -#include "rand-internal.h" -#include "dynload.h" -#else -#include "gnupg-rmd.h" -#include "gnupg-random.h" -#endif - -#ifndef RAND_MAX /* for SunOS */ - #define RAND_MAX 32767 -#endif - - -#if SIZEOF_UNSIGNED_LONG == 8 - #define ADD_VALUE 0xa5a5a5a5a5a5a5a5 -#elif SIZEOF_UNSIGNED_LONG == 4 - #define ADD_VALUE 0xa5a5a5a5 -#else - #error weird size for an unsigned long -#endif - -#define BLOCKLEN 64 /* hash this amount of bytes */ -#define DIGESTLEN 20 /* into a digest of this length (rmd160) */ -/* poolblocks is the number of digests which make up the pool - * and poolsize must be a multiple of the digest length - * to make the AND operations faster, the size should also be - * a multiple of ulong - */ -#define POOLBLOCKS 30 -#define POOLSIZE (POOLBLOCKS*DIGESTLEN) -#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) - #error Please make sure that poolsize is a multiple of ulong -#endif -#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) - - -static int is_initialized; -#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) -static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */ -static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */ -static size_t pool_readpos; -static size_t pool_writepos; -static int pool_filled; -static int pool_balance; -static int just_mixed; -static int did_initial_extra_seeding; -static char *seed_file_name; -static int allow_seed_file_update; - -static int secure_alloc; -static int quick_test; -static int faked_rng; - - -#ifndef __HURD__ -static void read_pool( byte *buffer, size_t length, int level ); -#else -int read_pool( byte *buffer, size_t length, int level ); -#endif -static void add_randomness( const void *buffer, size_t length, int source ); -static void random_poll(void); -#ifndef __HURD__ -static void read_random_source( int requester, size_t length, int level); -#else -static int read_random_source( int requester, size_t length, int level); -#endif -static int gather_faked( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ); - -static struct { - ulong mixrnd; - ulong mixkey; - ulong slowpolls; - ulong fastpolls; - ulong getbytes1; - ulong ngetbytes1; - ulong getbytes2; - ulong ngetbytes2; - ulong addbytes; - ulong naddbytes; -} rndstats; - -static void -initialize(void) -{ - /* The data buffer is allocated somewhat larger, so that - * we can use this extra space (which is allocated in secure memory) - * as a temporary hash buffer */ - rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) - : m_alloc_clear(POOLSIZE+BLOCKLEN); - keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) - : m_alloc_clear(POOLSIZE+BLOCKLEN); - is_initialized = 1; -#ifndef __HURD__ - cipher_modules_constructor(); -#endif -} - -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - -void -random_dump_stats() -{ - fprintf(stderr, - "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" - " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n", - POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, - rndstats.naddbytes, rndstats.addbytes, - rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, - rndstats.ngetbytes2, rndstats.getbytes2 ); -} - -void -secure_random_alloc() -{ - secure_alloc = 1; -} - - -int -quick_random_gen( int onoff ) -{ - int last; - - read_random_source(0,0,0); /* init */ - last = quick_test; - if( onoff != -1 ) - quick_test = onoff; - return faked_rng? 1 : last; -} - - -/**************** - * Fill the buffer with LENGTH bytes of cryptographically strong - * random bytes. level 0 is not very strong, 1 is strong enough - * for most usage, 2 is good for key generation stuff but may be very slow. - */ -void -randomize_buffer( byte *buffer, size_t length, int level ) -{ - char *p = get_random_bits( length*8, level, 1 ); - memcpy( buffer, p, length ); - m_free(p); -} - - -int -random_is_faked() -{ - if( !is_initialized ) - initialize(); - return faked_rng || quick_test; -} - -/**************** - * Return a pointer to a randomized buffer of level 0 and LENGTH bits - * caller must free the buffer. - * Note: The returned value is rounded up to bytes. - */ -byte * -get_random_bits( size_t nbits, int level, int secure ) -{ - byte *buf, *p; - size_t nbytes = (nbits+7)/8; - - if( quick_test && level > 1 ) - level = 1; - MASK_LEVEL(level); - if( level == 1 ) { - rndstats.getbytes1 += nbytes; - rndstats.ngetbytes1++; - } - else if( level >= 2 ) { - rndstats.getbytes2 += nbytes; - rndstats.ngetbytes2++; - } - - buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes ); - for( p = buf; nbytes > 0; ) { - size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes; -#ifdef __HURD__ - n = -#endif - read_pool( p, n, level ); - nbytes -= n; - p += n; - - } - return buf; -} - - -/**************** - * Mix the pool - */ -static void -mix_pool(byte *pool) -{ - char *hashbuf = pool + POOLSIZE; - char *p, *pend; - int i, n; - RMD160_CONTEXT md; - - rmd160_init( &md ); - #if DIGESTLEN != 20 - #error must have a digest length of 20 for ripe-md-160 - #endif - /* loop over the pool */ - pend = pool + POOLSIZE; - memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); - memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); - rmd160_mixblock( &md, hashbuf); - memcpy(pool, hashbuf, 20 ); - - p = pool; - for( n=1; n < POOLBLOCKS; n++ ) { - memcpy(hashbuf, p, DIGESTLEN ); - - p += DIGESTLEN; - if( p+DIGESTLEN+BLOCKLEN < pend ) - memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); - else { - char *pp = p+DIGESTLEN; - for(i=DIGESTLEN; i < BLOCKLEN; i++ ) { - if( pp >= pend ) - pp = pool; - hashbuf[i] = *pp++; - } - } - - rmd160_mixblock( &md, hashbuf); - memcpy(p, hashbuf, 20 ); - } - burn_stack (200); /* for the rmd160_mixblock() */ -} - - -void -set_random_seed_file( const char *name ) -{ - if( seed_file_name ) - BUG(); - seed_file_name = m_strdup( name ); -} - -/**************** - * Read in a seed form the random_seed file - * and return true if this was successful - */ -static int -read_seed_file() -{ - int fd; - struct stat sb; - unsigned char buffer[POOLSIZE]; - int n; - - if( !seed_file_name ) - return 0; - - #ifdef HAVE_DOSISH_SYSTEM - fd = open( seed_file_name, O_RDONLY | O_BINARY ); - #else - fd = open( seed_file_name, O_RDONLY ); - #endif - if( fd == -1 && errno == ENOENT) { - allow_seed_file_update = 1; - return 0; - } - - if( fd == -1 ) { - log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); - return 0; - } - if( fstat( fd, &sb ) ) { - log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); - close(fd); - return 0; - } - if( !S_ISREG(sb.st_mode) ) { - log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); - close(fd); - return 0; - } - if( !sb.st_size ) { - log_info(_("note: random_seed file is empty\n") ); - close(fd); - allow_seed_file_update = 1; - return 0; - } - if( sb.st_size != POOLSIZE ) { - log_info(_("warning: invalid size of random_seed file - not used\n") ); - close(fd); - return 0; - } - do { - n = read( fd, buffer, POOLSIZE ); - } while( n == -1 && errno == EINTR ); - if( n != POOLSIZE ) { - log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); - close(fd); - return 0; - } - - close(fd); - - add_randomness( buffer, POOLSIZE, 0 ); - /* add some minor entropy to the pool now (this will also force a mixing) */ - { pid_t x = getpid(); - add_randomness( &x, sizeof(x), 0 ); - } - { time_t x = time(NULL); - add_randomness( &x, sizeof(x), 0 ); - } - { clock_t x = clock(); - add_randomness( &x, sizeof(x), 0 ); - } - /* And read a few bytes from our entropy source. By using - * a level of 0 this will not block and might not return anything - * with some entropy drivers, however the rndlinux driver will use - * /dev/urandom and return some stuff - Do not read to much as we - * want to be friendly to the scare system entropy resource. */ - read_random_source( 0, 16, 0 ); - - allow_seed_file_update = 1; - return 1; -} - -void -update_random_seed_file() -{ - ulong *sp, *dp; - int fd, i; - - if( !seed_file_name || !is_initialized || !pool_filled ) - return; - if( !allow_seed_file_update ) { - log_info(_("note: random_seed file not updated\n")); - return; - } - - - /* copy the entropy pool to a scratch pool and mix both of them */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) { - *dp = *sp + ADD_VALUE; - } - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - - #ifdef HAVE_DOSISH_SYSTEM - fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, - S_IRUSR|S_IWUSR ); - #else - fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); - #endif - if( fd == -1 ) { - log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); - return; - } - do { - i = write( fd, keypool, POOLSIZE ); - } while( i == -1 && errno == EINTR ); - if( i != POOLSIZE ) { - log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); - } - if( close(fd) ) - log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); -} - -#ifdef __HURD__ -int readable_pool( size_t length, int level ) -{ - size_t needed = 0; - size_t my_balance = pool_balance; - size_t available = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; - - if (length > POOLSIZE) - length = POOLSIZE; - - if (level < 2) - return length; - - if( !pool_filled ) { - if( read_seed_file() ) - pool_filled = 1; - } - - if (!did_initial_extra_seeding) - { - /* Take account for initial extra seeding. */ - needed = length; - if (needed < POOLSIZE/2) - needed = POOLSIZE/2; - my_balance = needed; - - if (!pool_filled && pool_writepos + needed < POOLSIZE) - { - /* If the pool is not filled yet, we couldn't read the seed - file. Too bad. We will now have to take account for so many - random_poll()s as fit into the remaining pool. */ - - needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); - } - } - else - { - if (!pool_filled) - needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); - } - - /* NEEDED contains the bytes needed for initialization, MY_BALANCE the resulting - available bytes. */ - if (available < needed) - return 0; - return available + my_balance - needed; -} -#endif - -#ifndef __HURD__ -static void -#else -int -#endif -read_pool( byte *buffer, size_t length, int level ) -{ - int i; - ulong *sp, *dp; - - if( length > POOLSIZE ) { -#ifndef __HURD__ - log_fatal(_("too many random bits requested; the limit is %d\n"), - POOLSIZE*8-1 ); -#else - length = POOLSIZE; -#endif - } - - if( !pool_filled ) { - if( read_seed_file() ) - pool_filled = 1; - } - - /* For level 2 quality (key generation) we alwas make - * sure that the pool has been seeded enough initially */ - if( level == 2 && !did_initial_extra_seeding ) { - size_t needed; - - pool_balance = 0; - needed = length - pool_balance; - if( needed < POOLSIZE/2 ) - needed = POOLSIZE/2; - else if( needed > POOLSIZE ) - BUG(); -#ifdef __HURD__ - needed = -#endif - read_random_source( 3, needed, 2 ); -#ifdef __HURD__ - if (! needed) - return 0; - /* XXX This will succeed with needed < POOLSIZE/2 even. But - erroring out will waste the random we already got. */ -#endif - pool_balance += needed; - did_initial_extra_seeding=1; - } - - /* for level 2 make sure that there is enough random in the pool */ - if( level == 2 && pool_balance < length ) { - size_t needed; - - if( pool_balance < 0 ) - pool_balance = 0; - needed = length - pool_balance; - if( needed > POOLSIZE ) - BUG(); -#ifdef __HURD__ - needed = -#endif - read_random_source( 3, needed, 2 ); - pool_balance += needed; - } - -#ifdef __HURD__ - /* XXX This makes level 0 and 1 worse than needed at first start up. */ - if (level == 2) -#endif - /* make sure the pool is filled */ - while( !pool_filled ) - random_poll(); - - /* do always a fast random poll */ - fast_random_poll(); - - if( !level ) { /* no need for cryptographic strong random */ - /* create a new pool */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - *dp = *sp + ADD_VALUE; - /* must mix both pools */ - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - memcpy( buffer, keypool, length ); - return length; - } - else { -#ifdef __HURD__ - int amount; -#endif - /* mix the pool (if add_randomness() didn't it) */ - if( !just_mixed ) { - mix_pool(rndpool); - rndstats.mixrnd++; - } - /* create a new pool */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - *dp = *sp + ADD_VALUE; - /* and mix both pools */ - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - /* read the required data - * we use a readpoiter to read from a different postion each - * time */ -#ifdef __HURD__ - if (level == 2 && length > pool_balance) - length = pool_balance; - amount = length; -#endif - while( length-- ) { - *buffer++ = keypool[pool_readpos++]; - if( pool_readpos >= POOLSIZE ) - pool_readpos = 0; - pool_balance--; - } - if( pool_balance < 0 ) - pool_balance = 0; - /* and clear the keypool */ - memset( keypool, 0, POOLSIZE ); -#ifdef __HURD__ - return amount; -#endif - } -} - - -/**************** - * Add LENGTH bytes of randomness from buffer to the pool. - * source may be used to specify the randomness source. - * Source is: - * 0 - used ony for initialization - * 1 - fast random poll function - * 2 - normal poll function - * 3 - used when level 2 random quality has been requested - * to do an extra pool seed. - */ -static void -add_randomness( const void *buffer, size_t length, int source ) -{ - const byte *p = buffer; - - if( !is_initialized ) - initialize(); - rndstats.addbytes += length; - rndstats.naddbytes++; - while( length-- ) { - rndpool[pool_writepos++] = *p++; - if( pool_writepos >= POOLSIZE ) { - if( source > 1 ) - pool_filled = 1; - pool_writepos = 0; - mix_pool(rndpool); rndstats.mixrnd++; - just_mixed = !length; - } - } -} - - - -static void -random_poll() -{ - rndstats.slowpolls++; - read_random_source( 2, POOLSIZE/5, 1 ); -} - - -void -fast_random_poll() -{ - static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL; - static int initialized = 0; - - rndstats.fastpolls++; - if( !initialized ) { - if( !is_initialized ) - initialize(); - initialized = 1; - fnc = dynload_getfnc_fast_random_poll(); - } - if( fnc ) { - (*fnc)( add_randomness, 1 ); - return; - } - - /* fall back to the generic function */ - #if HAVE_GETHRTIME - { hrtime_t tv; - tv = gethrtime(); - add_randomness( &tv, sizeof(tv), 1 ); - } - #elif HAVE_GETTIMEOFDAY - { struct timeval tv; - if( gettimeofday( &tv, NULL ) ) - BUG(); - add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); - add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); - } - #elif HAVE_CLOCK_GETTIME - { struct timespec tv; - if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) - BUG(); - add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); - add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); - } - #else /* use times */ - #ifndef HAVE_DOSISH_SYSTEM - { struct tms buf; - times( &buf ); - add_randomness( &buf, sizeof buf, 1 ); - } - #endif - #endif - #ifdef HAVE_GETRUSAGE - #ifndef RUSAGE_SELF - #ifdef __GCC__ - #warning There is no RUSAGE_SELF on this system - #endif - #else - { struct rusage buf; - /* QNX/Neutrino does return ENOSYS - so we just ignore it and - * add whatever is in buf. In a chroot environment it might not - * work at all (i.e. because /proc/ is not accessible), so we better - * ognore all error codes and hope for the best - */ - getrusage( RUSAGE_SELF, &buf ); - - add_randomness( &buf, sizeof buf, 1 ); - memset( &buf, 0, sizeof buf ); - } - #endif - #endif - /* time and clock are availabe on all systems - so - * we better do it just in case one of the above functions - * didn't work */ - { time_t x = time(NULL); - add_randomness( &x, sizeof(x), 1 ); - } - { clock_t x = clock(); - add_randomness( &x, sizeof(x), 1 ); - } -} - - -#ifndef __HURD__ -static void -#else -static int -#endif -read_random_source( int requester, size_t length, int level ) -{ - static int (*fnc)(void (*)(const void*, size_t, int), int, - size_t, int) = NULL; -#ifdef __HURD__ - int got; -#endif - if( !fnc ) { - if( !is_initialized ) - initialize(); - fnc = dynload_getfnc_gather_random(); - if( !fnc ) { - faked_rng = 1; - fnc = gather_faked; - } - if( !requester && !length && !level ) -#ifndef __HURD__ - return; /* init only */ -#else - return 0; -#endif - } -#ifndef __HURD__ - if( (*fnc)( add_randomness, requester, length, level ) < 0 ) - log_fatal("No way to gather entropy for the RNG\n"); -#else - got = (*fnc)( add_randomness, requester, length, level ); - if (got < 0) - log_fatal("No way to gather entropy for the RNG\n"); - return got; -#endif -} - - -static int -gather_faked( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - static int initialized=0; - size_t n; - char *buffer, *p; - - if( !initialized ) { - log_info(_("WARNING: using insecure random number generator!!\n")); - tty_printf(_("The random number generator is only a kludge to let\n" - "it run - it is in no way a strong RNG!\n\n" - "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); - initialized=1; - #ifdef HAVE_RAND - srand(make_timestamp()*getpid()); - #else - srandom(make_timestamp()*getpid()); - #endif - } - printf("WAITING FOR %i bytes.\n", length); - p = buffer = m_alloc( length ); - n = length; - #ifdef HAVE_RAND - while( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); - #else - while( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); - #endif - add_randomness( buffer, length, requester ); - m_free(buffer); - return 0; /* okay */ -} - diff --git a/gnupg-random.h b/gnupg-random.h deleted file mode 100644 index ee18febc..00000000 --- a/gnupg-random.h +++ /dev/null @@ -1,47 +0,0 @@ -/* random.h - random functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG 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 General Public License for more details. - * - * You should have received a copy of the GNU 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 - */ -#ifndef G10_RANDOM_H -#define G10_RANDOM_H - -#ifndef __HURD__ -#include "types.h" -#else -#include "gnupg-glue.h" -int read_pool (byte *, size_t, int); -int readable_pool (size_t, int); -#endif - -/*-- random.c --*/ -void random_dump_stats(void); -void secure_random_alloc(void); -void set_random_seed_file(const char *); -void update_random_seed_file(void); -int quick_random_gen( int onoff ); -int random_is_faked(void); -void randomize_buffer( byte *buffer, size_t length, int level ); -byte *get_random_bits( size_t nbits, int level, int secure ); -void fast_random_poll( void ); - -/*-- rndw32.c --*/ -#ifdef USE_STATIC_RNDW32 -void rndw32_set_dll_name( const char *name ); -#endif - -#endif /*G10_RANDOM_H*/ diff --git a/gnupg-rmd.h b/gnupg-rmd.h deleted file mode 100644 index 2446fc7d..00000000 --- a/gnupg-rmd.h +++ /dev/null @@ -1,38 +0,0 @@ -/* rmd.h - RIPE-MD hash functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG 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 General Public License for more details. - * - * You should have received a copy of the GNU 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 - */ -#ifndef G10_RMD_H -#define G10_RMD_H - -#ifdef __HURD__ -#include "gnupg-glue.h" -#endif - -/* we need this here because random.c must have direct access */ -typedef struct { - u32 h0,h1,h2,h3,h4; - u32 nblocks; - byte buf[64]; - int count; -} RMD160_CONTEXT; - -void rmd160_init( RMD160_CONTEXT *hd ); -void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); - -#endif /*G10_RMD_H*/ diff --git a/gnupg-rmd160.c b/gnupg-rmd160.c deleted file mode 100644 index 66107685..00000000 --- a/gnupg-rmd160.c +++ /dev/null @@ -1,656 +0,0 @@ -/* rmd160.c - RIPE-MD160 - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG 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 General Public License for more details. - * - * You should have received a copy of the GNU 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 - */ - -#ifndef __HURD__ -#include -#endif -#include -#include -#include -#include -#ifndef __HURD__ -#include "util.h" -#include "memory.h" -#include "rmd.h" -#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ -#include "dynload.h" - -#include "bithelp.h" -#else -#include "gnupg-rmd.h" -#include "gnupg-bithelp.h" -#endif - - -/********************************* - * RIPEMD-160 is not patented, see (as of 25.10.97) - * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html - * Note that the code uses Little Endian byteorder, which is good for - * 386 etc, but we must add some conversion when used on a big endian box. - * - * - * Pseudo-code for RIPEMD-160 - * - * RIPEMD-160 is an iterative hash function that operates on 32-bit words. - * The round function takes as input a 5-word chaining variable and a 16-word - * message block and maps this to a new chaining variable. All operations are - * defined on 32-bit words. Padding is identical to that of MD4. - * - * - * RIPEMD-160: definitions - * - * - * nonlinear functions at bit level: exor, mux, -, mux, - - * - * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) - * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) - * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) - * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) - * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) - * - * - * added constants (hexadecimal) - * - * K(j) = 0x00000000 (0 <= j <= 15) - * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) - * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) - * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) - * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) - * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) - * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) - * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) - * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) - * K'(j) = 0x00000000 (64 <= j <= 79) - * - * - * selection of message word - * - * r(j) = j (0 <= j <= 15) - * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 - * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 - * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 - * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 - * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 - * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 - * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 - * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 - * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 - * - * - * amount for rotate left (rol) - * - * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 - * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 - * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 - * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 - * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 - * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 - * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 - * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 - * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 - * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 - * - * - * initial value (hexadecimal) - * - * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; - * h4 = 0xC3D2E1F0; - * - * - * RIPEMD-160: pseudo-code - * - * It is assumed that the message after padding consists of t 16-word blocks - * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. - * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left - * shift (rotate) over s positions. - * - * - * for i := 0 to t-1 { - * A := h0; B := h1; C := h2; D = h3; E = h4; - * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; - * for j := 0 to 79 { - * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; - * A := E; E := D; D := rol_10(C); C := B; B := T; - * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] - [+] K'(j)) [+] E'; - * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; - * } - * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; - * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; - * } - */ - -/* Some examples: - * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 - * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe - * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc - * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 - * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc - * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b - * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 - * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb - * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 - */ - -static void -burn_stack (int bytes) -{ - char buf[150]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - - -void -rmd160_init( RMD160_CONTEXT *hd ) -{ - hd->h0 = 0x67452301; - hd->h1 = 0xEFCDAB89; - hd->h2 = 0x98BADCFE; - hd->h3 = 0x10325476; - hd->h4 = 0xC3D2E1F0; - hd->nblocks = 0; - hd->count = 0; -} - - - -/**************** - * Transform the message X which consists of 16 32-bit-words - */ -static void -transform( RMD160_CONTEXT *hd, byte *data ) -{ - u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; - #ifdef BIG_ENDIAN_HOST - u32 x[16]; - { int i; - byte *p2, *p1; - for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } - #else - #if 0 - u32 *x =(u32*)data; - #else - /* this version is better because it is always aligned; - * The performance penalty on a 586-100 is about 6% which - * is acceptable - because the data is more local it might - * also be possible that this is faster on some machines. - * This function (when compiled with -02 on gcc 2.7.2) - * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; - * [measured with a 4MB data and "gpgm --print-md rmd160"] */ - u32 x[16]; - memcpy( x, data, 64 ); - #endif - #endif - - -#define K0 0x00000000 -#define K1 0x5A827999 -#define K2 0x6ED9EBA1 -#define K3 0x8F1BBCDC -#define K4 0xA953FD4E -#define KK0 0x50A28BE6 -#define KK1 0x5C4DD124 -#define KK2 0x6D703EF3 -#define KK3 0x7A6D76E9 -#define KK4 0x00000000 -#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) -#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) -#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) -#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) -#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) -#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ - a = rol(t,s) + e; \ - c = rol(c,10); \ - } while(0) - - /* left lane */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - R( a, b, c, d, e, F0, K0, 0, 11 ); - R( e, a, b, c, d, F0, K0, 1, 14 ); - R( d, e, a, b, c, F0, K0, 2, 15 ); - R( c, d, e, a, b, F0, K0, 3, 12 ); - R( b, c, d, e, a, F0, K0, 4, 5 ); - R( a, b, c, d, e, F0, K0, 5, 8 ); - R( e, a, b, c, d, F0, K0, 6, 7 ); - R( d, e, a, b, c, F0, K0, 7, 9 ); - R( c, d, e, a, b, F0, K0, 8, 11 ); - R( b, c, d, e, a, F0, K0, 9, 13 ); - R( a, b, c, d, e, F0, K0, 10, 14 ); - R( e, a, b, c, d, F0, K0, 11, 15 ); - R( d, e, a, b, c, F0, K0, 12, 6 ); - R( c, d, e, a, b, F0, K0, 13, 7 ); - R( b, c, d, e, a, F0, K0, 14, 9 ); - R( a, b, c, d, e, F0, K0, 15, 8 ); - R( e, a, b, c, d, F1, K1, 7, 7 ); - R( d, e, a, b, c, F1, K1, 4, 6 ); - R( c, d, e, a, b, F1, K1, 13, 8 ); - R( b, c, d, e, a, F1, K1, 1, 13 ); - R( a, b, c, d, e, F1, K1, 10, 11 ); - R( e, a, b, c, d, F1, K1, 6, 9 ); - R( d, e, a, b, c, F1, K1, 15, 7 ); - R( c, d, e, a, b, F1, K1, 3, 15 ); - R( b, c, d, e, a, F1, K1, 12, 7 ); - R( a, b, c, d, e, F1, K1, 0, 12 ); - R( e, a, b, c, d, F1, K1, 9, 15 ); - R( d, e, a, b, c, F1, K1, 5, 9 ); - R( c, d, e, a, b, F1, K1, 2, 11 ); - R( b, c, d, e, a, F1, K1, 14, 7 ); - R( a, b, c, d, e, F1, K1, 11, 13 ); - R( e, a, b, c, d, F1, K1, 8, 12 ); - R( d, e, a, b, c, F2, K2, 3, 11 ); - R( c, d, e, a, b, F2, K2, 10, 13 ); - R( b, c, d, e, a, F2, K2, 14, 6 ); - R( a, b, c, d, e, F2, K2, 4, 7 ); - R( e, a, b, c, d, F2, K2, 9, 14 ); - R( d, e, a, b, c, F2, K2, 15, 9 ); - R( c, d, e, a, b, F2, K2, 8, 13 ); - R( b, c, d, e, a, F2, K2, 1, 15 ); - R( a, b, c, d, e, F2, K2, 2, 14 ); - R( e, a, b, c, d, F2, K2, 7, 8 ); - R( d, e, a, b, c, F2, K2, 0, 13 ); - R( c, d, e, a, b, F2, K2, 6, 6 ); - R( b, c, d, e, a, F2, K2, 13, 5 ); - R( a, b, c, d, e, F2, K2, 11, 12 ); - R( e, a, b, c, d, F2, K2, 5, 7 ); - R( d, e, a, b, c, F2, K2, 12, 5 ); - R( c, d, e, a, b, F3, K3, 1, 11 ); - R( b, c, d, e, a, F3, K3, 9, 12 ); - R( a, b, c, d, e, F3, K3, 11, 14 ); - R( e, a, b, c, d, F3, K3, 10, 15 ); - R( d, e, a, b, c, F3, K3, 0, 14 ); - R( c, d, e, a, b, F3, K3, 8, 15 ); - R( b, c, d, e, a, F3, K3, 12, 9 ); - R( a, b, c, d, e, F3, K3, 4, 8 ); - R( e, a, b, c, d, F3, K3, 13, 9 ); - R( d, e, a, b, c, F3, K3, 3, 14 ); - R( c, d, e, a, b, F3, K3, 7, 5 ); - R( b, c, d, e, a, F3, K3, 15, 6 ); - R( a, b, c, d, e, F3, K3, 14, 8 ); - R( e, a, b, c, d, F3, K3, 5, 6 ); - R( d, e, a, b, c, F3, K3, 6, 5 ); - R( c, d, e, a, b, F3, K3, 2, 12 ); - R( b, c, d, e, a, F4, K4, 4, 9 ); - R( a, b, c, d, e, F4, K4, 0, 15 ); - R( e, a, b, c, d, F4, K4, 5, 5 ); - R( d, e, a, b, c, F4, K4, 9, 11 ); - R( c, d, e, a, b, F4, K4, 7, 6 ); - R( b, c, d, e, a, F4, K4, 12, 8 ); - R( a, b, c, d, e, F4, K4, 2, 13 ); - R( e, a, b, c, d, F4, K4, 10, 12 ); - R( d, e, a, b, c, F4, K4, 14, 5 ); - R( c, d, e, a, b, F4, K4, 1, 12 ); - R( b, c, d, e, a, F4, K4, 3, 13 ); - R( a, b, c, d, e, F4, K4, 8, 14 ); - R( e, a, b, c, d, F4, K4, 11, 11 ); - R( d, e, a, b, c, F4, K4, 6, 8 ); - R( c, d, e, a, b, F4, K4, 15, 5 ); - R( b, c, d, e, a, F4, K4, 13, 6 ); - - aa = a; bb = b; cc = c; dd = d; ee = e; - - /* right lane */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - R( a, b, c, d, e, F4, KK0, 5, 8); - R( e, a, b, c, d, F4, KK0, 14, 9); - R( d, e, a, b, c, F4, KK0, 7, 9); - R( c, d, e, a, b, F4, KK0, 0, 11); - R( b, c, d, e, a, F4, KK0, 9, 13); - R( a, b, c, d, e, F4, KK0, 2, 15); - R( e, a, b, c, d, F4, KK0, 11, 15); - R( d, e, a, b, c, F4, KK0, 4, 5); - R( c, d, e, a, b, F4, KK0, 13, 7); - R( b, c, d, e, a, F4, KK0, 6, 7); - R( a, b, c, d, e, F4, KK0, 15, 8); - R( e, a, b, c, d, F4, KK0, 8, 11); - R( d, e, a, b, c, F4, KK0, 1, 14); - R( c, d, e, a, b, F4, KK0, 10, 14); - R( b, c, d, e, a, F4, KK0, 3, 12); - R( a, b, c, d, e, F4, KK0, 12, 6); - R( e, a, b, c, d, F3, KK1, 6, 9); - R( d, e, a, b, c, F3, KK1, 11, 13); - R( c, d, e, a, b, F3, KK1, 3, 15); - R( b, c, d, e, a, F3, KK1, 7, 7); - R( a, b, c, d, e, F3, KK1, 0, 12); - R( e, a, b, c, d, F3, KK1, 13, 8); - R( d, e, a, b, c, F3, KK1, 5, 9); - R( c, d, e, a, b, F3, KK1, 10, 11); - R( b, c, d, e, a, F3, KK1, 14, 7); - R( a, b, c, d, e, F3, KK1, 15, 7); - R( e, a, b, c, d, F3, KK1, 8, 12); - R( d, e, a, b, c, F3, KK1, 12, 7); - R( c, d, e, a, b, F3, KK1, 4, 6); - R( b, c, d, e, a, F3, KK1, 9, 15); - R( a, b, c, d, e, F3, KK1, 1, 13); - R( e, a, b, c, d, F3, KK1, 2, 11); - R( d, e, a, b, c, F2, KK2, 15, 9); - R( c, d, e, a, b, F2, KK2, 5, 7); - R( b, c, d, e, a, F2, KK2, 1, 15); - R( a, b, c, d, e, F2, KK2, 3, 11); - R( e, a, b, c, d, F2, KK2, 7, 8); - R( d, e, a, b, c, F2, KK2, 14, 6); - R( c, d, e, a, b, F2, KK2, 6, 6); - R( b, c, d, e, a, F2, KK2, 9, 14); - R( a, b, c, d, e, F2, KK2, 11, 12); - R( e, a, b, c, d, F2, KK2, 8, 13); - R( d, e, a, b, c, F2, KK2, 12, 5); - R( c, d, e, a, b, F2, KK2, 2, 14); - R( b, c, d, e, a, F2, KK2, 10, 13); - R( a, b, c, d, e, F2, KK2, 0, 13); - R( e, a, b, c, d, F2, KK2, 4, 7); - R( d, e, a, b, c, F2, KK2, 13, 5); - R( c, d, e, a, b, F1, KK3, 8, 15); - R( b, c, d, e, a, F1, KK3, 6, 5); - R( a, b, c, d, e, F1, KK3, 4, 8); - R( e, a, b, c, d, F1, KK3, 1, 11); - R( d, e, a, b, c, F1, KK3, 3, 14); - R( c, d, e, a, b, F1, KK3, 11, 14); - R( b, c, d, e, a, F1, KK3, 15, 6); - R( a, b, c, d, e, F1, KK3, 0, 14); - R( e, a, b, c, d, F1, KK3, 5, 6); - R( d, e, a, b, c, F1, KK3, 12, 9); - R( c, d, e, a, b, F1, KK3, 2, 12); - R( b, c, d, e, a, F1, KK3, 13, 9); - R( a, b, c, d, e, F1, KK3, 9, 12); - R( e, a, b, c, d, F1, KK3, 7, 5); - R( d, e, a, b, c, F1, KK3, 10, 15); - R( c, d, e, a, b, F1, KK3, 14, 8); - R( b, c, d, e, a, F0, KK4, 12, 8); - R( a, b, c, d, e, F0, KK4, 15, 5); - R( e, a, b, c, d, F0, KK4, 10, 12); - R( d, e, a, b, c, F0, KK4, 4, 9); - R( c, d, e, a, b, F0, KK4, 1, 12); - R( b, c, d, e, a, F0, KK4, 5, 5); - R( a, b, c, d, e, F0, KK4, 8, 14); - R( e, a, b, c, d, F0, KK4, 7, 6); - R( d, e, a, b, c, F0, KK4, 6, 8); - R( c, d, e, a, b, F0, KK4, 2, 13); - R( b, c, d, e, a, F0, KK4, 13, 6); - R( a, b, c, d, e, F0, KK4, 14, 5); - R( e, a, b, c, d, F0, KK4, 0, 15); - R( d, e, a, b, c, F0, KK4, 3, 13); - R( c, d, e, a, b, F0, KK4, 9, 11); - R( b, c, d, e, a, F0, KK4, 11, 11); - - - t = hd->h1 + d + cc; - hd->h1 = hd->h2 + e + dd; - hd->h2 = hd->h3 + a + ee; - hd->h3 = hd->h4 + b + aa; - hd->h4 = hd->h0 + c + bb; - hd->h0 = t; -} - - -/* Update the message digest with the contents - * of INBUF with length INLEN. - */ -static void -rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) -{ - if( hd->count == 64 ) { /* flush the buffer */ - transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); - hd->count = 0; - hd->nblocks++; - } - if( !inbuf ) - return; - if( hd->count ) { - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; - rmd160_write( hd, NULL, 0 ); - if( !inlen ) - return; - } - - while( inlen >= 64 ) { - transform( hd, inbuf ); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - burn_stack (108+5*sizeof(void*)); - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; -} - -/**************** - * Apply the rmd160 transform function on the buffer which must have - * a length 64 bytes. Do not use this function together with the - * other functions, use rmd160_init to initialize internal variables. - * Returns: 16 bytes in buffer with the mixed contentes of buffer. - */ -void -rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) -{ - char *p = buffer; - transform( hd, buffer ); - #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) - X(0); - X(1); - X(2); - X(3); - X(4); - #undef X -} - - -/* The routine terminates the computation - */ - -static void -rmd160_final( RMD160_CONTEXT *hd ) -{ - u32 t, msb, lsb; - byte *p; - - rmd160_write(hd, NULL, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a byte count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if( (lsb += hd->count) < t ) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if( hd->count < 56 ) { /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while( hd->count < 56 ) - hd->buf[hd->count++] = 0; /* pad */ - } - else { /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while( hd->count < 64 ) - hd->buf[hd->count++] = 0; - rmd160_write(hd, NULL, 0); /* flush */; - memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = lsb ; - hd->buf[57] = lsb >> 8; - hd->buf[58] = lsb >> 16; - hd->buf[59] = lsb >> 24; - hd->buf[60] = msb ; - hd->buf[61] = msb >> 8; - hd->buf[62] = msb >> 16; - hd->buf[63] = msb >> 24; - transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); - - p = hd->buf; - #ifdef BIG_ENDIAN_HOST - #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ - *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) - #else /* little endian */ - #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) - #endif - X(0); - X(1); - X(2); - X(3); - X(4); - #undef X -} - -static byte * -rmd160_read( RMD160_CONTEXT *hd ) -{ - return hd->buf; -} - - - -/**************** - * Shortcut functions which puts the hash value of the supplied buffer - * into outbuf which must have a size of 20 bytes. - */ -void -rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) -{ - RMD160_CONTEXT hd; - - rmd160_init( &hd ); - rmd160_write( &hd, (byte*)buffer, length ); - rmd160_final( &hd ); - memcpy( outbuf, hd.buf, 20 ); -} - - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -static const char * -rmd160_get_info( int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ) -{ - static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, - 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; - - if( algo != 3 ) - return NULL; - - *contextsize = sizeof(RMD160_CONTEXT); - *r_asnoid = asn; - *r_asnlen = DIM(asn); - *r_mdlen = 20; - *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init; - *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; - *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; - *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; - - return "RIPEMD160"; -} - - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "RMD160 ($Revision: 1.17.2.4 $)"; - -static struct { - int class; - int version; - int value; - void (*func)(void); -} func_table[] = { - { 10, 1, 0, (void(*)(void))rmd160_get_info }, - { 11, 1, 3 }, -}; - - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - switch( *class ) { - case 11: - case 21: - case 31: - ret = &func_table[i].value; - break; - default: - ret = func_table[i].func; - break; - } - i++; - } while( what && what != *class ); - - *sequence = i; - return ret; -} - - - -#ifndef __HURD__ -#ifndef IS_MODULE -void -rmd160_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); -} -#endif -#endif diff --git a/random.c b/random.c deleted file mode 100644 index 0ae31f5f..00000000 --- a/random.c +++ /dev/null @@ -1,624 +0,0 @@ -/* random.c - A single-file translator providing random data - Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, 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 - General Public License for more details. - - You should have received a copy of the GNU 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 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "random.h" -#include "gnupg-random.h" - -/* Our control port. */ -struct trivfs_control *fsys; - -int read_blocked; /* For read and select. */ -struct condition wait; /* For read and select. */ -struct condition select_alert; /* For read and select. */ - - -/* The quality of randomness we provide. - 0: Very weak randomness based on time() and getrusage(). - No external random data is used. - 1: Pseudo random numbers based on all available real random - numbers. - 2: Strong random numbers with a somewhat guaranteed entropy. -*/ -#define DEFAULT_LEVEL 2 -static int level = DEFAULT_LEVEL; - -/* Name of file to use as seed. */ -static char *seed_file; - -/* The random bytes we collected. */ -char gatherbuf[GATHERBUFSIZE]; - -/* The current positions in gatherbuf[]. */ -int gatherrpos; -int gatherwpos; - -/* XXX Yuk Yuk. */ -#define POOLSIZE 600 - -/* Take up to length bytes from gather_random if available. If - nothing is available, sleep until something becomes available. - Must be called with global_lock held. */ -int -gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - int avail = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; - int first = GATHERBUFSIZE - gatherrpos; - int second = length - first; - - /* If level is zero, we should not block and not add anything - to the pool. */ - if( !level ) - return 0; - - /* io_read() should guarantee that there is always data available. */ - if (level == 2) - assert (avail); - - if (length > avail) - length = avail; - - if (first > length) - first = length; - (*add) (&gatherbuf[gatherrpos], first, requester); - gatherrpos = (gatherrpos + first) % GATHERBUFSIZE; - if (second > 0) - { - (*add) (&gatherbuf[gatherrpos], second, requester); - gatherrpos += second; - } - return length; -} - - -const char *argp_program_version = STANDARD_HURD_VERSION (random); - -/* This lock protects the GnuPG code. */ -static struct mutex global_lock; - -/* Trivfs hooks. */ -int trivfs_fstype = FSTYPE_MISC; -int trivfs_fsid = 0; - -int trivfs_allow_open = O_READ | O_WRITE; - -int trivfs_support_read = 1; -int trivfs_support_write = 1; -int trivfs_support_exec = 0; - -void -trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) -{ - /* Mark the node as a read-only plain file. */ - st->st_mode &= ~S_IFMT; - st->st_mode |= (S_IFCHR); - st->st_size = 0; -} - -error_t -trivfs_goaway (struct trivfs_control *cntl, int flags) -{ - update_random_seed_file (); - exit (0); -} - -/* Read data from an IO object. If offset is -1, read from the object - maintained file pointer. If the object is not seekable, offset is - ignored. The amount desired to be read is in AMOUNT. */ -error_t -trivfs_S_io_read (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - data_t *data, mach_msg_type_number_t *data_len, - loff_t offs, mach_msg_type_number_t amount) -{ - /* Deny access if they have bad credentials. */ - if (! cred) - return EOPNOTSUPP; - else if (! (cred->po->openmodes & O_READ)) - return EBADF; - - mutex_lock (&global_lock); - - if (amount > 0) - { - while (readable_pool (amount, level) == 0) - { - if (cred->po->openmodes & O_NONBLOCK) - { - mutex_unlock (&global_lock); - return EWOULDBLOCK; - } - read_blocked = 1; - if (hurd_condition_wait (&wait, &global_lock)) - { - mutex_unlock (&global_lock); - return EINTR; - } - /* See term/users.c for possible race? */ - } - - /* Possibly allocate a new buffer. */ - if (*data_len < amount) - *data = mmap (0, amount, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - - amount = read_pool ((byte *) *data, amount, level); - } - *data_len = amount; - - /* Set atime, see term/users.c */ - - mutex_unlock (&global_lock); - - return 0; -} - -/* Write data to an IO object. If offset is -1, write at the object - maintained file pointer. If the object is not seekable, offset is - ignored. The amount successfully written is returned in amount. A - given user should not have more than one outstanding io_write on an - object at a time; servers implement congestion control by delaying - responses to io_write. Servers may drop data (returning ENOBUFS) - if they receive more than one write when not prepared for it. */ -error_t -trivfs_S_io_write (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t replytype, - data_t data, - mach_msg_type_number_t datalen, - loff_t offset, - mach_msg_type_number_t *amount) -{ - int i = 0; - /* Deny access if they have bad credentials. */ - if (! cred) - return EOPNOTSUPP; - else if (! (cred->po->openmodes & O_WRITE)) - return EBADF; - - mutex_lock (&global_lock); - - while (i < datalen) - { - gatherbuf[gatherwpos] = data[i++]; - gatherwpos = (gatherwpos + 1) % GATHERBUFSIZE; - if (gatherrpos == gatherwpos) - /* Overrun. */ - gatherrpos = (gatherrpos + 1) % GATHERBUFSIZE; - } - *amount = datalen; - - if (datalen > 0 && read_blocked) - { - read_blocked = 0; - condition_broadcast (&wait); - } - - mutex_unlock (&global_lock); - return 0; -} - -/* Tell how much data can be read from the object without blocking for - a "long time" (this should be the same meaning of "long time" used - by the nonblocking flag. */ -kern_return_t -trivfs_S_io_readable (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - mach_msg_type_number_t *amount) -{ - /* Deny access if they have bad credentials. */ - if (! cred) - return EOPNOTSUPP; - else if (! (cred->po->openmodes & O_READ)) - return EBADF; - - mutex_lock (&global_lock); - - /* XXX: Before initialization, the amount depends on the amount we - want to read. Assume some medium value. */ - *amount = readable_pool (POOLSIZE/2, level); - - mutex_unlock (&global_lock); - - return 0; -} - -/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG. - Block until one of the indicated types of i/o can be done "quickly", and - return the types that are then available. ID_TAG is returned as passed; it - is just for the convenience of the user in matching up reply messages with - specific requests sent. */ -error_t -trivfs_S_io_select (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - int *type) -{ - if (!cred) - return EOPNOTSUPP; - - /* We only deal with SELECT_READ and SELECT_WRITE here. */ - if (*type & ~(SELECT_READ | SELECT_WRITE)) - return EINVAL; - - if (*type == 0) - return 0; - - mutex_lock (&global_lock); - - while (1) - { - /* XXX Before initialization, readable_pool depends on length. */ - int avail = readable_pool (POOLSIZE/2, level); - - if (avail != 0 || *type & SELECT_WRITE) - { - *type = (avail ? SELECT_READ : 0) | (*type & SELECT_WRITE); - mutex_unlock (&global_lock); - return 0; - } - - ports_interrupt_self_on_port_death (cred, reply); - read_blocked = 1; - - if (hurd_condition_wait (&select_alert, &global_lock)) - { - *type = 0; - mutex_unlock (&global_lock); - return EINTR; - } - } -} - - -/* Change current read/write offset */ -error_t -trivfs_S_io_seek (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - loff_t offs, int whence, loff_t *new_offs) -{ - if (! cred) - return EOPNOTSUPP; - - /* Not seekable. */ - return ESPIPE; -} - -/* Change the size of the file. If the size increases, new blocks are - zero-filled. After successful return, it is safe to reference mapped - areas of the file up to NEW_SIZE. */ -error_t -trivfs_S_file_set_size (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - loff_t size) -{ - if (!cred) - return EOPNOTSUPP; - - return size == 0 ? 0 : EINVAL; -} - -/* These four routines modify the O_APPEND, O_ASYNC, O_FSYNC, and - O_NONBLOCK bits for the IO object. In addition, io_get_openmodes - will tell you which of O_READ, O_WRITE, and O_EXEC the object can - be used for. The O_ASYNC bit affects icky async I/O; good async - I/O is done through io_async which is orthogonal to these calls. */ -error_t -trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - int mode) -{ - if (!cred) - return EOPNOTSUPP; - - return 0; -} - -error_t -trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - int bits) -{ - if (!cred) - return EOPNOTSUPP; - - return 0; -} - -error_t -trivfs_S_io_get_owner (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - pid_t *owner) -{ - if (!cred) - return EOPNOTSUPP; - - *owner = 0; - return 0; -} - -error_t -trivfs_S_io_mod_owner (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - pid_t owner) -{ - if (!cred) - return EOPNOTSUPP; - - return EINVAL; -} - -/* Return objects mapping the data underlying this memory object. If - the object can be read then memobjrd will be provided; if the - object can be written then memobjwr will be provided. For objects - where read data and write data are the same, these objects will be - equal, otherwise they will be disjoint. Servers are permitted to - implement io_map but not io_map_cntl. Some objects do not provide - mapping; they will set none of the ports and return an error. Such - objects can still be accessed by io_read and io_write. */ -error_t -trivfs_S_io_map(struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - mach_port_t *rdobj, - mach_msg_type_name_t *rdtype, - mach_port_t *wrobj, - mach_msg_type_name_t *wrtype) -{ - if (!cred) - return EOPNOTSUPP; - - return EINVAL; -} - - -int -random_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - extern int startup_notify_server (mach_msg_header_t *, mach_msg_header_t *); - - return (trivfs_demuxer (inp, outp) - || startup_notify_server (inp, outp)); -} - - -/* Options processing. We accept the same options on the command line - and from fsys_set_options. */ - -static const struct argp_option options[] = -{ - {"weak", 'w', 0, 0, "Output weak pseudo random data"}, - {"fast", 'f', 0, 0, "Output cheap random data fast"}, - {"secure", 's', 0, 0, "Output cryptographically secure random"}, - {"seed-file", 'S', "FILE", 0, "Use FILE to remember the seed"}, - {0} -}; - -static error_t -parse_opt (int opt, char *arg, struct argp_state *state) -{ - switch (opt) - { - default: - return ARGP_ERR_UNKNOWN; - case ARGP_KEY_INIT: - case ARGP_KEY_SUCCESS: - case ARGP_KEY_ERROR: - break; - - case 'w': - { - level = 0; - break; - } - case 'f': - { - level = 1; - break; - } - case 's': - { - level = 2; - break; - } - case 'S': - { - seed_file = strdup (arg); - set_random_seed_file (arg); - } - } - return 0; -} - -/* This will be called from libtrivfs to help construct the answer - to an fsys_get_options RPC. */ -error_t -trivfs_append_args (struct trivfs_control *fsys, - char **argz, size_t *argz_len) -{ - error_t err = 0; - char *opt; - - mutex_lock (&global_lock); - switch (level) - { - case 0: - { - opt = "--weak"; - break; - } - case 1: - { - opt = "--fast"; - break; - } - default: - { - opt = "--secure"; - break; - } - } - if (level != DEFAULT_LEVEL) - err = argz_add (argz, argz_len, opt); - - if (!err && seed_file) - { - if (asprintf (&opt, "--seed-file=%s", seed_file) < 0) - err = ENOMEM; - else - { - err = argz_add (argz, argz_len, opt); - free (opt); - } - } - mutex_unlock (&global_lock); - - return err; -} - -static struct argp random_argp = -{ options, parse_opt, 0, - "A translator providing random output." }; - -/* Setting this variable makes libtrivfs use our argp to - parse options passed in an fsys_set_options RPC. */ -struct argp *trivfs_runtime_argp = &random_argp; - -struct port_class *shutdown_notify_class; - -/* The system is going down; destroy all the extant port rights. That - will cause net channels and such to close promptly. */ -error_t -S_startup_dosync (mach_port_t handle) -{ - struct port_info *inpi = ports_lookup_port (fsys->pi.bucket, handle, - shutdown_notify_class); - - if (!inpi) - return EOPNOTSUPP; - - update_random_seed_file (); - return 0; -} - -void -sigterm_handler (int signo) -{ - update_random_seed_file (); - signal (SIGTERM, SIG_DFL); - raise (SIGTERM); -} - -void -arrange_shutdown_notification () -{ - error_t err; - mach_port_t initport, notify; - process_t procserver; - struct port_info *pi; - - shutdown_notify_class = ports_create_class (0, 0); - - signal (SIGTERM, sigterm_handler); - - /* Arrange to get notified when the system goes down, - but if we fail for some reason, just silently give up. No big deal. */ - - err = ports_create_port (shutdown_notify_class, fsys->pi.bucket, - sizeof (struct port_info), &pi); - if (err) - return; - - procserver = getproc (); - if (!procserver) - return; - - err = proc_getmsgport (procserver, 1, &initport); - mach_port_deallocate (mach_task_self (), procserver); - if (err) - return; - - notify = ports_get_send_right (pi); - ports_port_deref (pi); - startup_request_notification (initport, notify, - MACH_MSG_TYPE_MAKE_SEND, - program_invocation_short_name); - mach_port_deallocate (mach_task_self (), notify); - mach_port_deallocate (mach_task_self (), initport); -} - - -int -main (int argc, char **argv) -{ - error_t err; - mach_port_t bootstrap; - - /* Initialize the lock that will protect everything. - We must do this before argp_parse, because parse_opt (above) will - use the lock. */ - mutex_init (&global_lock); - - /* The conditions are used to implement proper read/select - behaviour. */ - condition_init (&wait); - condition_init (&select_alert); - condition_implies (&wait, &select_alert); - - /* We use the same argp for options available at startup - as for options we'll accept in an fsys_set_options RPC. */ - argp_parse (&random_argp, argc, argv, 0, 0, 0); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "Must be started as a translator"); - - /* Reply to our parent */ - err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys); - mach_port_deallocate (mach_task_self (), bootstrap); - if (err) - error (3, err, "trivfs_startup"); - - arrange_shutdown_notification (); - - /* Launch. */ - ports_manage_port_operations_multithread (fsys->pi.bucket, random_demuxer, - 10 * 1000, /* idle thread */ - 10 * 60 * 1000, /* idle server */ - 0); - return 0; -} diff --git a/random.h b/random.h deleted file mode 100644 index a38a4177..00000000 --- a/random.h +++ /dev/null @@ -1,32 +0,0 @@ -/* random.c - A single-file translator providing random data - Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, 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 - General Public License for more details. - - You should have received a copy of the GNU 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 */ - -#ifndef __RANDOM_H__ -#define __RANDOM_H__ - -/* How many random bytes to gather at most. - XXX: Should be at least POOLSIZE. */ -#define GATHERBUFSIZE 32768 - -/* The random bytes we collected. */ -extern char gatherbuf[GATHERBUFSIZE]; - -/* The current positions in gatherbuf[]. */ -extern int gatherrpos; -extern int gatherwpos; - -#endif diff --git a/random/Makefile b/random/Makefile new file mode 100644 index 00000000..9b3a95dd --- /dev/null +++ b/random/Makefile @@ -0,0 +1,29 @@ +# +# Copyright (C) 1994,95,96,97,99,2000,2001 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2, 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +dir := random +makemode := server + +CFLAGS += -D__HURD__ + +target = random +SRCS = random.c gnupg-random.c gnupg-rmd160.c +OBJS = $(SRCS:.c=.o) startup_notifyServer.o +LCLHDRS = gnupg-random.h gnupg-rmd.h gnupg-bithelp.h random.h +HURDLIBS = trivfs threads ports fshelp ihash shouldbeinlibc + +include ../Makeconf diff --git a/random/TODO b/random/TODO new file mode 100644 index 00000000..9cc57ab9 --- /dev/null +++ b/random/TODO @@ -0,0 +1,11 @@ +* read_poll uses random_poll until the pool is filled. This is ian + issue at first initialization, as this requries POOLSIZE good random (level 1 from + gather_random) even in level 0 and 1. + For now, the code is only applied to level 2. Eventually, readable_pool + should be fixed to return 0 if initialization is not done yet and not enough bytes + are available. Otherwise it enters an infinite loop. + +* Permissions? + +* Off by one error in gather_random/io_write? I can only get GATHERBUFSIZE - 1 + bytes from it. diff --git a/random/gnupg-bithelp.h b/random/gnupg-bithelp.h new file mode 100644 index 00000000..188db168 --- /dev/null +++ b/random/gnupg-bithelp.h @@ -0,0 +1,41 @@ +/* bithelp.h - Some bit manipulation helpers + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ +#ifndef G10_BITHELP_H +#define G10_BITHELP_H + + +/**************** + * Rotate a 32 bit integer by n bytes + */ +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol( u32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else + #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + + +#endif /*G10_BITHELP_H*/ diff --git a/random/gnupg-glue.h b/random/gnupg-glue.h new file mode 100644 index 00000000..cbf0a103 --- /dev/null +++ b/random/gnupg-glue.h @@ -0,0 +1,40 @@ +#ifndef __GNUPG_GLUE_H__ +#define __GNUPG_GLUE_H__ + +#include +#include + +#define SIZEOF_UNSIGNED_LONG 4 +typedef unsigned int u32; +typedef unsigned char byte; + +/* GnuPG's config.h */ +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_GETRUSAGE 1 +#define HAVE_RAND 1 + +/* GnuPG's memory.h */ +#define m_alloc malloc +#define m_alloc_secure malloc +#define m_alloc_clear(x) calloc(x, 1) +#define m_alloc_secure_clear(x) calloc(x, 1) +#define m_free free +#define m_strdup strdup + +/* GnuPG's dynaload.h */ +#define dynload_getfnc_fast_random_poll() (0) +#define dynload_getfnc_gather_random() &gather_random +int +gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ); + +/* GnuPG's miscellaneous stuff. */ +#define BUG() assert(0) +#define _(x) x +#define make_timestamp() time(0) +#define tty_printf printf +#define log_info(format, args...) printf(format , ## args) +#define log_fatal(format, args...) { printf(format , ## args) ; exit(2); } +#define DIM(v) (sizeof(v)/sizeof((v)[0])) + +#endif /* __GNUPG_GLUE_H__ */ diff --git a/random/gnupg-random.c b/random/gnupg-random.c new file mode 100644 index 00000000..8f308621 --- /dev/null +++ b/random/gnupg-random.c @@ -0,0 +1,810 @@ +/* random.c - random number generator + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + + +/**************** + * This random number generator is modelled after the one described + * in Peter Gutmann's Paper: "Software Generation of Practically + * Strong Random Numbers". + */ + +#ifndef __HURD__ +#include +#else +#include "gnupg-glue.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_GETHRTIME + #include +#endif +#ifdef HAVE_GETTIMEOFDAY + #include +#endif +#ifdef HAVE_GETRUSAGE + #include +#endif +#ifdef __MINGW32__ + #include +#endif +#ifndef __HURD__ +#include "util.h" +#endif +#ifndef __HURD__ +#include "rmd.h" +#include "ttyio.h" +#include "i18n.h" +#include "random.h" +#include "rand-internal.h" +#include "dynload.h" +#else +#include "gnupg-rmd.h" +#include "gnupg-random.h" +#endif + +#ifndef RAND_MAX /* for SunOS */ + #define RAND_MAX 32767 +#endif + + +#if SIZEOF_UNSIGNED_LONG == 8 + #define ADD_VALUE 0xa5a5a5a5a5a5a5a5 +#elif SIZEOF_UNSIGNED_LONG == 4 + #define ADD_VALUE 0xa5a5a5a5 +#else + #error weird size for an unsigned long +#endif + +#define BLOCKLEN 64 /* hash this amount of bytes */ +#define DIGESTLEN 20 /* into a digest of this length (rmd160) */ +/* poolblocks is the number of digests which make up the pool + * and poolsize must be a multiple of the digest length + * to make the AND operations faster, the size should also be + * a multiple of ulong + */ +#define POOLBLOCKS 30 +#define POOLSIZE (POOLBLOCKS*DIGESTLEN) +#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) + #error Please make sure that poolsize is a multiple of ulong +#endif +#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) + + +static int is_initialized; +#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) +static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */ +static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */ +static size_t pool_readpos; +static size_t pool_writepos; +static int pool_filled; +static int pool_balance; +static int just_mixed; +static int did_initial_extra_seeding; +static char *seed_file_name; +static int allow_seed_file_update; + +static int secure_alloc; +static int quick_test; +static int faked_rng; + + +#ifndef __HURD__ +static void read_pool( byte *buffer, size_t length, int level ); +#else +int read_pool( byte *buffer, size_t length, int level ); +#endif +static void add_randomness( const void *buffer, size_t length, int source ); +static void random_poll(void); +#ifndef __HURD__ +static void read_random_source( int requester, size_t length, int level); +#else +static int read_random_source( int requester, size_t length, int level); +#endif +static int gather_faked( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ); + +static struct { + ulong mixrnd; + ulong mixkey; + ulong slowpolls; + ulong fastpolls; + ulong getbytes1; + ulong ngetbytes1; + ulong getbytes2; + ulong ngetbytes2; + ulong addbytes; + ulong naddbytes; +} rndstats; + +static void +initialize(void) +{ + /* The data buffer is allocated somewhat larger, so that + * we can use this extra space (which is allocated in secure memory) + * as a temporary hash buffer */ + rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) + : m_alloc_clear(POOLSIZE+BLOCKLEN); + keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) + : m_alloc_clear(POOLSIZE+BLOCKLEN); + is_initialized = 1; +#ifndef __HURD__ + cipher_modules_constructor(); +#endif +} + +static void +burn_stack (int bytes) +{ + char buf[128]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + +void +random_dump_stats() +{ + fprintf(stderr, + "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" + " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n", + POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, + rndstats.naddbytes, rndstats.addbytes, + rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, + rndstats.ngetbytes2, rndstats.getbytes2 ); +} + +void +secure_random_alloc() +{ + secure_alloc = 1; +} + + +int +quick_random_gen( int onoff ) +{ + int last; + + read_random_source(0,0,0); /* init */ + last = quick_test; + if( onoff != -1 ) + quick_test = onoff; + return faked_rng? 1 : last; +} + + +/**************** + * Fill the buffer with LENGTH bytes of cryptographically strong + * random bytes. level 0 is not very strong, 1 is strong enough + * for most usage, 2 is good for key generation stuff but may be very slow. + */ +void +randomize_buffer( byte *buffer, size_t length, int level ) +{ + char *p = get_random_bits( length*8, level, 1 ); + memcpy( buffer, p, length ); + m_free(p); +} + + +int +random_is_faked() +{ + if( !is_initialized ) + initialize(); + return faked_rng || quick_test; +} + +/**************** + * Return a pointer to a randomized buffer of level 0 and LENGTH bits + * caller must free the buffer. + * Note: The returned value is rounded up to bytes. + */ +byte * +get_random_bits( size_t nbits, int level, int secure ) +{ + byte *buf, *p; + size_t nbytes = (nbits+7)/8; + + if( quick_test && level > 1 ) + level = 1; + MASK_LEVEL(level); + if( level == 1 ) { + rndstats.getbytes1 += nbytes; + rndstats.ngetbytes1++; + } + else if( level >= 2 ) { + rndstats.getbytes2 += nbytes; + rndstats.ngetbytes2++; + } + + buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes ); + for( p = buf; nbytes > 0; ) { + size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes; +#ifdef __HURD__ + n = +#endif + read_pool( p, n, level ); + nbytes -= n; + p += n; + + } + return buf; +} + + +/**************** + * Mix the pool + */ +static void +mix_pool(byte *pool) +{ + char *hashbuf = pool + POOLSIZE; + char *p, *pend; + int i, n; + RMD160_CONTEXT md; + + rmd160_init( &md ); + #if DIGESTLEN != 20 + #error must have a digest length of 20 for ripe-md-160 + #endif + /* loop over the pool */ + pend = pool + POOLSIZE; + memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); + memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); + rmd160_mixblock( &md, hashbuf); + memcpy(pool, hashbuf, 20 ); + + p = pool; + for( n=1; n < POOLBLOCKS; n++ ) { + memcpy(hashbuf, p, DIGESTLEN ); + + p += DIGESTLEN; + if( p+DIGESTLEN+BLOCKLEN < pend ) + memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); + else { + char *pp = p+DIGESTLEN; + for(i=DIGESTLEN; i < BLOCKLEN; i++ ) { + if( pp >= pend ) + pp = pool; + hashbuf[i] = *pp++; + } + } + + rmd160_mixblock( &md, hashbuf); + memcpy(p, hashbuf, 20 ); + } + burn_stack (200); /* for the rmd160_mixblock() */ +} + + +void +set_random_seed_file( const char *name ) +{ + if( seed_file_name ) + BUG(); + seed_file_name = m_strdup( name ); +} + +/**************** + * Read in a seed form the random_seed file + * and return true if this was successful + */ +static int +read_seed_file() +{ + int fd; + struct stat sb; + unsigned char buffer[POOLSIZE]; + int n; + + if( !seed_file_name ) + return 0; + + #ifdef HAVE_DOSISH_SYSTEM + fd = open( seed_file_name, O_RDONLY | O_BINARY ); + #else + fd = open( seed_file_name, O_RDONLY ); + #endif + if( fd == -1 && errno == ENOENT) { + allow_seed_file_update = 1; + return 0; + } + + if( fd == -1 ) { + log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); + return 0; + } + if( fstat( fd, &sb ) ) { + log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); + close(fd); + return 0; + } + if( !S_ISREG(sb.st_mode) ) { + log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); + close(fd); + return 0; + } + if( !sb.st_size ) { + log_info(_("note: random_seed file is empty\n") ); + close(fd); + allow_seed_file_update = 1; + return 0; + } + if( sb.st_size != POOLSIZE ) { + log_info(_("warning: invalid size of random_seed file - not used\n") ); + close(fd); + return 0; + } + do { + n = read( fd, buffer, POOLSIZE ); + } while( n == -1 && errno == EINTR ); + if( n != POOLSIZE ) { + log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); + close(fd); + return 0; + } + + close(fd); + + add_randomness( buffer, POOLSIZE, 0 ); + /* add some minor entropy to the pool now (this will also force a mixing) */ + { pid_t x = getpid(); + add_randomness( &x, sizeof(x), 0 ); + } + { time_t x = time(NULL); + add_randomness( &x, sizeof(x), 0 ); + } + { clock_t x = clock(); + add_randomness( &x, sizeof(x), 0 ); + } + /* And read a few bytes from our entropy source. By using + * a level of 0 this will not block and might not return anything + * with some entropy drivers, however the rndlinux driver will use + * /dev/urandom and return some stuff - Do not read to much as we + * want to be friendly to the scare system entropy resource. */ + read_random_source( 0, 16, 0 ); + + allow_seed_file_update = 1; + return 1; +} + +void +update_random_seed_file() +{ + ulong *sp, *dp; + int fd, i; + + if( !seed_file_name || !is_initialized || !pool_filled ) + return; + if( !allow_seed_file_update ) { + log_info(_("note: random_seed file not updated\n")); + return; + } + + + /* copy the entropy pool to a scratch pool and mix both of them */ + for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; + i < POOLWORDS; i++, dp++, sp++ ) { + *dp = *sp + ADD_VALUE; + } + mix_pool(rndpool); rndstats.mixrnd++; + mix_pool(keypool); rndstats.mixkey++; + + #ifdef HAVE_DOSISH_SYSTEM + fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, + S_IRUSR|S_IWUSR ); + #else + fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); + #endif + if( fd == -1 ) { + log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); + return; + } + do { + i = write( fd, keypool, POOLSIZE ); + } while( i == -1 && errno == EINTR ); + if( i != POOLSIZE ) { + log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); + } + if( close(fd) ) + log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); +} + +#ifdef __HURD__ +int readable_pool( size_t length, int level ) +{ + size_t needed = 0; + size_t my_balance = pool_balance; + size_t available = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; + + if (length > POOLSIZE) + length = POOLSIZE; + + if (level < 2) + return length; + + if( !pool_filled ) { + if( read_seed_file() ) + pool_filled = 1; + } + + if (!did_initial_extra_seeding) + { + /* Take account for initial extra seeding. */ + needed = length; + if (needed < POOLSIZE/2) + needed = POOLSIZE/2; + my_balance = needed; + + if (!pool_filled && pool_writepos + needed < POOLSIZE) + { + /* If the pool is not filled yet, we couldn't read the seed + file. Too bad. We will now have to take account for so many + random_poll()s as fit into the remaining pool. */ + + needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); + } + } + else + { + if (!pool_filled) + needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); + } + + /* NEEDED contains the bytes needed for initialization, MY_BALANCE the resulting + available bytes. */ + if (available < needed) + return 0; + return available + my_balance - needed; +} +#endif + +#ifndef __HURD__ +static void +#else +int +#endif +read_pool( byte *buffer, size_t length, int level ) +{ + int i; + ulong *sp, *dp; + + if( length > POOLSIZE ) { +#ifndef __HURD__ + log_fatal(_("too many random bits requested; the limit is %d\n"), + POOLSIZE*8-1 ); +#else + length = POOLSIZE; +#endif + } + + if( !pool_filled ) { + if( read_seed_file() ) + pool_filled = 1; + } + + /* For level 2 quality (key generation) we alwas make + * sure that the pool has been seeded enough initially */ + if( level == 2 && !did_initial_extra_seeding ) { + size_t needed; + + pool_balance = 0; + needed = length - pool_balance; + if( needed < POOLSIZE/2 ) + needed = POOLSIZE/2; + else if( needed > POOLSIZE ) + BUG(); +#ifdef __HURD__ + needed = +#endif + read_random_source( 3, needed, 2 ); +#ifdef __HURD__ + if (! needed) + return 0; + /* XXX This will succeed with needed < POOLSIZE/2 even. But + erroring out will waste the random we already got. */ +#endif + pool_balance += needed; + did_initial_extra_seeding=1; + } + + /* for level 2 make sure that there is enough random in the pool */ + if( level == 2 && pool_balance < length ) { + size_t needed; + + if( pool_balance < 0 ) + pool_balance = 0; + needed = length - pool_balance; + if( needed > POOLSIZE ) + BUG(); +#ifdef __HURD__ + needed = +#endif + read_random_source( 3, needed, 2 ); + pool_balance += needed; + } + +#ifdef __HURD__ + /* XXX This makes level 0 and 1 worse than needed at first start up. */ + if (level == 2) +#endif + /* make sure the pool is filled */ + while( !pool_filled ) + random_poll(); + + /* do always a fast random poll */ + fast_random_poll(); + + if( !level ) { /* no need for cryptographic strong random */ + /* create a new pool */ + for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; + i < POOLWORDS; i++, dp++, sp++ ) + *dp = *sp + ADD_VALUE; + /* must mix both pools */ + mix_pool(rndpool); rndstats.mixrnd++; + mix_pool(keypool); rndstats.mixkey++; + memcpy( buffer, keypool, length ); + return length; + } + else { +#ifdef __HURD__ + int amount; +#endif + /* mix the pool (if add_randomness() didn't it) */ + if( !just_mixed ) { + mix_pool(rndpool); + rndstats.mixrnd++; + } + /* create a new pool */ + for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; + i < POOLWORDS; i++, dp++, sp++ ) + *dp = *sp + ADD_VALUE; + /* and mix both pools */ + mix_pool(rndpool); rndstats.mixrnd++; + mix_pool(keypool); rndstats.mixkey++; + /* read the required data + * we use a readpoiter to read from a different postion each + * time */ +#ifdef __HURD__ + if (level == 2 && length > pool_balance) + length = pool_balance; + amount = length; +#endif + while( length-- ) { + *buffer++ = keypool[pool_readpos++]; + if( pool_readpos >= POOLSIZE ) + pool_readpos = 0; + pool_balance--; + } + if( pool_balance < 0 ) + pool_balance = 0; + /* and clear the keypool */ + memset( keypool, 0, POOLSIZE ); +#ifdef __HURD__ + return amount; +#endif + } +} + + +/**************** + * Add LENGTH bytes of randomness from buffer to the pool. + * source may be used to specify the randomness source. + * Source is: + * 0 - used ony for initialization + * 1 - fast random poll function + * 2 - normal poll function + * 3 - used when level 2 random quality has been requested + * to do an extra pool seed. + */ +static void +add_randomness( const void *buffer, size_t length, int source ) +{ + const byte *p = buffer; + + if( !is_initialized ) + initialize(); + rndstats.addbytes += length; + rndstats.naddbytes++; + while( length-- ) { + rndpool[pool_writepos++] = *p++; + if( pool_writepos >= POOLSIZE ) { + if( source > 1 ) + pool_filled = 1; + pool_writepos = 0; + mix_pool(rndpool); rndstats.mixrnd++; + just_mixed = !length; + } + } +} + + + +static void +random_poll() +{ + rndstats.slowpolls++; + read_random_source( 2, POOLSIZE/5, 1 ); +} + + +void +fast_random_poll() +{ + static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL; + static int initialized = 0; + + rndstats.fastpolls++; + if( !initialized ) { + if( !is_initialized ) + initialize(); + initialized = 1; + fnc = dynload_getfnc_fast_random_poll(); + } + if( fnc ) { + (*fnc)( add_randomness, 1 ); + return; + } + + /* fall back to the generic function */ + #if HAVE_GETHRTIME + { hrtime_t tv; + tv = gethrtime(); + add_randomness( &tv, sizeof(tv), 1 ); + } + #elif HAVE_GETTIMEOFDAY + { struct timeval tv; + if( gettimeofday( &tv, NULL ) ) + BUG(); + add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); + add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); + } + #elif HAVE_CLOCK_GETTIME + { struct timespec tv; + if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) + BUG(); + add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); + add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); + } + #else /* use times */ + #ifndef HAVE_DOSISH_SYSTEM + { struct tms buf; + times( &buf ); + add_randomness( &buf, sizeof buf, 1 ); + } + #endif + #endif + #ifdef HAVE_GETRUSAGE + #ifndef RUSAGE_SELF + #ifdef __GCC__ + #warning There is no RUSAGE_SELF on this system + #endif + #else + { struct rusage buf; + /* QNX/Neutrino does return ENOSYS - so we just ignore it and + * add whatever is in buf. In a chroot environment it might not + * work at all (i.e. because /proc/ is not accessible), so we better + * ognore all error codes and hope for the best + */ + getrusage( RUSAGE_SELF, &buf ); + + add_randomness( &buf, sizeof buf, 1 ); + memset( &buf, 0, sizeof buf ); + } + #endif + #endif + /* time and clock are availabe on all systems - so + * we better do it just in case one of the above functions + * didn't work */ + { time_t x = time(NULL); + add_randomness( &x, sizeof(x), 1 ); + } + { clock_t x = clock(); + add_randomness( &x, sizeof(x), 1 ); + } +} + + +#ifndef __HURD__ +static void +#else +static int +#endif +read_random_source( int requester, size_t length, int level ) +{ + static int (*fnc)(void (*)(const void*, size_t, int), int, + size_t, int) = NULL; +#ifdef __HURD__ + int got; +#endif + if( !fnc ) { + if( !is_initialized ) + initialize(); + fnc = dynload_getfnc_gather_random(); + if( !fnc ) { + faked_rng = 1; + fnc = gather_faked; + } + if( !requester && !length && !level ) +#ifndef __HURD__ + return; /* init only */ +#else + return 0; +#endif + } +#ifndef __HURD__ + if( (*fnc)( add_randomness, requester, length, level ) < 0 ) + log_fatal("No way to gather entropy for the RNG\n"); +#else + got = (*fnc)( add_randomness, requester, length, level ); + if (got < 0) + log_fatal("No way to gather entropy for the RNG\n"); + return got; +#endif +} + + +static int +gather_faked( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) +{ + static int initialized=0; + size_t n; + char *buffer, *p; + + if( !initialized ) { + log_info(_("WARNING: using insecure random number generator!!\n")); + tty_printf(_("The random number generator is only a kludge to let\n" + "it run - it is in no way a strong RNG!\n\n" + "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); + initialized=1; + #ifdef HAVE_RAND + srand(make_timestamp()*getpid()); + #else + srandom(make_timestamp()*getpid()); + #endif + } + printf("WAITING FOR %i bytes.\n", length); + p = buffer = m_alloc( length ); + n = length; + #ifdef HAVE_RAND + while( n-- ) + *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); + #else + while( n-- ) + *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); + #endif + add_randomness( buffer, length, requester ); + m_free(buffer); + return 0; /* okay */ +} + diff --git a/random/gnupg-random.h b/random/gnupg-random.h new file mode 100644 index 00000000..ee18febc --- /dev/null +++ b/random/gnupg-random.h @@ -0,0 +1,47 @@ +/* random.h - random functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ +#ifndef G10_RANDOM_H +#define G10_RANDOM_H + +#ifndef __HURD__ +#include "types.h" +#else +#include "gnupg-glue.h" +int read_pool (byte *, size_t, int); +int readable_pool (size_t, int); +#endif + +/*-- random.c --*/ +void random_dump_stats(void); +void secure_random_alloc(void); +void set_random_seed_file(const char *); +void update_random_seed_file(void); +int quick_random_gen( int onoff ); +int random_is_faked(void); +void randomize_buffer( byte *buffer, size_t length, int level ); +byte *get_random_bits( size_t nbits, int level, int secure ); +void fast_random_poll( void ); + +/*-- rndw32.c --*/ +#ifdef USE_STATIC_RNDW32 +void rndw32_set_dll_name( const char *name ); +#endif + +#endif /*G10_RANDOM_H*/ diff --git a/random/gnupg-rmd.h b/random/gnupg-rmd.h new file mode 100644 index 00000000..2446fc7d --- /dev/null +++ b/random/gnupg-rmd.h @@ -0,0 +1,38 @@ +/* rmd.h - RIPE-MD hash functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ +#ifndef G10_RMD_H +#define G10_RMD_H + +#ifdef __HURD__ +#include "gnupg-glue.h" +#endif + +/* we need this here because random.c must have direct access */ +typedef struct { + u32 h0,h1,h2,h3,h4; + u32 nblocks; + byte buf[64]; + int count; +} RMD160_CONTEXT; + +void rmd160_init( RMD160_CONTEXT *hd ); +void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); + +#endif /*G10_RMD_H*/ diff --git a/random/gnupg-rmd160.c b/random/gnupg-rmd160.c new file mode 100644 index 00000000..66107685 --- /dev/null +++ b/random/gnupg-rmd160.c @@ -0,0 +1,656 @@ +/* rmd160.c - RIPE-MD160 + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + +#ifndef __HURD__ +#include +#endif +#include +#include +#include +#include +#ifndef __HURD__ +#include "util.h" +#include "memory.h" +#include "rmd.h" +#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ +#include "dynload.h" + +#include "bithelp.h" +#else +#include "gnupg-rmd.h" +#include "gnupg-bithelp.h" +#endif + + +/********************************* + * RIPEMD-160 is not patented, see (as of 25.10.97) + * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html + * Note that the code uses Little Endian byteorder, which is good for + * 386 etc, but we must add some conversion when used on a big endian box. + * + * + * Pseudo-code for RIPEMD-160 + * + * RIPEMD-160 is an iterative hash function that operates on 32-bit words. + * The round function takes as input a 5-word chaining variable and a 16-word + * message block and maps this to a new chaining variable. All operations are + * defined on 32-bit words. Padding is identical to that of MD4. + * + * + * RIPEMD-160: definitions + * + * + * nonlinear functions at bit level: exor, mux, -, mux, - + * + * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) + * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) + * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) + * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) + * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) + * + * + * added constants (hexadecimal) + * + * K(j) = 0x00000000 (0 <= j <= 15) + * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) + * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) + * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) + * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) + * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) + * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) + * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) + * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) + * K'(j) = 0x00000000 (64 <= j <= 79) + * + * + * selection of message word + * + * r(j) = j (0 <= j <= 15) + * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 + * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 + * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 + * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 + * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 + * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 + * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 + * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + * + * + * amount for rotate left (rol) + * + * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 + * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 + * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 + * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 + * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 + * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 + * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 + * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 + * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + * + * + * initial value (hexadecimal) + * + * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; + * h4 = 0xC3D2E1F0; + * + * + * RIPEMD-160: pseudo-code + * + * It is assumed that the message after padding consists of t 16-word blocks + * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. + * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left + * shift (rotate) over s positions. + * + * + * for i := 0 to t-1 { + * A := h0; B := h1; C := h2; D = h3; E = h4; + * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; + * for j := 0 to 79 { + * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; + * A := E; E := D; D := rol_10(C); C := B; B := T; + * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] + [+] K'(j)) [+] E'; + * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; + * } + * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; + * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; + * } + */ + +/* Some examples: + * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 + * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe + * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc + * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 + * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc + * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b + * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 + * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb + * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 + */ + +static void +burn_stack (int bytes) +{ + char buf[150]; + + memset (buf, 0, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + burn_stack (bytes); +} + + + +void +rmd160_init( RMD160_CONTEXT *hd ) +{ + hd->h0 = 0x67452301; + hd->h1 = 0xEFCDAB89; + hd->h2 = 0x98BADCFE; + hd->h3 = 0x10325476; + hd->h4 = 0xC3D2E1F0; + hd->nblocks = 0; + hd->count = 0; +} + + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void +transform( RMD160_CONTEXT *hd, byte *data ) +{ + u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; + #ifdef BIG_ENDIAN_HOST + u32 x[16]; + { int i; + byte *p2, *p1; + for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } + #else + #if 0 + u32 *x =(u32*)data; + #else + /* this version is better because it is always aligned; + * The performance penalty on a 586-100 is about 6% which + * is acceptable - because the data is more local it might + * also be possible that this is faster on some machines. + * This function (when compiled with -02 on gcc 2.7.2) + * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; + * [measured with a 4MB data and "gpgm --print-md rmd160"] */ + u32 x[16]; + memcpy( x, data, 64 ); + #endif + #endif + + +#define K0 0x00000000 +#define K1 0x5A827999 +#define K2 0x6ED9EBA1 +#define K3 0x8F1BBCDC +#define K4 0xA953FD4E +#define KK0 0x50A28BE6 +#define KK1 0x5C4DD124 +#define KK2 0x6D703EF3 +#define KK3 0x7A6D76E9 +#define KK4 0x00000000 +#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) +#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) +#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) +#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) +#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) +#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ + a = rol(t,s) + e; \ + c = rol(c,10); \ + } while(0) + + /* left lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F0, K0, 0, 11 ); + R( e, a, b, c, d, F0, K0, 1, 14 ); + R( d, e, a, b, c, F0, K0, 2, 15 ); + R( c, d, e, a, b, F0, K0, 3, 12 ); + R( b, c, d, e, a, F0, K0, 4, 5 ); + R( a, b, c, d, e, F0, K0, 5, 8 ); + R( e, a, b, c, d, F0, K0, 6, 7 ); + R( d, e, a, b, c, F0, K0, 7, 9 ); + R( c, d, e, a, b, F0, K0, 8, 11 ); + R( b, c, d, e, a, F0, K0, 9, 13 ); + R( a, b, c, d, e, F0, K0, 10, 14 ); + R( e, a, b, c, d, F0, K0, 11, 15 ); + R( d, e, a, b, c, F0, K0, 12, 6 ); + R( c, d, e, a, b, F0, K0, 13, 7 ); + R( b, c, d, e, a, F0, K0, 14, 9 ); + R( a, b, c, d, e, F0, K0, 15, 8 ); + R( e, a, b, c, d, F1, K1, 7, 7 ); + R( d, e, a, b, c, F1, K1, 4, 6 ); + R( c, d, e, a, b, F1, K1, 13, 8 ); + R( b, c, d, e, a, F1, K1, 1, 13 ); + R( a, b, c, d, e, F1, K1, 10, 11 ); + R( e, a, b, c, d, F1, K1, 6, 9 ); + R( d, e, a, b, c, F1, K1, 15, 7 ); + R( c, d, e, a, b, F1, K1, 3, 15 ); + R( b, c, d, e, a, F1, K1, 12, 7 ); + R( a, b, c, d, e, F1, K1, 0, 12 ); + R( e, a, b, c, d, F1, K1, 9, 15 ); + R( d, e, a, b, c, F1, K1, 5, 9 ); + R( c, d, e, a, b, F1, K1, 2, 11 ); + R( b, c, d, e, a, F1, K1, 14, 7 ); + R( a, b, c, d, e, F1, K1, 11, 13 ); + R( e, a, b, c, d, F1, K1, 8, 12 ); + R( d, e, a, b, c, F2, K2, 3, 11 ); + R( c, d, e, a, b, F2, K2, 10, 13 ); + R( b, c, d, e, a, F2, K2, 14, 6 ); + R( a, b, c, d, e, F2, K2, 4, 7 ); + R( e, a, b, c, d, F2, K2, 9, 14 ); + R( d, e, a, b, c, F2, K2, 15, 9 ); + R( c, d, e, a, b, F2, K2, 8, 13 ); + R( b, c, d, e, a, F2, K2, 1, 15 ); + R( a, b, c, d, e, F2, K2, 2, 14 ); + R( e, a, b, c, d, F2, K2, 7, 8 ); + R( d, e, a, b, c, F2, K2, 0, 13 ); + R( c, d, e, a, b, F2, K2, 6, 6 ); + R( b, c, d, e, a, F2, K2, 13, 5 ); + R( a, b, c, d, e, F2, K2, 11, 12 ); + R( e, a, b, c, d, F2, K2, 5, 7 ); + R( d, e, a, b, c, F2, K2, 12, 5 ); + R( c, d, e, a, b, F3, K3, 1, 11 ); + R( b, c, d, e, a, F3, K3, 9, 12 ); + R( a, b, c, d, e, F3, K3, 11, 14 ); + R( e, a, b, c, d, F3, K3, 10, 15 ); + R( d, e, a, b, c, F3, K3, 0, 14 ); + R( c, d, e, a, b, F3, K3, 8, 15 ); + R( b, c, d, e, a, F3, K3, 12, 9 ); + R( a, b, c, d, e, F3, K3, 4, 8 ); + R( e, a, b, c, d, F3, K3, 13, 9 ); + R( d, e, a, b, c, F3, K3, 3, 14 ); + R( c, d, e, a, b, F3, K3, 7, 5 ); + R( b, c, d, e, a, F3, K3, 15, 6 ); + R( a, b, c, d, e, F3, K3, 14, 8 ); + R( e, a, b, c, d, F3, K3, 5, 6 ); + R( d, e, a, b, c, F3, K3, 6, 5 ); + R( c, d, e, a, b, F3, K3, 2, 12 ); + R( b, c, d, e, a, F4, K4, 4, 9 ); + R( a, b, c, d, e, F4, K4, 0, 15 ); + R( e, a, b, c, d, F4, K4, 5, 5 ); + R( d, e, a, b, c, F4, K4, 9, 11 ); + R( c, d, e, a, b, F4, K4, 7, 6 ); + R( b, c, d, e, a, F4, K4, 12, 8 ); + R( a, b, c, d, e, F4, K4, 2, 13 ); + R( e, a, b, c, d, F4, K4, 10, 12 ); + R( d, e, a, b, c, F4, K4, 14, 5 ); + R( c, d, e, a, b, F4, K4, 1, 12 ); + R( b, c, d, e, a, F4, K4, 3, 13 ); + R( a, b, c, d, e, F4, K4, 8, 14 ); + R( e, a, b, c, d, F4, K4, 11, 11 ); + R( d, e, a, b, c, F4, K4, 6, 8 ); + R( c, d, e, a, b, F4, K4, 15, 5 ); + R( b, c, d, e, a, F4, K4, 13, 6 ); + + aa = a; bb = b; cc = c; dd = d; ee = e; + + /* right lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F4, KK0, 5, 8); + R( e, a, b, c, d, F4, KK0, 14, 9); + R( d, e, a, b, c, F4, KK0, 7, 9); + R( c, d, e, a, b, F4, KK0, 0, 11); + R( b, c, d, e, a, F4, KK0, 9, 13); + R( a, b, c, d, e, F4, KK0, 2, 15); + R( e, a, b, c, d, F4, KK0, 11, 15); + R( d, e, a, b, c, F4, KK0, 4, 5); + R( c, d, e, a, b, F4, KK0, 13, 7); + R( b, c, d, e, a, F4, KK0, 6, 7); + R( a, b, c, d, e, F4, KK0, 15, 8); + R( e, a, b, c, d, F4, KK0, 8, 11); + R( d, e, a, b, c, F4, KK0, 1, 14); + R( c, d, e, a, b, F4, KK0, 10, 14); + R( b, c, d, e, a, F4, KK0, 3, 12); + R( a, b, c, d, e, F4, KK0, 12, 6); + R( e, a, b, c, d, F3, KK1, 6, 9); + R( d, e, a, b, c, F3, KK1, 11, 13); + R( c, d, e, a, b, F3, KK1, 3, 15); + R( b, c, d, e, a, F3, KK1, 7, 7); + R( a, b, c, d, e, F3, KK1, 0, 12); + R( e, a, b, c, d, F3, KK1, 13, 8); + R( d, e, a, b, c, F3, KK1, 5, 9); + R( c, d, e, a, b, F3, KK1, 10, 11); + R( b, c, d, e, a, F3, KK1, 14, 7); + R( a, b, c, d, e, F3, KK1, 15, 7); + R( e, a, b, c, d, F3, KK1, 8, 12); + R( d, e, a, b, c, F3, KK1, 12, 7); + R( c, d, e, a, b, F3, KK1, 4, 6); + R( b, c, d, e, a, F3, KK1, 9, 15); + R( a, b, c, d, e, F3, KK1, 1, 13); + R( e, a, b, c, d, F3, KK1, 2, 11); + R( d, e, a, b, c, F2, KK2, 15, 9); + R( c, d, e, a, b, F2, KK2, 5, 7); + R( b, c, d, e, a, F2, KK2, 1, 15); + R( a, b, c, d, e, F2, KK2, 3, 11); + R( e, a, b, c, d, F2, KK2, 7, 8); + R( d, e, a, b, c, F2, KK2, 14, 6); + R( c, d, e, a, b, F2, KK2, 6, 6); + R( b, c, d, e, a, F2, KK2, 9, 14); + R( a, b, c, d, e, F2, KK2, 11, 12); + R( e, a, b, c, d, F2, KK2, 8, 13); + R( d, e, a, b, c, F2, KK2, 12, 5); + R( c, d, e, a, b, F2, KK2, 2, 14); + R( b, c, d, e, a, F2, KK2, 10, 13); + R( a, b, c, d, e, F2, KK2, 0, 13); + R( e, a, b, c, d, F2, KK2, 4, 7); + R( d, e, a, b, c, F2, KK2, 13, 5); + R( c, d, e, a, b, F1, KK3, 8, 15); + R( b, c, d, e, a, F1, KK3, 6, 5); + R( a, b, c, d, e, F1, KK3, 4, 8); + R( e, a, b, c, d, F1, KK3, 1, 11); + R( d, e, a, b, c, F1, KK3, 3, 14); + R( c, d, e, a, b, F1, KK3, 11, 14); + R( b, c, d, e, a, F1, KK3, 15, 6); + R( a, b, c, d, e, F1, KK3, 0, 14); + R( e, a, b, c, d, F1, KK3, 5, 6); + R( d, e, a, b, c, F1, KK3, 12, 9); + R( c, d, e, a, b, F1, KK3, 2, 12); + R( b, c, d, e, a, F1, KK3, 13, 9); + R( a, b, c, d, e, F1, KK3, 9, 12); + R( e, a, b, c, d, F1, KK3, 7, 5); + R( d, e, a, b, c, F1, KK3, 10, 15); + R( c, d, e, a, b, F1, KK3, 14, 8); + R( b, c, d, e, a, F0, KK4, 12, 8); + R( a, b, c, d, e, F0, KK4, 15, 5); + R( e, a, b, c, d, F0, KK4, 10, 12); + R( d, e, a, b, c, F0, KK4, 4, 9); + R( c, d, e, a, b, F0, KK4, 1, 12); + R( b, c, d, e, a, F0, KK4, 5, 5); + R( a, b, c, d, e, F0, KK4, 8, 14); + R( e, a, b, c, d, F0, KK4, 7, 6); + R( d, e, a, b, c, F0, KK4, 6, 8); + R( c, d, e, a, b, F0, KK4, 2, 13); + R( b, c, d, e, a, F0, KK4, 13, 6); + R( a, b, c, d, e, F0, KK4, 14, 5); + R( e, a, b, c, d, F0, KK4, 0, 15); + R( d, e, a, b, c, F0, KK4, 3, 13); + R( c, d, e, a, b, F0, KK4, 9, 11); + R( b, c, d, e, a, F0, KK4, 11, 11); + + + t = hd->h1 + d + cc; + hd->h1 = hd->h2 + e + dd; + hd->h2 = hd->h3 + a + ee; + hd->h3 = hd->h4 + b + aa; + hd->h4 = hd->h0 + c + bb; + hd->h0 = t; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) +{ + if( hd->count == 64 ) { /* flush the buffer */ + transform( hd, hd->buf ); + burn_stack (108+5*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + rmd160_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + burn_stack (108+5*sizeof(void*)); + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + +/**************** + * Apply the rmd160 transform function on the buffer which must have + * a length 64 bytes. Do not use this function together with the + * other functions, use rmd160_init to initialize internal variables. + * Returns: 16 bytes in buffer with the mixed contentes of buffer. + */ +void +rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) +{ + char *p = buffer; + transform( hd, buffer ); + #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) + X(0); + X(1); + X(2); + X(3); + X(4); + #undef X +} + + +/* The routine terminates the computation + */ + +static void +rmd160_final( RMD160_CONTEXT *hd ) +{ + u32 t, msb, lsb; + byte *p; + + rmd160_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else { /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + rmd160_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + burn_stack (108+5*sizeof(void*)); + + p = hd->buf; + #ifdef BIG_ENDIAN_HOST + #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ + *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) + #else /* little endian */ + #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) + #endif + X(0); + X(1); + X(2); + X(3); + X(4); + #undef X +} + +static byte * +rmd160_read( RMD160_CONTEXT *hd ) +{ + return hd->buf; +} + + + +/**************** + * Shortcut functions which puts the hash value of the supplied buffer + * into outbuf which must have a size of 20 bytes. + */ +void +rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) +{ + RMD160_CONTEXT hd; + + rmd160_init( &hd ); + rmd160_write( &hd, (byte*)buffer, length ); + rmd160_final( &hd ); + memcpy( outbuf, hd.buf, 20 ); +} + + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + */ +static const char * +rmd160_get_info( int algo, size_t *contextsize, + byte **r_asnoid, int *r_asnlen, int *r_mdlen, + void (**r_init)( void *c ), + void (**r_write)( void *c, byte *buf, size_t nbytes ), + void (**r_final)( void *c ), + byte *(**r_read)( void *c ) + ) +{ + static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + + if( algo != 3 ) + return NULL; + + *contextsize = sizeof(RMD160_CONTEXT); + *r_asnoid = asn; + *r_asnlen = DIM(asn); + *r_mdlen = 20; + *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init; + *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; + *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; + *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; + + return "RIPEMD160"; +} + + +#ifndef IS_MODULE +static +#endif +const char * const gnupgext_version = "RMD160 ($Revision: 1.17.2.4 $)"; + +static struct { + int class; + int version; + int value; + void (*func)(void); +} func_table[] = { + { 10, 1, 0, (void(*)(void))rmd160_get_info }, + { 11, 1, 3 }, +}; + + +#ifndef IS_MODULE +static +#endif +void * +gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) +{ + void *ret; + int i = *sequence; + + do { + if( i >= DIM(func_table) || i < 0 ) { + return NULL; + } + *class = func_table[i].class; + *vers = func_table[i].version; + switch( *class ) { + case 11: + case 21: + case 31: + ret = &func_table[i].value; + break; + default: + ret = func_table[i].func; + break; + } + i++; + } while( what && what != *class ); + + *sequence = i; + return ret; +} + + + +#ifndef __HURD__ +#ifndef IS_MODULE +void +rmd160_constructor(void) +{ + register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); +} +#endif +#endif diff --git a/random/random.c b/random/random.c new file mode 100644 index 00000000..0ae31f5f --- /dev/null +++ b/random/random.c @@ -0,0 +1,624 @@ +/* random.c - A single-file translator providing random data + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, 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 + General Public License for more details. + + You should have received a copy of the GNU 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 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "random.h" +#include "gnupg-random.h" + +/* Our control port. */ +struct trivfs_control *fsys; + +int read_blocked; /* For read and select. */ +struct condition wait; /* For read and select. */ +struct condition select_alert; /* For read and select. */ + + +/* The quality of randomness we provide. + 0: Very weak randomness based on time() and getrusage(). + No external random data is used. + 1: Pseudo random numbers based on all available real random + numbers. + 2: Strong random numbers with a somewhat guaranteed entropy. +*/ +#define DEFAULT_LEVEL 2 +static int level = DEFAULT_LEVEL; + +/* Name of file to use as seed. */ +static char *seed_file; + +/* The random bytes we collected. */ +char gatherbuf[GATHERBUFSIZE]; + +/* The current positions in gatherbuf[]. */ +int gatherrpos; +int gatherwpos; + +/* XXX Yuk Yuk. */ +#define POOLSIZE 600 + +/* Take up to length bytes from gather_random if available. If + nothing is available, sleep until something becomes available. + Must be called with global_lock held. */ +int +gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) +{ + int avail = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; + int first = GATHERBUFSIZE - gatherrpos; + int second = length - first; + + /* If level is zero, we should not block and not add anything + to the pool. */ + if( !level ) + return 0; + + /* io_read() should guarantee that there is always data available. */ + if (level == 2) + assert (avail); + + if (length > avail) + length = avail; + + if (first > length) + first = length; + (*add) (&gatherbuf[gatherrpos], first, requester); + gatherrpos = (gatherrpos + first) % GATHERBUFSIZE; + if (second > 0) + { + (*add) (&gatherbuf[gatherrpos], second, requester); + gatherrpos += second; + } + return length; +} + + +const char *argp_program_version = STANDARD_HURD_VERSION (random); + +/* This lock protects the GnuPG code. */ +static struct mutex global_lock; + +/* Trivfs hooks. */ +int trivfs_fstype = FSTYPE_MISC; +int trivfs_fsid = 0; + +int trivfs_allow_open = O_READ | O_WRITE; + +int trivfs_support_read = 1; +int trivfs_support_write = 1; +int trivfs_support_exec = 0; + +void +trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) +{ + /* Mark the node as a read-only plain file. */ + st->st_mode &= ~S_IFMT; + st->st_mode |= (S_IFCHR); + st->st_size = 0; +} + +error_t +trivfs_goaway (struct trivfs_control *cntl, int flags) +{ + update_random_seed_file (); + exit (0); +} + +/* Read data from an IO object. If offset is -1, read from the object + maintained file pointer. If the object is not seekable, offset is + ignored. The amount desired to be read is in AMOUNT. */ +error_t +trivfs_S_io_read (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + data_t *data, mach_msg_type_number_t *data_len, + loff_t offs, mach_msg_type_number_t amount) +{ + /* Deny access if they have bad credentials. */ + if (! cred) + return EOPNOTSUPP; + else if (! (cred->po->openmodes & O_READ)) + return EBADF; + + mutex_lock (&global_lock); + + if (amount > 0) + { + while (readable_pool (amount, level) == 0) + { + if (cred->po->openmodes & O_NONBLOCK) + { + mutex_unlock (&global_lock); + return EWOULDBLOCK; + } + read_blocked = 1; + if (hurd_condition_wait (&wait, &global_lock)) + { + mutex_unlock (&global_lock); + return EINTR; + } + /* See term/users.c for possible race? */ + } + + /* Possibly allocate a new buffer. */ + if (*data_len < amount) + *data = mmap (0, amount, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + amount = read_pool ((byte *) *data, amount, level); + } + *data_len = amount; + + /* Set atime, see term/users.c */ + + mutex_unlock (&global_lock); + + return 0; +} + +/* Write data to an IO object. If offset is -1, write at the object + maintained file pointer. If the object is not seekable, offset is + ignored. The amount successfully written is returned in amount. A + given user should not have more than one outstanding io_write on an + object at a time; servers implement congestion control by delaying + responses to io_write. Servers may drop data (returning ENOBUFS) + if they receive more than one write when not prepared for it. */ +error_t +trivfs_S_io_write (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t replytype, + data_t data, + mach_msg_type_number_t datalen, + loff_t offset, + mach_msg_type_number_t *amount) +{ + int i = 0; + /* Deny access if they have bad credentials. */ + if (! cred) + return EOPNOTSUPP; + else if (! (cred->po->openmodes & O_WRITE)) + return EBADF; + + mutex_lock (&global_lock); + + while (i < datalen) + { + gatherbuf[gatherwpos] = data[i++]; + gatherwpos = (gatherwpos + 1) % GATHERBUFSIZE; + if (gatherrpos == gatherwpos) + /* Overrun. */ + gatherrpos = (gatherrpos + 1) % GATHERBUFSIZE; + } + *amount = datalen; + + if (datalen > 0 && read_blocked) + { + read_blocked = 0; + condition_broadcast (&wait); + } + + mutex_unlock (&global_lock); + return 0; +} + +/* Tell how much data can be read from the object without blocking for + a "long time" (this should be the same meaning of "long time" used + by the nonblocking flag. */ +kern_return_t +trivfs_S_io_readable (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t replytype, + mach_msg_type_number_t *amount) +{ + /* Deny access if they have bad credentials. */ + if (! cred) + return EOPNOTSUPP; + else if (! (cred->po->openmodes & O_READ)) + return EBADF; + + mutex_lock (&global_lock); + + /* XXX: Before initialization, the amount depends on the amount we + want to read. Assume some medium value. */ + *amount = readable_pool (POOLSIZE/2, level); + + mutex_unlock (&global_lock); + + return 0; +} + +/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG. + Block until one of the indicated types of i/o can be done "quickly", and + return the types that are then available. ID_TAG is returned as passed; it + is just for the convenience of the user in matching up reply messages with + specific requests sent. */ +error_t +trivfs_S_io_select (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + int *type) +{ + if (!cred) + return EOPNOTSUPP; + + /* We only deal with SELECT_READ and SELECT_WRITE here. */ + if (*type & ~(SELECT_READ | SELECT_WRITE)) + return EINVAL; + + if (*type == 0) + return 0; + + mutex_lock (&global_lock); + + while (1) + { + /* XXX Before initialization, readable_pool depends on length. */ + int avail = readable_pool (POOLSIZE/2, level); + + if (avail != 0 || *type & SELECT_WRITE) + { + *type = (avail ? SELECT_READ : 0) | (*type & SELECT_WRITE); + mutex_unlock (&global_lock); + return 0; + } + + ports_interrupt_self_on_port_death (cred, reply); + read_blocked = 1; + + if (hurd_condition_wait (&select_alert, &global_lock)) + { + *type = 0; + mutex_unlock (&global_lock); + return EINTR; + } + } +} + + +/* Change current read/write offset */ +error_t +trivfs_S_io_seek (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + loff_t offs, int whence, loff_t *new_offs) +{ + if (! cred) + return EOPNOTSUPP; + + /* Not seekable. */ + return ESPIPE; +} + +/* Change the size of the file. If the size increases, new blocks are + zero-filled. After successful return, it is safe to reference mapped + areas of the file up to NEW_SIZE. */ +error_t +trivfs_S_file_set_size (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + loff_t size) +{ + if (!cred) + return EOPNOTSUPP; + + return size == 0 ? 0 : EINVAL; +} + +/* These four routines modify the O_APPEND, O_ASYNC, O_FSYNC, and + O_NONBLOCK bits for the IO object. In addition, io_get_openmodes + will tell you which of O_READ, O_WRITE, and O_EXEC the object can + be used for. The O_ASYNC bit affects icky async I/O; good async + I/O is done through io_async which is orthogonal to these calls. */ +error_t +trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + int mode) +{ + if (!cred) + return EOPNOTSUPP; + + return 0; +} + +error_t +trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + int bits) +{ + if (!cred) + return EOPNOTSUPP; + + return 0; +} + +error_t +trivfs_S_io_get_owner (struct trivfs_protid *cred, + mach_port_t reply, + mach_msg_type_name_t reply_type, + pid_t *owner) +{ + if (!cred) + return EOPNOTSUPP; + + *owner = 0; + return 0; +} + +error_t +trivfs_S_io_mod_owner (struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + pid_t owner) +{ + if (!cred) + return EOPNOTSUPP; + + return EINVAL; +} + +/* Return objects mapping the data underlying this memory object. If + the object can be read then memobjrd will be provided; if the + object can be written then memobjwr will be provided. For objects + where read data and write data are the same, these objects will be + equal, otherwise they will be disjoint. Servers are permitted to + implement io_map but not io_map_cntl. Some objects do not provide + mapping; they will set none of the ports and return an error. Such + objects can still be accessed by io_read and io_write. */ +error_t +trivfs_S_io_map(struct trivfs_protid *cred, + mach_port_t reply, mach_msg_type_name_t reply_type, + mach_port_t *rdobj, + mach_msg_type_name_t *rdtype, + mach_port_t *wrobj, + mach_msg_type_name_t *wrtype) +{ + if (!cred) + return EOPNOTSUPP; + + return EINVAL; +} + + +int +random_demuxer (mach_msg_header_t *inp, + mach_msg_header_t *outp) +{ + extern int startup_notify_server (mach_msg_header_t *, mach_msg_header_t *); + + return (trivfs_demuxer (inp, outp) + || startup_notify_server (inp, outp)); +} + + +/* Options processing. We accept the same options on the command line + and from fsys_set_options. */ + +static const struct argp_option options[] = +{ + {"weak", 'w', 0, 0, "Output weak pseudo random data"}, + {"fast", 'f', 0, 0, "Output cheap random data fast"}, + {"secure", 's', 0, 0, "Output cryptographically secure random"}, + {"seed-file", 'S', "FILE", 0, "Use FILE to remember the seed"}, + {0} +}; + +static error_t +parse_opt (int opt, char *arg, struct argp_state *state) +{ + switch (opt) + { + default: + return ARGP_ERR_UNKNOWN; + case ARGP_KEY_INIT: + case ARGP_KEY_SUCCESS: + case ARGP_KEY_ERROR: + break; + + case 'w': + { + level = 0; + break; + } + case 'f': + { + level = 1; + break; + } + case 's': + { + level = 2; + break; + } + case 'S': + { + seed_file = strdup (arg); + set_random_seed_file (arg); + } + } + return 0; +} + +/* This will be called from libtrivfs to help construct the answer + to an fsys_get_options RPC. */ +error_t +trivfs_append_args (struct trivfs_control *fsys, + char **argz, size_t *argz_len) +{ + error_t err = 0; + char *opt; + + mutex_lock (&global_lock); + switch (level) + { + case 0: + { + opt = "--weak"; + break; + } + case 1: + { + opt = "--fast"; + break; + } + default: + { + opt = "--secure"; + break; + } + } + if (level != DEFAULT_LEVEL) + err = argz_add (argz, argz_len, opt); + + if (!err && seed_file) + { + if (asprintf (&opt, "--seed-file=%s", seed_file) < 0) + err = ENOMEM; + else + { + err = argz_add (argz, argz_len, opt); + free (opt); + } + } + mutex_unlock (&global_lock); + + return err; +} + +static struct argp random_argp = +{ options, parse_opt, 0, + "A translator providing random output." }; + +/* Setting this variable makes libtrivfs use our argp to + parse options passed in an fsys_set_options RPC. */ +struct argp *trivfs_runtime_argp = &random_argp; + +struct port_class *shutdown_notify_class; + +/* The system is going down; destroy all the extant port rights. That + will cause net channels and such to close promptly. */ +error_t +S_startup_dosync (mach_port_t handle) +{ + struct port_info *inpi = ports_lookup_port (fsys->pi.bucket, handle, + shutdown_notify_class); + + if (!inpi) + return EOPNOTSUPP; + + update_random_seed_file (); + return 0; +} + +void +sigterm_handler (int signo) +{ + update_random_seed_file (); + signal (SIGTERM, SIG_DFL); + raise (SIGTERM); +} + +void +arrange_shutdown_notification () +{ + error_t err; + mach_port_t initport, notify; + process_t procserver; + struct port_info *pi; + + shutdown_notify_class = ports_create_class (0, 0); + + signal (SIGTERM, sigterm_handler); + + /* Arrange to get notified when the system goes down, + but if we fail for some reason, just silently give up. No big deal. */ + + err = ports_create_port (shutdown_notify_class, fsys->pi.bucket, + sizeof (struct port_info), &pi); + if (err) + return; + + procserver = getproc (); + if (!procserver) + return; + + err = proc_getmsgport (procserver, 1, &initport); + mach_port_deallocate (mach_task_self (), procserver); + if (err) + return; + + notify = ports_get_send_right (pi); + ports_port_deref (pi); + startup_request_notification (initport, notify, + MACH_MSG_TYPE_MAKE_SEND, + program_invocation_short_name); + mach_port_deallocate (mach_task_self (), notify); + mach_port_deallocate (mach_task_self (), initport); +} + + +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t bootstrap; + + /* Initialize the lock that will protect everything. + We must do this before argp_parse, because parse_opt (above) will + use the lock. */ + mutex_init (&global_lock); + + /* The conditions are used to implement proper read/select + behaviour. */ + condition_init (&wait); + condition_init (&select_alert); + condition_implies (&wait, &select_alert); + + /* We use the same argp for options available at startup + as for options we'll accept in an fsys_set_options RPC. */ + argp_parse (&random_argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "Must be started as a translator"); + + /* Reply to our parent */ + err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys); + mach_port_deallocate (mach_task_self (), bootstrap); + if (err) + error (3, err, "trivfs_startup"); + + arrange_shutdown_notification (); + + /* Launch. */ + ports_manage_port_operations_multithread (fsys->pi.bucket, random_demuxer, + 10 * 1000, /* idle thread */ + 10 * 60 * 1000, /* idle server */ + 0); + return 0; +} diff --git a/random/random.h b/random/random.h new file mode 100644 index 00000000..a38a4177 --- /dev/null +++ b/random/random.h @@ -0,0 +1,32 @@ +/* random.c - A single-file translator providing random data + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, 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 + General Public License for more details. + + You should have received a copy of the GNU 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 */ + +#ifndef __RANDOM_H__ +#define __RANDOM_H__ + +/* How many random bytes to gather at most. + XXX: Should be at least POOLSIZE. */ +#define GATHERBUFSIZE 32768 + +/* The random bytes we collected. */ +extern char gatherbuf[GATHERBUFSIZE]; + +/* The current positions in gatherbuf[]. */ +extern int gatherrpos; +extern int gatherwpos; + +#endif -- cgit v1.2.3 From a86a4a149b67a83d5c08238d0b802d372332bfba Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 23 Aug 2011 19:06:18 +0200 Subject: Use __clockid_t instead of clockid_t Using clockid_t just for pthread types makes us pull , which defines time(), which may conflict with applications. * include/pthread/pthread.h (pthread_condattr_getclock, pthread_condattr_setclock, pthread_getcpuclockid): Use __clockid_t instead of clockid_t. * include/pthread/pthreadtypes.h: Include , instead of and defining clockid_t ourself when not defined by time.h. * sysdeps/generic/bits/condition-attr.h: Include instead of . (__pthread_condattr): Use __clockid_t instead of clockid_t. --- sysdeps/generic/bits/condition-attr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sysdeps/generic/bits/condition-attr.h b/sysdeps/generic/bits/condition-attr.h index a1311286..4cd4e8c4 100644 --- a/sysdeps/generic/bits/condition-attr.h +++ b/sysdeps/generic/bits/condition-attr.h @@ -20,7 +20,7 @@ #ifndef _BITS_CONDITION_ATTR_H #define _BITS_CONDITION_ATTR_H 1 -#include +#include enum __pthread_process_shared; @@ -28,7 +28,7 @@ enum __pthread_process_shared; struct __pthread_condattr { enum __pthread_process_shared pshared; - clockid_t clock; + __clockid_t clock; }; #endif /* bits/condition.h */ -- cgit v1.2.3 From 3def2cde1dc7e071976a174aa43ca076ae356a13 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Wed, 7 Sep 2011 19:38:22 +0200 Subject: Tiny build and GCC warning fixes. * pthread/cthreads-compat.c: #include for NULL. * pthread/pt-exit.c (pthread_exit): Remove stray need_dealloc variable. * sysdeps/generic/pt-attr-getschedparam.c: #include for memcpy. * sysdeps/mach/hurd/ia32/pt-setup.c (stack_setup): Apply some more typecasting. * tests/test-1.c: #include . * tests/test-6.c: Likewise. * tests/test-7.c: Likewise. * tests/test-16.c (handler): Take parameters for sa_handler, not sa_sigaction. --- pthread/cthreads-compat.c | 1 + pthread/pt-exit.c | 1 - sysdeps/generic/pt-attr-getschedparam.c | 1 + sysdeps/mach/hurd/ia32/pt-setup.c | 2 +- tests/test-1.c | 1 + tests/test-16.c | 2 +- tests/test-6.c | 1 + tests/test-7.c | 1 + 8 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pthread/cthreads-compat.c b/pthread/cthreads-compat.c index e0536ef2..799d3a4a 100644 --- a/pthread/cthreads-compat.c +++ b/pthread/cthreads-compat.c @@ -19,6 +19,7 @@ #include #include +#include typedef void *cthread_t; typedef void *(*cthread_fn_t) (void *arg); diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c index 5fe0ba86..3b3853e3 100644 --- a/pthread/pt-exit.c +++ b/pthread/pt-exit.c @@ -35,7 +35,6 @@ pthread_exit (void *status) struct __pthread *self = _pthread_self (); struct __pthread_cancelation_handler **handlers; int oldstate; - int need_dealloc; /* Run any cancelation handlers. According to POSIX, the cancellation cleanup handlers should be called with cancellation diff --git a/sysdeps/generic/pt-attr-getschedparam.c b/sysdeps/generic/pt-attr-getschedparam.c index 6c3f15be..190cf9d0 100644 --- a/sysdeps/generic/pt-attr-getschedparam.c +++ b/sysdeps/generic/pt-attr-getschedparam.c @@ -19,6 +19,7 @@ #include #include +#include #include diff --git a/sysdeps/mach/hurd/ia32/pt-setup.c b/sysdeps/mach/hurd/ia32/pt-setup.c index ba438d6a..7eb223c2 100644 --- a/sysdeps/mach/hurd/ia32/pt-setup.c +++ b/sysdeps/mach/hurd/ia32/pt-setup.c @@ -64,7 +64,7 @@ stack_setup (struct __pthread *thread, { /* And then the call frame. */ top -= 2; - top = (uintptr_t) top & ~0xf; + top = (uintptr_t *) ((uintptr_t) top & ~0xf); top[1] = (uintptr_t) arg; /* Argument to START_ROUTINE. */ top[0] = (uintptr_t) start_routine; *--top = 0; /* Fake return address. */ diff --git a/tests/test-1.c b/tests/test-1.c index 318fd6e9..6ec1afb3 100644 --- a/tests/test-1.c +++ b/tests/test-1.c @@ -1,6 +1,7 @@ #define _GNU_SOURCE #include +#include #include #include #include diff --git a/tests/test-16.c b/tests/test-16.c index b6a52d01..3660f5f7 100644 --- a/tests/test-16.c +++ b/tests/test-16.c @@ -33,7 +33,7 @@ test (void *arg) } static void -handler (int sig, siginfo_t *info, void *context) +handler (int sig) { assert (pthread_equal (pthread_self (), testthread)); printf ("handler: %d\n", pthread_self ()); diff --git a/tests/test-6.c b/tests/test-6.c index 98aa8ba7..edf2919e 100644 --- a/tests/test-6.c +++ b/tests/test-6.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #define THREADS 500 diff --git a/tests/test-7.c b/tests/test-7.c index bd97acfa..8159be34 100644 --- a/tests/test-7.c +++ b/tests/test-7.c @@ -1,6 +1,7 @@ #define _GNU_SOURCE #include +#include #include #include #include -- cgit v1.2.3 From 33d3344be6ab376cc73f12c8355a262cb3057021 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Thu, 15 Sep 2011 00:26:24 +0200 Subject: must pull in a NULL definition. Thus, revert a bit of commit 769e2108a0f5fc49eff9f3addbaf5f0646bcb253. * pthread/cthreads-compat.c: Don't #include . --- pthread/cthreads-compat.c | 1 - 1 file changed, 1 deletion(-) diff --git a/pthread/cthreads-compat.c b/pthread/cthreads-compat.c index 799d3a4a..e0536ef2 100644 --- a/pthread/cthreads-compat.c +++ b/pthread/cthreads-compat.c @@ -19,7 +19,6 @@ #include #include -#include typedef void *cthread_t; typedef void *(*cthread_fn_t) (void *arg); -- cgit v1.2.3 From 1b37ff3740644d3febf6ae6e7f756a8d152a37e6 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Wed, 13 Jun 2007 00:00:00 +0200 Subject: TLS support for libpthread, Mach/Hurd (x86). * Makefile (CFLAGS): Define ENABLE_TLS. * pthread/pt-create.c (__pthread_create_internal) [ENABLE_TLS]: Call into glibc to allocate static TLS block. * pthread/pt-exit.c (pthread_exit) [ENABLE_TLS]: Call into glibc to deallocate static TLS block. * pthread/pt-internal.h [ENABLE_TLS] (tcbhead_t): New structure; as in glibc. (__pthread) [ENABLE_TLS]: Add TCB member. [ENABLE_TLS] (_dl_allocate_tls, _dl_deallocate_tls): Declare; from glibc. * sysdeps/mach/hurd/pt-sysdep.h (__thread_set_pcsp): Rename to __thread_set_pcsptp. Add SET_TP and TP parameters. Change all callers. * sysdeps/mach/hurd/i386/pt-machdep.c (__thread_set_pcsptp): Imlement TLS support. * sysdeps/mach/hurd/i386/pt-setup.c (__pthread_setup): Likewise. --- pthread/pt-create.c | 13 ++++++++++++- pthread/pt-exit.c | 6 +++++- pthread/pt-internal.h | 29 ++++++++++++++++++++++++++- sysdeps/mach/hurd/i386/pt-machdep.c | 39 ++++++++++++++++++++++++++++++++----- sysdeps/mach/hurd/i386/pt-setup.c | 9 ++++++--- sysdeps/mach/hurd/pt-docancel.c | 6 +++--- sysdeps/mach/hurd/pt-sysdep.h | 12 +++++++----- 7 files changed, 95 insertions(+), 19 deletions(-) diff --git a/pthread/pt-create.c b/pthread/pt-create.c index bad5d83f..0d66d6ce 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -1,5 +1,5 @@ /* Thread creation. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2007 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 @@ -127,6 +127,13 @@ __pthread_create_internal (struct __pthread **thread, if (err) goto failed_thread_alloc; +#ifdef ENABLE_TLS + pthread->tcb = _dl_allocate_tls (NULL); + if (!pthread->tcb) + goto failed_thread_tls_alloc; + pthread->tcb->tcb = pthread->tcb; +#endif /* ENABLE_TLS */ + /* And initialize the rest of the machine context. This may include additional machine- and system-specific initializations that prove convenient. */ @@ -192,6 +199,10 @@ __pthread_create_internal (struct __pthread **thread, failed_sigstate: __pthread_sigstate_destroy (pthread); failed_setup: +#ifdef ENABLE_TLS + _dl_deallocate_tls (pthread->tcb, 1); + failed_thread_tls_alloc: +#endif /* ENABLE_TLS */ __pthread_thread_dealloc (pthread); __pthread_thread_halt (pthread, 0); failed_thread_alloc: diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c index 7484ffd1..941526ae 100644 --- a/pthread/pt-exit.c +++ b/pthread/pt-exit.c @@ -1,5 +1,5 @@ /* Thread termination. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2007 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 @@ -70,6 +70,10 @@ pthread_exit (void *status) if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) status = PTHREAD_CANCELED; +#ifdef ENABLE_TLS + if (self->tcb) + _dl_deallocate_tls (self->tcb, 1); +#endif /* ENABLE_TLS */ __pthread_thread_dealloc (self); switch (self->state) diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index efd4ffb9..159f1cbd 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2005, 2007 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 @@ -50,6 +50,16 @@ enum pthread_state # define PTHREAD_SYSDEP_MEMBERS #endif +#ifdef ENABLE_TLS +/* Type of the TCB. */ +typedef struct +{ + void *tcb; /* Points to this structure. */ + void *dtv; /* Vector of pointers to TLS data. */ + thread_t self; /* This thread's control port. */ +} tcbhead_t; +#endif /* ENABLE_TLS */ + /* This structure describes a POSIX thread. */ struct __pthread { @@ -85,6 +95,10 @@ struct __pthread PTHREAD_SYSDEP_MEMBERS +#ifdef ENABLE_TLS + tcbhead_t *tcb; +#endif /* ENABLE_TLS */ + struct __pthread *next, **prevp; }; @@ -272,4 +286,17 @@ const struct __pthread_rwlockattr __pthread_default_rwlockattr; /* Default condition attributes. */ const struct __pthread_condattr __pthread_default_condattr; + +#ifdef ENABLE_TLS + +/* From glibc. */ + +/* Dynamic linker TLS allocation. */ +extern void *_dl_allocate_tls(void *); + +/* Dynamic linker TLS deallocation. */ +extern void _dl_deallocate_tls(void *, int); + +#endif /* ENABLE_TLS */ + #endif /* pt-internal.h */ diff --git a/sysdeps/mach/hurd/i386/pt-machdep.c b/sysdeps/mach/hurd/i386/pt-machdep.c index face46c5..f3c8cf50 100644 --- a/sysdeps/mach/hurd/i386/pt-machdep.c +++ b/sysdeps/mach/hurd/i386/pt-machdep.c @@ -1,5 +1,5 @@ /* Machine dependent pthreads code. Hurd/i386 version. - Copyright (C) 2000,02 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2007 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 @@ -21,12 +21,28 @@ #include #include +#include +#include #include +#define HURD_TLS_DESC_DECL(desc, tcb) \ + struct descriptor desc = \ + { /* low word: */ \ + 0xffff /* limit 0..15 */ \ + | (((unsigned int) (tcb)) << 16) /* base 0..15 */ \ + , /* high word: */ \ + ((((unsigned int) (tcb)) >> 16) & 0xff) /* base 16..23 */ \ + | ((0x12 | 0x60 | 0x80) << 8) /* access = ACC_DATA_W|ACC_PL_U|ACC_P */ \ + | (0xf << 16) /* limit 16..19 */ \ + | ((4 | 8) << 20) /* granularity = SZ_32|SZ_G */ \ + | (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \ + } + int -__thread_set_pcsp (thread_t thread, +__thread_set_pcsptp (thread_t thread, int set_ip, void *ip, - int set_sp, void *sp) + int set_sp, void *sp, + int set_tp, void *tp) { error_t err; struct i386_thread_state state; @@ -34,7 +50,7 @@ __thread_set_pcsp (thread_t thread, state_count = i386_THREAD_STATE_COUNT; - err = __thread_get_state (thread, i386_THREAD_STATE, + err = __thread_get_state (thread, i386_REGS_SEGS_STATE, (thread_state_t) &state, &state_count); if (err) return err; @@ -43,8 +59,21 @@ __thread_set_pcsp (thread_t thread, state.uesp = (unsigned int) sp; if (set_ip) state.eip = (unsigned int) ip; + if (set_tp) { + HURD_TLS_DESC_DECL(desc, tp); + int sel; + + asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0)); + if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ + err = __i386_set_ldt (thread, sel, &desc, 1); + else + err = __i386_set_gdt (thread, &sel, desc); + if (err) + return err; + state.gs = sel; + } - err = __thread_set_state (thread, i386_THREAD_STATE, + err = __thread_set_state (thread, i386_REGS_SEGS_STATE, (thread_state_t) &state, i386_THREAD_STATE_COUNT); if (err) diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c index 32ace6ad..020f677a 100644 --- a/sysdeps/mach/hurd/i386/pt-setup.c +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -1,5 +1,5 @@ /* Setup thread stack. Hurd/i386 version. - Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005, 2007 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 @@ -89,12 +89,15 @@ __pthread_setup (struct __pthread *thread, thread->mcontext.pc = entry_point; thread->mcontext.sp = stack_setup (thread, start_routine, arg); + thread->tcb->self = thread->kernel_thread; + ktid = __mach_thread_self (); if (thread->kernel_thread != ktid) { - err = __thread_set_pcsp (thread->kernel_thread, + err = __thread_set_pcsptp (thread->kernel_thread, 1, thread->mcontext.pc, - 1, thread->mcontext.sp); + 1, thread->mcontext.sp, + 1, thread->tcb); assert_perror (err); } __mach_port_deallocate (__mach_task_self (), ktid); diff --git a/sysdeps/mach/hurd/pt-docancel.c b/sysdeps/mach/hurd/pt-docancel.c index bac62a71..84f04c0c 100644 --- a/sysdeps/mach/hurd/pt-docancel.c +++ b/sysdeps/mach/hurd/pt-docancel.c @@ -1,5 +1,5 @@ /* Cancel a thread. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2007 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 @@ -52,8 +52,8 @@ __pthread_do_cancel (struct __pthread *p) err = __thread_abort (p->kernel_thread); assert_perror (err); - err = __thread_set_pcsp (p->kernel_thread, - 1, (void *) call_exit, 0, 0); + err = __thread_set_pcsptp (p->kernel_thread, + 1, (void *) call_exit, 0, 0, 0, 0); assert_perror (err); err = __thread_resume (p->kernel_thread); diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h index 83bad963..f652b687 100644 --- a/sysdeps/mach/hurd/pt-sysdep.h +++ b/sysdeps/mach/hurd/pt-sysdep.h @@ -1,5 +1,5 @@ /* Internal defenitions for pthreads library. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2007 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 @@ -59,11 +59,13 @@ __pthread_stack_dealloc (void *stackaddr, size_t stacksize) __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize); } -/* Change thread THREAD's program counter to PC if SET_PC is true and - its stack pointer to SP if SET_IP is true. */ -extern int __thread_set_pcsp (thread_t thread, +/* Change thread THREAD's program counter to PC if SET_PC is true, + its stack pointer to SP if SET_IP is true, and its thread pointer + to TP if SET_TP is true. */ +extern int __thread_set_pcsptp (thread_t thread, int set_pc, void *pc, - int set_sp, void *sp); + int set_sp, void *sp, + int set_tp, void *tp); #endif /* pt-sysdep.h */ -- cgit v1.2.3 From 710717fec5f135c65a2856fd2e2360d99742e058 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Wed, 2 Nov 2011 17:38:46 +0100 Subject: Remove all the values when deleting a key When deleting a key using `pthread_key_delete', delete all the values associated to that key in all the threads available. Otherwise, the key reuse in `pthread_key_create' can cause new keys to have thread specific data of the previously used key with the same index. Add a test for this case, which creates and deletes pairs of keys checking that they have a NULL thread specific data after creation. * sysdeps/hurd/pt-key-delete.c (pthread_key_delete): Remove all the values of the key in all the threads. * tests/Makefile (CHECK_SRC): Add test-17.c. * tests/test-17.c: New file. --- sysdeps/hurd/pt-key-delete.c | 19 +++++++++++++++ tests/Makefile | 2 +- tests/test-17.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 tests/test-17.c diff --git a/sysdeps/hurd/pt-key-delete.c b/sysdeps/hurd/pt-key-delete.c index 2426bb11..9d88647e 100644 --- a/sysdeps/hurd/pt-key-delete.c +++ b/sysdeps/hurd/pt-key-delete.c @@ -35,8 +35,27 @@ pthread_key_delete (pthread_key_t key) err = EINVAL; else { + int i; + __pthread_key_destructors[key] = PTHREAD_KEY_INVALID; __pthread_key_invalid_count ++; + + pthread_rwlock_rdlock (&__pthread_threads_lock); + for (i = 0; i < __pthread_num_threads; ++i) + { + struct __pthread *t; + + t = __pthread_threads[i]; + + if (t == NULL) + continue; + + /* Just remove the key, no need to care whether it was + already there. */ + if (t->thread_specifics) + hurd_ihash_remove (t->thread_specifics, key); + } + pthread_rwlock_unlock (&__pthread_threads_lock); } __pthread_mutex_unlock (&__pthread_key_lock); diff --git a/tests/Makefile b/tests/Makefile index 9509c957..4e2a4a8d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,7 +4,7 @@ LDLIBS = -lpthread CHECK_SRC := test-1.c test-2.c test-3.c test-6.c test-7.c test-8.c \ test-9.c test-10.c test-11.c test-12.c test-13.c test-14.c \ - test-15.c test-16.c + test-15.c test-16.c test-17.c CHECK_OBJS := $(addsuffix .o,$(basename $(notdir $(CHECK_SRC)))) CHECK_PROGS := $(basename $(notdir $(CHECK_SRC))) \ diff --git a/tests/test-17.c b/tests/test-17.c new file mode 100644 index 00000000..a8bd1503 --- /dev/null +++ b/tests/test-17.c @@ -0,0 +1,57 @@ +/* Test that the key reuse inside libpthread does not cause thread + specific values to persist. */ + +#define _GNU_SOURCE 1 + +#include +#include +#include +#include + +void +work (int iter) +{ + error_t err; + pthread_key_t key1; + pthread_key_t key2; + void *value1; + void *value2; + + printf ("work/%d: start\n", iter); + err = pthread_key_create (&key1, NULL); + assert (err == 0); + err = pthread_key_create (&key2, NULL); + assert (err == 0); + + value1 = pthread_getspecific (key1); + value2 = pthread_getspecific (key2); + printf ("work/%d: pre-setspecific: %p,%p\n", iter, value1, value2); + assert (value1 == NULL); + assert (value2 == NULL); + err = pthread_setspecific (key1, (void *)(0x100 + iter)); + assert (err == 0); + err = pthread_setspecific (key2, (void *)(0x200 + iter)); + assert (err == 0); + + value1 = pthread_getspecific (key1); + value2 = pthread_getspecific (key2); + printf ("work/%d: post-setspecific: %p,%p\n", iter, value1, value2); + assert (value1 == (void *)(0x100 + iter)); + assert (value2 == (void *)(0x200 + iter)); + + err = pthread_key_delete (key1); + assert (err == 0); + err = pthread_key_delete (key2); + assert (err == 0); +} + +int +main (int argc, char *argv[]) +{ + int i; + + for (i = 0; i < 8; ++i) + work (i + 1); + + return 0; +} -- cgit v1.2.3 From c3ef50224c88053e40017665abc2628d0931f6c5 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Sat, 5 Nov 2011 01:16:41 +0100 Subject: Correct logic for PTHREAD_KEY_INVALID slots. * sysdeps/hurd/pt-destroy-specific.c (__pthread_destroy_specific): Correct logic for PTHREAD_KEY_INVALID slots. * tests/test-__pthread_destroy_specific-skip.c: New file. * tests/Makefile (CHECK_SRC): Add test-__pthread_destroy_specific-skip.c. --- sysdeps/hurd/pt-destroy-specific.c | 2 +- tests/Makefile | 2 +- tests/test-__pthread_destroy_specific-skip.c | 83 ++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 tests/test-__pthread_destroy_specific-skip.c diff --git a/sysdeps/hurd/pt-destroy-specific.c b/sysdeps/hurd/pt-destroy-specific.c index 23c7fbc0..f7896e5e 100644 --- a/sysdeps/hurd/pt-destroy-specific.c +++ b/sysdeps/hurd/pt-destroy-specific.c @@ -48,7 +48,7 @@ __pthread_destroy_specific (struct __pthread *thread) void *value; if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID) - break; + continue; value = hurd_ihash_find (thread->thread_specifics, i); if (value) diff --git a/tests/Makefile b/tests/Makefile index 9509c957..343a6446 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,7 +4,7 @@ LDLIBS = -lpthread CHECK_SRC := test-1.c test-2.c test-3.c test-6.c test-7.c test-8.c \ test-9.c test-10.c test-11.c test-12.c test-13.c test-14.c \ - test-15.c test-16.c + test-15.c test-16.c test-__pthread_destroy_specific-skip.c CHECK_OBJS := $(addsuffix .o,$(basename $(notdir $(CHECK_SRC)))) CHECK_PROGS := $(basename $(notdir $(CHECK_SRC))) \ diff --git a/tests/test-__pthread_destroy_specific-skip.c b/tests/test-__pthread_destroy_specific-skip.c new file mode 100644 index 00000000..b2c4c0bd --- /dev/null +++ b/tests/test-__pthread_destroy_specific-skip.c @@ -0,0 +1,83 @@ +/* Check that __pthread_destroy_specific works correctly if it has to skip + unused slots. */ + +#define _GNU_SOURCE + +#include +#include +#include + + +#define N_k 42 + +static volatile int v; + +static void +d (void *x) +{ + int *i = (int *) x; + + if (v != *i) + error (1, 0, "FAILED %d %d", v, *i); + v += 2; + + printf ("%s %d\n", __FUNCTION__, *i); + fflush (stdout); +} + +static void * +test (void *x) +{ + pthread_key_t k[N_k]; + static int k_v[N_k]; + + int err, i; + + for (i = 0; i < N_k; i += 1) + { + err = pthread_key_create (&k[i], &d); + if (err != 0) + error (1, err, "pthread_key_create %d", i); + } + + for (i = 0; i < N_k; i += 1) + { + k_v[i] = i; + err = pthread_setspecific (k[i], &k_v[i]); + if (err != 0) + error (1, err, "pthread_setspecific %d", i); + } + + /* Delete every even key. */ + for (i = 0; i < N_k; i += 2) + { + err = pthread_key_delete (k[i]); + if (err != 0) + error (1, err, "pthread_key_delete %d", i); + } + + v = 1; + pthread_exit (NULL); + + return NULL; +} + + +int main(void) +{ + pthread_t tid; + int err; + + err = pthread_create (&tid, 0, test, NULL); + if (err != 0) + error (1, err, "pthread_create"); + + err = pthread_join(tid, NULL); + if (err) + error (1, err, "pthread_join"); + + if (v != N_k + 1) + error (1, 0, "FAILED END %d %d", v, N_k + 1); + + return 0; +} -- cgit v1.2.3 From 384808e214350e3f4cae9fdabde70aea410c4a21 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Sun, 6 Nov 2011 12:39:04 +0100 Subject: pthread_getspecific, pthread_setspecific: check the key validity When getting a TSD, handle gracefully the case of an invalid key. When setting a TSD, check for the validity of the key as recommended (although not required) by POSIX. This also avoids potentially filling the `thread_specifics' hash of threads with TSD of invalid keys. Add two simple checks in test-7.c for the two situations above. * sysdeps/hurd/pt-getspecific.c (pthread_getspecific): Check the validity of the specified key. * sysdeps/hurd/pt-setspecific.c (pthread_setspecific): Likewise. * tests/test-7.c (main): Add two assertions. --- sysdeps/hurd/pt-getspecific.c | 4 +++- sysdeps/hurd/pt-setspecific.c | 4 ++++ tests/test-7.c | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sysdeps/hurd/pt-getspecific.c b/sysdeps/hurd/pt-getspecific.c index 30605984..71ec63c6 100644 --- a/sysdeps/hurd/pt-getspecific.c +++ b/sysdeps/hurd/pt-getspecific.c @@ -27,7 +27,9 @@ pthread_getspecific (pthread_key_t key) { struct __pthread *self; - assert (key < __pthread_key_count); + if (key < 0 || key >= __pthread_key_count + || __pthread_key_destructors[key] == PTHREAD_KEY_INVALID) + return NULL; self = _pthread_self (); if (! self->thread_specifics) diff --git a/sysdeps/hurd/pt-setspecific.c b/sysdeps/hurd/pt-setspecific.c index 89ca4d7f..d0b7302f 100644 --- a/sysdeps/hurd/pt-setspecific.c +++ b/sysdeps/hurd/pt-setspecific.c @@ -28,6 +28,10 @@ pthread_setspecific (pthread_key_t key, const void *value) error_t err; struct __pthread *self = _pthread_self (); + if (key < 0 || key >= __pthread_key_count + || __pthread_key_destructors[key] == PTHREAD_KEY_INVALID) + return EINVAL; + if (! self->thread_specifics) { err = hurd_ihash_create (&self->thread_specifics, HURD_IHASH_NO_LOCP); diff --git a/tests/test-7.c b/tests/test-7.c index 8159be34..22fb1caa 100644 --- a/tests/test-7.c +++ b/tests/test-7.c @@ -42,6 +42,9 @@ main (int argc, char **argv) assert ((pthread_t) val == pthread_self ()); } + assert (pthread_getspecific ((pthread_key_t) 0) == NULL); + assert (pthread_setspecific ((pthread_key_t) 0, (void *) 0x1) == EINVAL); + for (i = 0; i < KEYS; i ++) err = pthread_key_create (&key[i], des); -- cgit v1.2.3 From cb8b53b9961543d9069284eedbe89abfc1d7713b Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 27 Nov 2011 18:39:25 +0100 Subject: Fix __mutex_unlock_solid safety libc releases the spinlock before calling __mutex_unlock_solid, so we have to try to reacquire it before possibly giving it to some blocked thread. * pthread/cthreads-compat.c (__mutex_unlock_solid): Call __pthread_spin_trylock before calling __pthread_mutex_unlock. --- pthread/cthreads-compat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pthread/cthreads-compat.c b/pthread/cthreads-compat.c index e0536ef2..cbe8170e 100644 --- a/pthread/cthreads-compat.c +++ b/pthread/cthreads-compat.c @@ -100,5 +100,8 @@ __mutex_lock_solid (void *lock) void __mutex_unlock_solid (void *lock) { + if (__pthread_spin_trylock (lock) != 0) + /* Somebody already got the lock, that one will manage waking up others */ + return; __pthread_mutex_unlock (lock); } -- cgit v1.2.3