diff options
| author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-05-07 02:04:55 +0000 | 
|---|---|---|
| committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2005-05-07 02:04:55 +0000 | 
| commit | 0b3366f6a93ac0f7e2028745ea557c0acd8722c6 (patch) | |
| tree | 2a87cb353c106eb55a44437d3b4d5e0d60af1d36 | |
| parent | 2274f6b2ddc7d7ea919a8fa1f9c54ef1920cb180 (diff) | |
Import in NPTL code from glibc. For further information please
consult the 'README.NPTL' file.
264 files changed, 27370 insertions, 0 deletions
diff --git a/libpthread/README.NPTL b/libpthread/README.NPTL new file mode 100644 index 000000000..7e50984cb --- /dev/null +++ b/libpthread/README.NPTL @@ -0,0 +1,307 @@ +The base NPTL code for uClibc is from the glibc project located at +<http://sourceware.org/glibc/>. The starting version was the HEAD of +the glibc CVS repository dated 2005-05-06. Important changes from +glibc will continue to be brought in as necessary until the version +for uClibc is standing on its own. All of the files were originally +brought over verbatim with no modifications. Obviously, these will +undergo any necessary changes needed for integration into uClibc. +Additionally (or subtractingly), the files and directories below +were removed and not imported. + +-- Steven J. Hill <sjhill@realitydiluted.com> on 2005-05-06 + + +nptl/Makeconfig +nptl/configure +nptl/shlib-versions +nptl/sysdeps/generic +nptl/sysdeps/ia64 +nptl/sysdeps/pthread/Makefile +nptl/sysdeps/pthread/Subdirs +nptl/sysdeps/pthread/allocalim.h +nptl/sysdeps/pthread/configure +nptl/sysdeps/pthread/configure.in +nptl/sysdeps/pthread/createthread.c +nptl/sysdeps/pthread/flockfile.c +nptl/sysdeps/pthread/ftrylockfile.c +nptl/sysdeps/pthread/funlockfile.c +nptl/sysdeps/pthread/librt-cancellation.c +nptl/sysdeps/pthread/list.h +nptl/sysdeps/pthread/malloc-machine.h +nptl/sysdeps/pthread/posix-timer.h +nptl/sysdeps/pthread/pt-initfini.c +nptl/sysdeps/pthread/pt-longjmp.c +nptl/sysdeps/pthread/pthread-functions.h +nptl/sysdeps/pthread/pthread.h +nptl/sysdeps/pthread/pthread_barrier_wait.c +nptl/sysdeps/pthread/pthread_cond_broadcast.c +nptl/sysdeps/pthread/pthread_cond_signal.c +nptl/sysdeps/pthread/pthread_cond_timedwait.c +nptl/sysdeps/pthread/pthread_cond_wait.c +nptl/sysdeps/pthread/pthread_getcpuclockid.c +nptl/sysdeps/pthread/pthread_once.c +nptl/sysdeps/pthread/pthread_rwlock_rdlock.c +nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c +nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c +nptl/sysdeps/pthread/pthread_rwlock_unlock.c +nptl/sysdeps/pthread/pthread_rwlock_wrlock.c +nptl/sysdeps/pthread/pthread_sigmask.c +nptl/sysdeps/pthread/pthread_spin_destroy.c +nptl/sysdeps/pthread/pthread_spin_init.c +nptl/sysdeps/pthread/pthread_spin_unlock.c +nptl/sysdeps/pthread/rt-unwind-resume.c +nptl/sysdeps/pthread/setxid.h +nptl/sysdeps/pthread/sigaction.c +nptl/sysdeps/pthread/sigfillset.c +nptl/sysdeps/pthread/sigprocmask.c +nptl/sysdeps/pthread/tcb-offsets.h +nptl/sysdeps/pthread/timer_create.c +nptl/sysdeps/pthread/timer_delete.c +nptl/sysdeps/pthread/timer_getoverr.c +nptl/sysdeps/pthread/timer_gettime.c +nptl/sysdeps/pthread/timer_routines.c +nptl/sysdeps/pthread/timer_settime.c +nptl/sysdeps/pthread/tst-mqueue8x.c +nptl/sysdeps/pthread/tst-timer.c +nptl/sysdeps/pthread/unwind-forcedunwind.c +nptl/sysdeps/pthread/unwind-resume.c +nptl/sysdeps/s390 +nptl/sysdeps/unix +nptl/tst-_res1.c +nptl/tst-_res1mod1.c +nptl/tst-_res1mod2.c +nptl/tst-align.c +nptl/tst-align2.c +nptl/tst-atfork1.c +nptl/tst-atfork2.c +nptl/tst-atfork2mod.c +nptl/tst-attr1.c +nptl/tst-attr2.c +nptl/tst-attr3.c +nptl/tst-backtrace1.c +nptl/tst-barrier1.c +nptl/tst-barrier2.c +nptl/tst-barrier3.c +nptl/tst-barrier4.c +nptl/tst-basic1.c +nptl/tst-basic2.c +nptl/tst-basic3.c +nptl/tst-basic4.c +nptl/tst-basic5.c +nptl/tst-basic6.c +nptl/tst-cancel-wrappers.sh +nptl/tst-cancel1.c +nptl/tst-cancel10.c +nptl/tst-cancel11.c +nptl/tst-cancel12.c +nptl/tst-cancel13.c +nptl/tst-cancel14.c +nptl/tst-cancel15.c +nptl/tst-cancel16.c +nptl/tst-cancel17.c +nptl/tst-cancel18.c +nptl/tst-cancel19.c +nptl/tst-cancel2.c +nptl/tst-cancel20.c +nptl/tst-cancel21.c +nptl/tst-cancel22.c +nptl/tst-cancel23.c +nptl/tst-cancel3.c +nptl/tst-cancel4.c +nptl/tst-cancel5.c +nptl/tst-cancel6.c +nptl/tst-cancel7.c +nptl/tst-cancel8.c +nptl/tst-cancel9.c +nptl/tst-cancelx1.c +nptl/tst-cancelx10.c +nptl/tst-cancelx11.c +nptl/tst-cancelx12.c +nptl/tst-cancelx13.c +nptl/tst-cancelx14.c +nptl/tst-cancelx15.c +nptl/tst-cancelx16.c +nptl/tst-cancelx17.c +nptl/tst-cancelx18.c +nptl/tst-cancelx2.c +nptl/tst-cancelx20.c +nptl/tst-cancelx21.c +nptl/tst-cancelx3.c +nptl/tst-cancelx4.c +nptl/tst-cancelx5.c +nptl/tst-cancelx6.c +nptl/tst-cancelx7.c +nptl/tst-cancelx8.c +nptl/tst-cancelx9.c +nptl/tst-cleanup0.c +nptl/tst-cleanup0.expect +nptl/tst-cleanup1.c +nptl/tst-cleanup2.c +nptl/tst-cleanup3.c +nptl/tst-cleanup4.c +nptl/tst-cleanup4aux.c +nptl/tst-cleanupx0.c +nptl/tst-cleanupx0.expect +nptl/tst-cleanupx1.c +nptl/tst-cleanupx2.c +nptl/tst-cleanupx3.c +nptl/tst-cleanupx4.c +nptl/tst-clock1.c +nptl/tst-clock2.c +nptl/tst-cond1.c +nptl/tst-cond10.c +nptl/tst-cond11.c +nptl/tst-cond12.c +nptl/tst-cond13.c +nptl/tst-cond14.c +nptl/tst-cond15.c +nptl/tst-cond16.c +nptl/tst-cond17.c +nptl/tst-cond18.c +nptl/tst-cond19.c +nptl/tst-cond2.c +nptl/tst-cond20.c +nptl/tst-cond21.c +nptl/tst-cond3.c +nptl/tst-cond4.c +nptl/tst-cond5.c +nptl/tst-cond6.c +nptl/tst-cond7.c +nptl/tst-cond8.c +nptl/tst-cond9.c +nptl/tst-context1.c +nptl/tst-detach1.c +nptl/tst-dlsym1.c +nptl/tst-eintr1.c +nptl/tst-eintr2.c +nptl/tst-eintr3.c +nptl/tst-eintr4.c +nptl/tst-eintr5.c +nptl/tst-exec1.c +nptl/tst-exec2.c +nptl/tst-exec3.c +nptl/tst-exec4.c +nptl/tst-execstack-mod.c +nptl/tst-execstack.c +nptl/tst-exit1.c +nptl/tst-exit2.c +nptl/tst-exit3.c +nptl/tst-fini1.c +nptl/tst-fini1mod.c +nptl/tst-flock1.c +nptl/tst-flock2.c +nptl/tst-fork1.c +nptl/tst-fork2.c +nptl/tst-fork3.c +nptl/tst-fork4.c +nptl/tst-getpid1.c +nptl/tst-getpid2.c +nptl/tst-join1.c +nptl/tst-join2.c +nptl/tst-join3.c +nptl/tst-join4.c +nptl/tst-join5.c +nptl/tst-key1.c +nptl/tst-key2.c +nptl/tst-key3.c +nptl/tst-key4.c +nptl/tst-kill1.c +nptl/tst-kill2.c +nptl/tst-kill3.c +nptl/tst-kill4.c +nptl/tst-kill5.c +nptl/tst-kill6.c +nptl/tst-locale1.c +nptl/tst-locale2.c +nptl/tst-mutex1.c +nptl/tst-mutex2.c +nptl/tst-mutex3.c +nptl/tst-mutex4.c +nptl/tst-mutex5.c +nptl/tst-mutex5a.c +nptl/tst-mutex6.c +nptl/tst-mutex7.c +nptl/tst-mutex7a.c +nptl/tst-mutex8.c +nptl/tst-mutex9.c +nptl/tst-oddstacklimit.c +nptl/tst-once1.c +nptl/tst-once2.c +nptl/tst-once3.c +nptl/tst-once4.c +nptl/tst-oncex3.c +nptl/tst-oncex4.c +nptl/tst-popen1.c +nptl/tst-raise1.c +nptl/tst-rwlock1.c +nptl/tst-rwlock10.c +nptl/tst-rwlock11.c +nptl/tst-rwlock12.c +nptl/tst-rwlock13.c +nptl/tst-rwlock14.c +nptl/tst-rwlock2.c +nptl/tst-rwlock3.c +nptl/tst-rwlock4.c +nptl/tst-rwlock5.c +nptl/tst-rwlock6.c +nptl/tst-rwlock7.c +nptl/tst-rwlock8.c +nptl/tst-rwlock9.c +nptl/tst-sched1.c +nptl/tst-sem1.c +nptl/tst-sem2.c +nptl/tst-sem3.c +nptl/tst-sem4.c +nptl/tst-sem5.c +nptl/tst-sem6.c +nptl/tst-sem7.c +nptl/tst-sem8.c +nptl/tst-sem9.c +nptl/tst-setuid1-static.c +nptl/tst-setuid1.c +nptl/tst-signal1.c +nptl/tst-signal2.c +nptl/tst-signal3.c +nptl/tst-signal4.c +nptl/tst-signal5.c +nptl/tst-signal6.c +nptl/tst-spin1.c +nptl/tst-spin2.c +nptl/tst-spin3.c +nptl/tst-stack1.c +nptl/tst-stack2.c +nptl/tst-stack3.c +nptl/tst-stdio1.c +nptl/tst-stdio2.c +nptl/tst-sysconf.c +nptl/tst-tls1.c +nptl/tst-tls2.c +nptl/tst-tls3.c +nptl/tst-tls3mod.c +nptl/tst-tls4.c +nptl/tst-tls4moda.c +nptl/tst-tls4modb.c +nptl/tst-tls5.c +nptl/tst-tls5.h +nptl/tst-tls5mod.c +nptl/tst-tls5moda.c +nptl/tst-tls5modb.c +nptl/tst-tls5modc.c +nptl/tst-tls5modd.c +nptl/tst-tls5mode.c +nptl/tst-tls5modf.c +nptl/tst-tls6.sh +nptl/tst-tsd1.c +nptl/tst-tsd2.c +nptl/tst-tsd3.c +nptl/tst-tsd4.c +nptl/tst-tsd5.c +nptl/tst-umask1.c +nptl/tst-unload.c +nptl/tst-vfork1.c +nptl/tst-vfork1x.c +nptl/tst-vfork2.c +nptl/tst-vfork2x.c +nptl/version.c +nptl_db/ChangeLog +nptl_db/shlib-versions diff --git a/libpthread/nptl/ANNOUNCE b/libpthread/nptl/ANNOUNCE new file mode 100644 index 000000000..b63c657b8 --- /dev/null +++ b/libpthread/nptl/ANNOUNCE @@ -0,0 +1,92 @@ +Now that the Linux kernel is once again able to run all the tests we +have and since glibc 2.3 was released it was time for a new code drop. +I've uploaded the second code drop for the Native POSIX Thread +Library: + +  ftp://people.redhat.com/drepper/nptl/nptl-0.2.tar.bz2 + +You need + +- the latest of Linus' kernel from BitKeeper (or 2.5.41 when it +  is released); + +- glibc 2.3 + +- the very latest in tools such as + +  + gcc either from the current development branch or the gcc 3.2 +    from Red Hat Linux 8; + +  + binutils preferrably from CVS, from H.J. Lu's latest release for +    Linux, or from RHL 8. + + +Compiling glibc should proceed smoothly.  But there are a number of +tests which fail, mostly because some functionality is missing in +glibc.  Ignore those errors.  It is only important that all tests in +nptl/ are passing.  Run + +  make subdirs=nptl check + +to run all thread tests. + + +This version features several improvements: + +- all APIs are now implemented; + +- fork handling has been improved; stacks in the child are freed; +  atfork handlers are removed if they were registered from a module +  which gets unloaded. + +- pthread_tryjoin_np and pthread_timedjoin_np are implemented + +- TSD handling corrected and optimized. + +- many more tests which also test the underlying kernel implementation. + +- the build infrastructure has been implemented so that the DSO and +  archives are built in usable form and with correct named. + +- libthread_db has been implemented.  This is the library which is +  needed by all program which need to get access to internals of +  libpthread (mainly debuggers). + +- the CPU clock functions are implemented + + + +The white paper hasn't yet been updated.  It's still available at + +  http://people.redhat.com/drepper/nptl-design.pdf + + +This release should be ready for some serious testing.  I know it is +hard to compile which I why I'm looking into providing binary RPMs. +They can be used on non-critical systems.  I'll only be able to +provide binaries for RHL8 based systems, though, and the kernel still +must be installed separately. + + +The next steps will include: + +- write more tests and fix the bugs which are discovered this way + +- update the white paper + +- write and run more performance tests + +- port to IA-64 + + +Interested parties are once again invited to join the mailing we +created: + + +  phil-list@redhat.com + +Go to + +  https://listman.redhat.com/mailman/listinfo/phil-list + +to subscribe, unsubscribe, or review the archive. diff --git a/libpthread/nptl/Banner b/libpthread/nptl/Banner new file mode 100644 index 000000000..7c1487e7b --- /dev/null +++ b/libpthread/nptl/Banner @@ -0,0 +1 @@ +Native POSIX Threads Library by Ulrich Drepper et al diff --git a/libpthread/nptl/ChangeLog b/libpthread/nptl/ChangeLog new file mode 100644 index 000000000..6fb56a93f --- /dev/null +++ b/libpthread/nptl/ChangeLog @@ -0,0 +1,7160 @@ +2005-05-03  Ulrich Drepper  <drepper@redhat.com> + +	[BZ #915] +	* sysdeps/pthread/pthread.h: Avoid empty initializers. + +2005-05-03  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Remove explicit +	.eh_frame section, use cfi_* directives. + +2005-04-27  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: Use <> instead +	of "" includes. + +2005-04-27  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel17.c (do_test): Add arbitrary factor to make sure +	aio_write blocks. + +2005-04-27  Roland McGrath  <roland@redhat.com> + +	* Makefile (tests): Remove tst-clock2. + +	* sysdeps/unix/sysv/linux/timer_create.c (timer_create): Handle +	CLOCK_PROCESS_CPUTIME_ID and CLOCK_PROCESS_THREAD_ID specially, +	translating to the kernel clockid_t for our own process/thread clock. + +	* sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: New file. + +2005-04-15  Jakub Jelinek  <jakub@redhat.com> + +	* old_pthread_cond_init.c: Include <errno.h>. +	(__pthread_cond_init_2_0): Fail with EINVAL if COND_ATTR is +	process shared or uses clock other than CLOCK_REALTIME. +	* pthread_cond_init.c (__pthread_cond_init): Remove bogus comment. + +2005-04-13  David S. Miller  <davem@davemloft.net> + +	* sysdeps/sparc/sparc64/jmpbuf-unwind.h: New file. +	* sysdeps/sparc/sparc64/clone.S: New file. + +2005-04-05  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread.h (__pthread_cleanup_routine): Use +	__inline instead of inline. +	* sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_routine): Likewise. + +2005-03-31  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Use +	functionally equivalent, but shorter instructions. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + +2005-03-28  Daniel Jacobowitz  <dan@codesourcery.com> + +	* sysdeps/mips/Makefile: New file. +	* sysdeps/mips/nptl-sysdep.S: New file. +	* sysdeps/mips/tcb-offsets.sym: New file. +	* sysdeps/mips/pthread_spin_lock.S: New file. +	* sysdeps/mips/pthread_spin_trylock.S: New file. +	* sysdeps/mips/pthreaddef.h: New file. +	* sysdeps/mips/tls.h: New file. +	* sysdeps/mips/jmpbuf-unwind.h: New file. +	* sysdeps/unix/sysv/linux/mips/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h: New file. +	* sysdeps/unix/sysv/linux/mips/bits/semaphore.h: New file. +	* sysdeps/unix/sysv/linux/mips/pthread_once.c: New file. +	* sysdeps/unix/sysv/linux/mips/fork.c: New file. +	* sysdeps/unix/sysv/linux/mips/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/mips/vfork.S: New file. +	* sysdeps/unix/sysv/linux/mips/clone.S: New file. +	* sysdeps/unix/sysv/linux/mips/createthread.c: New file. +	* sysdeps/unix/sysv/linux/mips/sysdep-cancel.h: New file. + +2005-03-23  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_create.c (__pthread_create_2_1): Rename syscall error +	variable to scerr. + +2005-03-10  Jakub Jelinek  <jakub@redhat.com> + +	* tst-getpid1.c (do_test): Align stack passed to clone{2,}. + +2005-02-25  Roland McGrath  <roland@redhat.com> + +	* alloca_cutoff.c: Correct license text. +	* tst-unload.c: Likewise. +	* sysdeps/pthread/allocalim.h: Likewise. +	* sysdeps/pthread/pt-initfini.c: Likewise. +	* sysdeps/pthread/bits/libc-lock.h: Likewise. +	* sysdeps/pthread/bits/sigthread.h: Likewise. +	* sysdeps/unix/sysv/linux/bits/local_lim.h: Likewise. +	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Likewise. + +2005-02-16  Roland McGrath  <roland@redhat.com> + +	* sysdeps/pthread/pthread-functions.h (struct pthread_functions): +	Use unsigned int * for ptr_nthreads. + +2005-02-14  Alan Modra  <amodra@bigpond.net.au> + +	* sysdeps/powerpc/tcb-offsets.sym (thread_offsetof): Redefine to suit +	gcc4. + +2005-02-07  Richard Henderson  <rth@redhat.com> + +	[BZ #787] +	* sysdeps/pthread/pthread.h (__sigsetjmp): Use pointer as first +	argument. + +2004-11-03  Marcus Brinkmann  <marcus@gnu.org> + +	* sysdeps/generic/lowlevellock.h (__generic_mutex_unlock): Fix +	order of arguments in invocation of atomic_add_zero. + +2005-01-26  Jakub Jelinek  <jakub@redhat.com> + +	[BZ #737] +	* sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S (__new_sem_trywait): +	Use direct %gs segment access or, if NO_TLS_DIRECT_SEG_REFS, +	at least gotntpoff relocation and addition. +	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__new_sem_post): +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): +	Likewise. + +2005-01-06  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (init_one_static_tls): Adjust initialization of DTV +	entry for static tls deallocation fix. +	* sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which +	also contains information whether the memory pointed to is static +	TLS or not. +	* sysdeps/i386/tls.h: Likewise. +	* sysdeps/ia64/tls.h: Likewise. +	* sysdeps/powerpc/tls.h: Likewise. +	* sysdeps/s390/tls.h: Likewise. +	* sysdeps/sh/tls.h: Likewise. +	* sysdeps/sparc/tls.h: Likewise. +	* sysdeps/x86_64/tls.h: Likewise. + +2004-12-27  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (__pthread_initialize_minimal_internal): Use __sigemptyset. + +2004-12-21  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/i386/tls.h (CALL_THREAD_FCT): Maintain 16 byte alignment of +	%esp. +	* Makefile (tests): Add tst-align2. +	* tst-align2.c: New test. +	* sysdeps/i386/Makefile (CFLAGS-tst-align{,2}.c): Add +	-mpreferred-stack-boundary=4. + +2004-12-18  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/bits/local_lim.h: +	New file removed withdrawn for the moment. + +2004-12-17  Richard Henderson  <rth@redhat.com> + +	* sysdeps/unix/sysv/linux/alpha/clone.S: New file. +	* sysdeps/alpha/tcb-offsets.sym (TID_OFFSET): New. + +2004-12-16  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/bits/local_lim.h: New file. +	Increased PTHREAD_STACK_MIN. + +	* tst-context1.c (stacks): Use bigger stack size. + +2004-12-16  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: New file. +	* sysdeps/sparc/tcb-offsets.sym: Add TID. + +2004-12-15  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/s390-32/clone.S: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/clone.S: New file. +	* sysdeps/s390/tcb-offsets.sym (TID): Add. + +2004-12-15  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S: New file. + +2004-12-14  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/powerpc/tcb-offsets.sym: Add TID. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: New file. + +	* tst-getpid1.c: If child crashes, report this first.  Print which +	signal. + +2004-12-09  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (__pthread_initialize_minimal_internal): Also unblock +	SIGSETXID. + +2004-12-01  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_CPUTIME, +	_POSIX_THREAD_CPUTIME): Define to 0. +	* sysdeps/pthread/timer_create.c (timer_create): Remove unused code +	handling CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID. +	* sysdeps/pthread/timer_routines.c (__timer_signal_thread_pclk, +	__timer_signal_thread_tclk): Remove. +	(init_module): Remove their initialization. +	(thread_cleanup): Remove their cleanup assertions. +	* sysdeps/pthread/posix-timer.h (__timer_signal_thread_pclk, +	__timer_signal_thread_tclk): Remove. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Removed. +	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Removed. +	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Removed. + +2004-12-07  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/ia64/tcb-offsets.sym (TID): Add. +	* sysdeps/unix/sysv/linux/ia64/clone2.S: New file. + +	* Makefile (tests): Add tst-getpid2. +	* tst-getpid1.c (TEST_CLONE_FLAGS): Define. +	(do_test): Use it.  Use __clone2 instead of clone on ia64. +	* tst-getpid2.c: New test. + +2004-12-07  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/clone.S: New file. + +2004-12-04  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-getpid1. +	* tst-getpid1.c: New file. +	* sysdeps/unix/sysv/linux/i386/clone.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/clone.S: New file. + +2004-12-02  Roland McGrath  <roland@redhat.com> + +	* Makefile (libpthread-nonshared): Variable removed. +	($(objpfx)libpthread_nonshared.a): Target removed. +	($(inst_libdir)/libpthread_nonshared.a): Likewise. +	These are now handled by generic magic from +	libpthread-static-only-routines being set. + +2004-11-27  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_PRIORITIZED_IO, +	_POSIX2_CHAR_TERM, _POSIX_THREAD_PRIO_INHERIT, +	_POSIX_THREAD_PRIO_PROTECT): Define. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2004-11-26  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_ADVISORY_INFO, +	_POSIX_SPORADIC_SERVER, _POSIX_THREAD_SPORADIC_SERVER, _POSIX_TRACE, +	_POSIX_TRACE_EVENT_FILTER, _POSIX_TRACE_INHERIT, _POSIX_TRACE_LOG, +	_POSIX_TYPED_MEMORY_OBJECTS, _POSIX_IPV6, _POSIX_RAW_SOCKETS): Define. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2004-11-24  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/x86_64/Makefile [nptl]: Define CFLAGS-pthread_create.c. + +	* Makefile (libpthread-routines): Add pthread_setschedprio. +	* Versions [libpthread, GLIBC_2.3.4]: Add pthread_setschedprio. +	* sysdeps/pthread/pthread.h: Declare pthread_setschedprio. +	* pthread_setschedprio.c: New file. + +2004-11-20  Jakub Jelinek  <jakub@redhat.com> + +	* pthread_create.c (pthread_cancel): Add PTHREAD_STATIC_FN_REQUIRE. +	* pthread_cancel.c (pthread_create): Likewise. + +	* Makefile (libpthread-routines): Add vars. +	* sysdeps/pthread/createthread.c (__pthread_multiple_threads): Remove. +	* init.c (__default_stacksize, __is_smp): Remove. +	* vars.c: New file. +	* pthreadP.h (__find_thread_by_id): If !SHARED, add weak_function +	and define a wrapper macro. +	(PTHREAD_STATIC_FN_REQUIRE): Define. +	* allocatestack.c (__find_thread_by_id): Undefine. +	* pthread_create (__pthread_keys): Remove. +	(pthread_mutex_lock, pthread_mutex_unlock, pthread_once, +	pthread_key_create, pthread_setspecific, pthread_getspecific): Add +	PTHREAD_STATIC_FN_REQUIRE. + +2004-11-18  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/sh/tls.h (DB_THREAD_SELF): Set the correct bias +	parameter to REGISTER macro. + +2004-11-17  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/timer_routines.c (__start_helper_thread): +	Make sure SIGCANCEL is blocked as well. + +2004-11-10  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/setxid.h: New file. +	* sysdeps/pthread/pthread-functions.h (HAVE_PTR__NPTL_SETXID): Remove. +	(struct xid_command): Add forward decl. +	(struct pthread_functions): Change return type of __nptl_setxid hook +	to int. +	* pthreadP.h (__nptl_setxid): Change return type to int. +	* allocatestack.c (__nptl_setxid): Call INTERNAL_SYSCALL_NCS in the +	calling thread, return its return value and set errno on failure. +	* descr.h (struct xid_command): Change id type to long array. + +	* Makefile: Add rules to build and test tst-setuid1 and +	tst-setuid1-static. +	* tst-setuid1.c: New test. +	* tst-setuid1-static.c: New test. + +2004-11-10  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-exit3. +	* tst-exit3.c: New test. + +2004-11-09  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-exit2. +	* tst-exit2.c: New file. + +2004-11-09  Roland McGrath  <roland@redhat.com> + +	[BZ #530] +	* sysdeps/pthread/createthread.c (do_clone): Increment __nptl_nthreads +	here, before calling clone. +	* pthread_create.c (start_thread): Don't do it here. + +2004-11-02  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/smp.h: Include <errno.h>. + +2004-10-29  Kaz  Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): +	Set ETIMEDOUT to errno when time is up.  Tweak to avoid +	assembler warning. + +2004-10-28  Jakub Jelinek  <jakub@redhat.com> + +	* pthread_create.c (__pthread_create_2_1): Avoid leaking stacks +	if sched_priority is not between minprio and maxprio. + +2004-10-25  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Use clock_gettime syscall if exists. + +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S +	(__lll_mutex_timedlock_wait): Fix a bad branch condition. + +2004-10-24  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/smp.h (is_smp_system): Use +	not-cancelable I/O functions. + +2004-10-21  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S +	(__lll_mutex_timedlock_wait): If woken but cannot get the lock, +	make sure 2 is stored in the futex and we looked at the old value. +	Fix a few other problems to return the correct value. + +2004-10-14  Richard Henderson  <rth@redhat.com> + +	* sysdeps/alpha/tcb-offsets.sym (thread_offsetof): Redefine to +	make gcc4 happy. + +2004-10-06  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/jmp-unwind.c: Include pthreadP.h instead +	of pthread-functions.h and pthreaddef.h. +	* sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): +	Change __data.__nwaiters from int to unsigned int. + +	* tst-clock2.c (do_test): Don't fail if _POSIX_THREAD_CPUTIME == 0 and +	sysconf (_SC_THREAD_CPUTIME) returns negative value. + +	* allocatestack.c (__find_thread_by_id): Move attribute_hidden +	before return type. + +	* sysdeps/s390/jmpbuf-unwind.h: Include bits/wordsize.h. +	(JMPBUF_CFA_UNWINDS_ADJ): Subtract 96 resp. 160 bytes from CFA. + +2004-10-06  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel4.c (tf_msgrcv): Check for failure in msgget.  If the +	test fails, remove message queue. +	(tf_msgsnd): Likewise. + +2004-10-05  Jakub Jelinek  <jakub@redhat.com> + +	* tst-clock1.c: Change #ifdef to #if defined. +	* tst-clock2.c: Likewise. +	* tst-cond11.c: Likewise. + +	* sysdeps/pthread/timer_create.c (timer_create): Use +	defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 instead of +	defined CLOCK_PROCESS_CPUTIME_ID #ifs and similarly for +	THREAD_CPUTIME. + +2004-10-05  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h (_POSIX_CPUTIME, +	_POSIX_THREAD_CPUTIME): Define to 0. + +2004-10-04  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Define _POSIX_CPUTIME +	and _POSIX_THREAD_CPUTIME to zero. +	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. +	* tst-barrier2.c: Fix testing for POSIX feature. +	* tst-clock1.c: Likewise. +	* tst-clock2.c: Likewise. +	* tst-cond11.c: Likewise. +	* tst-cond4.c: Likewise. +	* tst-cond6.c: Likewise. +	* tst-flock2.c: Likewise. +	* tst-mutex4.c: Likewise. +	* tst-mutex9.c: Likewise. +	* tst-rwlock12.c: Likewise. +	* tst-rwlock4.c: Likewise. +	* tst-signal1.c: Likewise. +	* tst-spin2.c: Likewise. +	* sysdeps/pthread/posix-timer.h: Likewise. +	* sysdeps/pthread/timer_create.c: Likewise. +	* sysdeps/pthread/timer_routines.c: Likewise. + +2004-10-01  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +	(__lll_mutex_timedlock_wait): Address futex correctly. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +	(__lll_mutex_timedlock_wait): If woken but cannot get the lock, +	make sure 2 is stored in the futex and we looked at the old value. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +	(__lll_mutex_timedlock_wait): Likewise.  Fix a few other problems +	which might very well made the code not working at all before. +	[BZ #417] + +2004-09-28  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Don't +	allow SIGSETXID to be sent. +	* sysdeps/pthread/sigaction.c (__sigaction): Don't allow action +	for SIGSETXID to be defined. +	* sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Make sure +	SIGSETXID cannot be blocked. + +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): +	Add __extension__ to long long types. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2004-09-25  Ulrich Drepper  <drepper@redhat.com> + +	* descr.h (struct pthread): Add stopped_start field. +	* sysdeps/pthread/createthread.c (create_thread): Set +	start_stopped flag in descriptor for new thread appropriately. +	* pthread_create.c (start_thread): Only take lock to be stopped on +	startup if stopped_start flag says so. + +2004-09-24  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_create.c (__pthread_create_2_1): Remember whether thread +	is created detached and if yes, do not try to free the stack in case +	the thread creation failed. +	* sysdeps/pthread/createthread.c (do_clone): Free stack here if clone +	call fails.  Don't depend on INTERNAL_SYSCALL_ERRNO return zero in +	case there has been no error.  [BZ #405] + +	* pthread_create.c (start_thread): Don't wait for scheduler data +	etc to be set at the beginning of the function.  The cancellation +	infrastructure must have been set up.  And enable async +	cancellation before potentially going to sleep.  [BZ #401] + +2004-09-20  Ulrich Drepper  <drepper@redhat.com> + +	* Versions: Remove exports for pthread_set*id_np functions. +	* sysdeps/pthread/pthread.h: Remove pthread_set*id_np prototypes +	for now. +	* Makefile: Don't build pthread_set*id code for now. + +2004-09-19  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/allocrtsig.c: Allocate second signal for +	internal use. +	* allocatestack.c (__nptl_setxid): New function. +	* descr.h (struct xid_command): Define type. +	* init.c (pthread_functions): Add ptr__nptl_setxid initialization. +	(sighandler_setxid): New function. +	(__pthread_initialize_minimal): Register sighandler_setxid for +	SIGCANCEL. +	* pt-allocrtsig.c: Update comment. +	* pthreadP.h: Define SIGSETXID.  Declare __xidcmd variable. +	Declare __nptl_setxid. +	* sysdeps/pthread/pthread-functions.h: Add ptr__nptl_setxid. +	* sysdeps/pthread/pthread.h: Declare pthread_setgid_np, +	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, +	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, +	and pthread_setresuid_np. +	* pthread_setgid_np.c: New file. +	* pthread_setuid_np.c: New file. +	* pthread_setegid_np.c: New file. +	* pthread_seteuid_np.c: New file. +	* pthread_setregid_np.c: New file. +	* pthread_setreuid_np.c: New file. +	* pthread_setresgid_np.c: New file. +	* pthread_setresuid_np.c: New file. +	* Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np, +	pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, +	pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, +	and pthread_setresuid_np. +	* Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid, +	pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid, +	pthread_setregid, and pthread_setresgid. + +2004-09-18  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (allocate_stack): Return EAGAIN instead of +	ENOMEM when out of memory. + +2004-09-10  Roland McGrath  <roland@redhat.com> + +	[BZ #379] +	* allocatestack.c (allocate_stack): Remove [__ASSUME_CLONE_STOPPED] +	code, since we don't try to use the broken CLONE_STOPPED any more. +	* pthread_create.c (start_thread): Likewise. + +2004-09-15  Richard Henderson  <rth@redhat.com> + +	* sysdeps/unix/sysv/linux/alpha/vfork.S: Use libc_hidden_def. + +2004-09-01  David Mosberger  <davidm@hpl.hp.com> + +	* sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h +	(__libc_unwind_longjmp): Delete macro and declare as function. +	* sysdeps/unix/sysv/linux/ia64/Makefile (sysdep_routines): Mention +	__ia64_longjmp, sigstack_longjmp, and __sigstack_longjmp for +	nptl directory. +	* sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S: New file. +	* sysdeps/unix/sysv/linux/ia64/__sigstack_longjmp.c: New file. +	* sysdeps/unix/sysv/linux/ia64/unwind_longjmp.c: New file. + +2004-09-12  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h: Make rwlock prototypes available also +	for __USE_XOPEN2K. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define rwlock +	types also for __USE_XOPEN2K. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. +	[BZ #320] + +2004-09-08  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h +	(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Make safe for C++. +	(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise. +	(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP): Likewise. +	(PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP): Likewise. +	[BZ #375] + +2004-09-07  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Allow +	PSEUDO to be used with . prefix. + +	* sysdeps/unix/sysv/linux/alpha/pthread_once.c (__pthread_once): +	Use atomic_increment instead of atomic_exchange_and_add. +	* sysdeps/unix/sysv/linux/sparc/pthread_once.c (__pthread_once): +	Likewise. +	* sysdeps/unix/sysv/linux/ia64/pthread_once.c (__pthread_once): +	Likewise. +	* sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): +	Likewise. + +	* allocatestack.c (allocate_stack): Use atomic_increment_val +	instead of atomic_exchange_and_add. +	* sysdeps/unix/sysv/linux/sem_post.c (__new_sem_post): Likewise. +	* sysdeps/unix/sysv/linux/powerpc/sem_post.c (__new_sem_post): +	Likewise. +	* sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): +	Likewise. + +	* sysdeps/pthread/pthread.h (pthread_once): Remove __THROW since +	the initialization function might throw. + +2005-09-05  Richard Henderson  <rth@redhat.com> + +	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): +	Move definition inside libpthread, libc, librt check.  Provide +	definition for rtld. + +2004-09-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/alpha/jmpbuf-unwind.h: Define __libc_unwind_longjmp. +	* sysdeps/i386/jmpbuf-unwind.h: Likewise +	* sysdeps/powerpc/jmpbuf-unwind.h: Likewise. +	* sysdeps/s390/jmpbuf-unwind.h: Likewise. +	* sysdeps/sh/jmpbuf-unwind.h: Likewise. +	* sysdeps/sparc/sparc32/jmpbuf-unwind.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Likewise. +	* sysdeps/x86_64/jmpbuf-unwind.h: Likewise. +	* unwind.c: Use it. + +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): +	Rename __data.__clock to __data.__nwaiters, make it unsigned int. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: +	Decrement __nwaiters.  If pthread_cond_destroy has been called and +	this is the last waiter, signal pthread_cond_destroy caller and +	avoid using the pthread_cond_t structure after unlock. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	Read clock type from the least significant bits of __nwaiters instead +	of __clock. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/internaltypes.h: Define COND_CLOCK_BITS. + +2004-08-31  Jakub Jelinek  <jakub@redhat.com> + +	[BZ #342] +	* Makefile (tests): Add tst-cond20 and tst-cond21. +	* tst-cond20.c: New test. +	* tst-cond21.c: New test. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h +	(pthread_cond_t): Rename __data.__clock to __data.__nwaiters, make +	it unsigned int. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): +	Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +	(pthread_cond_t): Likewise. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): +	Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): +	Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): +	Likewise. +	* sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_clock): Remove. +	(cond_nwaiters): New. +	(clock_bits): New. +	* pthread_cond_destroy.c (__pthread_cond_destroy): Return EBUSY +	if there are waiters not signalled yet. +	Wait until all already signalled waiters wake up. +	* sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Decrement +	__nwaiters.  If pthread_cond_destroy has been called and this is the +	last waiter, signal pthread_cond_destroy caller and avoid using +	the pthread_cond_t structure after unlock. +	(__pthread_cond_wait): Increment __nwaiters in the beginning, +	decrement it when leaving.  If pthread_cond_destroy has been called +	and this is the last waiter, signal pthread_cond_destroy caller. +	* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): +	Likewise.  Read clock type from the least significant bits of +	__nwaiters instead of __clock. +	* pthread_condattr_setclock.c (pthread_condattr_setclock): Check +	whether clock ID can be encoded in COND_CLOCK_BITS bits. +	* pthread_condattr_getclock.c (pthread_condattr_getclock): Decode +	clock type just from the last COND_CLOCK_BITS bits of value. +	* pthread_cond_init.c (__pthread_cond_init): Initialize __nwaiters +	instead of __clock, just from second bit of condattr's value. + +2004-08-30  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Include +	bits/wordsize.h.  Make the header match i386 header when __WORDSIZE +	!= 64. +	* sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. + +2004-08-15  Roland McGrath  <roland@frob.com> + +	* pthread_atfork.c: Update copyright terms including special exception +	for these trivial files, which are statically linked into executables +	that use dynamic linking for the significant library code. + +2004-08-09  Jakub Jelinek  <jakub@redhat.com> + +	* DESIGN-rwlock.txt: Add decreasing of nr_readers_queued to +	pthread_rwlock_rdlock. +	* sysdeps/pthread/pthread_rwlock_rdlock (__pthread_rwlock_rdlock): +	Decrease __nr_readers_queued after reacquiring lock. +	* sysdeps/pthread/pthread_rwlock_timedrdlock +	(pthread_rwlock_timedrdlock): Likewise. +	Reported by Bob Cook <bobcook47@hotmail.com>. + +2004-08-11  Jakub Jelinek  <jakub@redhat.com> + +	* tst-rwlock14.c (tf): Read main thread handle from *ARG +	before pthread_barrier_wait. + +2004-08-07  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: +	Remove unnecessary exception handling data. + +2004-07-23  Jakub Jelinek  <jakub@redhat.com> + +	[BZ #284] +	* sysdeps/pthread/pthread.h (pthread_getcpuclockid): Use __clockid_t +	instead of clockid_t. + +2004-07-21  Roland McGrath  <roland@redhat.com> + +	* Makefile ($(objpfx)multidir.mk): Use $(make-target-directory). + +2004-07-19  Roland McGrath  <roland@redhat.com> + +	* tst-cancel4.c (tf_waitid): Use WEXITED flag bit if available. + +2004-07-02  Roland McGrath  <roland@redhat.com> + +	* configure: Don't exit. + +2004-07-14  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Check for invalid nanosecond in +	timeout value. + +2004-07-07  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile: Add rules to build and run tst-fini1. +	* tst-fini1.c: New file. +	* tst-fini1mod.c: New file. + +2004-07-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define NO_CANCELLATION +	if no cancellation support is needed. +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Define __NR_futex +	only if not already defined. + +2004-07-05  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_unlock): Use +	constraint "m" instead of "0" for futex. + +	* shlib-versions: Add powerpc64-.*-linux.*. + +2004-07-04  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S +	(pthread_rwlock_timedrdlock): Use cmpq instead of cmpl to check +	for valid tv_nsec. +	* tst-rwlock14.c (do_test): Test for invalid tv_nsec equal to +	1 billion and 64-bit tv_nsec which is valid when truncated to 32 +	bits. + +2004-06-29  Roland McGrath  <roland@redhat.com> + +	* Banner: NPTL no longer has its own version number. +	* Makefile (nptl-version): Variable removed. +	* sysdeps/pthread/Makefile (CFLAGS-confstr.c): Set LIBPTHREAD_VERSION +	using $(version), the glibc version number. + +2004-06-29  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/pthread_once.S (__pthread_once): +	Fix branch offset for a PLT entry. +	* sysdeps/unix/sysv/linux/sh/sem_post.S (__new_sem_post): +	Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): +	Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_trywait.S (__new_sem_trywait): +	Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_wait.S (__new_sem_wait): +	Likewise. + +2004-06-28  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/alpha/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Define +	unconditionally. + +2004-06-28  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread_rwlock_timedwrlock.c +	(pthread_rwlock_timedwrlock): Return EINVAL if tv_nsec is negative, +	instead of tv_sec. +	* sysdeps/pthread/pthread_rwlock_timedrdlock.c +	(pthread_rwlock_timedrdlock): Likewise. + +2004-06-22  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue): +	Set __r7 to val, not mutex. + +2004-06-27  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile: Add rules to build tst-rwlock14. +	* tst-rwlock14.c: New file. + +2004-06-24  Boris Hu  <boris.hu@intel.com> + +	* sysdeps/pthread/pthread_rwlock_timedrdlock.c: Add timeout validation +	check. +	* sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. + +2004-06-19  Andreas Jaeger  <aj@suse.de> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Fix +	assembler in last patch. + +2004-06-17  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread_cond_timedwait.c +	(__pthread_cond_timedwait): Also check for negativ nanoseconds. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Check for invalid nanosecond in +	timeout value. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* tst-cond19.c: New file. +	* Makefile: Add rules to build and run tst-cond19. + +2004-06-15  Steven Munroe  <sjmunroe@us.ibm.com> + +	* tst-context1.c (GUARD_PATTERN): Defined. +	(tst_context_t): Define struct containing ucontext_t & guard words. +	(ctx): Declare as an array of tst_context_t. +	(fct): Verify uc_link & guard words are still valid. +	(tf): Initialize guard words in ctx.  Adjust ctx refs for new struct. + +2004-06-13  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): +	Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S +	(__pthread_cond_signal): Increment __futex at the same time as +	__wakeup_seq or __total_seq.  Pass address of __futex instead of +	address of low 32-bits of __wakeup_seq to futex syscall. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S +	(__pthread_cond_wait): Likewise.  Pass __futex value from before +	releasing internal lock to FUTEX_WAIT. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S +	(FUTEX_CMP_REQUEUE): Define. +	(__pthread_cond_broadcast): Set __futex to 2 * __total_seq. +	Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. +	Pass __futex value from before the unlock and __futex address instead +	of address of low 32-bits of __wakeup_seq to futex syscall. +	Fallback to FUTEX_WAKE all on any errors. + +2004-06-08  Jakub Jelinek  <jakub@redhat.com> + +	* pthread_mutexattr_getpshared.c (pthread_mutex_getpshared): Fix +	comment typo. +	* pthread_mutexattr_gettype.c (pthread_mutexattr_gettype): Likewise. +	* pthread_mutexattr_init.c (__pthread_mutexattr_init): Likewise. +	* pthread_mutexattr_settype.c (__pthread_mutexattr_settype): Likewise. +	* pthread_mutexattr_setpshared.c (pthread_mutexattr_setpshared): +	Likewise.  Reported by Bob Cook <bobcook47@hotmail.com>. + +2004-06-11  Martin Schwidefsky  <schwidefsky@de.ibm.com> + +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_compare_and_swap): +	Add memory clobber to inline assembly. +	(__lll_mutex_trylock): Likewise. +	(__lll_mutex_cond_trylock): Likewise. + +2004-06-07  Martin Schwidefsky  <schwidefsky@de.ibm.com> + +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue): +	Pass val argument as 6th system call argument in %r7. + +2004-05-21  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-cond16. +	* sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_futex): Add. +	* pthread_cond_init.c (__pthread_cond_init): Clear __data.__futex. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): +	Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S +	(__pthread_cond_signal): Increment __futex at the same time as +	__wakeup_seq or __total_seq.  Pass address of __futex instead of +	address of low 32-bits of __wakeup_seq to futex syscall. +	* sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S +	(__pthread_cond_wait): Likewise.  Pass __futex value from before +	releasing internal lock to FUTEX_WAIT. +	* sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S +	(FUTEX_CMP_REQUEUE): Define. +	(__pthread_cond_broadcast): Set __futex to 2 * __total_seq. +	Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. +	Pass __futex value from before the unlock and __futex address instead +	of address of low 32-bits of __wakeup_seq to futex syscall. +	Fallback to FUTEX_WAKE all on any errors. +	* sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_CMP_REQUEUE): +	Define. +	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE +	internally.  Return non-zero if error, zero if success. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): +	Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_CMP_REQUEUE): +	Define. +	(lll_futex_requeue): Add val argument, return 1 unconditionally +	for the time being. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): +	Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_CMP_REQUEUE): +	Define. +	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE +	internally.  Return non-zero if error, zero if success. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +	(pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_CMP_REQUEUE): +	Define. +	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE +	internally.  Return non-zero if error, zero if success. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): +	Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_CMP_REQUEUE): +	Define. +	(lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE +	internally.  Return non-zero if error, zero if success. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): +	Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): +	Add __data.__futex field, reshuffle __data.__clock. +	* sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): +	Increment __futex at the same time as __wakeup_seq or __total_seq. +	Pass address of __futex instead of address of low 32-bits of +	__wakeup_seq to futex syscall. +	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. +	Pass __futex value from before releasing internal lock +	to FUTEX_WAIT. +	* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): +	Likewise.  Avoid unnecessary shadowing of variables. +	* sysdeps/pthread/pthread_cond_broadcast.c (__pthread_cond_broadcast): +	Set __futex to 2 * __total_seq.  Pass __futex value from before the +	unlock and __futex address instead of address of low 32-bits of +	__wakeup_seq to futex_requeue macro, adjust for new return value +	meaning. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S +	(__pthread_cond_signal): Increment __futex at the same time as +	__wakeup_seq or __total_seq.  Pass address of __futex instead of +	address of low 32-bits of __wakeup_seq to futex syscall. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S +	(__pthread_cond_wait): Likewise.  Pass __futex value from before +	releasing internal lock to FUTEX_WAIT. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S +	(FUTEX_CMP_REQUEUE): Define. +	(__pthread_cond_broadcast): Set __futex to 2 * __total_seq. +	Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. +	Pass __futex value from before the unlock and __futex address instead +	of address of low 32-bits of __wakeup_seq to futex syscall. +	Fallback to FUTEX_WAKE all on any errors. + +2004-06-03  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_mutex_lock): +	Add nop to align the end of critical section. +	(lll_mutex_cond_lock, lll_mutex_timedlock): Likewise. + +2004-06-01  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): +	Add __broadcast_seq field. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Mark +	all waiters as woken with woken_seq and bump broadcast counter. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Use new +	__broadcast_seq.  Increment __woken_seq correctly when cleanuped. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. +	Comment typo fixes.  Avoid returning -ETIMEDOUT. + +2004-06-01  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__condvar_tw_cleanup): Fix access to saved broadcast_seq value. +	Reported by Kaz Kojima. + +2004-05-25  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/aio_misc.h: New file. + +2004-05-21  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Compare +	__broadcast_seq with bc_seq after acquiring internal lock instead of +	before it. + +2004-05-18  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (.NOTPARALLEL): Only serialize make check/xcheck, not +	compilation. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Avoid returning -ETIMEDOUT. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h +	(pthread_cond_t): Add __data.__broadcast_seq field. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +	(FRAME_SIZE): Define. +	(__pthread_cond_timedwait): Use it.  Store/check broadcast_seq. +	Comment typo fixes. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S (FRAME_SIZE): +	Define. +	(__pthread_cond_wait): Use it.  Store/check broadcast_seq.  Comment +	typo fixes. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S +	(__pthread_cond_broadcast): Increment broadcast_seq.  Comment typo +	fixes. + +2004-05-18  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/lowlevelcond.sym: Add broadcast_seq entry. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): +	Add __broadcast_seq field. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Mark +	all waiters as woken with woken_seq and bump broadcast counter. +	* sysdeps/pthread/pthread_cond_broadcast.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Use new +	__broadcast_seq field. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/pthread/pthread_cond_wait.c: Likewise. +	* sysdeps/pthread/pthread_cond_timedwait.c: Likewise. +	* pthread_cond_init.c: Initialize __broadcast_seq field. +	* Makefile (tests): Add tst-cond17 and tst-cond18. +	Add .NOTPARALLEL goal. +	* tst-cond16.c: New file.  From Jakub. +	* tst-cond17.c: New file.  From Jakub. +	* tst-cond18.c: New file.  From Jakub. + +2004-05-16  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Correct some +	unwind info. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: +	Parametrize frame size.  Correct some unwind info. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +2004-05-04  Jakub Jelinek  <jakub@redhat.com> + +	* tst-stack3.c: Note testing functionality beyond POSIX. + +2004-05-04  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (USE___THREAD): +	Change conditional from ifdef to if. + +2004-04-23  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SYSDEP_CANCEL_ERRNO, +	SYSDEP_CANCEL_ERROR): Define. +	(PSEUDO): Use it. + +2004-05-01  Jakub Jelinek  <jakub@redhat.com> + +	* Versions (libpthread): Remove __pthread_cleanup_upto@@GLIBC_PRIVATE. + +2004-04-20  Jakub Jelinek  <jakub@redhat.com> + +	* sem_unlink.c (sem_unlink): Change EPERM into EACCES. + +2004-04-19  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Add frame info. +	Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. +	* sysdeps/unix/sysv/linux/sh/sem_wait.S: Remove unneeded frame +	info.  Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. + +2004-04-19  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/timer_routines.c: Make sure helper +	thread has all signals blocked. + +2004-04-18  Andreas Jaeger  <aj@suse.de> + +	* sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h +	(SEM_VALUE_MAX): Add missing brace. + +2004-04-17  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/Makefile (tests): Add tst-mqueue8x +	in rt subdir. +	(CFLAGS-tst-mqueue8x.c): Add -fexceptions. +	* sysdeps/pthread/tst-mqueue8x.c: New test. +	* tst-cancel4.c: Update comment about message queues. + +	* sysdeps/pthread/timer_gettime.c (timer_gettime): For expired timer +	return it_value { 0, 0 }. +	* sysdeps/pthread/timer_create.c (timer_create): Handle SIGEV_NONE +	like SIGEV_SIGNAL. +	* sysdeps/pthread/timer_routines.c (thread_expire_timer): Remove +	assertion for SIGEV_NONE. +	(thread_attr_compare): Compare all attributes, not just a partial +	subset. + +2004-04-17  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/mq_notify.c: Include stdlib.h. + +2004-04-17  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/alpha/bits/semaphore.h (SEM_VALUE_MAX): +	Just use a plain number. +	* sysdeps/unix/sysv/linux/i386/bits/semaphore.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/semaphore.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/semaphore.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. + +2004-04-16  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Remove unneeded +	frame info. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + +2004-04-15  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/timer_routines.c: Include errno.h. +	(timer_helper_thread): Use inline rt_sigtimedwait syscall instead +	of calling sigwaitinfo. + +2004-04-16  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (allocate_stack): Set reported_guardsize +	unconditionally. +	* pthread_getattr_np.c (pthread_getattr_np): Use +	reported_guardsize instead of guardsize. +	* descr.h (struct pthread): Add reported_guardsize field. + +2004-04-13  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/mq_notify.c: Shut up GCC warning. + +2004-04-12  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/mq-notify.c: New file. + +2004-04-08  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/bits/local_lim.h (MQ_PRIO_MAX): Define. +	* sysdeps/unix/sysv/linux/alpha/bits/local_lim.h (MQ_PRIO_MAX): Define. +	* sysdeps/unix/sysv/linux/ia64/bits/local_lim.h (MQ_PRIO_MAX): Define. +	* sysdeps/unix/sysv/linux/sparc/bits/local_lim.h (MQ_PRIO_MAX): Define. +	* sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_MESSAGE_PASSING): +	Define. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h +	(_POSIX_MESSAGE_PASSING): Define. +	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h +	(_POSIX_MESSAGE_PASSING): Define. +	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h +	(_POSIX_MESSAGE_PASSING): Define. + +2004-04-04  Ulrich Drepper  <drepper@redhat.com> + +	* tst-context1.c (fct): Check whether correct stack is used. + +2004-04-03  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Never use +	matching constraints for asm mem parameters. + +	* tst-clock2.c (tf): Don't define unless needed. + +2004-03-30  H.J. Lu  <hongjiu.lu@intel.com> + +	* Makefile (link-libc-static): Use $(static-gnulib) instead of +	$(gnulib). + +2004-03-30  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread-functions.h: Add ptr__nptl_deallocate_tsd. +	* init.c (pthread_functions): Add ptr__nptl_deallocate_tsd. +	* pthreadP.h: Declare __nptl_deallocate_tsd. +	* pthread_create.c (deallocate_tsd): Remove to __nptl_deallocate_tsd. +	Adjust caller. + +	* Makefile (tests): Add tst-tsd5. +	* tst-tsd5.c: New file. + +2004-03-29  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c +	(__pthread_attr_setaffinity_old): Prepend GLIBC_ to version names +	is SHLIB_COMPAT check. +	* sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c +	(__pthread_attr_getaffinity_old): Likewise. +	* sysdeps/unix/sysv/linux/pthread_getaffinity.c +	(__pthread_getaffinity_old): Likewise. +	* sysdeps/unix/sysv/linux/pthread_setaffinity.c +	(__pthread_setaffinity_old): Likewise. + +2004-03-26  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (_make_stacks_executable): Call +	_dl_make_stack_executable first. + +2004-03-24  Roland McGrath  <roland@redhat.com> + +	* sysdeps/i386/pthread_spin_lock.c (pthread_spin_lock): Use "m" +	constraint instead of "0". + +2004-03-24  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h +	(lll_mutex_cond_trylock): Define as wrapper around __lll_cond_trylock. + +	* sysdeps/unix/sysv/linux/getpid.c (really_getpid): Reorganize +	code to avoid warning. + +2004-03-24  Andreas Jaeger  <aj@suse.de> + +	* sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c +	(__pthread_attr_setaffinity_old): Remove const. + +2004-03-23  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/smp.h: New file. +	* sysdeps/unix/sysv/linux/sh/smp.h: New file. +	* init.c: Define __is_smp. +	(__pthread_initialize_minimal_internal): Call is_smp_system to +	initialize __is_smp. +	* pthreadP.h: Declare __is_smp. +	Define MAX_ADAPTIVE_COUNT is necessary. +	* pthread_mutex_init.c: Add comment regarding __spins field. +	* pthread_mutex_lock.c: Implement adaptive mutex type. +	* pthread_mutex_timedlock.c: Likewise. +	* sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t): +	Add __spins field. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define +	lll_mutex_cond_trylock. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. +	Define BUSY_WAIT_NOP. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +	* tst-mutex5.c: Add support for testing adaptive mutexes. +	* tst-mutex7.c: Likewise. +	* tst-mutex5a.c: New file. +	* tst-mutex7a.c: New file. +	* Makefile (tests): Add tst-mutex5a and tst-mutex7a. + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +	(__lll_mutex_timedlock_wait): Preserve r8 and r9 since the +	vgettimeofday call might destroy the content. + +	* sysdeps/ia64/pthread_spin_lock.c (pthread_spin_lock): Use hint +	@pause in the loop. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_mutex_trylock): +	No need to restrict type of ret.  Make it int.  Add comment. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_mutex_trylock): +	Remove unnecessary setne instruction. + +2004-03-22  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/pthread_getaffinity.c +	(__pthread_getaffinity_new): Use INT_MAX instead of UINT_MAX. +	* pthread_getattr_np.c (pthread_getattr_np): Double size every cycle. +	If realloc fails, break out of the loop. + +2004-03-20  Andreas Jaeger  <aj@suse.de> + +	* sysdeps/unix/sysv/linux/pthread_setaffinity.c +	(__pthread_setaffinity_old): Fix interface. +	* sysdeps/unix/sysv/linux/pthread_getaffinity.c +	(__pthread_getaffinity_old): Likewise. + +	* sysdeps/unix/sysv/linux/pthread_setaffinity.c +	(__pthread_setaffinity_new): Remove duplicate declaration. + +2004-03-20  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (CENABLE): Save +	the return value to a safe register. +	(CDISABLE): Set the function argument correctly. + +2004-03-17  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h (XCHG): Define. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_mutex_lock_wait): +	Rewrite so that only one locked memory operation per round is needed. +	* sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S +	(pthread_barrier_wait): After wakeup, release lock only when the +	last thread stopped using the barrier object. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S +	(__pthread_cond_wait): Don't store mutex address if the current +	value is ~0l.  Add correct cleanup support and unwind info. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S +	(__pthread_cond_broadcast): Don't use requeue for pshared condvars. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Update comment. +	* sysdeps/unix/sysv/linux/sh/pthread_once.S (__pthread_once): +	Add correct cleanup support and unwind info. +	* sysdeps/unix/sysv/linux/sh/sem_wait.S (__new_sem_wait): Likewise. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Add unwind +	information for syscall wrappers. + +2004-03-18  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_attr): Add +	cpusetsize field, remove next. +	* sysdeps/pthread/pthread.h (pthread_getaffinity_np): Add new second +	parameter for size of the CPU set. +	(pthread_setaffinity_np): Likewise. +	(pthread_attr_getaffinity_np): Likewise. +	(pthread_attr_setaffinity_np): Likewise. +	* sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: Implement +	interface change, keep compatibility code. +	* sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: Likewise. +	* sysdeps/unix/sysv/linux/pthread_getaffinity.c: Likewise. +	* sysdeps/unix/sysv/linux/pthread_setaffinity.c: Likewise. +	* pthreadP.h: Remove hidden_proto for pthread_getaffinity_np.  Declare +	__pthread_getaffinity_np. +	* Versions: Add version for changed interfaces. +	* tst-attr3.c: Adjust test for interface change. +	* pthread_getattr_np.c: Query the kernel about the affinity mask with +	increasing buffer sizes. +	* pthread_attr_destroy.c: Remove unused list handling. +	* pthread_attr_init.c: Likewise. + +2004-03-17  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/timer_create.c (timer_create): Pass missing +	first argument to clock_getres so we ever enable kernel timers. + +2004-03-15  Ulrich Weigand  <uweigand@de.ibm.com> + +	* init.c (nptl_version): Add __attribute_used__ to nptl_version. + +2004-03-12  Richard Henderson  <rth@redhat.com> + +	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: Propagate +	oldvalue from CENABLE to CDISABLE. + +2004-03-12  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/bits/local_lim.h: Define HOST_NAME_MAX. +	* sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise. +	* sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise. + +2004-03-11  Richard Henderson  <rth@redhat.com> + +	* sysdeps/alpha/tcb-offsets.sym (PID_OFFSET): New. +	* sysdeps/unix/sysv/linux/alpha/pt-vfork.S: Save/restore PID. +	* sysdeps/unix/sysv/linux/alpha/vfork.S: New file. + +2004-03-11  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Use jgnl +	instead of jnl instruction to jump to SYSCALL_ERROR_LABEL. +	* sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S (__vfork): Likewise. + +2004-03-11  Jakub Jelinek  <jakub@redhat.com> + +	* forward.c (__pthread_cond_broadcast_2_0, +	__pthread_cond_destroy_2_0, __pthread_cond_init_2_0, +	__pthread_cond_signal_2_0, __pthread_cond_wait_2_0, +	__pthread_cond_timedwait_2_0): Use return 0 as defaction instead of 0. + +2004-03-11  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/sh/tcb-offsets.sym: Add PID. +	* sysdeps/unix/sysv/linux/sh/pt-vfork.S: Properly handle PID cache. +	* sysdeps/unix/sysv/linux/sh/vfork.S: New file. + +2004-03-10  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: No need to +	include <sysdep-cancel.h>, vfork is no cancellation point. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S: Likewise. + +2004-03-10  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/s390-32/vfork.S (__vfork): Add +	libc_hidden_def. +	* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S (__vfork): +	Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S (__vfork): +	Likewise. +	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): Likewise. +	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S (__vfork): Likewise. +	* sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Include tcb-offsets.h. +	* sysdeps/unix/sysv/linux/ia64/vfork.S (__vfork): Use DO_CALL instead +	of DO_CALL_VIA_BREAK.  Work around a gas problem. + +	* sysdeps/unix/sysv/linux/powerpc/pt-vfork.S: Remove. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S: New file. +	* sysdeps/powerpc/tcb-offsets.sym: Add PID. + +	* sysdeps/unix/sysv/linux/ia64/pt-vfork.S (__vfork): Don't use +	a local register for saving old PID.  Negate PID in parent upon exit. + +	* sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S: Include +	tcb-offsets.h. +	(__vfork): Negate PID if non-zero and set to INT_MIN if zero +	before syscall, set to the old value in the parent afterwards. +	* sysdeps/unix/sysv/linux/s390/s390-32/vfork.S: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S: Include +	tcb-offsets.h. +	(__vfork): Negate PID if non-zero and set to INT_MIN if zero +	before syscall, set to the old value in the parent afterwards. +	* sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: New file. +	* sysdeps/s390/tcb-offsets.sym: Add PID. + +	* sysdeps/unix/sysv/linux/sparc/pt-vfork.S: Remove. +	* sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S: New file. +	* sysdeps/sparc/tcb-offsets.sym: Add PID. + +2004-03-10  Andreas Schwab  <schwab@suse.de> + +	* sysdeps/ia64/tcb-offsets.sym: Add PID. +	* sysdeps/unix/sysv/linux/ia64/vfork.S: New file. +	* sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Properly handle PID cache. + +2004-03-09  Jakub Jelinek  <jakub@redhat.com> + +	* tst-cancel20.c (do_one_test): Clear in_sh_body first. +	* tst-cancel21.c (do_one_test): Likewise. +	Reported by Gordon Jin <gordon.jin@intel.com>. + +2004-02-09  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/vfork.S (SAVE_PID): Negate PID +	if non-zero and set to INT_MIN if zero. +	* sysdeps/unix/sysv/linux/x86_64/vfork.S (SAVE_PID): Likewise. +	* sysdeps/unix/sysv/linux/i386/pt-vfork.S: Include tcb-offsets.h. +	(SAVE_PID, RESTORE_PID): Define. +	(__vfork): Use it. +	* sysdeps/unix/sysv/linux/x86_64/pt-vfork.S: Include tcb-offsets.h. +	Use relative path to avoid including NPTL i386/vfork.S. +	(SAVE_PID, RESTORE_PID): Define. +	* sysdeps/unix/sysv/linux/raise.c: Include limits.h. +	(raise): Handle THREAD_SELF->pid INT_MIN the same as 0. +	* Makefile (tests): Add tst-vfork1, tst-vfork2, tst-vfork1x and +	tst-vfork2x. +	(tests-reverse): Add tst-vfork1x and tst-vfork2x. +	* tst-vfork1.c: New test. +	* tst-vfork2.c: New test. +	* tst-vfork1x.c: New test. +	* tst-vfork2x.c: New test. + +2004-03-08  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/tcb-offsets.sym: Add PID. +	* sysdeps/x86_64/tcb-offsets.sym: Likewise. +	* sysdeps/unix/sysv/linux/i386/vfork.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/vfork.S: New file. + +2004-03-08  Steven Munroe  <sjmunroe@us.ibm.com> + +	* sysdeps/unix/sysv/linux/powerpc/Versions: Remove leading tabs. + +2004-03-08  H.J. Lu  <hongjiu.lu@intel.com> + +	* sysdeps/s390/tls.h (INIT_SYSINFO): _dl_sysinfo is now in +	_rtld_global_ro. + +2004-03-07  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/ia64/tls.h (INIT_SYSINFO): _dl_sysinfo is now in +	_rtld_global_ro. + +	* tst-once4.c: Remove unnecessary macro definition. + +	* tst-mutex7.c (do_test): Limit thread stack size. +	* tst-once2.c (do_test): Likewise. +	* tst-tls3.c (do_test): Likewise. +	* tst-tls1.c (do_test): Likewise. +	* tst-signal3.c (do_test): Likewise. +	* tst-kill6.c (do_test): Likewise. +	* tst-key4.c (do_test): Likewise. +	* tst-join4.c (do_test): Likewise. +	* tst-fork1.c (do_test): Likewise. +	* tst-context1.c (do_test): Likewise. +	* tst-cond2.c (do_test): Likewise. +	* tst-cond10.c (do_test): Likewise. +	* tst-clock2.c (do_test): Likewise. +	* tst-cancel10.c (do_test): Likewise. +	* tst-basic2.c (do_test): Likewise. +	* tst-barrier4.c (do_test): Likewise. + +2004-03-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/tls.h: Use GLRO instead of GL where appropriate. + +2004-03-01  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Optimize wakeup test. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +	(__pthread_cond_wait): Likewise. +	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. +	* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): +	Likewise. + +2004-02-29  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +	(__lll_mutex_lock_wait): Optimize a bit more.  Just one copy of +	the atomic instruction needed. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +	(__lll_mutex_lock_wait): Likewise. + +2004-02-28  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-cond14 and tst-cond15. +	* tst-cond14.c: New file. +	* tst-cond15.c: New file. + +2004-02-27  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/createthread.c (create_thread): Remove use of +	CLONE_STOPPED.  We cannot use SIGCONT which means CLONE_STOPPED +	needs to be implemented differently to be useful. + +2004-02-26  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_attr_setschedparam.c: Don't test priority against limits +	here.  Set ATTR_FLAG_SCHED_SET flag. +	* pthread_attr_setschedpolicy.c: Set ATTR_FLAG_POLICY_SET flag. +	* pthread_create.c (__pthread_create_2_1): Copy scheduling attributes +	from parent thread to child.  If attribute is used and scheduling +	parameters are not inherited, copy parameters from attribute or +	compute them.  Check priority value. +	* pthread_getschedparam.c: If the parameters aren't known yet get +	them from the kernel. +	* pthread_setschedparam.c: Set ATTR_FLAG_SCHED_SET and +	ATTR_FLAG_POLICY_SET flag for thread. +	* sysdeps/unix/sysv/linux/internaltypes.h: Define ATTR_FLAG_SCHED_SET +	and ATTR_FLAG_POLICY_SET. + +	* sysdeps/pthread/createthread.c: Use tgkill if possible. + +	* pthread_attr_getstackaddr.c (__pthread_attr_getstackaddr): Don't +	fail if stack address hasn't been set.  Just return 0. + +2004-02-25  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests-nolibpthread): Add tst-unload.  Don't link with +	libpthread for the files in this list. +	(CFLAGS-tst-unload): Removed. +	* tst-unload.c (do_test): Don't use complete path for +	LIBPHREAD_SO. + +	* Makefile: Define sonames for tst-tls5mod, tst-_res1mod1, and +	tst-_res1mod2. + +2004-02-22  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +	(__lll_mutex_lock_wait): Rewrite so that only one locked memory +	operation per round is needed. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +	(__lll_mutex_lock_wait): Likewise. + +2004-02-20  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel9.c (cleanup): Don't print to stderr. + +2004-02-20  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/sh/jmpbuf-unwind.h (_JMPBUF_UNWINDS_ADJ): Fix variable name. + +2004-02-20  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h +	(__syscall_error_handler2): Call CDISABLE. +	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h +	(__syscall_error_handler2): Call CDISABLE. + +	* sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): +	Release lock before the loop, don't reacquire it. + +	* sysdeps/unix/sysv/linux/ia64/dl-sysdep.h (DL_ARGV_NOT_RELRO): Define. + +2004-02-19  Andreas Schwab  <schwab@suse.de> + +	* sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): +	Fix last change. + +2004-02-18  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S +	(pthread_barrier_wait): After wakeup, release lock only when the +	last thread stopped using the barrier object. +	* sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S +	(pthread_barrier_wait): Likewise. +	* sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): +	Likewise. +	* Makefile (tests): Add tst-barrier4. +	* tst-barrier4.c: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Perform timeout test while holding +	internal lock to prevent wakeup race. +	Patch by Dinakar Guniguntala <dgunigun@in.ibm.com>. +	* sysdeps/pthread/pthread_cond_timedwait.c +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Likewise. + +2004-02-18  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S +	(__pthread_rwlock_unlock): Access WRITER as 32-bit value. +	* Makefile (tests): Add tst-rwlock13. +	* tst-rwlock13.c: New test. + +2004-02-16  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__condvar_tw_cleanup): Little optimization. +	Patch by Dinakar Guniguntala <dgunigun@in.ibm.com>. + +2004-02-16  Steven Munroe  <sjmunroe@us.ibm.com> + +	* sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: Replace libc with +	libpthread as "lib" parameter to SHLIB_COMPAT. +	(__novmx_siglongjmp): Fix typo in function name. +	(__novmx_longjmp): Fix typo in function name. + +2004-02-13  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Add a +	__builtin_expect. + +	* sysdeps/generic/pt-longjmp.c: Moved to... +	* sysdeps/pthread/pt-longjmp.c: ...here.  New file. + +2004-01-29  Steven Munroe  <sjmunroe@us.ibm.com> + +	* Makefile (libpthread-routines): Add pt-cleanup. +	* pt-longjmp.c: Removed. +	* pt-cleanup.c: Copied __pthread_cleanup_upto to here. New file. +	* sysdeps/generic/pt-longjmp.c: Copied longjmp to here. New file. +	* sysdeps/unix/sysv/linux/powerpc/Versions: New file. +	Version longjmp, siglongjmp for GLIBC_2.3.4. +	* sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: New File. + +2004-02-13  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread_cond_timedwait.c +	(__pthread_cond_timedwait): Optimize.  Drop internal lock earlier. +	Reuse code.  Add __builtin_expects. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Get internal lock in case timeout has +	passed before the futex syscall. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2004-01-20  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c: Pretty printing. + +	* sysdeps/pthread/createthread.c (create_thread): Don't add +	CLONE_DETACHED bit if it is not necessary. + +2004-01-16  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_getattr_np.c: Include ldsodefs.h. + +2004-01-16  Richard Henderson  <rth@redhat.com> + +	* allocatestack.c: Don't declare __libc_stack_end. +	* init.c (__pthread_initialize_minimal_internal): Likewise. +	* pthread_getattr_np.c (pthread_getattr_np): Likewise. + +2004-01-15  Richard Henderson  <rth@redhat.com> + +	* sysdeps/alpha/tls.h (tcbhead_t): Add private. +	(TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN, TLS_TCB_SIZE, +	TLS_PRE_TCB_SIZE, TLS_TCB_ALIGN, INSTALL_DTV, INSTALL_NEW_DTV, +	GET_DTV, THREAD_DTV, THREAD_SELF, DB_THREAD_SELF): Match ia64. +	(TLS_TCB_OFFSET, THREAD_ID, NO_TLS_OFFSET): Remove. +	(THREAD_GETMEM, THREAD_GETMEM_NC): Simplify. +	(THREAD_SETMEM, THREAD_SETMEM_NC): Likewise. +	* sysdeps/unix/sysv/linux/alpha/createthread.c (TLS_VALUE): Match ia64. + +2004-01-14  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (pthread_functions): Make array const. + +2004-01-13  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (__make_stacks_executable): Change interface. +	Check parameters.  Pass parameter on to libc counterpart. +	* pthreadP.h: Change declaration. + +2004-01-13  Richard Henderson  <rth@redhat.com> + +	* pthread_attr_setstack.c (__old_pthread_attr_setstack): Use +	prototype form. +	* pthread_attr_setstacksize.c (__old_pthread_attr_setstacksize): +	Likewise. + +	* sysdeps/alpha/Makefile: New file. +	* sysdeps/alpha/tcb-offsets.sym: New file. +	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): +	Use MULTIPLE_THREADS_OFFSET to implement !libpthread !libc version. + +	* sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Rewrite based +	on powerpc version. + +2004-01-08  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-backtrace1. +	* tst-backtrace1.c: New test. + +2003-12-11  Ulrich Weigand  <uweigand@de.ibm.com> + +	* sysdeps/alpha/tls.h (DB_THREAD_SELF): Pass bit size of thread +	register as second parameter to the REGISTER macro. +	* sysdeps/ia64/tls.h (DB_THREAD_SELF): Likewise. +	* sysdeps/powerpc/tls.h (DB_THREAD_SELF): Likewise. +	* sysdeps/sh/tls.h (DB_THREAD_SELF): Likewise. +	* sysdeps/sparc/tls.h (DB_THREAD_SELF): Likewise. +	* sysdeps/s390/tls.h (DB_THREAD_SELF): Pass __WORDSIZE as bit size +	of thread register as second parameter to REGISTER macro in 64 case. + +2004-01-03  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/Makefile (CFLAGS-getpid.c): Removed. +	(CFLAGS-getpid.o): Defined. +	(CFLAGS-getpid.os): Defined. + +2003-12-31  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_getattr_np.c (pthread_getattr_np): Make sure stack info +	returned for main thread does not overlap with any other VMA. +	Patch by Jakub Jelinek. + +2003-12-29  Jakub Jelinek  <jakub@redhat.com> + +	* tst-raise1.c: Include stdio.h. + +2003-12-23  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/raise.c (raise): Protect pid = selftid +	setting with __ASSUME_TGKILL || defined __NR_tgkill. +	If pid is 0, set it to selftid. +	* sysdeps/unix/sysv/linux/getpid.c (really_getpid): Make inline. +	Don't set self->pid but self->tid.  If self->pid == 0 and self->tid +	!= 0, return self->tid without doing a syscall. +	* descr.h (struct pthread): Move pid field after tid. + +	* Makefile (tests): Add tst-raise1. +	* tst-raise1.c: New file. + +2003-12-23  Roland McGrath  <roland@redhat.com> + +	* tst-oddstacklimit.c: New file. +	* Makefile (tests): Add it. +	(tst-oddstacklimit-ENV): New variable. + +	* init.c (__pthread_initialize_minimal_internal): Round stack rlimit +	value up to page size for __default_stacksize. + +2003-12-21  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-eintr5. +	* tst-eintr5.c: New file. + +	* eintr.c (eintr_source): Prevent sending signal to self. + +	* tst-eintr2.c (tf1): Improve error message. + +2003-12-20  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/Makefile (CFLAGS-getpid.c): Define. +	* sysdeps/unix/sysv/linux/getpid.c: New file. +	* pthread_cancel.c: Add comment explaining use of PID field. +	* sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. +	* pthread_getattr_np.c: Use abs() when comparing PID and TID fields. +	* sysdeps/unix/sysv/linux/fork.c: Negate PID field of parent +	temporarily to signal the field must not be relied on and updated +	by getpid(). +	* sysdeps/unix/sysv/linux/pt-raise.c: Handle case where PID is +	temporarily negative. +	* sysdeps/unix/sysv/linux/raise.c: Likewise. + +2003-12-19  Ulrich Drepper  <drepper@redhat.com> + +	* eintr.c (setup_eintr): Add new parameter.  Pass to thread function. +	(eintr_source): If ARG != NULL, use pthread_kill. +	* tst-eintr1.c: Adjust for this change. +	* tst-eintr2.c: Likewise. +	* Makefile (tests): Add tst-eintr3 and tst-eintr4. +	* tst-eintr3.c: New file. +	* tst-eintr4.c: New file. + +2003-12-19  Jakub Jelinek  <jakub@redhat.com> + +	* libc-cancellation.c (__libc_enable_asynccancel): Don't cancel +	if CANCELSTATE_BITMASK is set. +	* sysdeps/pthread/librt-cancellation.c (__librt_enable_asynccancel): +	Likewise. + +	* Makefile (tests): Add tst-cancel22 and tst-cancel23. +	(tests-reverse): Add tst-cancel23. +	* tst-cancel22.c: New test. +	* tst-cancel23.c: New test. + +2003-12-18  Ulrich Drepper  <drepper@redhat.com> + +	* tst-eintr1.c: Better error messages. + +	* Makefile (tests): Add tst-eintr2. +	* tst-eintr2.c: New file. + +2003-12-18  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-cancel21 and tst-cancelx21. +	(CFLAGS-tst-cancelx21.c): Set. +	* tst-cancel21.c: New test. +	* tst-cancelx21.c: New test. + +	* unwind.c (FRAME_LEFT): Add adj argument.  Subtract it from each +	comparison operand. +	(unwind_stop): Use _JMPBUF_CFA_UNWINDS_ADJ macro instead of +	_JMPBUF_CFA_UNWINDS.  Adjust FRAME_LEFT invocations. +	* pt-longjmp.c: Include jmpbuf-unwind.h. +	(__pthread_cleanup_upto): Use _JMPBUF_UNWINDS_ADJ macro instead of +	_JMPBUF_UNWINDS.  Adjust compared pointers. +	* init.c (__pthread_initialize_minimal_internal): Initialize +	pd->stackblock_size. +	* sysdeps/pthread/jmpbuf-unwind.h: Removed. +	* sysdeps/alpha/jmpbuf-unwind.h: New file. +	* sysdeps/i386/jmpbuf-unwind.h: New file. +	* sysdeps/powerpc/jmpbuf-unwind.h: New file. +	* sysdeps/s390/jmpbuf-unwind.h: New file. +	* sysdeps/sh/jmpbuf-unwind.h: New file. +	* sysdeps/sparc/sparc32/jmpbuf-unwind.h: New file. +	* sysdeps/x86_64/jmpbuf-unwind.h: New file. +	* sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Include stdint.h. +	(_JMPBUF_CFA_UNWINDS): Remove. +	(_JMPBUF_CFA_UNWINDS_ADJ, _JMPBUF_UNWINDS_ADJ): Define. + +2003-12-12  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-cancel20 and tst-cancelx20. +	(CFLAGS-tst-cancelx20.c): Set. +	* tst-cancel20.c: New test. +	* tst-cancelx20.c: New test. + +2003-12-17  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (__pthread_initialize_minimal_internal): Don't treat +	architectures with separate register stack special here when +	computing default stack size. + +2003-12-17  Roland McGrath  <roland@redhat.com> + +	* Makefile (tst-cancelx7-ARGS): New variable. +	Reportd by Greg Schafer <gschafer@zip.com.au>. + +2003-12-17  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-stack3.  Depend on $(objpfx)tst-stack3-mem. +	(generated): Add tst-stack3.mtrace and tst-stack3-mem. +	(tst-stack3-ENV): Set. +	($(objpfx)tst-stack3-mem): New. +	* tst-stack3.c: New test. + +2003-12-10  David Mosberger  <davidm@hpl.hp.com> + +	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c (_init_EPILOG_BEGINS): +	Add unwind directives.  Drop unused .regstk directive. +	(_fini_EPILOG_BEGINS): Add unwind directives. + +2003-12-11  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait): +	Assume parameter is a pointer. +	(lll_futex_wake): Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_futex_wait): +	Likewise. +	(lll_futex_wake): Likewise. +	Reported by Boris Hu. +	* sysdeps/unix/sysv/linux/unregister-atfork.c +	(__unregister_atfork): Pass pointer to refcntr to lll_futex_wait. + +	* sysdeps/unix/sysv/linux/sem_wait.c (__new_sem_wait): Simplify a bit. + +2003-12-10  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/bits/libc-lock.h (__rtld_lock_initialize): Define. +	* sysdeps/unix/sysv/linux/fork.c (__libc_fork): Call +	__rtld_lock_initialize for ld.so lock. +	Patch in part by Adam Li <adam.li@intel.com>. + +2003-12-02  David Mosberger  <davidm@hpl.hp.com> + +	* Makefile (link-libc-static): Remove -lgcc_eh---it's already mentioned +	in $(gnulib).  Also, remove stale comment. + +2003-11-12  David Mosberger  <davidm@hpl.hp.com> + +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO): Take +	advantage of new syscall stub and optimize accordingly. + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__NR_futex): Rename +	from SYS_futex, to match expectations of +	sysdep.h:DO_INLINE_SYSCALL. +	(lll_futex_clobbers): Remove. +	(lll_futex_timed_wait): Rewrite in terms of DO_INLINE_SYSCALL. +	(lll_futex_wake): Likewise. +	(lll_futex_requeue): Likewise. +	(__lll_mutex_trylock): Rewrite to a macro, so we can include this +	file before DO_INLINE_SYSCALL is defined (proposed by Jakub +	Jelinek). +	(__lll_mutex_lock): Likewise. +	(__lll_mutex_cond_lock): Likewise. +	(__lll_mutex_timed_lock): Likewise. +	(__lll_mutex_unlock): Likewise. +	(__lll_mutex_unlock_force): Likewise. + +	* sysdeps/ia64/tls.h: Move declaration of __thread_self up so it +	comes before the include of <sysdep.h>. +	(THREAD_SELF_SYSINFO): New macro. +	(THREAD_SYSINFO): Likewise. +	(INIT_SYSINFO): New macro. +	(TLS_INIT_TP): Call INIT_SYSINFO. + +	* sysdeps/ia64/tcb-offsets.sym: Add SYSINFO_OFFSET. + +	* sysdeps/pthread/createthread.c (create_thread): Use +	THREAD_SELF_SYSINFO and THREAD_SYSINFO instead of open code. +	* allocatestack.c (allocate_stack): Use THREAD_SYSINFO and +	THREAD_SELF_SYSINFO instead of open code. +	* sysdeps/i386/tls.h (THREAD_SELF_SYSINFO): New macro. +	(THREAD_SYSINFO): Likewise. + +	* sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: New file. + +	* sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Work around gas problem. + +2003-12-06  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Use .init_array +	instead of .init.  Patch by David Mosberger. + +2003-11-30  Thorsten Kukuk  <kukuk@suse.de> + +	* sysdeps/pthread/configure.in: Remove broken declaration in C +	cleanup handling check. + +2003-11-30  Andreas Jaeger  <aj@suse.de> + +	* Makefile (CFLAGS-pt-initfini.s): Add $(fno_unit_at_a_time). +	* sysdeps/unix/sysv/linux/x86_64/Makefile (CFLAGS-pt-initfini.s): +	Likewise. + +2003-11-27  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/internaltypes.h (ATTR_FLAG_OLDATTR): Define. +	* pthread_attr_destroy.c: Include shlib-compat.h. +	(__pthread_attr_destroy): Return immediately if ATTR_FLAG_OLDATTR +	is set in iattr->flags. +	* pthread_attr_init.c (__pthread_attr_init_2_0): Set ATTR_FLAG_OLDATTR. + +2003-11-21  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (distribute): Add tst-cleanup4aux.c. + +	* tst-cond12.c (prepare): Add prototype.  Move after test-skeleton.c +	include. + +2003-11-21  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cond12.c (do_test): If USE_COND_SIGNAL is defined, use +	pthread_cond_signal. + +	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Don't +	store mutex address if the current value is ~0l. +	* sysdeps/pthread/pthread_cond_timedwait.c +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/pthread/pthread_cond_broadcast.c +	(__pthread_cond_broadcast): Don't use requeue for pshared +	condvars. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S +	(__pthread_cond_wait): Don't store mutex address if the current +	value is ~0l. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S +	(__pthread_cond_broadcast): Don't use requeue for pshared +	condvars. + +	* pthread_cond_init.c (__pthread_cond_init): Initialize __mutex +	element with ~0l for pshared condvars, with NULL otherwise. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +	(__pthread_cond_wait): Don't store mutex address if the current +	value is ~0l. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S +	(__pthread_cond_broadcast): Don't use requeue for pshared +	condvars. + +	* Makefile: Add rules to build and run tst-cond12 and tst-cond13. +	* tst-cond12.c: New file. +	* tst-cond13.c: New file. + +2003-11-17  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/configure.in: Make missing forced unwind support +	fatal. + +2003-11-11  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h: Don't declare __pthread_unwind as weak inside libpthread. + +2003-11-06  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile: Add magic to clean up correctly. + +2003-11-05  Jakub Jelinek  <jakub@redhat.com> + +	* unwind.c (FRAME_LEFT): Define. +	(unwind_stop): Handle old style cleanups here. +	(__pthread_unwind): Handle old style cleanups only if +	!HAVE_FORCED_UNWIND. +	* Makefile (tests): Add tst-cleanup4 and tst-cleanupx4. +	(CFLAGS-tst-cleanupx4.c): Add -fexceptions. +	($(objpfx)tst-cleanup4): Depend on $(objpfx)tst-cleanup4aux.o. +	($(objpfx)tst-cleanupx4): Likewise. +	* tst-cleanup4.c: New test. +	* tst-cleanup4aux.c: New. +	* tst-cleanupx4.c: New test. + +2003-11-04  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/bits/stdio-lock.h: Use lll_*lock instead of +	lll_mutex_*lock macros to skip atomic operations on some archs. + +2003-11-03  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/tst-timer.c (main): Initialize +	sigev2.sigev_value as well. + +2003-10-15  Roland McGrath  <roland@redhat.com> + +	* sysdeps/pthread/configure.in: Barf if visibility attribute support +	is missing. +	* sysdeps/pthread/configure: Regenerated. + +2003-10-09  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/unix/sysv/linux/sh/lowlevellock.h: Completely revamp the +	locking macros.  No distinction between normal and mutex locking +	anymore. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S: Rewrite mutex locking. +	Merge bits from lowlevelmutex.S we still need. +	* sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: Remove. +	* sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/not-cancel.h: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Adjust for +	new mutex implementation. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (PSEUDO): Also defined +	symbol for entry point to avoid cancellation. + +2003-10-07  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Backout 2003-10-02 +	changes. +	(SAVE_OLDTYPE_0): Fix a typo. + +2003-10-03  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): +	Check __sigsetjmp return value.  Reported by Daniel Jacobowitz. + +2003-10-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (DOCARGS_1): Use +	correct offset. + +2003-10-02  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-cancel19. +	* tst-cancel19.c: New test. + +2003-10-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Fix saving and +	restoring of the old cancellation type. + +2003-09-30  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/malloc-machine.h: Remove misleading comment. + +2003-09-27  Wolfram Gloger  <wg@malloc.de> + +	* sysdeps/pthread/malloc-machine.h: New file + +2003-09-24  Roland McGrath  <roland@redhat.com> + +	* allocatestack.c (__make_stacks_executable): Don't ignore return +	value from _dl_make_stack_executable. + +2003-09-24  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (__make_stacks_executable): Also change +	permission of the currently unused stacks. + +	* allocatestack.c (change_stack_perm): Split out from +	__make_stacks_executable. +	(allocate_stack): If the required permission changed between the time +	we started preparing the stack and queueing it, change the permission. +	(__make_stacks_executable): Call change_stack_perm. + +	* Makefile: Build tst-execstack-mod locally. +	* tst-execstack-mod.c: New file. + +2003-09-23  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Only add tst-execstack if have-z-execstack is yes. + +2003-09-23  Roland McGrath  <roland@redhat.com> + +	* tst-execstack.c: New file. +	* Makefile (tests): Add it. +	($(objpfx)tst-execstack, $(objpfx)tst-execstack.out): New targets. +	(LDFLAGS-tst-execstack): New variable. + +	* allocatestack.c (allocate_stack): Use GL(dl_stack_flags) to decide +	whether to use PROT_EXEC for stack mmap. +	(__make_stacks_executable): New function. +	* pthreadP.h: Declare it. +	* init.c (__pthread_initialize_minimal_internal): Set +	GL(dl_make_stack_executable_hook) to that. + +2003-09-22  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Adjust for latest +	recommendation from AMD re avoidance of lock prefix. + +2003-09-22  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): Use +	lll_futex_timed_wait instead of lll_futex_wait. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.c: Removed. +	* sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: Removed. +	* sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: Removed. +	* sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c: Removed. +	* sysdeps/unix/sysv/linux/s390/sem_trywait.c: Removed. +	* sysdeps/unix/sysv/linux/s390/sem_wait.c: Removed. +	* sysdeps/unix/sysv/linux/s390/sem_post.c: Removed. +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Removed. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h: Include atomic.h. +	Completely revamp the locking macros.  No distinction between +	normal and mutex locking anymore. +	* sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_lock_wait, +	__lll_lock_timedwait): Fix prototypes. +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_lock_wait, +	__lll_lock_timedwait): Likewise. +	(lll_mutex_lock, lll_mutex_cond_lock): Use _val instead of _bool +	macros, add __builtin_expect. +	(lll_mutex_timedlock): Likewise.  Fix return value. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Removed. +	* sysdeps/unix/sysv/linux/i386/i586/libc-lowlevelmutex.S: Removed. +	* sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S: Removed. +	* sysdeps/unix/sysv/linux/i386/i686/libc-lowlevelmutex.S: Removed. +	* sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S: Removed. +	* sysdeps/unix/sysv/linux/x86_64/libc-lowlevelmutex.S: Removed. +	* sysdeps/unix/sysv/linux/lowlevelmutex.c: Removed. +	* sysdeps/unix/sysv/linux/libc-lowlevelmutex.c: Removed. + +2003-09-22  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +	(__lll_mutex_lock_wait): Minor optimization to avoid one atomic +	operation if possible. + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Don't play tricks +	like jumping over the lock prefix. + +2003-09-21  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Completely revamp the +	locking macros.  No distinction between normal and mutex locking +	anymore. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Rewrite mutex +	locking.  Merge bits from lowlevelmutex.S we still need. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/lowlevellock.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Removed. +	* sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Removed. +	* Makefile (routines): Remove libc-lowlevelmutex. +	(libpthread-rountines): Remove lowlevelmutex. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Adjust +	for new mutex implementation. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. +	Don't use requeue. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. +	* sysdeps/pthread/pthread_cond_signal.c: Don't use requeue. + +2003-09-20  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Don't match memory +	in parameters of asm with output parameters. + +	* pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Change +	type of DECR parameter to int. +	* pthreadP.h: Adjust prototype of __pthread_mutex_unlock_usercnt. + +2003-09-18  Jakub Jelinek  <jakub@redhat.com> + +	* tst-attr3.c (tf, do_test): Print stack start/end/size and +	guardsize for each thread. + +2003-09-17  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread.h (pthread_getattr_np): Clarify usage. +	* sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c +	(pthread_attr_setaffinity_np): Handle cpuset == NULL. + +	* sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c +	(pthread_attr_getaffinity_np): Don't segfault if iattr->cpuset is +	NULL. +	* pthread_getattr_np.c: Set cpuset using pthread_getaffinity_np. +	* pthreadP.h (pthread_getaffinity_np): Add hidden_proto. +	* sysdeps/unix/sysv/linux/pthread_getaffinity.c +	(pthread_getaffinity_np): Add hidden_def. + +	* Makefile (tests): Add tst-attr3. +	* tst-attr3.c: New test. + +	* sysdeps/i386/Makefile (CFLAGS-tst-align.c): Remove. + +2003-09-15  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/i386/Makefile (CFLAGS-pthread_create.c, +	CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4. + +2003-09-17  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (CFLAGS-tst-align.c): Add $(stack-align-test-flags). +	* tst-align.c: Include tst-stack-align.h. +	(tf, do_test): Use TEST_STACK_ALIGN macro. + +2003-09-17  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_attr_init.c (__pthread_attr_init_2_0): Remove unused +	variable. + +2003-09-16  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_getattr_np.c (pthread_getattr_np): Correctly fill in the +	stack-related values for the initial thread. + +2003-09-15  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (CFLAGS-pthread_once.c): Add $(uses-callbacks). + +2003-09-11  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_mutex_lock.c: Minor code rearrangements. + +2003-09-05  Roland McGrath  <roland@redhat.com> + +	* pthread_create.c (__pthread_pthread_sizeof_descr): Removed. +	Instead, include ../nptl_db/db_info.c to do its magic. +	* pthread_key_create.c (__pthread_pthread_keys_max): Removed. +	(__pthread_pthread_key_2ndlevel_size): Likewise. +	* sysdeps/alpha/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/i386/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/ia64/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/powerpc/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/s390/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/sh/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/sparc/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/x86_64/tls.h (DB_THREAD_SELF): New macro. +	* sysdeps/alpha/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/generic/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/i386/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/ia64/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/powerpc/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/s390/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/sh/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/sparc/td_ta_map_lwp2thr.c: File removed. +	* sysdeps/x86_64/td_ta_map_lwp2thr.c: File removed. + +2003-09-08  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Change type +	of pthread_t to be compatible with LT. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + +2003-09-04  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/not-cancel.h (fcntl_not_cancel): Define. + +2003-09-04  Jakub Jelinek  <jakub@redhat.com> + +	* unwind-forcedunwind.c: Move to... +	* sysdeps/pthread/unwind-forcedunwind.c: ...here. +	(pthread_cancel_init): Use ARCH_CANCEL_INIT if defined. +	* sysdeps/pthread/jmpbuf-unwind.h: New file. +	* sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c: New file. +	* sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: New file. +	* unwind.c: Include jmpbuf-unwind.h. +	(unwind_stop): Use _JMPBUF_CFA_UNWINDS macro. + +2003-09-02  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: New file. +	* sysdeps/unix/sysv/linux/ia64/Versions (libpthread): Export +	pthread_attr_setstack and pthread_attr_setstacksize @@GLIBC_2.3.3. +	* sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: New file. +	* sysdeps/unix/sysv/linux/alpha/Versions: New file. +	* sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: New file. +	* sysdeps/unix/sysv/linux/sparc/Versions: New file. +	* pthread_attr_setstack.c (__old_pthread_attr_setstack): New function. +	(pthread_attr_setstack): If PTHREAD_STACK_MIN != 16384, export +	as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.2. +	* pthread_attr_setstacksize.c (__old_pthread_attr_setstacksize): New +	function. +	(pthread_attr_setstacksize): If PTHREAD_STACK_MIN != 16384, export +	as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.1. +	* Makefile (tests): Add tst-stack2. +	* tst-stack2.c: New test. +	* tst-stack1.c: Include limits.h and sys/param.h. +	(do_test): Set size to MAX (4 * getpagesize (), PTHREAD_STACK_MIN). + +	* pthread_condattr_setpshared.c: Include errno.h. +	(pthread_condattr_setpshared): Return EINVAL if pshared +	is neither PTHREAD_PROCESS_PRIVATE nor PTHREAD_PROCESS_SHARED. + +	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Also +	defined symbol for entry point to avoid cancellation. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): +	Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO): +	Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): +	Likewise. +	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h (PSEUDO): +	Likewise. +	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h (PSEUDO): +	Likewise. +	* sysdeps/unix/sysv/linux/i386/not-cancel.h (__open_nocancel, +	__close_nocancel, __read_nocancel, __write_nocancel, +	__waitpid_nocancel): Add attribute_hidden.  If not in libc.so, +	libpthread.so or librt.so, define to corresponding function +	without _nocancel suffix. +	* sysdeps/unix/sysv/linux/s390/not-cancel.h: New file. +	* sysdeps/unix/sysv/linux/powerpc/not-cancel.h: New file. +	* sysdeps/unix/sysv/linux/sparc/not-cancel.h: New file. + +	* sysdeps/unix/sysv/linux/x86_64/not-cancel.h: Fix a typo. + +2003-09-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/not-cancel.h: New file. +	* sysdeps/unix/sysv/linux/x86_64/not-cancel.h: New file. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Make sure the code +	in subsections has a symbol associated with it. + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Also +	defined symbol for entry point to avoid cancellation. +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Likewise. + +2003-09-01  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests): Add tst-tls5. +	(module-names): Add tst-tls5mod{,a,b,c,d,e,f}. +	($(objpfx)tst-tls5mod{,a,b,c,d,e,f}.so-no-z-defs): Set to yes. +	($(objpfx)tst-tls5): New. +	($(objpfx)tst-tls6.out): Likewise. +	(tests): Depend on $(objpfx)tst-tls6.out. +	* tst-tls3.c: Include stdint.h and pthreaddef.h. +	(do_test): Check pthread_self () return value alignment. +	* tst-tls3mod.c: Include stdint.h and pthreaddef.h. +	(tf): Check pthread_self () return value alignment. +	* tst-tls5.c: New test. +	* tst-tls5.h: New. +	* tst-tls5mod.c: New. +	* tst-tls5moda.c: New. +	* tst-tls5modb.c: New. +	* tst-tls5modc.c: New. +	* tst-tls5modd.c: New. +	* tst-tls5mode.c: New. +	* tst-tls5modf.c: New. +	* tst-tls6.sh: New test. + +	* sysdeps/pthread/pthread-functions.h (struct pthread_functions): Add +	ptr___pthread_cond_timedwait and ptr___pthread_cond_timedwait_2_0. +	* init.c (pthread_functions): Initialize them. +	* forward.c (pthread_cond_timedwait@GLIBC_2.0, +	pthread_cond_timedwait@@GLIBC_2.3.2): New forwards. +	* Versions (libc): Export pthread_cond_timedwait@GLIBC_2.0, +	pthread_cond_timedwait@@GLIBC_2.3.2. + +2003-09-01  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/alpha/timer_create.c: New file. +	* sysdeps/unix/sysv/linux/alpha/timer_delete.c: New file. +	* sysdeps/unix/sysv/linux/alpha/timer_getoverr.c: New file. +	* sysdeps/unix/sysv/linux/alpha/timer_gettime.c: New file. +	* sysdeps/unix/sysv/linux/alpha/timer_settime.c: New file. +	* sysdeps/unix/sysv/linux/alpha/Versions: New file. + +	* sysdeps/unix/sysv/linux/alpha/aio_cancel.c: New file. + +	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Define +	_POSIX_THREAD_PRIORITY_SCHEDULING. +	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2003-08-31  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock): Avoid +	nested function, use static inline function from libio.h. +	Code by Richard Henderson. + +	* sysdeps/pthread/bits/libc-lock.h: Mark pthread_setcancelstate as +	weak. + +2003-08-30  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/sparc/sparc64/Versions: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: New file. +	* sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: New file. +	* sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: New file. +	* sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: New file. +	* sysdeps/unix/sysv/linux/sparc/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/sparc/pthread_once.c: New file. +	* sysdeps/unix/sysv/linux/sparc/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/sparc/fork.c: New file. +	* sysdeps/unix/sysv/linux/sparc/aio_cancel.c: New file. +	* sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c: New file. +	* sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c: New file. +	* sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c: New file. +	* sysdeps/sparc/sparc32/pthread_spin_lock.c: New file. +	* sysdeps/sparc/sparc32/pthread_spin_trylock.c: New file. +	* sysdeps/sparc/sparc32/pthreaddef.h: New file. +	* sysdeps/sparc/sparc64/pthread_spin_lock.c: New file. +	* sysdeps/sparc/sparc64/pthread_spin_trylock.c: New file. +	* sysdeps/sparc/sparc64/pthread_spin_unlock.c: New file. +	* sysdeps/sparc/sparc64/pthreaddef.h: New file. +	* sysdeps/sparc/tls.h: New file. +	* sysdeps/sparc/tcb-offsets.sym: New file. +	* sysdeps/sparc/Makefile: New file. +	* sysdeps/sparc/td_ta_map_lwp2thr.c: New file. +	* init.c [__sparc__] (__NR_set_tid_address): Define. + +2003-08-29  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock, +	_IO_release_lock): Define. + +2003-08-29  Jakub Jelinek  <jakuB@redhat.com> + +	* tst-cancel4.c (tf_sigwait, tf_sigwaitinfo, tf_sigtimedwait): Add +	sigemptyset before sigaddset.  Reported by jreiser@BitWagon.com. + +2003-08-27  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h (pthread_exit): Remove __THROW. +	(__pthread_cleanup_class): Add missing return types of member +	functions. + +2003-08-26  Steven Munroe <sjmunroe@us.ibm.com> + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h +	(lll_mutex_unlock_force): Add memory barrier between store and futex +	syscall. + +2003-08-25  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel4.c (do_test): Also unlink tempfname and remove +	tempmsg in first loop. + +2003-08-18  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define +	_POSIX_THREAD_PRIORITY_SCHEDULING. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + +2003-08-07  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/bits/libc-lock.h [_LIBC && SHARED] +	(__rtld_lock_default_lock_recursive, +	__rtld_lock_default_unlock_recursive): Define. +	[_LIBC && SHARED] (__rtld_lock_lock_recursive, +	__rtld_lock_unlock_recursive): Define using +	GL(_dl_rtld_*lock_recursive). +	* init.c (__pthread_initialize_minimal_internal): Initialize +	_dl_rtld_lock_recursive and _dl_rtld_unlock_recursive. +	Lock GL(_dl_load_lock) the same number of times as +	GL(_dl_load_lock) using non-mt implementation was nested. + +	* pthreadP.h (__pthread_cleanup_upto): Add hidden_proto. +	* pt-longjmp.c (__pthread_cleanup_upto): Add hidden_def. + +2003-08-06  Jakub Jelinek  <jakub@redhat.com> + +	* tst-cancel17.c (do_test): Make len2 maximum of page size and +	PIPE_BUF. + +2003-08-07  Jakub Jelinek  <jakub@redhat.com> + +	* pthread_create.c (__pthread_create_2_0): Clear new_attr.cpuset. + +2003-08-03  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/createthread.c (do_clone): Move error handling +	to first syscall error check.  Move syscall error check for tkill +	into __ASSUME_CLONE_STOPPED #ifdef. + +2003-08-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/createthread.c (do_clone): If __ASSUME_CLONE_STOPPED +	is not defined, do explicit synchronization. +	(create_thread): Do not lock pd->lock here.  If __ASSUME_CLONE_STOPPED +	is not defined also unlock pd->lock for non-debugging case in case +	it is necessary. +	* pthread_create.c (start_thread): Always get and release pd->lock +	if __ASSUME_CLONE_STOPPED is not defined. +	(start_thread_debug): Removed.  Adjust users. +	* allocatestack.c (allocate_stack): Always initialize lock if +	__ASSUME_CLONE_STOPPED is not defined. +	* Makefile (tests): Add tst-sched1. +	* tst-sched1.c: New file. + +	* sysdeps/pthread/createthread.c (do_clone): Only use +	sched_setschduler and pass correct parameters. + +2003-07-31  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread.h (pthread_attr_setstackaddr, +	pthread_attr_setstacksize): Change PTHREAD_STACK_SIZE to +	PTHREAD_STACK_MIN in comments. + +2003-07-31  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): +	Shut up warnings if INTERNAL_SYSCALL_ERROR_P does not use its first +	argument. +	* sysdeps/unix/sysv/linux/timer_create.c (timer_create): Likewise. +	* pthread_condattr_setclock.c (pthread_condattr_setclock): Likewise. +	* sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Include pthreaddef.h. +	(__pthread_cleanup_upto): Fix prototype. +	(_longjmp_unwind): Adjust caller. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_mutex_timedlock): +	Change second argument to const struct pointer. +	* tst-sem8.c (main): Remove unused s2 and s3 variables. +	* tst-sem9.c (main): Likewise. +	* unwind.c: Include string.h for strlen prototype. + +2003-07-31  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Don't use cmov unless HAVE_CMOV is defined. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: +	Define HAVE_CMOV. +	Patch by Nicholas Miell <nmiell@attbi.com>. + +2003-07-30  Jakub Jelinek  <jakub@redhat.com> + +	* init.c (__pthread_initialize_minimal_internal): Initialize +	GL(dl_init_static_tls). +	* pthreadP.h (__pthread_init_static_tls): New prototype. +	* allocatestack.c (init_one_static_tls, __pthread_init_static_tls): +	New functions. +	* Makefile (tests): Add tst-tls4. +	(modules-names): Add tst-tls4moda and tst-tls4modb. +	($(objpfx)tst-tls4): Link against libdl and libpthread. +	($(objpfx)tst-tls4.out): Depend on tst-tls4moda.so and +	tst-tls4modb.so. +	* tst-tls4.c: New file. +	* tst-tls4moda.c: New file. +	* tst-tls4modb.c: New file. + +2003-06-19  Daniel Jacobowitz  <drow@mvista.com> + +	* sysdeps/pthread/timer_create.c (timer_create): Call timer_delref +	before __timer_dealloc. +	* sysdeps/pthread/timer_routines.c (__timer_thread_find_matching): +	Don't call list_unlink. + +2003-07-29  Roland McGrath  <roland@redhat.com> + +	* Makefile [$(build-shared) = yes] (tests): Depend on $(test-modules). + +2003-07-25  Jakub Jelinek  <jakub@redhat.com> + +	* tst-cancel17.c (do_test): Check if aio_cancel failed. +	Don't reuse struct aiocb A if it failed. +	Write fpathconf (fds[1], _PC_PIPE_BUF) + 2 bytes using aio_write, +	not just one byte, as that does not block. + +2003-07-22  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/unwind-resume.c: New file. +	* sysdeps/pthread/Makefile (routines, shared-only-routines): Add +	unwind-resume in csu subdir. +	(CFLAGS-unwind-resume.c, CFLAGS-rt-unwind-resume.c): Compile with +	exceptions. +	(librt-sysdep_routines, librt-shared-only-routines): Add +	rt-unwind-resume. +	* sysdeps/pthread/rt-unwind-resume.c: New file. +	* unwind-forcedunwind.c: New file. +	* Makefile (libpthread-routines): Add unwind-forcedunwind. +	(libpthread-shared-only-routines): Likewise. +	(CFLAGS-unwind-forcedunwind.c): Compile with exceptions. +	* pthreadP.h (pthread_cancel_init): New prototype. +	* pthread_cancel.c (pthread_cancel): Call pthread_cancel_init. + +	* sysdeps/pthread/createthread.c (do_thread, create_thread): Make +	attr argument const struct pthread_attr *. + +	* res.c (__res_state): Return __resp. +	* descr.h: Include resolv.h. +	(struct pthread): Add res field. +	* pthread_create.c: Include resolv.h. +	(start_thread): Initialize __resp. +	* Makefile (tests): Add tst-_res1. +	(module-names): Add tst-_res1mod1, tst-_res1mod2. +	($(objpfx)tst-_res1mod2.so): Depend on $(objpfx)tst-_res1mod1.so. +	($(objpfx)tst-_res1): Depend on $(objpfx)tst-_res1mod2.so and +	libpthread. +	* tst-_res1.c: New file. +	* tst-_res1mod1.c: New file. +	* tst-_res1mod2.c: New file. + +2003-07-21  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/createthread.c: Don't define CLONE_STOPPED. + +	* Makefile: Define various *-no-z-defs variables for test DSOs +	which has undefined symbols. + +2003-07-21  Steven Munroe  <sjmunroe@us.ibm.com> + +	* sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): +	Retry if the stwcx fails to store once_control. + +2003-07-20  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (libpthread-routines): Add pthread_attr_getaffinity and +	pthread_attr_setaffinity. +	* Versions [libpthread] (GLIBC_2.3.3): Likewise. +	* sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: New file. +	* sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: New file. +	* pthread_attr_destroy.c: Free cpuset element if allocated. +	* pthread_create.c: Pass iattr as additional parameter to +	create_thread. +	* sysdeps/pthread/createthread.c: If attribute is provided and +	a new thread is created with affinity set or scheduling parameters, +	start thread with CLONE_STOPPED. +	* sysdeps/pthread/pthread.h: Declare pthread_attr_getaffinity and +	pthread_attr_setaffinity. +	* sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_attr): Add +	cpuset element. + +2003-07-15  Ulrich Drepper  <drepper@redhat.com> + +	* tst-tcancel-wrappers.sh: lseek and llseek are not cancelation points. + +2003-07-14  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/configure.in: Require CFI directives also for +	ppc and s390. + +2003-07-15  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): +	Add cfi directives. + +2003-07-12  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/sh/tcb-offsets.sym: Add RESULT, TID, CANCELHANDLING and +	CLEANUP_JMP_BUF. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Use more +	registers as variables.  Call __pthread_mutex_unlock_usercnt. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Store TID +	not self pointer in __writer.  Compare with TID to determine +	deadlocks. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_wait.S: Add cancellation support. +	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Define all the nice +	macros also when compiling librt. + +2003-07-11  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (CFLAGS-pthread_once.c): Add -fexceptions +	-fasynchronous-unwind-tables. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h +	(PSEUDO): Add cfi directives. +	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): +	Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): +	Likewise. + +2003-07-08  Jakub Jelinek  <jakub@redhat.com> + +	* pthreadP.h (__pthread_unwind_next, __pthread_register_cancel, +	__pthread_unregister_cancel): Add prototypes and hidden_proto. +	* unwind.c (__pthread_unwind_next): Add hidden_def. +	* cleanup.c (__pthread_register_cancel, __pthread_unregister_cancel): +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): +	Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. +	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S (sem_wait): Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): +	Likewise. +	* sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): Use +	HIDDEN_JUMPTARGET to call __pthread_register_cancel, +	__pthread_unregister_cancel and __pthread_unwind_next. + +2003-07-04  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO): Use +	different symbol for the cancellation syscall wrapper and +	non-cancellation syscall wrapper. +	(PSEUDO_END): Define. + +2003-07-05  Richard Henderson  <rth@redhat.com> + +	* sysdeps/alpha/elf/pt-initfini.c: Avoid .ent/.end. +	* sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_futex_wait, +	lll_futex_timed_wait, lll_futex_wake, lll_futex_requeue): On success +	return actual return value from the syscall, not 0. + +2003-07-07  Ulrich Drepper  <drepper@redhat.com> + +	* descr.h (struct pthread): Add pid field. +	* allocatestack.c (allocate_stack): Initialize pid field in descriptor. +	(__reclaim_stacks): Likewise. +	* init.c (sigcancel_handler): If __ASSUME_CORRECT_SI_PID is defined +	also check for PID of the signal source. +	(__pthread_initialize_minimal_internal): Also initialize pid field +	of initial thread's descriptor. +	* pthread_cancel.c: Use tgkill instead of tkill if possible. +	* sysdeps/unix/sysv/linux/fork.c: Likewise. +	* sysdeps/unix/sysv/linux/pt-raise.c: Likewise. +	* sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. +	* sysdeps/unix/sysv/linux/raise.c: Likewise. + +2003-07-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_push): Renamed. +	Fix use of parameter. +	(__libc_cleanup_pop): Likewise. + +2003-07-04  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (sigcancel_handler): Change parameters to match handler +	for SA_SIGACTION.  Check signal number and code to recognize +	invalid invocations. + +2003-07-03  Roland McGrath  <roland@redhat.com> + +	* sysdeps/ia64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): +	Apply sizeof (struct pthread) bias to r13 value. + +2003-07-03  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/configure.in: Require CFI directives. + +	* sysdeps/pthread/librt-cancellation.c (__pthread_unwind): Remove +	definition. +	* pthreadP.h (__pthread_unwind): Add hidden_proto if used in +	libpthread compilation. +	* unwind.c (__pthread_unwind): Add hidden_def. +	* Versions (libpthread) [GLIBC_PRIVATE]: Add __pthread_unwind. + +2003-07-01  Ulrich Drepper  <drepper@redhat.com> + +	* libc-cancellation.c (__libc_cleanup_routine): Define. +	* sysdeps/pthread/bits/libc-lock.h (__pthread_cleanup_push): Define. +	(__pthread_cleanup_pop): Define. + +2003-07-01  Richard Henderson  <rth@redhat.com> + +	* sysdeps/alpha/elf/pt-initfini.c: New file. +	* sysdeps/alpha/pthread_spin_lock.S: New file. +	* sysdeps/alpha/pthread_spin_trylock.S: New file. +	* sysdeps/alpha/pthreaddef.h: New file. +	* sysdeps/alpha/td_ta_map_lwp2thr.c: New file. +	* sysdeps/alpha/tls.h: New file. +	* sysdeps/unix/sysv/linux/alpha/Makefile: New file. +	* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: New file. +	* sysdeps/unix/sysv/linux/alpha/bits/semaphore.h: New file. +	* sysdeps/unix/sysv/linux/alpha/createthread.c: New file. +	* sysdeps/unix/sysv/linux/alpha/fork.c: New file. +	* sysdeps/unix/sysv/linux/alpha/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/alpha/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/alpha/pthread_once.c: New file. +	* sysdeps/unix/sysv/linux/alpha/sem_post.c: New file. +	* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: New file. + +2003-07-01  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Add correct +	cleanup support and unwind info. + +2003-06-30  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): +	Use correct cleanup handler registration.  Add unwind info. +	* sysdeps/unix/sysv/linux/unwindbuf.sym: New file. +	* sysdeps/unix/sysv/linux/Makefile: Add rule to build unwindbuf.h. +	* tst-once3.c: Add cleanup handler and check it is called. +	* tst-once4.c: Likewise. +	* tst-oncex3.c: New file. +	* tst-oncex4.c: New file. +	* Makefile: Add rules to build and run tst-oncex3 and tst-oncex4. + +2003-06-29  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/configure.in: Check for C cleanup handling in gcc. + +2003-06-27  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel4.c (tf_msgrcv): Use IPC_PRIVATE in msgget call. +	(tf_msgsnd): Likewise. + +	* tst-cancel4.c (tf_msgrcv): Strengthen test against valid +	premature returns a bit more. + +2003-06-26  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/librt-cancellation.c: Move __pthread_unwind +	definition to the front. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Rename +	the cleanup functions to make the names unique.  Fix dwarf opcode +	un unwind table. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Rename cleanup +	functions to make the names unique.  Fix CFA offset for two blocks. + +2003-06-25  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h (class __pthread_cleanup_class): Add +	missing closing braces. +	Patch by Christophe Saout <christophe@saout.de>. + +2003-06-24  Roland McGrath  <roland@redhat.com> + +	* pthread_mutex_trylock.c (__pthread_mutex_trylock): Typo fix. + +2003-06-24  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: New file. +	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: New file. + +	* pthreadP.h: Declare __find_thread_by_id. +	* allocatestack.c [HP_TIMING_AVAIL]: Define __find_thread_by_id. +	* pthread_clock_gettime.c: Allow using other thread's clock. +	* pthread_clock_settime.c: Likewise. +	* sysdeps/pthread/pthread_getcpuclockid.c: Likewise. +	* Makefile: Add rules to build and run tst-clock2. +	* tst-clock2.c: New file. + +2003-06-23  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Rewrite +	to use exception-based cleanup handler. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + +	* tst-cond8.c (ch): Announce that we are done. + +	* pthreadP.h (__pthread_mutex_cond_lock): Mark with internal_function. + +	* tst-cancel17.c (tf): Retry aio_suspend in case of EINTR. +	Also test aio_suspend with timeout value. + +2003-06-22  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h: Mark __pthread_mutex_unlock_usercnt also hidden. +	* pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Add +	attribute_hidden. + +	* pthreadP.h (__pthread_mutex_init_internal): Mark hidden. +	(__pthread_mutex_lock_internal): Likewise. +	(__pthread_mutex_unlock_internal): Likewise. +	(__pthread_mutex_unlock_usercnt): Declare. +	* pthread_mutex_destroy.c: Always fail if used in any way. +	* pthread_mutex_init.c: Update comment. +	* pthread_mutex_lock.c: If NO_INCR is not defined adjust __nusers. +	* pthread_mutex_timedlock.c: Adjust __nusers. +	* pthread_mutex_trylock.c: Adjust __nusers. +	* pthread_mutex_unlock.c: Old code is in __pthread_mutex_unlock_usercnt +	and public interfaces are wrapper with pass additional parameter. +	__pthread_mutex_unlock_usercnt does not adjust __nusers if second +	parameter zero. +	* tst-mutex8.c: New file. +	* Makefile (tests): Add tst-mutex8. +	* sysdeps/pthread/pthread_cond_timedwait.c: Call +	__pthread_mutex_unlock_usercnt. +	* sysdeps/pthread/pthread_cond_wait.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Define NO_INCR. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): +	Add __nusers. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +	* pthread_mutex_lock.c: Don't store THREAD_ID in __owner, use TID. +	* pthread_mutex_timedlock.c: Likewise. +	* pthread_mutex_trylock.c: Adjust __nusers. +	* pthread_mutex_unlock.c: Compare with TID not THREAD_ID. +	* tst-mutex9.c: New file. +	* Makefile (tests): Add tst-mutex9. +	* sysdeps/i386/tls.h: Remove THREAD_ID definition. +	* sysdeps/ia64/tls.h: Likewise. +	* sysdeps/powerpc/tls.h: Likewise. +	* sysdeps/s390/tls.h: Likewise. +	* sysdeps/sh/tls.h: Likewise. +	* sysdeps/x86_64/tls.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): +	Change type of __owner. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2003-06-19  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/sem_post.c: Move to... +	* sysdeps/unix/sysv/linux/sem_post.c: ...here. + +	* sysdeps/unix/sysv/linux/sem_post.c: Move to... +	* sysdeps/unix/sysv/linux/powerpc/sem_post.c: ... here.  Pass nr + 1 +	instead of nr to lll_futex_wake.  Only set errno and return -1 +	if err < 0. + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (lll_futex_wait, +	lll_futex_timed_wait, lll_futex_wake, lll_futex_requeue): On success +	return actual return value from the syscall, not 0. + +2003-06-18  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel4.c (tf_msgsnd): Don't always use 100 as the type, +	find a random value. +	(tf_msgrcv): Likewise.  Also don't report msgrcv returns if +	errno==EIDRM. + +	* sysdeps/unix/sysv/linux/timer_settime.c: Add prototype for +	compat_timer_settime. +	* sysdeps/unix/sysv/linux/timer_gettime.c: Add prototype for +	compat_timer_gettime. +	* sysdeps/unix/sysv/linux/timer_getoverr.c: Add prototype for +	compat_timer_getoverrun. +	* sysdeps/unix/sysv/linux/timer_delete.c: Add prototype for +	compat_timer_delete. + +	* pthread_mutex_destroy.c (__pthread_mutex_destroy): For +	error-checking mutex detect busy mutexes. + +2003-06-17  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_mutex_lock): +	Add ax to clobber list. +	(lll_mutex_cond_lock): Likewise. +	(lll_mutex_unlock): Likewise. +	(lll_lock): Likewise. +	(lll_unlock): Likewise. + +	* Makefile: Add rules to build and run tst-cancel18 and tst-cancelx18. +	* tst-cancel18.c: New file. +	* tst-cancelx18.c: New file. + +	* tst-cancel4.c: Test connect, creat, msgrcv, msgsnd, sendmsg, sendto, +	and tcdrain. + +	* Makefile: Add rules to build and run tst-cancel17 and tst-cancel17x. +	* tst-cancel17.c: New file. +	* tst-cancelx17.c: New file. + +	* sysdeps/unix/sysv/linux/sigtimedwait.c: New file. +	* sysdeps/unix/sysv/linux/sigwait.c: New file. +	* sysdeps/unix/sysv/linux/sigwaitinfo.c: New file. + +	* tst-cancel4.c: Test open, close, pread, pwrite, fsync, and msync. + +2003-06-16  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/createthread.c (create_thread): Set +	header.multiple_threads unconditionally. +	* allocatestack.c (allocate_stack): Likewise. +	* descr.h (struct pthread): Add header.multiple_threads +	unconditionally. +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (CENABLE, CDISABLE): +	Define for librt.  #error if neither libpthread, libc nor librt. +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (CENABLE, CDISABLE): +	Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (CENABLE, +	CDISABLE): Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (CENABLE, +	CDISABLE): Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (CENABLE, +	CDISABLE): Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (CENABLE, +	CDISABLE): Likewise.  Access header.multiple_threads outside of +	libc and libpthread. +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (CENABLE, CDISABLE): +	Likewise. +	* sysdeps/x86_64/tls.h (tcbhead_t): Add multiple_threads. +	* sysdeps/x86_64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Define. + +2003-06-17  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel4.c: Add tests for the socket and signal functions, pause. +	Also test early cancellation before the thread reaches the cancellation +	point. + +	* Makefile: Compile forward.c with exceptions. + +	* sysdeps/unix/sysv/linux/sleep.c: New file. + +2003-06-16  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile: Add CFLAGS definition to compile function wrappers +	duplicated from libc with exceptions. +	* tst-cancel4.c: Also check cancellation handlers. + +	* Makefile: Add rules to build and run tst-cancel16 and +	tst-cancelx16.  Add missing CFLAGS definitions. +	* tst-cancel16.c: New file. +	* tst-cancelx16.c: New file. + +2003-06-15  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h +	(DL_SYSINFO_IMPLEMENTATION): Use CFI opcodes. +	* sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h +	(DL_SYSINFO_IMPLEMENTATION): Likewise. + +	* pthreadP.h (LIBC_CANCEL_ASYNC): Also define for librt. +	(LIBC_CANCEL_RESET): Likewise. +	Declare __librt_enable_asynccancel and __librt_disable_asynccancel. +	* sysdeps/pthread/Makefile (librt-sysdep_routines): Add +	librt-cancellation. +	(CFLAGS-libcrt-cancellation.c): Define. +	* sysdeps/pthread/librt-cancellation.c: New file. +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define all the nice +	macros also when compiling librt. +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + +	* sysdeps/unix/sysv/linux/timer_create.c: Add prototype for +	compat_timer_create. + +2003-06-14  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/posix-timer.h (timespec_compare): Always inline. + +	* sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for +	__register_atfork. +	* sysdeps/unix/sysv/linux/register-atfork.c (__register_atfork): +	Add libc_hidden_def. + +2003-06-13  Roland McGrath  <roland@redhat.com> + +	* sysdeps/x86_64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Pass FS +	constant from <sys/reg.h> to ps_get_thread_area, not register contents. + +2003-06-11  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (queue_stack): Always inline. +	* ptreadhP.h (__do_cancel): Likewise. + +2003-06-10  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): Fix +	a typo. + +2003-06-10  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S +	(__pthread_cond_signal): Remove incorrect second addition for +	cond_lock!=0. + +2003-06-09  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S +	(__pthread_cond_signal): Use correct futex pointer in +	__lll_mutex_lock_wait call. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S +	(__pthread_cond_signal): Some more tweaks to handle cond_lock!=0. + +2003-06-08  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/sem_wait.c (__new_sem_wait): Make +	cancelable. +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): +	Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Remove +	hand-written CFI generation code.  Since ENTRY/END also initiated +	CFI frames this caused two CFI sets to be generated. + +2003-06-07  Ulrich Drepper  <drepper@redhat.com> + +	* cleanup_routine.c: New file. +	* Versions (libpthread) [GLIBC_2.3.3]: Add __pthread_cleanup_routine. +	* sysdeps/pthread/pthread.h: Add support for fully exception-based +	cleanup handling. +	* Makefile (libpthread-routines): Add cleanup_routine. +	Add more CFLAGS variables to compile with exceptions.  Add comments +	why which file needs unwind tables. +	(tests) [have-forced-unwind==yes]: Add tst-cancelx* and tst-cleanupx* +	tests. +	* tst-cancelx1.c: New file. +	* tst-cancelx2.c: New file. +	* tst-cancelx3.c: New file. +	* tst-cancelx4.c: New file. +	* tst-cancelx5.c: New file. +	* tst-cancelx6.c: New file. +	* tst-cancelx7.c: New file. +	* tst-cancelx8.c: New file. +	* tst-cancelx9.c: New file. +	* tst-cancelx10.c: New file. +	* tst-cancelx11.c: New file. +	* tst-cancelx12.c: New file. +	* tst-cancelx13.c: New file. +	* tst-cancelx14.c: New file. +	* tst-cancelx15.c: New file. +	* tst-cleanupx0.c: New file. +	* tst-cleanupx0.expect: New file. +	* tst-cleanupx1.c: New file. +	* tst-cleanupx2.c: New file. +	* tst-cleanupx3.c: New file. + +	* tst-cleanup0.c: Make standard compliant. +	* tst-cleanup1.c: Likewise. + +	* sysdeps/unix/sysv/linux/sem_timedwait.c: Add cancellation support. +	* sysdeps/unix/sysv/linux/sem_wait.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. +	* sysdeps/i386/tcb-offsets.sym: Add RESULT, CANCELHANDLING, and +	CLEANUP_JMP_BUF. +	* sysdeps/x86_64/tcb-offsets.sym: Likewise. +	* tst-cancel12.c: New file. +	* tst-cancel13.c: New file. +	* tst-cancel14.c: New file. +	* tst-cancel15.c: New file. +	* Makefile (tests): Add tst-cancel12, tst-cancel13, tst-cancel14, +	and tst-cancel15. + +	* tst-cancel1.c: Add some comments. + +	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Compute relative +	timeout correctly. + +2003-06-06  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (CFLAGS-pthread_cancel.c): Define. + +2003-06-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_rwlock_t): +	Change type of __writer element to int. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. +	* sysdeps/i386/tcb-offsets.sym: Replace SELF entry with TID entry. +	* sysdeps/x86_64/tcb-offsets.sym: Likewise. +	* pthread_rwlock_trywrlock.c: Store TID not self pointer in __writer. +	Compare with TID to determine deadlocks. +	* sysdeps/pthread/pthread_rwlock_rdlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_timedwrlock.: Likewise. +	* sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. +	* Makefile (tests): Add tst-rwlock12. +	* tst-rwlock12.c: New file. + +2003-06-05  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait, +	__lll_timedlock_wait, lll_unlock_wake_cb, __lll_timedwait_tid): +	Remove bogus hidden_proto. +	* sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c (___lll_lock): +	Likewise. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.c (___lll_lock, +	lll_unlock_wake_cb, ___lll_timedwait_tid): Likewise. +	* sysdeps/unix/sysv/linux/s390/lowlevelmutex.c (___lll_mutex_lock, +	___lll_mutex_timedlock): Likewise. + +2003-06-04  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S +	(__pthread_cond_signal): Add some code to eventually handle +	cond_lock!=0. + +2003-06-01  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-exec4. +	(tst-exec4-ARGS): Define. +	* tst-exec4.c: New file. + +2003-05-31  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): +	Also fail if tv_nsec < 0. +	(__lll_timedwait_tid): Likewise. +	* sysdeps/unix/sysv/linux/sem_timedwait.c (sem_timedwait): Likewise. +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_timedwait_tid): +	Likewise. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.c (___lll_timedwait_tid): +	Likewise. +	* sysdeps/unix/sysv/linux/s390/lowlevelmutex.c (__lll_mutex_timedlock): +	Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): +	Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_timedwait_tid): +	Likewise. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_timedwait_tid): +	Likewise. + +	* Makefile (tests): Add tst-sem8 and tst-sem9. +	* tst-sem8.c: New file. +	* tst-sem9.c: New file. +	* sem_open.c: Fix creation of in_use record if the file exists but +	no internal record. + +	* posix-timer.h: Remove old, unused timer_id2ptr and timer_ptr2id +	definitions. + +	* sysdeps/pthread/timer_create.c (timer_create): In case +	evp==NULL, assign timer ID to sival_ptr. + +	* descr.h (struct pthread_unwind_buf): Change type of prev element to +	struct pthread_unwind_buf *. +	(struct pthread): Likewise for cleanup_jmp_buf element. + +	* cleanup.c (__pthread_register_cancel): Add cast to avoid warning. +	* cleanup_defer.c (__pthread_register_cancel_defer): Likewise. +	* unwind.c (__pthread_unwind_next): Likewise. + +2003-05-30  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h +	(lll_futex_timed_wait): Use int for futex value parameter. +	(lll_futex_wake): Likewise. +	(lll_futex_requeue): Likewise. + +	* sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait): +	Replace one memory operation with one register operation. + +	* tst-join4.c (do_test): Fix error message. + +	* tst-rwlock6.c (do_test): Use correct format specifier. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S +	(__lll_mutex_lock_wait): Replace one memory operation with one +	register operation. +	* sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S +	(__lll_mutex_lock_wait): Likewise. + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h +	(__lll_mutex_cond_lock): Add one to value parameter of +	__lll_lock_wait to reflect reality in the futex syscall. +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h +	(lll_mutex_cond_lock): Likewise. + +2003-05-30  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_mutex_cond_lock): +	New function. +	(lll_mutex_cond_lock): Define. + +2003-05-29  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-signal6. +	* tst-signal6.c: New file. + +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h +	(__lll_mutex_unlock_force): New function +	(lll_mutex_unlock_force): Use __lll_mutex_unlock_force. + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h +	(__lll_mutex_unlock_force): New function. +	(lll_mutex_unlock_force): Use __lll_mutex_unlock_force. + +	* tst-rwlock7.c (do_test): Use correct format specifier. + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_requeue): +	Find break parameter in correct asm argument. + +2003-05-27  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_clobbers): +	Remove out4. +	(lll_futex_requeue): Fix __o3 constraint, return negative errno if +	error occured. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): +	Add __mutex. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_REQUEUE, +	lll_futex_requeue, lll_mutex_unlock_force): Define. + +2003-05-30  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +	(pthread_cond_t): Add __mutex. +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_REQUEUE, +	lll_futex_requeue, lll_mutex_unlock_force): Define. + +2003-05-28  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/sh/tcb-offsets.sym: Define MUTEX_FUTEX. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): +	Add __mutex field. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.h (SYSCALL_WITH_INST_PAD): +	Define. +	(lll_futex_wait, lll_futex_wake): Define. +	* sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Try using +	FUTEX_REQUEUE instead of FUTEX_WAIT. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Remember +	mutex which was used in condvar structure.  Call +	__pthread_mutex_cond_lock instead of __pthread_mutex_lock_internal. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. + +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Don't +	include tcb-offsets.h.  Read wakeup value in locked region. +	Use the value of gbr register as THREAD_ID. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + +	* sysdeps/unix/sysv/linux/sh/sem_trywait.S: Remove futex related +	macros. + +2003-05-28  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread_cond_broadcast.c +	(__pthread_cond_broadcast): Fix typo: MAX_INT -> INT_MAX. + +2003-05-26  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Fix +	typo in register name. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Use parameters +	correctly.  Actually use requeue.  Little optimization. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Store +	mutex address early.  Handle cancellation state as 32-bit value. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	Remove unnecessary label. + +2003-05-25  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread_cond_broadcast.c: Try using FUTEX_REQUEUE +	instead of FUTEX_WAIT. +	* sysdeps/pthread/pthread_cond_signal.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. +	* sysdeps/pthread/pthread_cond_timedwait.c: Remember mutex which was +	used in condvar structure.  Call __pthread_mutex_cond_lock instead +	of __pthread_mutex_lock_internal. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/pthread/pthread_cond_wait.c: Likewise. +	(__condvar_cleanup): Always call __pthread_mutex_cond_lock. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/Makefile (libpthread-sysdep_routines): +	Add pthread_mutex_cond_lock. +	* sysdeps/unix/sysv/linux/lowlevelcond.sym: Add dep_mutex. +	* sysdeps/unix/sysv/linux/pthread_cond_mutex_lock.c: New file. +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define +	lll_mutex_cond_lock. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): +	Add __mutex field. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +	* sysdeps/i386/tcb-offsets.sym: Define MUTEX_FUTEX. +	* sysdeps/x86_64/tcb-offsets.sym: Likewise. + +	* pthreadP.h: Declare __pthread_mutex_cond_lock. +	* pthread_mutex_lock.c: Define LLL_MUTEX_LOCK if not already defined. +	Use it instead of lll_mutex_lock.  If __pthread_mutex_lock is a +	macro don't define aliases. + +	* cancellation.c: Remove __pthread_enable_asynccancel_2. +	* pthreadP.h: Remove declaration of __pthread_enable_asynccancel_2. +	* sysdeps/pthread/pthread_cond_timedwait.c: Use +	__pthread_enable_asynccancel instead of __pthread_enable_asynccancel_2. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/pthread/pthread_cond_wait.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + +2003-05-17  Ulrich Drepper  <drepper@redhat.com> + +	* sem_open.c: Fix one endless loop.  Implement correct semantics +	wrt opening the same semaphore more then once. +	* sem_close.c: Adjust for sem_open change. +	* semaphoreP.h: Include <semaphore.h>.  Define struct inuse_sem. +	Declare __sem_mappings, __sem_mappings_lock, __sem_search. +	* Makefile (tests): Add tst-sem7. +	* tst-sem7.c: New file. + +2003-05-16  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/register-atfork.c (libc_freeres_fn): Fix +	uninitialized variable braino. + +2003-05-16  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/timer_gettime.c (timer_gettime): Correct +	test for syscall availability. + +	* sysdeps/unix/sysv/linux/timer_settime.c (timer_settime): Set +	__no_posix_timers to -1 if the syscalls don't exist. + +	* pthread_join.c (pthread_join): Set tid field of the joined +	thread to -1.  This isn't necessary but helps to recognize some +	error conditions with almost no cost. + +	* allocatestack.c (FREE_P): Also negative values indicate an +	unused stack. + +	* unwind.c: Include <unistd.h>. + +2003-05-14  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile ($(objpfx)$(multidir)): Add rule to create the directory. + +2003-05-14  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (crti-objs, crtn-objs): New variables. +	(omit-deps, extra-objs): Add crtn. +	($(objpfx)libpthread.so): Depend on both crti and crtn +	and links to them in multidir. +	($(objpfx)crtn.S, $(objpfx)crtn.o): New rules. + +2003-05-12  Steven Munroe  <sjmunroe@us.ibm.com> + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h +	(lll_mutex_unlock): Use atomic_exchange_rel. + +2003-05-11  Ulrich Drepper  <drepper@redhat.com> + +	* cond-perf.c (cons): Add missing locking around setting of alldone. + +2003-05-10  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Remove futex +	related macros. +	* sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + +2003-05-09  Ulrich Drepper  <drepper@redhat.com> + +	* tst-sem6.c: New file. +	* Makefile (tests): Add tst-sem6. + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (___lll_mutex_unlock): +	Use atomic_exchange_rel instead of atomic_exchange. +	* sysdeps/unix/sysv/linux/lowlevellock.c (lll_unlock_wake_cb): +	Likewise. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Improve quality of +	code for lll_futex_wait and lll_futex_wake in static apps.  Use +	vsyscall is possible. + +	* sysdeps/unix/sysv/linux/pthread_getaffinity.c: New file. +	* sysdeps/unix/sysv/linux/pthread_setaffinity.c: New file. +	* sysdeps/pthread/pthread.h: Declare pthread_getaffinity_np and +	pthread_setaffinity_np. +	* Versions [libpthread] (GLIBC_2.3.3): Add pthread_getaffinity_np +	and pthread_setaffinity_np. +	* Makefile (libpthread-routines): Add pthread_getaffinity and +	pthread_setaffinity. + +	* allocatestack.c (allocate_stack): If ARCH_RETRY_MMAP is defined, +	use it in case mmap to allocate the stack fails. +	* sysdeps/unix/sysv/linux/x86_64/Makefile: Don't define +	ARCH_MAP_FLAGS here. +	* sysdeps/x86_64/pthreaddef.h: Define ARCH_MAP_FLAGS and +	ARCH_RETRY_MMAP. + +2003-05-08  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/fork.c: Complete rewrite of the atfork +	handler implementation.  It is now lockless in fork(). +	* sysdeps/unix/sysv/linux/register-atfork.c: Likewise. +	* sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise. +	* sysdeps/unix/sysv/linux/fork.h: Don't include <link.h>.  Don't +	declare the __fork_*_lists. +	(struct fork_handler): Include pointers to all three functions. +	Add next, refcntr and need_signal elements. +	(__fork_handlers): New declaration. +	(__register_atfork_malloc): Remove declaration. +	(HAVE_register_atfork_malloc): Remove definition. +	* sysdeps/unix/sysv/linux/libc_pthread_init.c: Remove +	__pthread_child_handler variable. +	(__libc_pthread_init): Use __register_atfork instead of explicitly +	adding to the list. +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define lll_futex_wait +	and lll_futex_wake. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + +	* unwind.c (unwind_cleanup): Print error message and then abort.  This +	function must never be reached. + +	* cond-perf.c: New file. + +2003-05-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/tls.h (TLS_INIT_TP): Include \n in error message. + +2003-05-04  Roland McGrath  <roland@redhat.com> + +	* Makefile ($(objpfx)../libc.so): New target. + +2003-05-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +	(pthread_condattr_t): Size is only an int, don't use long for +	alignment. +	(pthread_mutexattr_t): Likewise. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + +2003-05-01  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/tls.h: Define THREAD_ID. +	* sysdeps/ia64/tls.h: Likewise. +	* sysdeps/powerpc/tls.h: Likewise. +	* sysdeps/s390/tls.h: Likewise. +	* sysdeps/sh/tls.h: Likewise. +	* sysdeps/x86_64/tls.h: Likewise. +	* pthread_mutex_lock.c: Use THREAD_ID instead of THREAD_SELF to +	record ownership. +	* pthread_mutex_timedlock.c: Likewise. +	* pthread_mutex_trylock.c: Likewise. +	* pthread_mutex_unlock.c: Likewise. +	* pthread_rwlock_trywrlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlocklock_rdlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + +	* sysdeps/pthread/createthread.c (create_thread): Use CLONE_SYSVSEM +	flag. + +2003-04-29  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h +	(__SIZEOF_PTHREAD_COND_T): Define to 48. +	(pthread_rwlock_t): Add 16 bytes of pad instead of 8 before __flags. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): +	Make __align long long instead of long. +	(pthread_rwlock_t): Formatting. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h +	(pthread_rwlock_t): Formatting. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +	(pthread_cond_t): Make __align long long instead of long. +	(pthread_rwlock_t): Move __flags field to the same position as in +	linuxthreads. + +2003-04-30  Ulrich Drepper  <drepper@redhat.com> + +	* tst-rwlock6.c (do_test): Use correct printf format specifiers. +	* tst-rwlock7.c (do_test): Likewise. + +2003-04-26  Roland McGrath  <roland@redhat.com> + +	* Makefile ($(test-modules)): Depend on $(common-objpfx)shlib.lds. + +2003-04-22  Jakub Jelinek  <jakub@redhat.com> + +	* allocatestack.c (TLS_TPADJ): Add TLS_PRE_TCB_SIZE instead of +	sizeof (struct pthread). +	(allocate_stack): Subtract TLS_PRE_TCB_SIZE bytes instead of +	1 struct pthread. +	* sysdeps/powerpc/tls.h (TLS_INIT_TCB_SIZE, TLS_TCB_SIZE): Define +	to 0. +	(TLS_INIT_TCB_ALIGN, TLS_TCB_ALIGN): Define to alignment of +	struct pthread. +	(TLS_PRE_TCB_SIZE): Increase to cover tcbhead_t preceeded by pad +	to 32-bit bytes. +	(INSTALL_DTV, GET_DTV, THREAD_DTV): tcbhead_t is immediately before +	tcbp. +	(TLS_INIT_TP, THREAD_SELF, INIT_THREAD_SELF): Don't add TLS_TCB_SIZE +	unneccessarily. +	(NO_TLS_OFFSET): Define. +	* sysdeps/unix/sysv/linux/powerpc/createthread.c (TLS_VALUE): Don't +	add TLS_TCB_SIZE unnecessarily. + +2003-04-22  Roland McGrath  <roland@redhat.com> + +	* Makeconfig (shared-thread-library): Reverse link order to work +	around linker bug. + +2003-04-22  Ulrich Drepper  <drepper@redhat.com> + +	* semaphore.h: Fix typo in comment. + +2003-04-21  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/sigfillset.c: New file. + +	* init.c (__pthread_initialize_minimal): Don't block SIGTIMER. +	* pthreadP.h: Make SIGTIMER and SIGCANCEL the same. +	* sysdeps/pthread/pthread_sigmask.c: Remove handling of SIGTIMER. +	* sysdeps/pthread/sigaction.c: Likewise. +	* sysdeps/pthread/sigprocmask.c: New file. +	* sysdeps/unix/sysv/linux/allocrtsig.c (current_rtmin): Define as +	__SIGRTMIN+1. +	* sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): +	Block SIGTIMER.  Also handle SI_TKILL events and terminate thread +	in this case. + +2003-04-19  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h +	(DL_SYSINFO_IMPLEMENTATION): Add .eh_frame information. + +	* sysdeps/unix/sysv/linux/unregister-atfork.c +	(__unregister_atfork): Don't free memory not allocated dynamically. + +	* semaphore.h: Remove __THROW marker from cancellation points. +	* nptl/sysdeps/pthread/pthread.h: Likewise. + +2003-04-18  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h: Don't mark pthread_testcancel, +	pthread_cancel, pthread_setcancelstate, and pthread_setcanceltype with +	__THROW. + +2003-04-16  Jakub Jelinek  <jakub@redhat.com> + +	* tst-cancel4.c (do_test): Use %zd instead of %d when printing cnt. + +2003-04-15  Roland McGrath  <roland@redhat.com> + +	* forward.c (__pthread_unwind): Tweak to avoid warning. + +2003-04-15  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h: Move THREAD_ATOMIC_* replacements to the top. + +2003-04-14  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Don't +	overflow CFA advance instructions. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2003-04-14  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/i386/tls.h: Rename LOCK to LOCK_PREFIX. +	* sysdeps/i386/pthread_spin_lock.c: Likewise. +	* sysdeps/x86_64/tls.h: Likewise.  Define LOCK_PREFIX if not already +	defined. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Use +	DW_CFA_advance_loc2 for .Laddl-.Lsubl. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Use +	DW_CFA_advance_loc for .Laddl-.Lsubl. + +2003-04-13  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Don't use +	position-independent unwind data for static libraries. +	Add missing unwind info.  Add comments. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Add unwind info. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +2003-04-12  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile: Make sure all cancellation points are compiled with +	exception and asynchronous unwind tables. + +	* sysdeps/x86_64/tls.h (THREAD_SETMEM): Word around compiler bug +	which mishandles loading of global object addresses in PIC. +	(THREAD_SETMEM_NC): Likewise. + +2003-04-11  Ulrich Drepper  <drepper@redhat.com> + +	* pthread.h: Define new data structure for cleanup buffer.  Declare +	new cleanup handler interfaces. +	* descr.h: Include <unwind.h> if necessary.  Define pthread_unwind_buf. +	(struct pthread): Add cleanup_jmp_buf pointer.  Define +	HAVE_CLEANUP_JMP_BUF and not HAVE_CANCELBUF. +	* pthreadP.h: Declare __pthread_unwind.  Define __do_cancel to use +	it.  Declare old cleanup handler installation functions. +	* cleanup.c: Rewrite.  Install handler for unwind-based cleanup +	handling. +	* cleanup_defer.c: Likewise. +	* cleanup_compat.c: New file.  Old cleanup code. +	* cleanup_def_compat.c: New file.  Old cleanup code. +	* pthread_create.c (start_thread): Initialize cleanup_jmp_buf element +	if own thread descriptor. +	* unwind.c: New file. +	* forward.c: Add __pthread_unwind. +	* init.c (pthread_functions): Add __pthread_unwind. +	* sysdeps/pthread/pthread-functions.s (struct pthread_functions): +	Add ptr___pthread_unwind. +	* Versions [GLIBC_2.3.3] (libpthread): Export new cleanup handling +	and unwind function. +	* Makefile (libpthread-routines): Add cleanup_compat, +	cleanup_def_compat, and unwind.  Define CFLAGS to enable unwind +	table generation if necessary. +	* version.c: Record whether unwind support is compiled in. +	* sysdeps/pthread/configure.in: Add checks for unwind unterfaces. +	* sysdeps/pthread/bits/libc-lock.h: Add prototypes of the old cleanup +	handler interfaces. +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add quite a bit of +	complication to generate unwind information for syscall wrappers. +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define +	__cleanup_fct_attribute. + +	* Makefile: Add rules to build and run tst-cleanup0. +	* tst-cleanup0.c: New file. +	* tst-cleanup0.expect: New file. + +	* pthread_create.c (deallocate_tsd): Don't take parameter.  Adjust +	caller.  Optimize to avoid often unecessary local variable. + +2003-04-11  Roland McGrath  <roland@redhat.com> + +	* Makefile ($(objpfx)multidir.mk): New target, generated makefile that +	sets variable `multidir'; include that. +	(generated): Add it. +	($(objpfx)$(multidir)/crti.o): New target. +	[$(multidir) != .] (generated-dirs, extra-objs, omit-deps): Add it. + +2003-04-11  Ulrich Drepper  <drepper@redhat.com> + +	* tst-attr2.c (do_test): Add cast to avoid warning. +	* tst-mutex4.c (do_test): Likewise. + +2003-04-10  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset CPU clocks +	in child. + +2003-04-09  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-detach1. +	* tst-detach1.c: New file. + +2003-04-08  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h: Remove duplicate +	pthread_cleanup_{push,pop} definitions. + +	* tst-barrier2.c: Eliminate warnings. +	* tst-cancel4.c: Likewise. +	* tst-cond4.c: Likewise. +	* tst-cond6.c: Likewise. +	* tst-detach1.c: Likewise. +	* tst-rwlock4.c: Likewise. +	* tst-rwlock6.c: Likewise. +	* tst-rwlock7.c: Likewise. +	* tst-sem3.c: Likewise. +	* tst-spin2.c: Likewise. +	* tst-umask1.c: Likewise. + +2003-04-07  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_detach.c (pthread_detach): Fix test for invalid TID. + +2003-04-06  Ulrich Drepper  <drepper@redhat.com> + +	* descr.h (struct pthread): Move cancelhandling member to the front. + +2003-04-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/register-atfork.c: Define malloc_prepare, +	malloc_parent, and malloc_child statically. +	(__register_atfork_malloc): New function. +	(free_mem): Don't free any of the malloc_* variables on the list. +	* sysdeps/unix/sysv/linux/fork.h: Declare __register_atfork_malloc. +	Define HAVE_register_atfork_malloc. + +2003-04-04  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/createthread.c (create_thread): Add some more +	comments explaining when to set multiple_threads and when not. + +	* pthreadP.h: Define THREAD_ATOMIC_CMPXCHG_VAL and +	THREAD_ATOMIC_BIT_SET if not already defined. +	* sysdeps/i386/tls.h: Define THREAD_ATOMIC_CMPXCHG_VAL and +	THREAD_ATOMIC_BIT_SET: +	* sysdeps/x86_64/tls.h: Likewise. +	* cleanup_defer.c (_pthread_cleanup_push_defer): Rewrite to use +	THREAD_ATOMIC_CMPXCHG_VAL. +	(_pthread_cleanup_pop_restore): Likewise. +	* cancellation.c (__pthread_enable_asynccancel): Likewise. +	(__pthread_enable_asynccancel_2): Likewise. +	(__pthread_disable_asynccancel): Likewise. +	* libc-cancellation.c (__libc_enable_asynccancel): Likewise. +	(__libc_disable_asynccancel): Likewise. +	* init.c (sigcancel_handler): Likewise. +	* pthread_setcancelstate.c (__pthread_setcancelstate): Likewise. +	* pthread_setcanceltype.c (__pthread_setcanceltype): Likewise. + +2003-04-03  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (sigcancel_handler): Don't set EXITING_BIT here. +	* libc-cancellation.c (__libc_enable_asynccancel): Likewise. +	* pthreadP.h (__do_cancel): Set EXITING_BIT here. +	* Makefile (tests): Add tst-cancel11. +	* tst-cancel11.c: New file. + +2003-04-01  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_create.c (deallocate_tsd): Clear/free memory after the last +	round, not the first.  Use specific_used flag instead of local +	found_nonzero variable.  Use THREAD_[SG]ETMEM where possible. +	(__free_tcb): Don't call deallocate_tsd here. +	(start_thread): Call deallocate_tsd here. +	* pthread_setspecific.c: Set specific_used flag really only when +	needed. +	* Makefile (tests): Add tst-tsd3.c and tst-tsd4. +	* tst-tsd3.c: New file. +	* tst-tsd4.c: New file. + +2003-03-31  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_mutex_lock): +	Use atomic_exchange_and_add instead of __lll_add. +	(__lll_mutex_timedlock): Likewise. +	Patch by Ian Wienand. + +2003-03-24  Steven Munroe  <sjmunroe@us.ibm.com> + +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h +	(SINGLE_THREAD_P): Fix typo. +	* tst-cancel-wrappers.sh: Handle '.'ed symbols. + +2003-03-31  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-align. +	* tst-align.c: New file. +	* sysdeps/i386/Makefile: Define CFLAGS-tst-align. + +	* sysdeps/i386/tls.h (CALL_THREAD_FCT): Align stack of called +	function correctly. + +	* tst-tsd2.c: Add casts to avoid warnings. + +2003-03-30  Ulrich Drepper  <drepper@redhat.com> + +	* descr.h (struct pthread): Move most often used elements to the front. + +2003-03-29  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (libpthread-routines): Add pthread_atfork. +	(libpthread-static-only-routines): Add pthread_atfork. + +2003-03-28  Kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/sh/tls.h: Include nptl/descr.h after the definition +	of TLS_DTV_AT_TP. +	(INSTALL_DTV): Add parens. +	(THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, THREAD_SETMEM_NC): +	Use passed descr instead of THREAD_SELF. +	* sysdeps/unix/sysv/linux/sh/lowlevelmutex.S +	(__lll_mutex_timedlock_wait): Correct expected value after +	spurious wakeup. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: +	Release lock before waking up the waiters. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Correct exit +	criteria.  Reorderstruct passed to cleanup handler.  Fix +	handling of cancellation and failung pthread_mutex_unlock call. +	Use __pthread_enable_asynccancel_2 instead of +	__pthread_enable_asynccancel. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. +	Return result of lock re-get if it fails. +	* sysdeps/unix/sysv/linux/sh/pthread_once.S: Fix wrong argument +	for __pthread_cleanup_push. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Fix +	completely broken rwlock implementation. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_post.S: Fix error value.  Use +	versioned_symbol macro. +	* sysdeps/unix/sysv/linux/sh/sem_trywait.S: Use	versioned_symbol macro. +	* sysdeps/unix/sysv/linux/sh/sem_wait.S: Likewise. + +2003-03-27  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/kernel-posix-timers.h: Don't declare +	__timer_helper_thread.  Declare __start_helper_thread, __helper_once, +	and __helper_tid. +	(struct timer): Remove th and bar field. +	* sysdeps/unix/sysv/linux/timer_create.c (timer_create): Remove +	debugging code.  Create only one helper thread. +	* sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Don't kill +	helper thread. +	* sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): +	Renamed.  Define statically.  Use thread info from siginfo. +	(__helper_once): New variable. +	(__helper_tid): New variable. +	(__reset_helper_control): New function. +	(__start_helper_thread): New function. + +	* pthread_create.c (start_thread): Don't use setjmp inside +	__builtin_expect to work around gcc bug. + +	* sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Even if +	timer_delete syscall fails, but not with ENOSYS, set +	__no_posix_timers. + +	* sysdeps/unix/sysv/linux/timer_settime.c [!__ASSUME_POSIX_TIMERS] +	(timer_settime): Fix typo. +	* sysdeps/unix/sysv/linux/timer_getoverr.c +	[!__ASSUME_POSIX_TIMERS] (timer_getoverrun): Likewise. + +2003-03-27  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Fix +	offset of cleanupbuf.__prev. + +2003-03-26  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/timer_getoverr.c: Fix typo in name +	of included file. + +2003-03-26  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/timer_create.c (timer_create): If EVP == +	NULL provide default definition to syscall. + +2003-03-25  Roland McGrath  <roland@redhat.com> + +	* sysdeps/pthread/posix-timer.h (TIMER_MAX): Define if not defined. +	(timer_id2ptr): Fix typo. + +2003-03-25  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h: Define SIGCANCEL and SIGTIMER. +	* sysdeps/i386/pthreaddef.h: Remove SIGCANCEL definition. +	* sysdeps/ia64/pthreaddef.h: Likewise. +	* sysdeps/powerpc/pthreaddef.h: Likewise. +	* sysdeps/s390/pthreaddef.h: Likewise. +	* sysdeps/sh/pthreaddef.h: Likewise. +	* sysdeps/x86_64/pthreaddef.h: Likewise. +	* init.c (__pthread_initialize_minimal): Block SIGTIMER. +	* sysdeps/pthread/sigaction.c: Also prevent SIGTIMER handler from +	being changed. +	* sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Make sure +	SIGTIMER is not unblocked. +	* sysdeps/unix/sysv/linux/allocrtsig.c (current_rtmin): One more +	RT signal taken. +	* sysdeps/unix/sysv/linux/pthread_kill.c: Do not allow SIGTIMER to +	be send. +	* sysdeps/pthread/posix-timer.h (timer_id2ptr, timer_ptr2id): Just +	pass pointer through as ID. +	* sysdeps/unix/sysv/linux/bits/local_lim.h (TIMER_MAX): Removed. +	* sysdeps/unix/sysv/linux/kernel-posix-timers.h: New file. +	* sysdeps/unix/sysv/linux/timer_create.c: New file. +	* sysdeps/unix/sysv/linux/timer_delete.c: New file. +	* sysdeps/unix/sysv/linux/timer_getoverr.c: New file. +	* sysdeps/unix/sysv/linux/timer_gettime.c: New file. +	* sysdeps/unix/sysv/linux/timer_routines.c: New file. +	* sysdeps/unix/sysv/linux/timer_settime.c: New file. +	* sysdeps/unix/sysv/linux/ia64/Versions: New file. +	* sysdeps/unix/sysv/linux/ia64/timer_create.c: New file. +	* sysdeps/unix/sysv/linux/ia64/timer_delete.c: New file. +	* sysdeps/unix/sysv/linux/ia64/timer_getoverr.c: New file. +	* sysdeps/unix/sysv/linux/ia64/timer_gettime.c: New file. +	* sysdeps/unix/sysv/linux/ia64/timer_settime.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/Versions: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/timer_create.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/timer_delete.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/timer_getoverr.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/timer_gettime.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/timer_settime.c: New file. +	* sysdeps/unix/sysv/linux/x86_64/Versions: New file. +	* sysdeps/unix/sysv/linux/x86_64/compat-timer.h: New file. +	* sysdeps/unix/sysv/linux/x86_64/timer_create.c: New file. +	* sysdeps/unix/sysv/linux/x86_64/timer_delete.c: New file. +	* sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c: New file. +	* sysdeps/unix/sysv/linux/x86_64/timer_gettime.c: New file. +	* sysdeps/unix/sysv/linux/x86_64/timer_settime.c: New file. + +	* pthreadP.h: Remove FRAME_LEFT definition. +	* cleanup.c (_pthread_cleanup_push): Don't check for reference to +	already left frame.  Programs which have this problem are not POSIX +	compliant. +	* cleanup_defer.c (_pthread_cleanup_push_defer): Likewise. + +2003-03-24  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/tst-timer.c: Check return values of the +	functions we test. + +2003-03-23  Roland McGrath  <roland@redhat.com> + +	* tst-tls3.c (do_test) [! HAVE___THREAD]: Don't test anything. +	* tst-tls3mod.c: Likewise. +	* tst-tls1.c: Likewise. +	* tst-tls2.c: Likewise. + +	* tst-mutex5.c (do_test): Unlock before destroy, otherwise we invoke +	undefined behavior. + +	* tst-join5.c (tf1, tf2): Add a cast. + +	* Makeconfig (includes): Append -I$(..)nptl to this variable. + +	* tst-barrier2.c (do_test) [! _POSIX_THREAD_PROCESS_SHARED]: +	Don't test anything. +	* tst-cond4.c: Likewise. +	* tst-cond6.c: Likewise. +	* tst-flock2.c: Likewise. +	* tst-mutex4.c: Likewise. +	* tst-rwlock4.c: Likewise. +	* tst-signal1.c: Likewise. +	* tst-spin2.c: Likewise. +	* tst-cond11.c [! _POSIX_CLOCK_SELECTION]: Likewise. + +	* tst-mutex4.c: Use test-skeleton.c. +	* tst-spin2.c: Likewise. +	* tst-sysconf.c: Likewise. +	* tst-barrier2.c: Likewise. +	* tst-cond4.c: Likewise. +	* tst-cond6.c: Likewise. +	* tst-rwlock4.c: Likewise. +	* tst-unload.c: Likewise. +	* tst-flock2.c (do_test): Use return instead of exit. + +2003-03-22  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/fork.c (__fork): Add libc_hidden_def. + +2003-03-21  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h +	(__lll_mutex_trylock): Use atomic_compare_and_exchange_val_acq +	instead of __lll_compare_and_swap. +	* sysdeps/unix/sysv/linux/ia64/pthread_once.c (__pthread_once): +	Likewise. +	Removed definition if __lll_compare_and_swap. + +	* cancellation.c: Adjust for new form of compare&exchange macros. +	* cleanup_defer.c: Likewise. +	* init.c: Likewise. +	* libc-cancellation.c: Likewise. +	* old_pthread_cond_broadcast.c: Likewise. +	* old_pthread_cond_signal.c: Likewise. +	* old_pthread_cond_timedwait.c: Likewise. +	* old_pthread_cond_wait.c: Likewise. +	* pthread_cancel.c: Likewise. +	* pthread_create.c: Likewise. +	* pthread_detach.c: Likewise. +	* pthread_join.c: Likewise. +	* pthread_key_delete.c: Likewise. +	* pthread_setcancelstate.c: Likewise. +	* pthread_setcanceltype.c: Likewise. +	* pthread_timedjoin.c: Likewise. +	* pthread_tryjoin.c: Likewise. +	* sysdeps/pthread/createthread.c: Likewise. + +2003-03-20  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Include <atomic.h>. +	Remove __lll_add, __lll_dec_if_positive, and __lll_test_and_set +	definitions.  Replace uses with calls to atomic_* functions. +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/lowlevellock.c: Replace __lll_add and +	__lll_test_and_set calls with atomic_exchange_and_add and +	atomic_exchange calls respectively. +	* sysdeps/unix/sysv/linux/sem_post.c: Likewise. +	* sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. +	* sysdeps/unix/sysv/linux/sem_trywait.c: Likewise. +	* sysdeps/unix/sysv/linux/sem_wait.c: Likewise. +	* sysdeps/unix/sysv/linux/ia64/pthread_once.c: Likewise. +	* sysdeps/unix/sysv/linux/ia64/sem_port.c: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/pthread_once.c: Likewise. + +	* allocatestack.c (allocate_stack): Assume atomic_exchange_and_add +	returns the old value. + +2003-03-20  Martin Schwidefsky  <sky@mschwid3.boeblingen.de.ibm.com> + +	* sysdeps/s390/pthread_spin_lock.c (pthread_spin_lock): Use type +	int for variable OLDVAL and correct inline assembler contraint. +	* sysdeps/s390/pthread_spin_trylock.c (pthread_spin_trylock): Use +	type int for variable OLD. + +	* sysdeps/s390/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define it +	only for s390-32. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h +	(SINGLE_THREAD_P): Use global variable __local_multiple_threads +	instead of multiple_threads field in the TCB. + +2003-03-19  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/i686/bits/atomic.h: Removed. +	* sysdeps/i386/i586/bits/atomic.h: Removed. +	* sysdeps/i386/i486/bits/atomic.h: Removed.  Moved to glibc. +	* sysdeps/x86_64/bits/atomic.h: Removed.  Moved to glibc. +	* sysdeps/s390/bits/atomic.h: Removed.  Moved to glibc. +	* sysdeps/sh/bits/atomic.h: Removed.  Moved to glibc. +	* sysdeps/ia64/bits/atomic.h: Removed.  Moved to glibc. +	* sysdeps/powerpc/bits/atomic.h: Removed.  Moved to glibc. +	* atomic.h: Removed.  Moved to glibc. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Add +	support for clock selection. + +	* sysdeps/pthread/pthread_cond_broadcast.c: Release lock before +	signalling waiters. + +2003-03-18  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_test_and_set): +	Add __lll_rel_instr first.  Add memory clobber. +	(lll_mutex_unlock): Use __lll_test_and_set. +	From Paul Mackerras <paulus@samba.org>. + +	* sysdeps/powerpc/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define +	unconditionally. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h +	(SINGLE_THREAD_P):  Add `header.' prefix. +	From Paul Mackerras <paulus@samba.org>. + +	* Versions (libpthread: GLIBC_2.3.2): Move pthread_tryjoin_np and +	pthread_timedjoin_np to ... +	(libpthread: GLIBC_2.3.3): ... here. +	(libpthread: GLIBC_2.2): Move pthread_barrierattr_getpshared there too. + +	* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): +	Avoid shadowing VAL variable. + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_test_and_set): +	New macro. + +2003-03-18  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-cond11. +	* tst-cond11.c: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Reorder +	struct passed to cleanup handler to eliminate one more +	instruction. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h +	(pthrad_cond_t): Replace __unused field with __clock. + +	* sysdeps/pthread/pthread_cond_wait.c: Release condvar lock before +	waken all waiters in cleanup handler. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + +	* pthread_condattr_getclock.c: New file. +	* pthread_condattr_setclock.c: New file. +	* sysdeps/pthread/pthread.h: Declare these new functions. +	* Versions [GLIBC_2.3.3] (libpthread): Add the new functions. +	* Makefile (libpthread-routines): Add the new functions. +	* sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_condattr): +	Renamed field to value.  Document use of the bits. +	* pthread_condattr_getpshared.c: Adjust for struct pthread_condattr +	change. +	* pthread_condattr_setpshared.c: Likewise. +	* pthread_cond_init.c (__pthread_cond_init): Initialized __clock field. +	* sysdeps/unix/sysv/linux/lowlevelcond.sym: Add cond_clock symbol. +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): +	Add __clock field. +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: +	Implement clock selection. +	* sysdeps/pthread/pthread_cond_timedwait.c: Likewise. +	* pthread-errnos.sym: Add ENOSYS. +	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define +	_POSIX_CLOCK_SELECTION. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Remove +	invalid .size directive. + +2003-03-17  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait): +	Formatting tweaks. + +2003-03-17  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/pthread_once.c: Use __builtin_expect. +	Use __lll_add instead of spelling it out.  Use protected symbol names. +	* sysdeps/unix/sysv/linux/ia64/sem_post.c: Use __builtin_expect. +	Use __lll_add. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_compare_and_swap): +	Renamed from lll_compare_and_swap.  Use new name where necessary. +	(__lll_add): Defined. +	(__lll_dec_if_positive): Defined. +	(__lll_test_and_set): Defined. +	* sysdeps/ia64/pthread_spin_init.c: Removed. +	* sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: Removed. +	* sysdeps/unix/sysv/linux/ia64/sem_trywait.c: Removed. +	* sysdeps/unix/sysv/linux/ia64/sem_wait.c: Removed. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.c: Removed. +	* sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c: Removed. +	* sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c: Removed. +	* sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Removed. +	* sysdeps/ia64/bits/atomic.h: Add __builtin_expect where appropriate. +	* sysdeps/ia64/pthread_spin_unlock.c (pthread_spin_unlock): Use +	__sync_lock_release_si. +	Patch by Jakub Jelinek. + +	* sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): +	Fix timeout handling. +	(__lll_timedwait_tid): Likewise. +	(lll_unlock_wake_cb): Wake up other waiters if necessary. +	Patch by Jakub Jelinek. + +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Pretty printing. + +2003-03-17  Roland McGrath  <roland@redhat.com> + +	PowerPC port contributed by Paul Mackerras <paulus@samba.org>. +	* sysdeps/pthread/pthread_spin_init.c: New file. +	* sysdeps/pthread/pthread_spin_unlock.c: New file. +	* sysdeps/powerpc/Makefile: New file. +	* sysdeps/powerpc/pthread_spin_lock.c: New file. +	* sysdeps/powerpc/pthread_spin_trylock.c: New file. +	* sysdeps/powerpc/pthreaddef.h: New file. +	* sysdeps/powerpc/tcb-offsets.sym: New file. +	* sysdeps/powerpc/td_ta_map_lwp2thr.c: New file. +	* sysdeps/powerpc/tls.h: New file. +	* sysdeps/powerpc/bits/atomic.h: New file. +	* sysdeps/unix/sysv/linux/libc-lowlevelmutex.c: New file. +	* sysdeps/unix/sysv/linux/libc-lowlevellock.c: New file. +	* sysdeps/unix/sysv/linux/lowlevellock.c: New file. + +	* sysdeps/unix/sysv/linux/lowlevelmutex.c: New file. +	* sysdeps/unix/sysv/linux/sem_post.c: New file. +	* sysdeps/unix/sysv/linux/sem_timedwait.c: New file. +	* sysdeps/unix/sysv/linux/sem_trywait.c: New file. +	* sysdeps/unix/sysv/linux/sem_wait.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/Makefile: New file. +	* sysdeps/unix/sysv/linux/powerpc/createthread.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/fork.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/powerpc/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/powerpc/pthread_once.c: New file. +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: New file. +	* sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: New file. +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: New file. + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.c: Use __gettimeofday, +	not gettimeofday. +	* sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: Likewise. +	* sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. + +2003-03-17  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread_cond_wait.c: Correct exit criteria. +	* sysdeps/pthread/pthread_cond_timedwait.c: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. +	Patch by Ewald Snel <ewald@rambo.its.tudelft.nl>. + +2003-03-16  Roland McGrath  <roland@redhat.com> + +	* tst-fork4.c: Include <string.h>. +	* tst-signal2.c: Likewise. +	* tst-mutex5.c (do_test): exit -> return. +	* tst-mutex2.c: Include <stdlib.h>. + +2003-03-16  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S +	(__lll_mutex_timedlock_wait): Correct expected value after +	spurious wakeup.  Otherwise we would never wait again. + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Work around red +	zone versus inline asm stupidity.  Use correct instructions. + +	* tst-rwlock6.c: Add some more status output. + +2003-03-15  Roland McGrath  <roland@redhat.com> + +	* sysdeps/pthread/configure.in: New file. +	* sysdeps/pthread/configure: New file (generated). + +2003-03-15  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (allocate_stack): Store the exact stack size of +	user allocated stacks. + +2003-03-15  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h +	(SINGLE_THREAD): Use `header' prefix instead of `header.data'. +	* sysdeps/sh/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Likewise. +	* sysdeps/sh/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define. +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SINGLE_THREAD_P): +	Use `header.' prefix. +	* sysdeps/ia64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Likewise. + +2003-03-15  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/x86_64/pthreaddef.h (CURRENT_STACK_FRAME): Don't use +	__builtin_frame_address, use stack pointer. + +	* sysdeps/unix/sysv/linux/jmp-unwind.c: Use CURRENT_STACK_FRAME +	instead of __builtin_frame_pointer. + +2003-03-14  Ulrich Drepper  <drepper@redhat.com> + +	* tst-basic1.c (do_test): Add cast to avoid warning. +	* tst-basic2.c (do_test): Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Use correct +	amount of stack correction. + +	* tst-fork4.c: Use test-skeleton.c. + +2003-03-14  Roland McGrath  <roland@redhat.com> + +	* init.c: Fix typo "#eli" for "#else". + +2003-03-14  Steven Munroe  <sjmunroe@us.ibm.com> + +	* allocatestack.c (__stack_user): Use hidden_data_def. +	* pthread_create.c (__pthread_keys): Likewise. + +	* init.c [__powerpc__] (__NR_set_tid_address): Define it. + +2003-03-14  Roland McGrath  <roland@redhat.com> + +	* tst-fork4.c: New file. +	* Makefile (tests): Add it. + +	* descr.h (struct pthread): Move the union out of [!TLS_DTV_AT_TP], so +	we always define the padding space. +	[!TLS_DTV_AT_TP]: Give tcbhead_t field a name, `header', since GCC +	stopped supporting its own extensions fully. +	[TLS_MULTIPLE_THREADS_IN_TCB]: Put `multiple_threads' inside a wrapper +	struct also called `header', so `header.multiple_threads' is the field +	name to use on all machines. +	* allocatestack.c (allocate_stack): Use `header.' prefix. +	* sysdeps/pthread/createthread.c (create_thread): Likewise. +	* pthread_create.c (__pthread_create_2_1): Likewise. +	* sysdeps/i386/tls.h (INSTALL_NEW_DTV, THREAD_DTV): Likewise. +	(THREAD_SELF): Likewise. +	* sysdeps/x86_64/tls.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h +	(SINGLE_THREAD_P): Likewise. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h +	(SINGLE_THREAD_P): Likewise. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h +	(SINGLE_THREAD_P): Likewise. + +	* sysdeps/s390/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Use REGS[18] +	value directly. + +2003-03-14  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_create.c (start_thread): Use CALL_THREAD_FCT if defined. +	* sysdeps/i386/tls.h: Define CALL_THREAD_FCT. + +	* pthread_create.c (start_thread): setjmp is expected to return 0. + +	* sysdeps/x86_64/tls.h (THREAD_GETMEM): Mark asms volatile. +	(THREAD_GETMEM_NC): Likewise. + +2003-03-13  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (allocate_stack): If MULTI_PAGE_ALIASING is defined +	and the size of the stack which must be allocated is a multiple, +	allocate one more page. +	* sysdeps/i386/i686/Makefile: Don't define COLORING_INCREMENT, but +	MULTI_PAGE_ALIASING. + +2003-03-13  Roland McGrath  <roland@redhat.com> + +	* pthread_create.c (start_thread): Set EXITING_BIT after the +	event-reporting (and destructors), not before. + +2003-03-13  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_timed_wait, +	lll_futex_wake): Declare register variables as long int instead of +	unsigned long int.  Patch by Ian Wienand <ianw@gelato.unsw.edu.au>. +	Make syscall arguments clobbered by the syscall. +	(lll_futex_wait): Define using lll_futex_timed_wait. + +	* sysdeps/ia64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Cast regs[13] +	to void *. + +	* sysdeps/unix/sysv/linux/fork.c (__libc_fork): Only declare and set +	PPID if [! NDEBUG]. + +	* allocatestack.c (nptl_ncreated): Only declare if +	COLORING_INCREMENT != 0. + +	* pthreadP.h (__pthread_enable_asynccancel_2): New prototype. +	(__libc_enable_asynccancel_2): Remove prototype. + +	* sysdeps/unix/sysv/linux/ia64/fork.c (ARCH_FORK): Swap ptid and +	ctid to match kernel. + +2003-03-12  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Add +	libc_multiple_threads. +	* sysdeps/unix/sysv/linux/libc_pthread_init.c: Move definition of +	__libc_multiple_threads to... +	* sysdeps/unix/sysv/linux/libc_multiple_threads.c: ...here.  New file. + +	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Remove unnecessary +	versioning. +	* sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S +	(__pthread_once_internal): Define. + +	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Use shlib-compat.h +	macros instead of .symver directly. +	* sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + +	* sysdeps/x86_64/tls.h [__ASSEMBLER__]: Include tcb-offsets.h. +	* sysdeps/x86_64/tcb-offsets.sym: New file. +	* sysdeps/x86_64/Makefile: New file. + +	* sysdeps/i386/tcb-offsets.sym: Add SELF. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Use SELF +	to access own pthread_t in TCB. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + +2003-03-12  Roland McGrath  <roland@redhat.com> + +	* pthread-errnos.sym: New file. +	* Makefile (gen-as-const-headers): New variable, list that file. +	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Include generated +	header <pthread-errnos.h> instead of defining errno values here. +	* sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_trywait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_post.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/sem_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Likewise. +	* sysdeps/i386/i486/pthread_spin_trylock.S: Likewise. +	* sysdeps/x86_64/pthread_spin_trylock.S: Likewise. +	* sysdeps/sh/pthread_spin_trylock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + +	* sysdeps/unix/sysv/linux/fork.c: Add an assert to check that +	CLONE_CHILD_SETTID worked. + +2003-03-12  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: New +	file. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: New +	file. + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h +	(pthread_cond_t): Add padding. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S +	(__pthread_rwlock_timedwrlock): Add missing opcode suffix. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S +	(__pthread_rwlock_timedrdlock): Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S +	(__pthread_rwlock_wrlock): Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S +	(__pthread_rwlock_rdlock): Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Return +	result of lock re-get if it fails. + +2003-03-11  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Fix asm syntax. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + +	* sysdeps/x86_64/tls.h (THREAD_SELF, THREAD_GETMEM, THREAD_GETMEM_NC, +	THREAD_SETMEM, THREAD_SETMEM_NC): Correct asm syntax. + +	* allocatestack.c [! TLS_MULTIPLE_THREADS_IN_TCB] (allocate_stack): +	Initialize *__libc_multiple_threads_ptr not __libc_multiple_threads. +	* sysdeps/pthread/createthread.c [! TLS_MULTIPLE_THREADS_IN_TCB] +	(create_thread): Likewise. +	Define __pthread_multiple_threads and __libc_multiple_threads_ptr. +	* init.c (__pthread_initialize_minimal_internal): Initialize +	__libc_multiple_threads_ptr if necessary. +	* pthreadP.h: Adjust prototype for __libc_pthread_init.  Declare +	__pthread_multiple_threads and __libc_multiple_threads_ptr. +	* sysdeps/unix/sysv/linux/libc_pthread_init.c: Define +	__libc_multiple_threads. +	(__libc_pthread_init): Return pointer to __libc_pthread_init if +	necessary. + +	* sysdeps/i386/tls.h (THREAD_SETMEM): Fix one-byte variant. +	(THREAD_SETMEM_NC): Likewise. + +	* sysdeps/x86_64/pthread_spin_trylock.c: Removed. +	* sysdeps/x86_64/pthread_spin_trylock.S: New file. +	* sysdeps/x86_64/pthread_spin_unlock.c: Removed. +	* sysdeps/x86_64/pthread_spin_unlock.S: New file. + +	* sysdeps/i386/i486/pthread_spin_trylock.S (pthread_spin_trylock): +	Eliminate one entire instruction. + +	* cancellation.c (__pthread_enable_asynccancel_2): New function. +	* pthreadP.h: Declare __pthread_enable_asynccancel_2. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +	(__pthread_cond_timedwait): Use __pthread_enable_asynccancel_2 +	instead of __pthread_enable_asynccancel. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +	(__pthread_cond_wait): Likewise. +	* sysdeps/pthread/pthread_cond_timedwait.c +	(__pthread_cond_timedwait): Likewise. +	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S +	(__condvar_cleanup): Wake up all waiters in case we got signaled +	after being woken up but before disabling asynchronous +	cancellation. +	* sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S +	(__condvar_cleanup): Likewise. + +	* init.c (__NR_set_tid_address): If already defined, don't redefine. +	Make it an error if architecture has no #if case.  Add x86-64. + +	* sysdeps/unix/sysv/linux/x86_64/Makefile: Add flags for +	pt-initfini.s generation. + +	* sysdeps/x86_64/tls.h: Include <asm/prctl.h>. +	(TLS_INIT_TP): Fix typo. + +2003-03-11  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/ia64/bits/atomic.h (atomic_exchange_and_add): Swap 2nd and +	3rd argument of __arch_compare_and_exchange_{32,64}_val_acq. + +	* sysdeps/unix/sysv/linux/ia64/sem_post.c: Include semaphore.h. +	* sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Likewise. +	* sysdeps/unix/sysv/linux/ia64/sem_trywait.c: Likewise. +	* sysdeps/unix/sysv/linux/ia64/sem_wait.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_post.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_trywait.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_wait.c: Likewise. + +2003-03-11  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread_cond_timedwait.c +	(__pthread_cond_timedwait): Return the result of the final +	locking.  If it succeeds, the regular function return value. + +	* sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): +	Return result of the final locking. +	* version.c (__nptl_main): Work around problems with the strange +	INTERNAL_SYSCALL macro on ppc32. +	* init.c (__pthread_initialize_minimal_internal): Unblock +	SIGCANCEL in case the parent blocked it. +	Reported by Paul Mackerras <paulus@samba.org>. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: New file. + +2003-03-11  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread_cond_timedwait.c +	(__pthread_cond_timedwait): Unlock and fail if +	__pthread_mutex_unlock_internal failed. + +	* sysdeps/pthread/createthread.c (ARCH_CLONE): Define if not defined. +	(create_thread): Only assert PD->tcb != NULL under [TLS_TCB_AT_TP]. +	Use ARCH_CLONE. +	* allocatestack.c (ALLOCATE_STACK_PARMS): New macro. +	[NEED_SEPARATE_REGISTER_STACK] (STACK_VARIABLES, +	STACK_VARIABLES_ARGS, STACK_VARIABLES_PARMS, ALLOCATE_STACK_PARMS, +	ALLOCATE_STACK): New macros. +	(TLS_TPADJ): New macro. +	(get_cached_stack, queue_stack, __deallocate_stack): Use TLS_TPADJ. +	(allocate_stack): Handle TLS_DTV_AT_TP and +	NEED_SEPARATE_REGISTER_STACK.  Use TLS_TPADJ. +	* pthread_create.c (__pthread_create_2_1) [! TLS_TCB_AT_TP]: +	Don't set PD->self. +	* init.c [__ia64__] (__NR_set_tid_address): Define. + +	* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: New file. +	* sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: New file. +	* sysdeps/unix/sysv/linux/ia64/fork.c: New file. +	* sysdeps/unix/sysv/linux/ia64/createthread.c: New file. +	* sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c: New file. +	* sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c: New file. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.c: New file. +	* sysdeps/unix/sysv/linux/ia64/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: New file. +	* sysdeps/unix/sysv/linux/ia64/pt-initfini.c: New file. +	* sysdeps/unix/sysv/linux/ia64/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/ia64/pthread_once.c: New file. +	* sysdeps/unix/sysv/linux/ia64/sem_post.c: New file. +	* sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: New file. +	* sysdeps/unix/sysv/linux/ia64/sem_trywait.c: New file. +	* sysdeps/unix/sysv/linux/ia64/sem_wait.c: New file. +	* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: New file. +	* sysdeps/ia64/bits/atomic.h: New file. +	* sysdeps/ia64/Makefile: New file. +	* sysdeps/ia64/pthread_spin_init.c: New file. +	* sysdeps/ia64/pthread_spin_lock.c: New file. +	* sysdeps/ia64/pthread_spin_trylock.c: New file. +	* sysdeps/ia64/pthread_spin_unlock.c: New file. +	* sysdeps/ia64/pthreaddef.h: New file. +	* sysdeps/ia64/tcb-offsets.sym: New file. +	* sysdeps/ia64/td_ta_map_lwp2thr.c: New file. +	* sysdeps/ia64/tls.h: New file. + +	* sysdeps/s390/pthreaddef.h (__exit_thread_inline): Pass 1 argument +	to syscall instead of no arguments. + +2003-03-10  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Fix error value in +	unused code. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: New file + +	* sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add +	lowlevelbarrier.sym. +	* sysdeps/unix/sysv/linux/lowlevelbarrier.sym: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: +	Include lowlevelbarrier.h and don't define offsets locally. +	* sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Likewise. + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +	(__lll_mutex_lock_wait): Reverse order of first two parameters. +	(__lll_mutex_timedlock_wait): Likewise. +	(lll_mutex_lock): Adjust asm for that. +	(lll_mutex_timedlock): Likewise.  Mark cx, cc, r10 as clobbered. +	(lll_lock): Adjust asm for operand order change. +	* sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/libc-lowlevelmutex.S: New file. + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (__lll_lock_wait): +	Reverse order of parameters. +	(__lll_timedwait_tid): Remove regparms attribute. +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: New file. +	* sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +	(__lll_timedwait_tid): Remove one unnecessary instruction. + +	* sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Define +	__lll_mutex_timedlock_wait only for NOT_IN_libc. +	* sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: Include +	lowlevelmutex.S. + +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S: Define +	lll_unlock_wake_cb, __lll_wait_tid, and __lll_timedwait_tid only +	for NOT_IN_libc. +	* sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Include +	lowlevellock.S. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Don't define +	LOCK is already defined.  Don't define __lll_mutex_timedlock_wait +	for libc.so. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Only +	define LOCK here (if UP is not defined).  The actual code is in +	lowlevelmutex.S. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Don't define +	LOCK is already defined.  Don't define lll_unlock_wake_cb and +	__lll_timedwait_tid for libc.so. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Only +	define LOCK here (if UP is not defined).  The actual code is in +	lowlevellock.S. + +	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Not needed anymore. +	* sysdeps/unix/sysv/linux/s390/lowlevelsem.h: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_post.c: Include lowlevellock.h +	instead of lowlevelsem.h. +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_trywait.c: Likewise. +	* sysdeps/unix/sysv/linux/s390/sem_wait.c: Likewise. + +	* sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add +	lowlevelrwlock.sym. +	* sysdeps/unix/sysv/linux/lowlevelrwlock.sym: New file. +	* sysdeps/unix/sysv/linux/i386/lowlevelrwlock.h: Removed. +	* sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h: Removed. + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_trylock): Fix +	register loading. +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_trylock): Undo +	last changed.  D'oh. + +	* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: New file. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove declaration +	of __libc_locking_needed. +	(lll_trylock): Initialize %eax to zero. + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Update +	pthread_cond_t definition. + +2003-03-10  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/lowlevelcond.sym: New file. +	* sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add it. +	* sysdeps/unix/sysv/linux/sh/lowlevelcond.h: File removed. +	* sysdeps/unix/sysv/linux/i386/lowlevelcond.h: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/lowlevelcond.h: Likewise. + +	* allocatestack.c (allocate_stack) [!TLS_MULTIPLE_THREADS_IN_TCB]: +	Instead of setting PD->multiple_threads, set globals +	__pthread_multiple_threads and __libc_multiple_threads. +	* sysdeps/pthread/createthread.c (create_thread): Likewise. +	* sysdeps/i386/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define it. +	* sysdeps/s390/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Likewise. + +	* descr.h (struct pthread): Conditionalize first member on +	[!TLS_DTV_AT_TP].  Replace the `header' member with an anonymous union +	containing an anonymous tcbhead_t.  Move `list' member out. +	[TLS_MULTIPLE_THREADS_IN_TCB]: Define a `multiple_threads' member. +	* allocatestack.c: Remove use of `header.data.' prefix. +	* pthread_create.c: Likewise. +	* init.c (__pthread_initialize_minimal_internal): Likewise. +	* sysdeps/pthread/createthread.c (create_thread): Likewise. +	* sysdeps/i386/tls.h (INSTALL_DTV): Add parens. +	(THREAD_SELF, THREAD_DTV, INSTALL_NEW_DTV): No `header.data.' prefix. +	* sysdeps/x86_64/tls.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h +	(SINGLE_THREAD_P): Likewise. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h +	(SINGLE_THREAD_P): Likewise. +	* sysdeps/i386/tls.h (tcbhead_t): Remove `list' member. +	* sysdeps/s390/tls.h (tcbhead_t): Likewise. + +2003-03-09  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/lowlevelcond.h: New file. + +	* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: New file. +	* sysdeps/unix/sysv/linux/x86_64/fork.c: New file. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Fix many +	leftovers from the ia32 code. + +	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Remove unneccessary +	memory load. +	(clear_once_control): Don't load %esi. + +	* sysdeps/x86_64/tls.h: Remove all traces of segment descriptor +	handling. + +	* sysdeps/unix/sysv/linux/x86_64/fork.c: New file. + +	* sysdeps/unix/sysv/linux/s390/createthread.c: Moved to... +	* sysdeps/unix/sysv/linux/createthread.c: ...here. + +	* Makefile (tests): Add tst-cond10. +	* tst-cond10.c: New file. + +2003-03-08  Ulrich Drepper  <drepper@redhat.com> + +	* tst-tls2.c (do_test): Add TEMP_FAILURE_RETRY around sem_wait call. +	* tst-signal3.c (do_test): Likewise. +	* tst-sem5.c (do_test): Likewise. +	* tst-kill6.c (do_test): Likewise. +	* tst-tls3.c (do_test): Likewise.  Include <errno.h>. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use add/sub instead +	of inc/dec. +	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Likewise. +	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise +	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + +	* allocatestack.c (allocate_stack): If mprotect() fails free the +	TLS memory. + +2003-03-07  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/i486/bits/atomic.h: Fix a few unused definitions. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove all trace of +	lll_wake_tid.  This was used only to work around kernel limits in +	the early days. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. +	* sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + +	* init.c (__static_tls_align_m1): Renamed from __static_tls_align. +	(__pthread_initialize_minimal_internal): Change initialization of +	__static_tls_align_m1 appropriately. +	* pthreadP.h (__static_tls_align_m1): Renamed from +	__static_tls_align. +	* allocatestack.c (allocate_stack): Use __static_tls_align_m1 +	instead of __static_tls_align-1. + +2003-03-04  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/x86_64/Makefile: New file. + +	* pthread_create.c: Define __pthread_keys using nocommon +	attribute, not by placing it explicitly in bss. +	Remove DEFINE_DEALLOC definition.  Not needed anymore. + +	* allocatestack.c: Define ARCH_MAP_FLAGS if not already defined. +	Use it in mmap call to allocate stacks. + +	* sysdeps/pthread/createthread.c (create_thread): Fix comment. + +	* pthread_create.c (start_thread): Use THREAD_SETMEM to store +	result of the thread function. + +2003-03-03  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/s390/dl-sysdep.h: Removed.  The generic +	version is just fine. + +	* sysdeps/unix/sysv/linux/libc_pthread_init.c +	(__pthread_child_handler): Renamed from pthread_child_handler, +	exported, and marked hidden.  Change all users. +	* sysdeps/unix/sysv/linux/register-atfork.c (free_mem): Do not +	free __pthread_child_handler from child list. + +2003-03-03  Martin Schwidefsky  <schwidefsky@de.ibm.com> + +	* atomic.h (atomic_exchange_and_add): Return newval, not oldval. + +	* sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): +	Fix handling of cancellation and failing pthread_mutex_unlock call. +	* sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. +	(__pthread_cond_wait): Likewise. + +	* sysdeps/pthread/pthread_rwlock_timedrdlock.c +	(pthread_rwlock_timedrdlock): Fix clobber of result variable by +	lll_futex_timed_wait call. +	* sysdeps/pthread/pthread_rwlock_timedwrlock.c +	(pthread_rwlock_timedwrlock): Likewise. + +	* sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c (___lll_lock): +	Don't define lll_unlock_wake_cb and ___lll_timedwait_tid in libc.so. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.c: Remove XXX comments. + +	* sysdeps/unix/sysv/linux/s390/sem_post.c (__new_sem_post): Fix +	check of lll_futex_wake return value. + +2003-03-03  Roland McGrath  <roland@redhat.com> + +	* forward.c: Fix typo in __pthread_attr_init_2_0 compat_symbol decl. + +	* sysdeps/pthread/pthread-functions.h (struct pthread_functions): +	Argument to ptr___pthread_cleanup_upto is __jmp_buf, not jmp_buf. +	* sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise. + +2003-03-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/timer_create.c (timer_create): Return correct +	error for CPU clocks. + +	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define +	_POSIX_MONOTONIC_CLOCK. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + +	* tst-cancel4.c (tf_sleep): Lower sleep time a bit to not upset +	recent kernels. + +2003-03-01  Ulrich Drepper  <drepper@redhat.com> + +	* descr.h (struct pthread): Move cleanup field to the front. + +2003-03-01  Roland McGrath  <roland@redhat.com> + +	* sem_open.c (sem_open): Braino fix. + +2003-03-01  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/tcb-offsets.sym: Add CLEANUP and CLEANUP_PREV. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Inline +	__pthread_cleanup_pop functionality. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +	* descr.h (struct pthread): Move tid field to the front now that +	it is often used. + +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S +	(__lll_mutex_timedlock_wait): Remove. +	(__lll_mutex_unlock_wake): Don't save, load, and restore %esi. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S +	(__lll_mutex_unlock_wake): Don't save, load, and restore %esi. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +	(lll_unlock_wake_cb): Don't save and restore %esi. +	(__lll_unlock_wake): Add alignment.  Don't save, load, and restore +	%esi. +	(__lll_timedwait_tid): Add alignment. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S +	(__lll_unlock_wake): Add alignment.  Don't save, load, and restore +	%esi. +	(__lll_timedwait_tid): Removed. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S +	(__pthread_cond_broadcast): Don't save, load, and restore %esi. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S +	(pthread_barrier_wait): Don't save, load, and restore %esi for +	last thread. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S +	(__pthread_cond_signal): Don't save, load, and restore %esi. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S +	(__pthread_rwlock_unlock): Don't save, load, and restore %esi. +	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__new_sem_post): +	Don't save, load, and restore %esi. + +2003-02-27  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: +	Release lock before waking up the waiters. + +	* tst-exit1.c (do_test): Don't start more than one thread in parallel. + +	* tst-rwlock9.c (writer_thread): Correct adding TIMEOUT. +	(reader_thread): Likewise. + +	* sysdeps/pthread/pthread_rwlock_unlock.c +	(__pthread_rwlock_unlock): Release internal lock early.  Don't try +	to wake up readers if there are none. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: +	Release internal lock before wake threads. + +2003-02-26  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-rwlock10 and tst-rwlock11. +	* tst-rwlock8.c: Initialize lock with INIT.  Allow INIT to be +	predefined. +	* tst-rwlock9.c: Likewise. +	* tst-rwlock10.c: New file. +	* tst-rwlock11.c: New file. + +	* Makefile (tests): Add tst-dlsym1. +	* tst-dlsym1.c: New file. + +	* init.c (__pthread_initialize_minimal_internal): Set +	GL(dl_error_catch_tsd) to __libc_dl_error_tsd. +	* Versions (libc:GLIBC_PRIVATE): Export __libc_dl_error_tsd. + +2003-02-24  Ulrich Drepper  <drepper@redhat.com> + +	* sem_open.c (sem_open): Fix handling of O_CREAT without O_EXCL. + +	* tst-cond2.c: Fix sychronization with child. + +	* tst-rwlock8.c (reader_thread): Remove unused variable. + +	* Makefile: Add rules to build and run tst-tls3. +	* tst-tls3.c: New file. +	* tst-tls3mod.c: New file. + +	* Makefile (tests): Add tst-rwlock8 and tst-rwlock9. +	* tst-rwlock8.c: New file. +	* tst-rwlock9.c: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Fix +	complete broken rwlock implementation. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. +	* sysdeps/pthread/pthread_rwlock_rdlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_unlock.c: Likewise. +	* sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + +2003-02-23  Roland McGrath  <roland@redhat.com> + +	* Makefile (nptl-version): Change regexp so case sensitivity is ok. + +2003-02-23  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-context1. +	* tst-context1.c: New file. + +	* Makefile (tests): Add tst-tls1 and tst-tls2. +	* tst-tls1.c: New file. +	* tst-tls2.c: New file. + +	* libc-cancellation.c (__libc_enable_asynccancel): Correct test +	for failed cmpxchg. + +	* pthread_create.c (start_thread): Set EXITING_BIT early. + +	* sysdeps/i386/tls.h (THREAD_GETMEM): Mark asm as volatile. +	(THREAD_GETMEM_NC): Likewise. + +2003-02-22  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Shave +	off 3 more bytes by using offset-less instructions when possible. + +	* Makefile: Add dependency for $(objpfx)version.d. + +	* eintr.c (eintr_source): Add unnecessary return but the compiler +	insists. + +	* tst-kill3.c: Include <unistd.h>. + +2003-02-21  Roland McGrath  <roland@redhat.com> + +	* pthread_create.c (start_thread): Call __libc_thread_freeres. + +2003-02-21  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-eintr1. +	(distribute): Add eintr.c. +	* tst-eintr1.c: New file. +	* eintr.c: New file. + +	* pthread_cancel.c (pthread_cancel): Use tkill directly. + +	* sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): +	Disallow sending SIGCANCEL. + +	* Makefile (tests): Remove tst-basic7.  Add tst-kill1, tst-kill2, +	tst-kill3, tst-kill4, tst-kill5, tst-kill6. +	* tst-kill1.c: New file. +	* tst-kill2.c: New file. +	* tst-kill3.c: New file. +	* tst-kill5.c: New file. +	* tst-kill6.c: New file. +	* tst-basic7.c: Renamed to... +	* tst-kill4.c: ...this. + +2003-02-21  Roland McGrath  <roland@redhat.com> + +	* Makefile (install-lib-ldscripts): New variable. + +2003-02-21  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h: Define INVALID_TD_P and INVALID_NOT_TERMINATED_TD_P. +	* pthread_cancel.c: Use INVALID_TD_P. +	* pthread_detach.c: Likewise. +	* pthread_getschedparam.c: Likewise. +	* pthread_setschedparam.c: Likewise. +	* sysdeps/pthread/pthread_getcpuclockid.c: Likewise. +	* sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. +	* pthread_join.c: Use INVALID_NOT_TERMINATED_TD_P. +	* pthread_timedjoin.c: Likewise. + +	* tst-basic7.c: Include <signal.h>. + +	* pthread_join.c (pthread_join): Limited checking for invalid +	descriptors. +	* pthread_timedjoin.c (pthread_timedjoin_np): Likewise. + +2003-02-20  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_create.c (deallocate_tsd): Reset found_nonzero at the +	beginning of the loop.  Clear the entire first block of TSD. +	* Makefile (tests): Add tst-key4. +	* tst-key4.c: New file. + +2003-02-18  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-basic7. +	* tst-basic7.c: New file. + +	* pthread_create.c (deallocate_tsd): Mark as internal_function. +	Add some more __builtin_expect. + +	* pthreadP.h: Define dummy version of DEBUGGING_P. + +2003-02-17  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Remnove +	_POSIX_THREAD_PRIORITY_SCHEDULING. +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Remove +	_XOPEN_REALTIME_THREADS. +	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Likewise. + +	* sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): The +	kernel returns EINVAL for PID <= 0, work around it. + +	* Makefile (tests): Add tst-signal5. +	* tst-signal5.c: New file. + +	* sysdeps/unix/sysv/linux/bits/local_lim.h: Define TTY_NAME_MAX +	and LOGIN_NAME_MAX. + +	* tst-cancel1.c (tf): Block all signals. + +	* Makefile (tests): Add tst-basic6. +	* tst-basic6.c: New file. + +	* tst-basic1.c: Add test for process ID. + +	* Makefile (tests): Add tst-cancel10. +	* tst-cancel10.c: New file. + +	* Makefile (tests): Add tst-signal4. +	* tst-signal4.c: New file. + +	* sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Use +	__sigismember instead of sigismember.  Add __builtin_expect. + +2003-02-16  Ulrich Drepper  <drepper@redhat.com> + +	* tst-attr1.c (do_test): Add tests for pthread_setcanceltype, +	pthread_setcancelstate, and pthread_rwlock_setpshared. + +	* tst-cancel7.c (do_test): Make sure the pid file exists before +	canceling the thread. + +	* tst-rwlock6.c: More pthread_rwlock_timedwrlock and +	pthread_rwlock_timedrdlock tests. +	* tst-rwlock7.c: More pthread_rwlock_timedwrlock tests. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	Check for invalid tv_nsec field. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	Likewise. + +	* pthread_mutex_trylock.c (__pthread_mutex_trylock): Protect +	recursive mutex of overflow. + +	* tst-attr1.c (do_test): Add test for pthread_mutexattr_setpshared. + +	* libc-cancellation.c (__libc_enable_asynccancel): Rewrite to avoid +	going into an endless loop. +	* Makefile (tests): Add tst-cancel9. +	* tst-cancel9.c: New file. + +	* pthread_cancel.c (pthread_cancel): Use the result of __pthread_kill. + +2003-02-15  Ulrich Drepper  <drepper@redhat.com> + +	* tst-mutex5.c (do_test): Add more timedlock tests. + +	* tst-mutex2.c: Tests of trylock and unlock with ERROR mutexes. +	* tst-mutex3.c (do_test): Add tests for trylock with RECURSIVE mutexes. + +	* sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Don't +	use INLINE_SYSCALL.  Error number is returned, not -1. + +	* pthreadP.h: Mark declarations of __find_in_stack_list, __free_tcb, +	and __deallocate_stack with internal_function. +	* pthread_create.c: Adjust definitions appropriately. +	* allocatestack.c: Likewise. + +	* pthread_join.c: Add one more __builtin_expect. +	* pthread_timedjoin.c: Likewise. + +	* pthread_getspecific.c (__pthread_getspecific): Clear data->data +	not data of sequence number does not match. +	Add one __builtin_expect. + +	* Makefile (tests): Add tst-clock1. +	* tst-clock1.c: New file. + +	* pthread_setconcurrency.c (pthread_setconcurrency): Fail for +	negative arguments. +	* Makefile (tests): Add tst-basic5. +	* tst-basic5.c: New file. + +2003-02-14  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-basic4. +	* tst-basic4.c: New file. + +	* pthreadP.h: Add declaraction for __nptl_nthreads. +	* pthread_create.c: Define __nptl_nthreads +	(start_thread): Increment __nptl_nthreads at beginning.  Decrement +	after thread is done.  If then zero, call exit(0). +	* sysdeps/pthread/pthread-functions.h (struct pthread_functions): +	Add ptr_nthreads.  Define HAVE_PTR_NTHREADS. +	* init.c (pthread_functions): Initialize ptr_nthreads. +	* allocatestack.c (nptl_nthreads): Remove definition and all uses. +	(__reclaim_stacks): Decrement __nptl_nthreads. +	* sysdeps/pthread/Makefile [$(subdir)==csu] (CFLAGS-libc-start.c): +	Define. +	* Makefile (tests): Add tst-basic3. +	* tst-basic3.c: New file. + +	* descr.h: Define CANCELING_BIT and CANCELING_BITMASK.  Introduce +	after CANCELTYPE_BIT, move the other bits up.  Update CANCEL_RESTMASK. +	* init.c (sigcancel_handler): Also set CANCELING_BITMASK bit in newval. +	* pthread_cancel.c (pthread_cancel): Likewise.  Also set CANCELING_BIT +	if asynchronous canceling is enabled. +	* pthread_join.c (pthread_join): When recognizing circular joins, +	take into account the other thread might be already canceled. +	* Makefile (tests): Add tst-join5. +	* tst-join5.c: New file. + +	* Makefile (tests): Add tst-join4. +	* tst-join4.c: New file. + +2003-02-13  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cond4.c (main): Add test of pthread_attr_getpshared. + +2003-02-13  Martin Schwidefsky  <schwidefsky@de.ibm.com> + +	* sysdeps/s390/tls.h (THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, +	THREAD_SETMEM_NC): Use passed descr instead of THREAD_SELF. +	* sysdeps/unix/sysv/linux/s390/jmp-unwind.c (_longjmp_unwind): Avoid +	warning. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.c: Include <sys/time.h> +	to avoid warning. +	* sysdeps/unix/sysv/linux/s390/sem_post.c (__new_sem_post): Return +	error if lll_futex_wake failed. + +2003-02-13  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Fix +	handling of cancellation and failung pthread_mutex_unlock call. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* Makefile (tests): Add tst-cond8 and tst-cond9. +	* tst-cond8.c: New file. +	* tst-cond9.c: New file. + +	* tst-cond7.c (do_test): Unlock the mutex before canceling the thread. + +	* sysdeps/pthread/pthread.h: Add missing initializers.  Protect +	non-standard initializers with __USE_GNU. + +	* Makefile (tests): Add tst-cleanup3. +	* tst-cleanup3.c: New file. + +2003-02-12  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-attr1 and tst-attr2. +	* tst-attr1.c: New file. +	* tst-attr2.c: New file. + +	* Makefile: Add rules to build and run tst-atfork2 test. +	* tst-atfork2.c: New file. +	* tst-atfork2mod.c: New file. + +	* sysdeps/unix/sysv/linux/unregister-atfork.c +	(__unregister_atfork): Free the memory allocated for the handlers +	after removing them from the lists. + +	* sysdeps/unix/sysv/linux/register-atfork.c: Define memeory +	cleanup function. + +	* tst-atfork1.c (do_test): Wait for the child we forked. +	Report error in child. + +	* sysdeps/unix/sysv/linux/fork.c (__libc_fork): Fix comment. + +	* sysdeps/pthread/Makefile: Define CFLAGS-confstr.c. + +2003-02-10  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-cancel8. +	* tst-cancel8.c: New file. + +	* sysdeps/unix/sysv/linux/i386/pthread_once.S (clear_once_control): Fix +	clearing of control variable. +	* Makefile (tests): Add tst-once3 and tst-once4. +	* tst-once3.c: New file. +	* tst-once4.c: New file. + +2003-02-08  kaz Kojima  <kkojima@rr.iij4u.or.jp> + +	* sysdeps/sh/Makefile: New file. +	* sysdeps/sh/bits/atomic.h: New file. +	* sysdeps/sh/pthread_spin_init.c: New file. +	* sysdeps/sh/pthread_spin_lock.c: New file. +	* sysdeps/sh/pthread_spin_trylock.S: New file. +	* sysdeps/sh/pthread_spin_unlock.S: New file. +	* sysdeps/sh/pthreaddef.h: New file. +	* sysdeps/sh/tcb-offsets.sym: New file. +	* sysdeps/sh/td_ta_map_lwp2thr.c: New file. +	* sysdeps/sh/tls.h: New file. +	* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: New file. +	* sysdeps/unix/sysv/linux/sh/bits/semaphore.h: New file. +	* sysdeps/unix/sysv/linux/sh/createthread.c: New file. +	* sysdeps/unix/sysv/linux/sh/fork.c: New file. +	* sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: New file. +	* sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: New file. +	* sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h: New file. +	* sysdeps/unix/sysv/linux/sh/lowlevelcond.h: New file. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.S: New file. +	* sysdeps/unix/sysv/linux/sh/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: New file. +	* sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h: New file. +	* sysdeps/unix/sysv/linux/sh/pt-initfini.c: New file. +	* sysdeps/unix/sysv/linux/sh/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_once.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: New file. +	* sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: New file. +	* sysdeps/unix/sysv/linux/sh/sem_post.S: New file. +	* sysdeps/unix/sysv/linux/sh/sem_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/sh/sem_trywait.S: New file. +	* sysdeps/unix/sysv/linux/sh/sem_wait.S: New file. +	* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: New file. + +2003-02-08  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cond2.c: Rearrange code to not rely on behavior undefined +	according to POSIX. + +	* tst-basic2.c (do_test): Lock mutex before creating the thread. + +2003-02-07  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/x86_64/tls.h: Remove unnecessary macros, left over from x86. +	(TLS_GET_FS): New #define. +	(TLS_SET_FS): New #define. +	Correct value of __NR_set_thread_area. + +	* sysdeps/x86_64/td_ta_map_lwp2thr.c: New file. + +2003-02-06  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-popen1. +	* tst-popen1.c: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Remove wrong +	but inactive generalization. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. +	Minor optimization, remove one instruction. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + +2003-02-04  Martin Schwidefsky  <schwidefsky@de.ibm.com> + +	* sysdeps/unix/sysv/linux/s390/fork.c: Correct order of parameters. + +2003-01-31  Martin Schwidefsky  <schwidefsky@de.ibm.com> + +	* init.c (__NR_set_tid_address): Add #ifdef for s390. +	* sysdeps/pthread/pthread_barrier_wait.c: New file. +	* sysdeps/pthread/pthread_cond_broadcast.c: New file. +	* sysdeps/pthread/pthread_cond_signal.c: New file. +	* sysdeps/pthread/pthread_cond_timedwait.c: New file. +	* sysdeps/pthread/pthread_cond_wait.c: New file. +	* sysdeps/pthread/pthread_rwlock_rdlock.c: New file. +	* sysdeps/pthread/pthread_rwlock_timedrdlock.c: New file. +	* sysdeps/pthread/pthread_rwlock_timedwrlock.c: New file. +	* sysdeps/pthread/pthread_rwlock_unlock.c: New file. +	* sysdeps/pthread/pthread_rwlock_wrlock.c: New file. +	* sysdeps/s390/Makefile: New file. +	* sysdeps/s390/bits/atomic.h: New file. +	* sysdeps/s390/pthread_spin_init.c: New file. +	* sysdeps/s390/pthread_spin_lock.c: New file. +	* sysdeps/s390/pthread_spin_trylock.c: New file. +	* sysdeps/s390/pthread_spin_unlock.c: New file. +	* sysdeps/s390/pthreaddef.h: New file. +	* sysdeps/s390/tcb-offsets.sym: New file. +	* sysdeps/s390/td_ta_map_lwp2thr.c: New file. +	* sysdeps/s390/tls.h: New file. +	* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: New file. +	* sysdeps/unix/sysv/linux/s390/bits/semaphore.h: New file. +	* sysdeps/unix/sysv/linux/s390/createthread.c: New file. +	* sysdeps/unix/sysv/linux/s390/dl-sysdep.h: New file. +	* sysdeps/unix/sysv/linux/s390/fork.c: New file. +	* sysdeps/unix/sysv/linux/s390/jmp-unwind.c: New file. +	* sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file. +	* sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c: New file. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.c: New file. +	* sysdeps/unix/sysv/linux/s390/lowlevellock.h: New file. +	* sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: New file. +	* sysdeps/unix/sysv/linux/s390/lowlevelsem.h: New file. +	* sysdeps/unix/sysv/linux/s390/pthread_once.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S: New file. +	* sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: New file. +	* sysdeps/unix/sysv/linux/s390/sem_post.c: New file. +	* sysdeps/unix/sysv/linux/s390/sem_timedwait.c: New file. +	* sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file. +	* sysdeps/unix/sysv/linux/s390/sem_wait.c: New file. + +2003-02-04  Ulrich Drepper  <drepper@redhat.com> + +	* atomic.h: Add a couple more default implementations. +	(atomic_compare_and_exchange_acq): Use +	__arch_compare_and_exchange_32_acq in return value definition.  It +	always exists. +	(atomic_bit_set): Renamed from atomic_set_bit. +	Add missing atomic_ prefixes. + +	* sysdeps/pthread/bits/libc-lock.h (__libc_once): In case no +	thread library is available, use correct value to mark initialized +	once variable. + +2003-02-03  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (allocate_stack): Use __getpagesize instead of +	__sysconf to determine pagesize. + +	* pthread_create.c: Include <atomic.h>. +	* allocatestack.c (allocate_stack): Implement coloring of the +	allocated stack memory.  Rename pagesize to pagesize_m1.  It's the +	size minus one.  Adjust users. +	* sysdeps/i386/i686/Makefile: New file. + +2003-02-02  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c: Improve comment throughout the file. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +	(__lll_lock_wait): Add branch prediction. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S +	(__lll_lock_wait): Likewise. +	(lll_unlock_wake_cb): Removed. + +2003-01-31  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Remove +	_POSIX_THREAD_PRIORITY_SCHEDULING. + +2003-01-30  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread-functions.h (struct pthread_functions): +	Fix return type of ptr___pthread_getspecific. + +2003-01-29  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-umask1. +	(tst-umask1-ARGS): Define. +	* tst-umask1.c: New file. + +2003-01-28  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (libpthread-routines): Remove lowlevelrwlock.  Add +	pthread_rwlock_rdlock, pthread_rwlock_timedrdlock, +	pthread_rwlock_wrlock, pthread_rwlock_timedwrlock, and +	pthread_rwlock_unlock. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Removed +	* sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S: Removed +	* sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S: Removed +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: +	New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: +	New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S: +	New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S: +	New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S: +	New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S: +	New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S: New file. + +	* Makefile (libpthread-routines): Remove lowlevelcond and +	lowlevelsem.  Add sem_wait, sem_trywait, sem_timedwait, sem_post, +	pthread_cond_wait, pthread_cond_timedwait, pthread_cond_signal, +	and pthread_cond_broadcast. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Removed +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Removed +	* sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S: Removed +	* sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S: Removed +	* sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S: Removed +	* sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S: Removed +	* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: New file. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/sem_wait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/sem_post.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/sem_wait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/sem_post.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: New file. +	* sysdeps/unix/sysv/linux/i386/lowlevelcond.h: New file. + +	* sysdeps/unix/sysv/linux/i386/createthread.c: Define +	PREPARE_CREATE and TLS_VALUE with x86-specific bits.  All the rest +	of the code is moved to ... +	* sysdeps/pthread/createthread.c: ...here.  New file. + +2003-01-27  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S +	(__new_sem_post): Clear %eax before returning. +	Reported by MAEDA Naoaki <maeda.naoaki@jp.fujitsu.com>. + +	* Makefile (tests): Add tst-cleanup2. +	* tst-cleanup2.c: New file. + +	* sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_region_start): +	Interpret first parameter correctly. + +2003-01-17  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (headers): Add bits/semaphore.h. + +2003-01-16  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/i386/tls.h (INIT_SYSINFO): Initialize _head->sysinfo even +	if not SHARED. + +2003-01-14  Ulrich Drepper  <drepper@redhat.com> + +	* sem_open.c (sem_open): Return SEM_FAILED if existing semaphore +	must be used and mapping failed. +	Reported by Luke Elliott <luke.elliott@activfinancial.com>. + +	* Makefile (CFLAGS-pthread_self.os): Define this, not +	CFLAGS-pthread_self.c. + +2003-01-13  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Don't export +	lll_unlock_wake_cb. + +	* Makefile (libpthread-routines): Add version.  Add rules to build +	version.os and banner.h. +	* version.c: New file. + +2003-01-13  Jakub Jelinek  <jakub@redhat.com> + +	* pthread_mutex_lock.c (__pthread_mutex_lock_internal): Make +	the alias unconditional. +	* pthread_mutex_unlock.c  (__pthread_mutex_unlock_internal): Likewise. + +2003-01-13  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (CFLAGS-pthread_self.c): New definition. + +2003-01-06  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Add +	INTERNAL_SYSCALL_DECL, add err argument to INTERNAL_SYSCALL* macros. +	* sysdeps/unix/sysv/linux/raise.c (raise): Likewise. +	* init.c (__pthread_initialize_minimal_internal): Likewise. + +2003-01-07  Jakub Jelinek  <jakub@redhat.com> + +	* pthreadP.h (__pthread_cond_timedwait): Add prototype. + +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h +	(RTLD_CORRECT_DYNAMIC_WEAK): Remove. +	(DL_SYSINFO_IMPLEMENTATION): Change into .text section and back. +	* sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h +	(RTLD_CORRECT_DYNAMIC_WEAK): Remove. +	(DL_SYSINFO_IMPLEMENTATION): Change into .text section and back. + +2003-01-06  Jakub Jelinek  <jakub@redhat.com> + +	* pthreadP.h (LIBC_CANCEL_HANDLED): Define. +	* pt-system.c (LIBC_CANCEL_HANDLED): Add. +	* tst-cancel-wrappers.sh: Remove all exceptions. + +2003-01-05  Ulrich Drepper  <drepper@redhat.com> + +	* tst-cancel-wrappers.sh: Invoke gawk not awk since we use GNU awk +	features.  Reported by Marijn Ros <marijn@mad.scientist.com>. + +	* sysdeps/unix/sysv/linux/jmp-unwind.c: Include <pthread-functions.h>. +	Use __libc_pthread_functions array if SHARED. + +	* pthreadP.h: Move pthread_cond_2_0_t definition to... +	* sysdeps/unix/sysv/linux/internaltypes.h: ...here. + +	* sysdeps/pthread/bits/libc-lock.h (__libc_ptf_call): New #define. +	(__libc_rwlock_rdlock, __libc_rwlock_wrlock, __libc_rwlock_unlock, +	__libc_key_create, __libc_getspecific, __libc_setspecific): Use +	__libc_ptf_call instead of __libc_maybe_call. +	(PTF): New #define. +	(__libc_cleanup_region_start): Wrap function name with PTF call. +	(__libc_cleanup_region_end): Likewise. +	(__libc_cleanup_end): Likewise. + +	* pthread_getspecific.c: Add __pthread_getspecific_internal alias. +	* pthread_setspecific.c: Add __pthread_setspecific_internal alias. +	* pthread_key_create.c: Add __pthread_key_create_internal alias. +	* pthreadP.h: Add prototypes. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Add +	__pthread_rwlock_rdlock, __pthread_rwlock_wrlock, and +	__pthread_rwlock_unlock aliases. +	* pthreadP.h: Add prototypes for new aliases. + +	* pthreadP.h (struct pthead_functions): Moved to... +	* sysdeps/pthread/pthread-functions.h: ...here.  New file. +	* init.c (pthread_functions): Add initializers for new elements. + +	* cleanup_defer.c: Add __pthread_cleanup_push_defer and +	__pthread_cleanup_pop_restore aliases. +	* pthreadP.h: Add prototypes. + +	* cleanup.c: Rename _GI_pthread_cleanup_push to __pthread_cleanup_push +	and _GI_pthread_cleanup_pop to __pthread_cleanup_pop. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Adjust caller. +	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise. +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. +	* pthreadP.h: Adjust prototypes and callers. + +2003-01-04  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-cancel7. +	(tst-cancel7-ARGS): New variable. +	* tst-cancel7.c: New file. + +	* old_pthread_cond_broadcast.c: Optimize initialization a bit to work +	around gcc defficiencies. +	* old_pthread_cond_signal.c: Likewise. +	* old_pthread_cond_timedwait.c: Likewise. +	* old_pthread_cond_wait.c: Likewise. + +	* pthreadP.h (pthread_cond_2_0_t): Remove unneeded lock element. + +2003-01-03  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-cond7. +	* tst-cond7.c: New file. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S +	(condvar_cleanup): Get condvar address from the right place. + +	* atomic.h: Correct definitions of atomic_full_barrier, +	atomic_read_barrier, atomic_write_barrier. + +	* old_pthread_cond_broadcast.c: Make memory allocate and initialization +	race-free. +	* old_pthread_cond_signal.c: Likewise. +	* old_pthread_cond_timedwait.c: Likewise. +	* old_pthread_cond_wait.c: Likewise. + +2003-01-03  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile ($(objpfx)libpthread.so): Depend on ld.so. + +2003-01-03  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h (pthread_cond_2_0_t): New type. +	(struct pthread_functions): Use new type for 2.0 condvar callbacks. +	Use new type for the 2.0 condvar function prototypes. +	* forward.c: Use pthread_cond_2_0_t for 2.0 condvar functions. +	* old_pthread_cond_init.c: Use pthread_cond_2_0_t for condvar +	parameter. +	* old_pthread_cond_destroy.c: Likewise. +	* old_pthread_cond_broadcast.c: Likewise.  Lock appropriately. +	* old_pthread_cond_signal.c: Likewise. +	* old_pthread_cond_timedwait.c: Likewise. +	* old_pthread_cond_wait.c: Likewise. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S +	(__pthread_cond_wait): Don't save cancellation mode and seq value +	in same location. + +	* herrno.c (__h_errno_location): Don't define as weak. + +2003-01-02  Jakub Jelinek  <jakub@redhat.com> + +	* Versions [libc] (GLIBC_2.3.2): Export pthread_cond_broadcast, +	pthread_cond_destroy, pthread_cond_init, pthread_cond_signal +	and pthread_cond_wait. +	* old_pthread_cond_broadcast.c (__old_pthread_cond_broadcast): +	Renamed to... +	(__pthread_cond_broadcast_2_0): ... this. +	* old_pthread_cond_destroy.c (__old_pthread_cond_destroy): +	Renamed to... +	(__pthread_cond_destroy_2_0): ... this. +	* old_pthread_cond_init.c (__old_pthread_cond_init): +	Renamed to... +	(__pthread_cond_init_2_0): ... this. +	* old_pthread_cond_signal.c (__old_pthread_cond_signal): +	Renamed to... +	(__pthread_cond_signal_2_0): ... this. +	* old_pthread_cond_wait.c (__old_pthread_cond_wait): +	Renamed to... +	(__pthread_cond_wait_2_0): ... this. +	* pthread_cond_destroy.c: Include shlib-compat.h. +	(pthread_cond_destroy): Change strong_alias into versioned_symbol. +	* pthread_cond_init.c: Include shlib-compat.h. +	(pthread_cond_init): Change strong_alias into versioned_symbol. +	* pthreadP.h (struct pthread_functions): Rename ptr_pthread_cond_* +	fields to ptr___pthread_cond_* and add ptr___pthread_cond_*_2_0 +	fields. +	(__pthread_cond_broadcast_2_0, __pthread_cond_destroy_2_0, +	__pthread_cond_init_2_0, __pthread_cond_signal_2_0, +	__pthread_cond_wait_2_0): New prototypes. +	(__old_pthread_cond_broadcast, __old_pthread_cond_destroy, +	__old_pthread_cond_init, __old_pthread_cond_signal, +	__old_pthread_cond_wait): Removed. +	* init.c: Include shlib-compat.h. +	(pthread_functions): Guard ptr___pthread_attr_init_2_0 +	initialization with SHLIB_COMPAT (GLIBC_2_0, GLIBC_2_1). +	Rename ptr_pthread_cond_* to ptr___pthread_cond_*, initialize +	ptr___pthread_cond_*_2_0 fields. +	* forward.c: Export both pthread_cond_*@@GLIBC_2.3.2 and +	pthread_cond_*@GLIBC_2.0 compatibility symbols. + +	* sysdeps/pthread/sigaction.c (SIGCANCEL): Only define if +	LIBC_SIGACTION was not yet defined. +	[!defined LIBC_SIGACTION]: Define LIBC_SIGACTION, #include self. +	[!defined LIBC_SIGACTION] (__sigaction): New function and +	libc_hidden_weak. +	[!defined LIBC_SIGACTION] (sigaction): New weak_alias. +	[defined LIBC_SIGACTION]: #include_next <sigaction.c>. + +2003-01-02  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (CFLAGS-pthread_atfork.c): Add -DNOT_IN_libc. + +2003-01-02  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): +	New, larger type definition. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: New condvar +	implementation. +	* Versions [libpthread]: Add definitions for new pthread_cond_* +	interfaces for version GLIBC_2.3.2. +	* pthread_cond_init.c: Update initialization for new type definition. +	* Makefile (libpthread-routines): Remove pthread_cond_wait, +	pthread_cond_timedwait, pthread_cond_signal, and +	pthread_cond_broadcast.  Add old_pthread_cond_init, +	old_pthread_cond_destroy, old_pthread_cond_wait, +	old_pthread_cond_timedwait, old_pthread_cond_signal, and +	old_pthread_cond_broadcast. +	* old_pthread_cond_broadcast.c: New file. +	* old_pthread_cond_destroy.c: New file. +	* old_pthread_cond_init.c: New file. +	* old_pthread_cond_signal.c: New file. +	* old_pthread_cond_timedwait.c: New file. +	* old_pthread_cond_wait.c: New file. +	* pthreadP.h: Add prototypes for the compatibility interfaces. + +	* pthread_cond_destroy.c: Don't include <errno.h>. + +2003-01-01  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Avoid +	unnecessary zero offset when addressing MUTEX. + +2002-12-31  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for +	__register_atfork. +	* sysdeps/unix/sysv/linux/register-atfork.c: Add libc_hidden_def +	for __register_atfork. + +2002-12-31  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Use __ASSEMBLER__ +	instead of ASSEMBLER test macro. + +	* sysdeps/unix/sysv/linux/allocrtsig.c (__libc_current_sigrtmin, +	__libc_current_sigrtmax): Add libc_hidden_def. + +	* sysdeps/pthread/list.h: Remove assert.h include. + +2002-12-31  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Use +	__pthread_initialize_minimal_internal not +	__pthread_initialize_minimal. + +2002-12-30  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Mark +	__pthread_initialize_minimal as hidden. + +	* init.c (__pthread_initialize_minimal_internal): Don't mark as +	constructor. + +2002-12-31  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile ($(inst_libdir)/libpthread.so): Depend on +	$(common-objpfx)format.lds, include that into the output script. +	Fix comment. +	(extra-B-pthread.so): Change linuxthreads/ into nptl/. + +2002-12-28  Andreas Jaeger  <aj@suse.de> + +	* sysdeps/unix/sysv/linux/xstatconv.c (xstat_conv): Adjust for +	nsec resolution changes. +	(xstat64_conv): Likewise. +	(xstat32_conv): Likewise. +	* sysdeps/unix/sysv/linux/kernel_stat.h: Add nsec resolution for +	struct kernel_stat. +	* sysdeps/unix/sysv/linux/bits/stat.h: Add nsec resolution for +	structs stat and stat64. +	* time/time.h (__timespec_defined): Define for __USE_MISC. +	* io/sys/stat.h [__USE_MISC]: Define __need_timespec for struct stat. + +2002-12-30  Jakub Jelinek  <jakub@redhat.com> + +	* forward.c (FORWARD2): Renamed from FORWARD3.  Remove unused export +	argument. +	(pthread_attr_init_2_0, pthread_attr_init_2_1): Use FORWARD macro. +	(pthread_exit): Use strong_alias to avoid warnings. +	* pthreadP.h (struct pthread_functions): Rename ptr_pthread_exit +	and ptr_pthread_attr_init_2_* to ptr___pthread_exit and +	ptr___pthread_attr_init_2_*. +	* init.c (pthread_functions): Adjust. + +2002-12-29  Ulrich Drepper  <drepper@redhat.com> + +	* forward.c: Make all functions available by default again.  It +	caused too much trouble. + +	* pt-siglongjmp.c: Removed. + +2002-12-28  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/i386/tls.h: Include tcb-offsets.h in assembler. +	(SYSINFO_OFFSET, MULTIPLE_THREADS_OFFSET): Remove. +	* sysdeps/i386/Makefile: New file. +	* sysdeps/i386/tcb-offsets.sym: New file. +	* sysdeps/pthread/tcb-offsets.h: New file. +	* sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): +	Remove MULTIPLE_THREADS_OFFSET and SYSINFO_OFFSET checks. + +	* sysdeps/unix/sysv/linux/Versions [libc] (GLIBC_PRIVATE): Move +	__register_atfork... +	(GLIBC_2.3.2): ...here. + +2002-12-28  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h: Mark pthread_attr_getstackaddr and +	pthread_attr_setstackaddr with __attribute_deprecated__. + +2002-12-27  Jakub Jelinek  <jakub@redhat.com> + +	* pt-system.c (system): Remove cancellation handling. +	* tst-cancel-wrappers.sh: Allow pt-system.o* to not use the +	cancellation routines. + +2002-12-28  Ulrich Drepper  <drepper@redhat.com> + +	* descr.h: Include <dl-sysdep.h>. +	(struct pthread): Move header.data.list to the back of the struct. +	* sysdeps/i386/tls.h (tcbhead_t): Move list to the back of the struct. +	(MULTIPLE_THREADS_OFFSET): Adjust offset. +	(SYSINFO_OFFSEET): Likewise. + +2002-12-27  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h (USE_DL_SYSINFO): +	Define. +	(DL_SYSINFO_DEFAULT): Cast to uintptr_t to avoid warnings. +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h (NEED_DL_SYSINFO, +	DL_SYSINFO_DEFAULT, DL_SYSINFO_IMPLEMENTATION): Define. +	(USE_DL_SYSINFO): Undef. + +2002-12-22  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (tests-reverse): Use $(objpfx)../libc.so instead of +	$(common-objpfx)libc.so. +	* tst-cancel4.c (tf_write, tf_writev): Increase buf sizes so that +	it is bigger than pipe buffer size even on arches with bigger +	page size. +	(tf_usleep): Cast usleep argument to useconds_t to avoid warnings. + +2002-12-25  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Implement +	correct errno access for case that USE___THREAD is not defined. + +2002-12-24  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Add missing #endif. +	Patch by Marijn Ros <marijn@mad.scientist.com>. + +2002-12-22  Roland McGrath  <roland@redhat.com> + +	* Makefile (omit-deps): Add $(unix-syscalls:%=ptw-%). + +2002-12-20  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/bits/stdio-lock.h (_IO_lock_inexpensive): Define. + +2002-12-19  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Don't define +	NEED_DL_SYSINFO since no processor < i686 had the sysenter opcode. +	* sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h: New file. + +	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Use ENTER_KERNEL instead +	of int $0x80. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Likewise. +	* sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Add support for using +	sysenter. +	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Likewise. + +	* sysdeps/i386/tls.h: Unconditionally include <dl-sysdep.h>. + +	* allocatestack.c (allocate_stack) [NEED_DL_SYSINFO]: Set sysinfo +	in new TCB. +	* sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Check +	that sysinfo is properly initialized. +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define RTLD_PRIVATE_ERRNO +	to 1 only for ld.so. + +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define +	RTLD_CORRECT_DYNAMIC_WEAK. + +2002-12-19  Jakub Jelinek  <jakub@redhat.com> + +	* forward.c (pthread_attr_init_2_0, pthread_attr_init_2_1): +	Use return 0 as 6th argument to FORWARD4. +	* pthread_equal.c: Include pthreadP.h instead of pthread.h. + +2002-12-18  Ulrich Drepper  <drepper@redhat.com> + +	* descr.h (struct pthread) [NEED_DL_SYSINFO]: Add sysinfo member. +	* sysdeps/i386/tls.h (tcbhead_t): Add sysinfo member. +	Define SYSINFO_OFFSEET if NEED_DL_SYSINFO is defined. +	(INIT_SYSINFO): New #define. +	(TLS_TP_INIT): Use INIT_SYSINFO. +	* sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): +	At test to make sure SYSINFO_OFFSET value is correct. +	* sysdeps/unix/sysv/linux/i386/dl-sysdep.h: New file. + +2002-12-18  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/flockfile.c (flockfile): Change into weak alias. +	* sysdeps/unix/sysv/linux/raise.c (gsignal): Add weak alias to raise. +	* Versions [libc: GLIBC_2.0]: Add pthread_attr_init. +	[libpthread: GLIBC_2.1]: Remove __pthread_rwlock_init, +	__pthread_rwlock_destroy, __pthread_rwlock_rdlock, +	__pthread_rwlock_wrlock, __pthread_rwlock_unlock, +	__pthread_rwlock_tryrdlock and __pthread_rwlock_trywrlock. + +2002-12-18  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Use ENTER_KERNEL +	macro instead of using int $0x80 directly. + +	* sysdeps/pthread/bits/stdio-lock.h: New file. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/libc-lowlevelmutex.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/libc-lowlevelmutex.S: New file. +	* Makefile (routines): Add libc-lowlevelmutex. + +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Remove +	__i686.get_pc_thunk.dx. + +2002-12-17  Jakub Jelinek  <jakub@redhat.com> + +	* Makefile (libpthread-shared-only-routines): Add pt-allocrtsig. +	(tests): Depend on $(objpfx)tst-cancel-wrappers.out. +	($(objpfx)tst-cancel-wrappers.out): New rule. +	* tst-cancel-wrappers.sh: New test. +	* tst-locale1.c: Include signal.h. +	(uselocale): Test static linking of __libc_current_sigrt*. + +2002-12-17  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-cancel6. +	* tst-cancel6.c: New file + +2002-12-17  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (SINGLE_THREAD_P): +	Define meaningfully for assembler as well. +	* pthreadP.h (struct pthread_functions): Remove +	ptr_pthread_attr_init field.  Add ptr_pthread_attr_init_2_0 +	and ptr_pthread_attr_init_2_1 fields. +	* init.c (pthread_functions): Initialize ptr_pthread_attr_init_2_0 +	and ptr_pthread_attr_init_2_1 instead of ptr_pthread_attr_init. +	* forward.c (FORWARD4): Renamed from FORWARD3. Add export argument. +	(FORWARD3): Define using FORWARD4. +	(pthread_attr_init): Provide both @GLIBC_2.0 and @@GLIBC_2.1 +	versions. +	* pt-system.c: Remove duplicate stdlib.h include. + +2002-12-16  Ulrich Drepper  <drepper@redhat.com> + +	* sem_init.c: Define sem_init@GLIBC_2.0. +	* sem_destroy.c: Define sem_destroy@GLIBC_2.0. +	* sem_getvalue.c: Define sem_getvalue@GLIBC_2.0. + +	* flockfile.c: Moved to... +	* sysdeps/pthread/flockfile.c: ...here.  New file. +	* funlockfile.c: Moved to... +	* sysdeps/pthread/funlockfile.c: ...here.  New file. +	* ftrylockfile.c: Moved to... +	* sysdeps/pthread/ftrylockfile.c: ...here.  New file. + +2002-12-16  Jakub Jelinek  <jakub@redhat.com> + +	* libc-cancellation.c: Guard both function with +	#if !defined NOT_IN_libc. +	* Makefile (libpthread-routines): Use ptw-, not pt- prefix for the +	automatically provided pthread wrappers. +	* pthreadP.h (LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): Define to +	CANCEL_* if IS_IN_libpthread and to dummy versions if not in libc +	nor in libpthread. +	* pt-open.c: Removed. +	* pt-fcntl.c: Removed. +	* pt-fsync.c: Removed. +	* pt-lseek.c: Removed. +	* pt-msgrcv.c: Removed. +	* pt-msgsnd.c: Removed. +	* pt-msync.c: Removed. +	* pt-nanosleep.c: Removed. +	* pt-open64.c: Removed. +	* pt-pause.c: Removed. +	* pt-pread.c: Removed. +	* pt-pread64.c: Removed. +	* pt-pwrite.c: Removed. +	* pt-pwrite64.c: Removed. +	* pt-read.c: Removed. +	* pt-recv.c: Removed. +	* pt-recvfrom.c: Removed. +	* pt-recvmsg.c: Removed. +	* pt-send.c: Removed. +	* pt-sendto.c: Removed. +	* pt-sigtimedwait.c: Removed. +	* pt-sigwait.c: Removed. +	* pt-wait.c: Removed. +	* pt-waitpid.c: Removed. +	* pt-write.c: Removed. +	* pt-accept.c: Removed. +	* pt-close.c: Removed. +	* pt-connect.c: Removed. +	* pt-lseek64.c: Removed. +	* pt-sendmsg.c: Removed. +	* pt-tcdrain.c: Removed. + +2002-12-15  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (__pthread_initialize_minimal_internal): Renamed from +	__pthread_initialize_minimal.  Make old name an alias.  This +	converts a normal relocation into a relative relocation. + +	* pt-fcntl.c (__fcntl): Use fcntl64 syscall, not fcntl. + +	* Versions [libpthread: GLIBC_2.3.2]: Remove creat, poll, pselect, +	readv, select, sigpause, sigsuspend, sigwaitinfo, waitid, writev. +	* Makefile (libpthread-routines): Remove pt-creat, pt-poll, +	pt-pselect, pt-readv, pt-select, pt-sigpause, pt-sigsuspend, +	pt-sigwaitinfo, pt-waitid, and pt-writev. +	* pt-creat.c: Removed. +	* pt-poll.c: Removed. +	* pt-pselect.c: Removed. +	* pt-readv.c: Removed. +	* pt-select.c: Removed. +	* pt-sigpause.c: Removed. +	* pt-sigsuspend.c: Removed. +	* pt-sigwaitinfo.c: Removed. +	* pt-waitid.c: Removed. +	* pt-writev.c: Removed. + +	* init.c (pthread_functions): New variable. +	(__pthread_initialize_minimal): Pass pointer to pthread_functions +	(or NULL) to __libc_pthread_init. +	* forward.c: Rewrite to use __libc:pthread_functions array to get +	function addresses. +	* sysdeps/unix/sysv/linux/fork.h: Remove __libc_pthread_init +	prototype. +	* sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): +	Take new parameter.  Copy content of variable pointed to by it +	to __libc_pthread_init. + +	* pthreadP.h (struct pthread_functions): New type. +	(__libc_pthread_init): Declare. + +	* pthread_attr_destroy.c: Add namespace protected alias. +	* pthread_attr_getdetachstate.c: Likewise. +	* pthread_attr_getinheritsched.c: Likewise. +	* pthread_attr_getschedparam.c: Likewise. +	* pthread_attr_getschedpolicy.c: Likewise. +	* pthread_attr_getscope.c: Likewise. +	* pthread_attr_setdetachstate.c: Likewise. +	* pthread_attr_setinheritsched.c: Likewise. +	* pthread_attr_setschedparam.c: Likewise. +	* pthread_attr_setschedpolicy.c: Likewise. +	* pthread_attr_setscope.c: Likewise. +	* pthread_cond_broadcast.c: Likewise. +	* pthread_cond_destroy.c: Likewise. +	* pthread_cond_init.c: Likewise. +	* pthread_cond_signal.c: Likewise. +	* pthread_cond_wait.c: Likewise. +	* pthread_condattr_destroy.c: Likewise. +	* pthread_condattr_init.c: Likewise. +	* pthread_equal.c: Likewise. +	* pthread_exit.c: Likewise. +	* pthread_getschedparam.c: Likewise. +	* pthread_self.c: Likewise. +	* pthread_setcancelstate.c: Likewise. +	* pthread_setschedparam.c: Likewise. +	* pthread_mutex_destroy.c: Likewise. +	* pthread_mutex_init.c: Likewise. +	* pthreadP.h: Add prototypes for the aliases. + +	* sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Set +	multiple_threads member in correct TCB to 1. + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define +	SINGLE_THREAD_P.  If in libc or libpthread examine multiple_thread +	member of thread decriptor, otherwise return unconditionally 1. + +2002-12-14  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/pt-socket.S: Changes folded into the +	regular Linux version.  Remove file. +	* sysdeps/unix/sysv/linux/connect.S: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/llseek.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/msgrcv.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/msgsnd.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/open64.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/poll.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/pread.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/pread64.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/pselect.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/pwrite.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/pwrite64.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/readv.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/recv.S: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/recvfrom.S: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/recvmsg.S: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/send.S: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/sendmsg.S: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/sendto.S: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/sigpause.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/sigsuspend.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/sigtimedwait.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/sigwait.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/sigwaitinfo.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/system.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/tcdrain.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/wait.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/waitid.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/waitpid.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/writev.c: Likewise.  Remove file. +	* sysdeps/unix/sysv/linux/i386/fcntl.c: Likewise.  Remove file. + +2002-12-14  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: New file. +	* sysdeps/unix/sysv/linux/open.c: Removed. +	* sysdeps/unix/sysv/linux/fsync.c: Removed. +	* sysdeps/unix/sysv/linux/lseek.c: Removed. +	* sysdeps/unix/sysv/linux/msync.c: Removed. +	* sysdeps/unix/sysv/linux/read.c: Removed. +	* sysdeps/unix/sysv/linux/close.c: Removed. +	* sysdeps/unix/sysv/linux/creat.c: Removed. +	* sysdeps/unix/sysv/linux/nanosleep.c: Removed. +	* sysdeps/unix/sysv/linux/pause.c: Removed. +	* sysdeps/unix/sysv/linux/select.c: Removed. +	* sysdeps/unix/sysv/linux/write.c: Removed. + +2002-12-14  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/pt-socket.S: Check multiple_threads +	element in TCB to see whether locking is needed. + +	* sysdeps/unix/sysv/linux/libc_pthread_init.c: Check that +	MULTIPLE_THREADS_OFFSET value is correct. + +	* sysdeps/unix/sysv/linux/close.c: New file. +	* sysdeps/unix/sysv/linux/connect.S: New file. +	* sysdeps/unix/sysv/linux/creat.c: New file. +	* sysdeps/unix/sysv/linux/fsync.c: New file. +	* sysdeps/unix/sysv/linux/llseek.c: New file. +	* sysdeps/unix/sysv/linux/lseek.c: New file. +	* sysdeps/unix/sysv/linux/msgrcv.c: New file. +	* sysdeps/unix/sysv/linux/msgsnd.c: New file. +	* sysdeps/unix/sysv/linux/msync.c: New file. +	* sysdeps/unix/sysv/linux/nanosleep.c: New file. +	* sysdeps/unix/sysv/linux/open.c: New file. +	* sysdeps/unix/sysv/linux/open64.c: New file. +	* sysdeps/unix/sysv/linux/pause.c: New file. +	* sysdeps/unix/sysv/linux/poll.c: New file. +	* sysdeps/unix/sysv/linux/pread.c: New file. +	* sysdeps/unix/sysv/linux/pread64.c: New file. +	* sysdeps/unix/sysv/linux/pselect.c: New file. +	* sysdeps/unix/sysv/linux/pwrite.c: New file. +	* sysdeps/unix/sysv/linux/pwrite64.c: New file. +	* sysdeps/unix/sysv/linux/readv.c: New file. +	* sysdeps/unix/sysv/linux/recv.S: New file. +	* sysdeps/unix/sysv/linux/recvfrom.S: New file. +	* sysdeps/unix/sysv/linux/recvmsg.S: New file. +	* sysdeps/unix/sysv/linux/select.c: New file. +	* sysdeps/unix/sysv/linux/send.S: New file. +	* sysdeps/unix/sysv/linux/sendmsg.S: New file. +	* sysdeps/unix/sysv/linux/sendto.S: New file. +	* sysdeps/unix/sysv/linux/sigpause.c: New file. +	* sysdeps/unix/sysv/linux/sigsuspend.c: New file. +	* sysdeps/unix/sysv/linux/sigtimedwait.c: New file. +	* sysdeps/unix/sysv/linux/sigwait.c: New file. +	* sysdeps/unix/sysv/linux/sigwaitinfo.c: New file. +	* sysdeps/unix/sysv/linux/system.c: New file. +	* sysdeps/unix/sysv/linux/tcdrain.c: New file. +	* sysdeps/unix/sysv/linux/wait.c: New file. +	* sysdeps/unix/sysv/linux/waitid.c: New file. +	* sysdeps/unix/sysv/linux/waitpid.c: New file. +	* sysdeps/unix/sysv/linux/writev.c: New file. +	* sysdeps/unix/sysv/linux/i386/fcntl.c: New file. + +	* pt-readv.c: Fix comment. + +2002-12-14  Jakub Jelinek  <jakub@redhat.com> + +	* tst-cleanup1.c: Include stdlib.h. + +	* tst-cancel5.c: New test. +	* Makefile (tests): Add tst-cancel5. +	(tst-cancel5): Link against libc.so libpthread.so in that order. + +2002-12-13  Ulrich Drepper  <drepper@redhat.com> + +	* forward.c (test_loaded): Prevent recursive calls. + +	* Makefile (routines): Add libc-cancellation. +	* libc-cancellation.c: New file. +	* descr.h (struct pthread): Add multiple_threads field. +	* allocatestack.c (allocate_stack): Initialize multiple_header field of +	new thread descriptor to 1. +	* sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): +	Initialize multiple_thread field after successful thread creation. +	* cancellation.c (__do_cancel): Move to pthreadP.h. +	(__pthread_enable_asynccancel): Remove parameter from __do_cancel call. +	(__pthread_disable_asynccancel): Add internal_function attribute. +	* init.c (sigcancel_handler): Remove parameter from __do_cancel call. +	* pthread_setcancelstate.c: Likewise. +	* pthread_setcanceltype.c: Likewise. +	* pthread_exit.c: Likewise. +	* pthreadP.h (CANCELLATION_P): Likewise. +	(__do_cancel): Define as static inline. +	(LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): New #defines. +	(__libc_enable_asynccancel, __libc_disable_asynccancel): New +	declarations. +	* sysdeps/i386/tls.h (tcbhead_t): Add list and multiple_threads +	fields.  Define MULTIPLE_THREADS_OFFSET. +	* sysdeps/pthread/bits/libc-lock.h: Remove __libc_locking_needed +	declaration. +	* sysdeps/unix/sysv/linux/accept.S: New file. +	* sysdeps/unix/sysv/linux/read.c: New file. +	* sysdeps/unix/sysv/linux/write.c: New file. +	* sysdeps/unix/sysv/linux/i386/pt-socket.S: New file. +	* sysdeps/unix/sysv/linux/libc_pthread_init.c: Remove definition and +	initialization of __libc_locking_needed. +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Don't use +	__libc_locking_needed, use multiple_threads field in TCB. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + +2002-12-12  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S: Use i486 +	version. +	* sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S: Likewise. + +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Correct +	access to __libc_locking_needed for PIC. + +2002-12-12  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/pthread/bits/libc-lock.h (__libc_locking_needed): Only +	declare for libc.so. +	(__libc_lock_init, __libc_lock_init_recursive): Change into comma +	expression. +	(__libc_lock_lock): Put into statement expression. +	(__libc_lock_unlock): Remove trailing semicolon. +	* sysdeps/unix/sysv/linux/fork.h (__libc_pthread_init): Fix typo. + +2002-12-12  Roland McGrath  <roland@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use asm operand with +	"m" constraint to refer to __libc_locking_needed.  Declare it here. + +2002-12-12  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/fork-gen.c: Renamed to... +	* sysdeps/unix/sysv/linux/libc_pthread_init.c: ...this. +	Initialize __libc_locking_needed. +	* init.c (__pthread_initialize_minimal): Call __libc_pthread_init +	instead of __register_pthread_fork_handler. +	* sysdeps/pthread/bits/libc-lock.h: Declare __libc_locking_needed. +	* sysdeps/unix/sysv/linux/Makefile (sysdep_routimes): Replace +	fork-gen with libc_pthread_init. +	* sysdeps/unix/sysv/linux/Versions: Use __libc_pthread_init instead +	of __register_pthread_fork_handler. +	* sysdeps/unix/sysv/linux/fork.h: Declare __libc_pthread_init instead +	of __register_pthread_fork_handler. +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use +	__libc_locking_needed to determine whether lock prefix can be avoided. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + +2002-12-11  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-cleanup1. +	* tst-cleanup1.c: New file. +	* cancellation.c (__cleanup_thread): Removed. +	(__do_cancel): Remove call to __cleanup_thread. +	* pthreadP.h: Remove __cleanup_thread prorotype. + +	* sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_region_start): +	Remember function and argument even if cancellation handler +	function is not available. +	(__libc_cleanup_region_end): Execute registered function directly if +	pthread functions are not available. +	(__libc_cleanup_end): Likewise. + +	* init.c (__pthread_initialize_minimal): Fix initialization in +	static lib by preventing gcc from being too clever. + +2002-12-10  Ulrich Drepper  <drepper@redhat.com> + +	* init.c (__pthread_initialize_minimal): Remove unneccesary +	sigaddset call. + +	* Makefile (tests): We can run tst-locale2 now. + +2002-12-09  Ulrich Drepper  <drepper@redhat.com> + +	* Versions: Remove duplicated sigwait entry. + +2002-12-08  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h: Enable pthread_cleanup_{push,pop} optimizations only +	inside libpthread. + +	* pt-fcntl.c (__fcntl): Initialize oldtype to avoid warning. + +	* pthreadP.h: Declare __pthread_enable_asynccancel and +	__pthread_disable_asynccancel. +	(CANCEL_ASYNC): Use __pthread_enable_asynccancel. +	(CANCEL_RESET): Use __pthread_disable_asynccancel. +	* cancellation.c (__pthread_enable_asynccancel): New function. +	(__pthread_disable_asynccancel): New function. +	* pt-accept.c: Adjust for CANCEL_ASYNC and CANCEL_RESET change. +	* pt-close.c: Likewise. +	* pt-connect.c: Likewise. +	* pt-creat.c: Likewise. +	* pt-fcntl.c: Likewise. +	* pt-fsync.c: Likewise. +	* pt-lseek.c: Likewise. +	* pt-lseek64.c: Likewise. +	* pt-msgrcv.c: Likewise. +	* pt-msgsnd.c: Likewise. +	* pt-msync.c: Likewise. +	* pt-nanosleep.c: Likewise. +	* pt-open.c: Likewise. +	* pt-open64.c: Likewise. +	* pt-pause.c: Likewise. +	* pt-poll.c: Likewise. +	* pt-pread.c: Likewise. +	* pt-pread64.c: Likewise. +	* pt-pselect.c: Likewise. +	* pt-pwrite.c: Likewise. +	* pt-pwrite64.c: Likewise. +	* pt-read.c: Likewise. +	* pt-readv.c: Likewise. +	* pt-recv.c: Likewise. +	* pt-recvfrom.c: Likewise. +	* pt-recvmsg.c: Likewise. +	* pt-select.c: Likewise. +	* pt-send.c: Likewise. +	* pt-sendmsg.c: Likewise. +	* pt-sendto.c: Likewise. +	* pt-sigpause.c: Likewise. +	* pt-sigsuspend.c: Likewise. +	* pt-sigtimedwait.c: Likewise. +	* pt-sigwait.c: Likewise. +	* pt-sigwaitinfo.c: Likewise. +	* pt-system.c: Likewise. +	* pt-tcdrain.c: Likewise. +	* pt-wait.c: Likewise. +	* pt-waitid.c: Likewise. +	* pt-waitpid.c: Likewise. +	* pt-write.c: Likewise. +	* pt-writev.c: Likewise. +	* pthread_join.c: Likewise. +	* pthread_timedjoin.c: Likewise. + +	* pt-sigpause.c (sigsuspend): Call __sigsuspend. +	(__xpg_sigpause): New function. +	* Versions (libpthread:GLIBC_2.3.2): Add __xpg_sigpause. + +2002-12-07  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (CFLAGS-ftrylockfile.c): Add -D_IO_MTSAFE_IO. + +	* cleanup.c: Move declarations of _GI_pthread_cleanup_push and +	_GI_pthread_cleanup_pop to pthreadP.h. + +	* ftrylockfile.c: Use _IO_lock_trylock instead of +	pthread_mutex_trylock. + +	* pthreadP.h (CANCEL_ASYNC): Use __pthread_setcanceltype. +	(CANCEL_RESET): Likewise. +	(__pthread_setcanceltype_): Declare. +	(__pthread_mutex_lock_internal): Declare. +	(__pthread_mutex_unlock_internal): Declare. +	(__pthread_once_internal): Declare. +	(pthread_cleanup_push): Redefine using _GI_pthread_cleanup_push. +	(pthread_cleanup_pop): Redefine using _GI_pthread_cleanup_pop. + +	* pthread_cond_timedwait.c: Use INTUSE is calls to pthread_mutex_lock +	and pthread_mutex_unlock. +	* pthread_cond_wait.c: Likewise. +	* pthread_mutex_lock.c: Use INTDEF to define alias if needed. +	* pthread_mutex_unlock.c: Likewise. + +	* pthread_setcanceltype.c: Add additional alias +	__pthread_setcanceltype. + +	* sem_unlink.c (sem_unlink): Use __pthread_once with INTDEF. +	* sem_open.c (sem_open): Likewise. +	Use __libc_open, __libc_write, and __libc_close instead of +	open, write, and close respectively. + +	* sysdeps/pthread/bits/libc-lock.h (__libc_lock_trylock_internal): +	Rewrite as statement expression since it must return a value. + +	* pthread_cancel.c: Use __pthread_kill instead of pthread_kill. +	* sysdeps/unix/sysv/linux/pthread_kill.c: Define additional alias +	__pthread_kill. + +	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Define additional +	alias __pthread_once_internal. + +	* sysdeps/unix/sysv/linux/raise.c: Use libc_hidden_def for raise. + +2002-12-06  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-stdio1 and tst-stdio2. +	* tst-stdio1.c: New file. +	* tst-stdio2.c: New file. + +	* init.c (__pthread_initialize_minimal): Correct INIT_LIST_HEAD use. + +	* Makefile (tests): Comment out tst-locale2 for now. +	(CFLAGS-flockfile.c, CFLAGS-funlockfile.c): Define to -D_IO_MTSAFE_IO. + +	* sysdeps/unix/sysv/linux/Makefile: Define CFLAGS-fork.c to +	-D_IO_MTSAFE_IO. +	* sysdeps/unix/sysv/linux/fork.c: Include <bits/stdio-lock.h>. +	Use _IO_lock_init instead of explicit assignment. + +	* sysdeps/pthread/bits/libc-lock.h: Define __rtld_lock_* macros. +	Define __libc_lock_* and __libc_lock_recursive macros with +	lowlevellock macros, not pthread mutexes. + +	* flockfile.c: Include <bits/stdio-lock.h>.  Use _IO_lock_lock instead +	of pthread_mutex_lock. +	* funlockfile.c: Include <bits/stdio-lock.h>.  Use _IO_lock_unlock +	instead of pthread_mutex_unlock. + +2002-12-06  Roland McGrath  <roland@redhat.com> + +	* allocatestack.c (__stack_user): Use uninitialized defn. +	* init.c (__pthread_initialize_minimal): Initialize it here. + +2002-12-05  Roland McGrath  <roland@redhat.com> + +	* sysdeps/i386/tls.h (TLS_INIT_TP): Make it return zero or an error +	string. +	* sysdeps/x86_64/tls.h (TLS_INIT_TP): Likewise. + +	* sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Add +	missing & here too. + +2002-12-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove +	lowlevellock. +	* sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S: New file. +	* sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S: New file. +	* sysdeps/pthread/bits/libc-lock.h: Use lowlevellock implementation +	for __libc_lock_* macros. +	* Makefile (routines): Add libc-lowlevellock. + +2002-10-09  Roland McGrath  <roland@redhat.com> + +	* sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call): New macro. +	Under [__PIC__], call the function via the pointer fetched for +	comparison rather than a call by name that uses the PLT. +	(__libc_lock_init, __libc_rwlock_init, __libc_lock_fini) +	(__libc_rwlock_fini, __libc_lock_lock, __libc_rwlock_rdlock) +	(__libc_rwlock_wrlock, __libc_lock_trylock, __libc_rwlock_tryrdlock) +	(__libc_rwlock_trywrlock, __libc_lock_unlock, __libc_rwlock_unlock) +	(__libc_key_create, __libc_getspecific, __libc_setspecific): Use it. + +2002-12-04  Roland McGrath  <roland@redhat.com> + +	* forward.c (pthread_self): Use FORWARD3 macro to correct return type. + +	* sysdeps/i386/td_ta_map_lwp2thr.c: Moved from ../nptl_db. +	* sysdeps/generic/td_ta_map_lwp2thr.c: New file. + +	* pthread_create.c (start_thread): Add missing & on __nptl_last_event. + +2002-12-04  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Make pthread_t +	a completely opaque, non-integer type. +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2002-12-05  Jakub Jelinek  <jakub@redhat.com> + +	* sysdeps/i386/tls.h: Include stdlib.h. +	* sysdeps/x86_64/tls.h: Likewise. + +2002-12-04  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-locale2. +	(tests-static): Likewise. +	* tst-locale2.c: New file. + +	* sysdeps/unix/sysv/linux/i386/lowlevellock.h: Mark asms as +	volatile and add memory clobbers to lock operations. + +2002-12-03  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/i686/bits/atomic.h: Use i486 version. +	* sysdeps/i386/i486/bits/atomic.h: New file. +	* sysdeps/i386/i586/bits/atomic.h: New file. +	* sysdeps/i386/i686/pthread_spin_trylock.S: Define HAVE_CMOV and +	include i486 version. +	* sysdeps/i386/i486/pthread_spin_trylock.S: New file. +	* sysdeps/i386/i586/pthread_spin_trylock.S: New file. +	Patch by Marijn Ros <marijn@mad.scientist.com>. + +	* allocatestack.c (get_cached_stack): Don't crash if we first +	found a stack with a larger size then needed. +	Reported by Hui Huang <hui.huang@sun.com>. + +	* Makefile (tests): Add tst-sysconf. +	* tst-sysconf.c: New file. + +	* sysdeps/unix/sysv/linux/bits/local_lim.h: Undefine +	PTHREAD_THREADS_MAX. + +2002-12-02  Roland McGrath  <roland@redhat.com> + +	* pthreadP.h (__stack_user, __nptl_create_event, __nptl_death_event): +	Declare using hidden_proto instead of attribute_hidden, so there are +	non-.hidden static symbols for gdb to find. +	(__pthread_keys): Likewise. +	* events.c (__nptl_create_event, __nptl_death_event): Add hidden_def. +	* allocatestack.c (__stack_user): Likewise. +	* pthread_create.c (__pthread_keys): Likewise. +	(__nptl_threads_events, __nptl_last_event): Make these static instead +	of hidden. +	* pthread_key_create.c (__pthread_pthread_keys_max, +	__pthread_pthread_key_2ndlevel_size): Renamed from __linuxthreads_*. + +2002-12-02  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-locale1.  If buid-static is yes link +	statically. +	* tst-locale1.c: New file. + +	* pthread_cond_timedwait.c: Include <stdlib.h>. + +	* Makefile (tests): Add tst-fork2 and tst-fork3. +	* tst-fork2.c: New file. +	* tst-fork3.c: New file. + +2002-11-28  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: New file. + +	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define macros which +	require it to 200112L. + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Use cmov +	instruction only if HAVE_CMOV is defined. +	* sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S: Define HAVE_CMOV. + +	* sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: New file. + +	* sysdeps/unix/sysv/linux/x86_64/pthread_once.S: New file. + +	* sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: New file. + +	* sysdeps/unix/sysv/linux/x86_64/pt-vfork.S: New file. + +2002-11-27  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/x86_64/bits/atomic.h: New file. + +	* sysdeps/i386/i686/bits/atomic.h: Fix asm syntax for 8- and +	16-bit operations. + +	* sysdeps/unix/sysv/linux/raise.c (raise): Use INTERNAL_SYSCALL if +	possible since gettid cannot fail. + +	* sysdeps/x86_64/pthreaddef.h: New file. + +	* sysdeps/i386/pthreaddef.h (gettid): Removed. + +	* sysdeps/x86_64/pthread_spin_init.c: New file. +	* sysdeps/x86_64/pthread_spin_lock.c: New file. +	* sysdeps/x86_64/pthread_spin_trylock.c: New file. +	* sysdeps/x86_64/pthread_spin_unlock.c: New file. + +	* sysdeps/i386/i686/pthread_spin_trylock.S (pthread_spin_trylock): +	Add missing lock prefix.  Minute optimization. + +	* tst-spin2.c (main): Also check successful trylock call. + +	* sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Use correct +	syscall.  Fix typo in case INTERNAL_SYSCALL is not used. + +	* sysdeps/i386/pthread_spin_destroy.c: Moved to... +	* sysdeps/pthread/pthread_spin_destroy.c: ...here.  New file. + +	* sysdeps/i386/pthread_sigmask.c: Removed.  Use the generic code. +	* sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Return correct +	value in case of an error.  Add support for INTERNAL_SYSCALL. + +	* sysdeps/i386/pthread_sigmask.c (pthread_sigmask): Return correct +	value in case of an error. + +	* sysdeps/x86_64/tls.h: New file. + +2002-11-26  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/i386/tls.h (THREAD_GETMEM_NC): Change interface.  It now +	takes the array member name and the index as parameters. +	(THREAD_SETMEM_NC): Likewise. +	* pthread_getspecific.c: Use new THREAD_GETMEM_NC interface. +	* pthread_setspecific.c: Use new THREAD_GETMEM_NC and THREAD_SETMEM_NC +	interfaces. + +	* sysdeps/i386/tls.h (THREAD_SETMEM): Use size of member element +	to decide which code to use. +	(THREAD_SETMEM_NC): Likewise. + +	* allocatestack.c (queue_stack): Don't remove stack from list here. +	Do it in the caller.  Correct condition to prematurely terminate +	loop to free stacks. +	(__deallocate_stack): Remove stack from list here. + +2002-11-26  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-stack1. +	* tst-stack1.c: New file. + +	* allocatestack.c (allocate_stack): Initialize the TCB on a user +	provided stack. + +	* pthread_attr_getstack.c: Return bottom of the thread area. + +2002-11-25  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (libpthread-routines): Add pt-allocrtsig and +	pthread_kill_other_threads. +	* pt-allocrtsig.c: New file. +	* pthread_kill_other_threads.c: New file. +	* sysdeps/unix/sysv/linux/allocrtsig.c: Add additional aliases for +	all three functions. +	* sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove +	allocrtsig. +	* sysdeps/unix/sysv/linux/Versions (libc:GLIBC_PRIVATE): Export +	__libc_current_sigrtmin_private, __libc_current_sigrtmax_private, +	and __libc_allocate_rtsig_private. +	* Versions (libpthread): Export pthread_kill_other_threads_np, +	__libc_current_sigrtmin, and __libc_current_sigrtmax. + +2002-11-24  Ulrich Drepper  <drepper@redhat.com> + +	* allocatestack.c (allocate_stack): stackaddr in attribute points to +	the end of the stack.  Adjust computations. +	When mprotect call fails dequeue stack and free it. +	* pthread_attr_setstack.c: Store top of the stack in stackaddr +	attribute. +	* pthread_getattr_np.c: Likewise. + +	* descr.h (IS_DETACHED): Add some more parenthesis to prevent +	surprises. + +2002-11-23  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/pthread/pthread.h (pthread_self): __THROW must come before +	attribute definitions.  Patch by Luca Barbieri <ldb@ldb.ods.org>. + +2002-11-22  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_getspecific.c: Optimize access to first 2nd-level array. +	* pthread_setspecific.c: Likewise. + +2002-11-21  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/createthread.c: Remove CLONE_ flags +	definitions.  Get them from the official place. +	* sysdeps/unix/sysv/linux/i386/fork.c: Likewise. + +	* sysdeps/unix/sysv/linux/i386/createthread.c: Update CLONE_* flags. +	Use new CLONE_ flags in clone() calls. + +	* sysdeps/unix/sysv/linux/fork.c: Use ARCH_FORK to actually fork. +	* sysdeps/unix/sysv/linux/i386/fork.c: New file. + +	* Versions: Add pthread_* functions for libc. +	* forward.c: New file. + +	* sysdeps/pthread/Makefile (libpthread-sysdeps_routines): Add +	errno-loc. +	* herrno.c: New file. +	* res.c: New file. + +	* Makefile (libpthread-routines): Remove sem_post, sem_wait, +	sem_trywait, and sem_timedwait.  Add herrno and res. +	* sem_init.c: Don't initialize lock and waiters members. +	* sem_open.c: Likewise. +	* sem_post.c: Removed. +	* sem_wait.c: Removed. +	* sem_trywait.c: Removed. +	* sem_timedwait.c: Removed. +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Complete rewrite. +	Includes full implementations of sem_post, sem_wait, sem_trywait, +	and sem_timedwait. +	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Adjust +	for new implementation. +	* sysdeps/unix/sysv/linux/internaltypes.h (struct sem): Remove lock +	and waiters fields. + +	* tst-sem3.c: Improve error message. +	* tst-signal3.c: Likewise. + +	* init.c (__pthread_initialize_minimal): Use set_tid_address syscall +	to tell the kernel about the termination futex and to initialize tid +	member.  Don't initialize main_thread. +	* descr.h (struct pthread): Remove main_thread member. +	* cancelllation.c (__do_cancel): Remove code handling main thread. +	The main thread is not special anymore. + +	* allocatestack.c (__reclaim_stacks): Mark stacks as unused.  Add +	size of the stacks to stack_cache_actsize. + +	* pt-readv.c: Add missing "defined". +	* pt-sigwait.c: Likewise. +	* pt-writev.c: Likewise. + +2002-11-09  Ulrich Drepper  <drepper@redhat.com> + +	* Versions: Export __connect from libpthread. +	Patch by Luca Barbieri <ldb@ldb.ods.org>. + +	* Makefile (libpthread-routines): Add pt-raise. +	* sysdeps/unix/sysv/linux/raise.c: New file. +	* sysdeps/unix/sysv/linux/pt-raise.c: New file. +	* sysdeps/generic/pt-raise.c: New file. + +	* pthread_cond_init.c: Initialize all data elements of the condvar +	structure.  Patch by Luca Barbieri <ldb@ldb.ods.org>. + +	* pthread_attr_init.c: Actually implement 2.0 compatibility version. +	* pthread_create.c: Likewise. + +	* Makefile (tests): Add tst-key1, tst-key2, tst-key3. +	* tst-key1.c: New file. +	* tst-key2.c: New file. +	* tst-key3.c: New file. + +	* Versions: Export pthread_detach for version GLIBC_2.0. +	Reported by Saurabh Desai <sdesai@austin.ibm.com>. + +2002-11-08  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_key_create.c: Terminate search after an unused key was found. +	Patch by Luca Barbieri <ldb@ldb.ods.org>. + +	* sysdeps/unix/sysv/linux/i386/pthread_once.S: Return zero. +	Patch by Luca Barbieri <ldb@ldb.ods.org>. + +2002-10-10  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Use slow generic +	dynamic lookup for errno in PIC. + +	* allocatestack.c (get_cached_stack): Rearrange code slightly to +	release the stack lock as soon as possible. +	Call _dl_allocate_tls_init for TCB from the cache to re-initialize +	the static TLS block. +	(allocate_stack): Call _dl_allocate_tls_init for user-provided stack. + +	* cancellation.c: Renamed from cancelation.c. +	* Makefile: Adjust accordingly. +	* pthreadP.h (CANCELLATION_P): Renamed from CANCELATION_P. +	* cleanup_defer.c: Use CANCELLATION_P. +	* pthread_testcancel.c: Likewise. +	* descr.h: Fix spelling in comments. +	* init.c: Likewise. +	* pthread_getattr_np.c: Likewise. +	* pthread_getschedparam.c: Likewise. +	* pthread_setschedparam.c: Likewise. +	* Versions: Likewise. + +	* pt-pselect.c: New file. +	* Makefile (libpthread-routines): Add pt-pselect. +	* Versions: Add pselect. + +	* tst-cancel4.c: New file. +	* Makefile (tests): Add tst-cancel4. + +2002-10-09  Ulrich Drepper  <drepper@redhat.com> + +	* pthread_mutex_lock.c: Always record lock ownership. +	* pthread_mutex_timedlock.c: Likewise. +	* pthread_mutex_trylock.c: Likewise. + +	* pt-readv.c: New file. +	* pt-writev.c: New file. +	* pt-creat.c: New file. +	* pt-msgrcv.c: New file. +	* pt-msgsnd.c: New file. +	* pt-poll.c: New file. +	* pt-select.c: New file. +	* pt-sigpause.c: New file. +	* pt-sigsuspend.c: New file. +	* pt-sigwait.c: New file. +	* pt-sigwaitinfo.c: New file. +	* pt-waitid.c: New file. +	* Makefile (libpthread-routines): Add pt-readv, pt-writev, pt-creat, +	pt-msgrcv, pt-msgsnd, pt-poll, pt-select, pt-sigpause, pt-sigsuspend, +	pt-sigwait, pt-sigwaitinfo, and pt-waitid. +	* Versions: Add all the new functions. + +	* tst-exit1.c: New file. +	* Makefile (tests): Add tst-exit1. + +	* sem_timedwait.c: Minor optimization for more optimal fastpath. + +2002-10-08  Ulrich Drepper  <drepper@redhat.com> + +	* pt-fcntl.c: Only enable asynchronous cancellation for F_SETLKW. + +	* pthread_join.c: Enable asynchronous cancellation around lll_wait_tid +	call.  pthread_join is an official cancellation point. +	* pthread_timedjoin.c: Likewise. + +	* pthread_cond_wait.c: Revert order in which internal lock are dropped +	and the condvar's mutex are retrieved. +	* pthread_cond_timedwait.c: Likewise. +	Reported by dice@saros.East.Sun.COM. + +2002-10-07  Ulrich Drepper  <drepper@redhat.com> + +	* pthreadP.h: Cut out all type definitions and move them... +	* sysdeps/unix/sysv/linux/internaltypes.h: ...here.  New file. +	* pthreadP.h: Include <internaltypes.h>. + +	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Little +	performance tweaks. + +	* sem_trywait.c: Shuffle #includes around to get right order. +	* sem_timedwait.c: Likewise. +	* sem_post.c: Likewise. +	* sem_wait.c: Likewise. + +	* nptl 0.3 released. + +	* Makefile (tests): Add tst-signal3. +	* tst-signal3.c: New file. + +2002-10-05  Ulrich Drepper  <drepper@redhat.com> + +	* sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Tell the compiler that +	the asms modify the sem object. +	(__lll_sem_timedwait): Now takes struct sem* as first parameter. + +	* sysdeps/unix/sysv/linux/i386/bits/semaphore.h (sem_t): Don't expose +	the actual members. +	* pthreadP.h (struct sem): New type.  Actual semaphore type. +	* semaphoreP.h: Include pthreadP.h. +	* sem_getvalue.c: Adjust to sem_t change. +	* sem_init.c: Likewise. +	* sem_open.c: Likewise. +	* sem_post.c: Likewise. +	* sem_timedwait.c: Likewise. +	* sem_trywait.c: Likewise. +	* sem_wait.c: Likewise. + +2002-10-04  Ulrich Drepper  <drepper@redhat.com> + +	* Makefile (tests): Add tst-basic2, tst-exec1, tst-exec3, tst-exec3. +	* tst-basic2.c: New file. +	* tst-exec1.c: New file. +	* tst-exec2.c: New file. +	* tst-exec3.c: New file. + +	* tst-fork1.c: Remove extra */. + +	* nptl 0.2 released.  The API for IA-32 is complete. diff --git a/libpthread/nptl/DESIGN-barrier.txt b/libpthread/nptl/DESIGN-barrier.txt new file mode 100644 index 000000000..23463c6b7 --- /dev/null +++ b/libpthread/nptl/DESIGN-barrier.txt @@ -0,0 +1,44 @@ +Barriers pseudocode +=================== + +    int pthread_barrier_wait(barrier_t *barrier); + +struct barrier_t { + +   unsigned int lock: +         - internal mutex + +   unsigned int left; +         - current barrier count, # of threads still needed. + +   unsigned int init_count; +         - number of threads needed for the barrier to continue. + +   unsigned int curr_event; +         - generation count +} + +pthread_barrier_wait(barrier_t *barrier) +{ +  unsigned int event; +  result = 0; + +  lll_lock(barrier->lock); +  if (!--barrier->left) { +    barrier->curr_event++; +    futex_wake(&barrier->curr_event, INT_MAX) + +    result = BARRIER_SERIAL_THREAD; +  } else { +    event = barrier->curr_event; +    lll_unlock(barrier->lock); +    do { +      futex_wait(&barrier->curr_event, event) +    } while (event == barrier->curr_event); +  } + +  if (atomic_increment_val (barrier->left) == barrier->init_count) +    lll_unlock(barrier->lock); + +  return result; +} diff --git a/libpthread/nptl/DESIGN-condvar.txt b/libpthread/nptl/DESIGN-condvar.txt new file mode 100644 index 000000000..4845251c7 --- /dev/null +++ b/libpthread/nptl/DESIGN-condvar.txt @@ -0,0 +1,134 @@ +Conditional Variable pseudocode. +================================ + +       int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex); +       int pthread_cond_signal    (pthread_cond_t *cv); +       int pthread_cond_broadcast (pthread_cond_t *cv); + +struct pthread_cond_t { + +   unsigned int cond_lock; + +         internal mutex + +   uint64_t total_seq; + +     Total number of threads using the conditional variable. + +   uint64_t wakeup_seq; + +     sequence number for next wakeup. + +   uint64_t woken_seq; + +     sequence number of last woken thread. + +   uint32_t broadcast_seq; + +} + + +struct cv_data { + +   pthread_cond_t *cv; + +   uint32_t bc_seq + +} + + + +cleanup_handler(cv_data) +{ +  cv = cv_data->cv; +  lll_lock(cv->lock); + +  if (cv_data->bc_seq == cv->broadcast_seq) { +    ++cv->wakeup_seq; +    ++cv->woken_seq; +  } + +  /* make sure no signal gets lost.  */ +  FUTEX_WAKE(cv->wakeup_seq, ALL); + +  lll_unlock(cv->lock); +} + + +cond_timedwait(cv, mutex, timeout): +{ +   lll_lock(cv->lock); +   mutex_unlock(mutex); + +   cleanup_push + +   ++cv->total_seq; +   val = seq =  cv->wakeup_seq; +   cv_data.bc = cv->broadcast_seq; +   cv_data.cv = cv; + +   while (1) { + +     lll_unlock(cv->lock); + +     enable_async(&cv_data); + +     ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); + +     restore_async + +     lll_lock(cv->lock); + +     if (bc != cv->broadcast_seq) +       goto bc_out; + +     val = cv->wakeup_seq; + +     if (val != seq && cv->woken_seq != val) { +       ret = 0; +       break; +     } + +     if (ret == TIMEDOUT) { +       ++cv->wakeup_seq; +       break; +     } +   } + +   ++cv->woken_seq; + + bc_out: +   lll_unlock(cv->lock); + +   cleanup_pop + +   mutex_lock(mutex); + +   return ret; +} + +cond_signal(cv) +{ +   lll_lock(cv->lock); + +   if (cv->total_seq > cv->wakeup_seq) { +     ++cv->wakeup_seq; +     FUTEX_WAKE(cv->wakeup_seq, 1); +   } + +   lll_unlock(cv->lock); +} + +cond_broadcast(cv) +{ +   lll_lock(cv->lock); + +   if (cv->total_seq > cv->wakeup_seq) { +     cv->wakeup_seq = cv->total_seq; +     cv->woken_seq = cv->total_seq; +     ++cv->broadcast_seq; +     FUTEX_WAKE(cv->wakeup_seq, ALL); +   } + +   lll_unlock(cv->lock); +} diff --git a/libpthread/nptl/DESIGN-rwlock.txt b/libpthread/nptl/DESIGN-rwlock.txt new file mode 100644 index 000000000..810d1b8f3 --- /dev/null +++ b/libpthread/nptl/DESIGN-rwlock.txt @@ -0,0 +1,113 @@ +Reader Writer Locks pseudocode +============================== + +	pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); +	pthread_rwlock_unlock(pthread_rwlock_t *rwlock); +	pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); + +struct pthread_rwlock_t { + +   unsigned int lock: +         - internal mutex + +   unsigned int writers_preferred; +         - locking mode: 0 recursive, readers preferred +                         1 nonrecursive, writers preferred + +   unsigned int readers; +         - number of read-only references various threads have + +   pthread_t writer; +         - descriptor of the writer or 0 + +   unsigned int readers_wakeup; +         - 'all readers should wake up' futex. + +   unsigned int writer_wakeup; +         - 'one writer should wake up' futex. + +   unsigned int nr_readers_queued; +         - number of readers queued up. + +   unsigned int nr_writers_queued; +         - number of writers queued up. +} + +pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) +{ +  lll_lock(rwlock->lock); +  for (;;) { +    if (!rwlock->writer && (!rwlock->nr_writers_queued || +					!rwlock->writers_preferred)) +        break; + +    rwlock->nr_readers_queued++; +    val = rwlock->readers_wakeup; +    lll_unlock(rwlock->lock); + +    futex_wait(&rwlock->readers_wakeup, val) + +    lll_lock(rwlock->lock); +    rwlock->nr_readers_queued--; +  } +  rwlock->readers++; +  lll_unlock(rwlock->lock); +} + +pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) +{ +  int result = EBUSY; +  lll_lock(rwlock->lock); +  if (!rwlock->writer && (!rwlock->nr_writers_queued || +					!rwlock->writers_preferred)) +    rwlock->readers++; +  lll_unlock(rwlock->lock); +  return result; +} + +pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) +{ +  lll_lock(rwlock->lock); +  for (;;) { +    if (!rwlock->writer && !rwlock->readers) +       break; + +    rwlock->nr_writers_queued++; +    val = rwlock->writer_wakeup; +    lll_unlock(rwlock->lock); + +    futex_wait(&rwlock->writer_wakeup, val); + +    lll_lock(rwlock->lock); +    rwlock->nr_writers_queued--; +  } +  rwlock->writer = pthread_self(); +  lll_unlock(rwlock->lock); +} + +pthread_rwlock_unlock(pthread_rwlock_t *rwlock) +{ +  lll_lock(rwlock->lock); + +  if (rwlock->writer) +    rwlock->writer = 0; +  else +    rwlock->readers--; + +  if (!rwlock->readers) { +    if (rwlock->nr_writers_queued) { +      ++rwlock->writer_wakeup; +      lll_unlock(rwlock->lock); +      futex_wake(&rwlock->writer_wakeup, 1); +      return; +    } else +      if (rwlock->nr_readers_queued) { +        ++rwlock->readers_wakeup; +        lll_unlock(rwlock->lock); +        futex_wake(&rwlock->readers_wakeup, MAX_INT); +        return; +      } +  } + +  lll_unlock(rwlock->lock); +} diff --git a/libpthread/nptl/DESIGN-sem.txt b/libpthread/nptl/DESIGN-sem.txt new file mode 100644 index 000000000..17eb0c11c --- /dev/null +++ b/libpthread/nptl/DESIGN-sem.txt @@ -0,0 +1,46 @@ +Semaphores pseudocode +============================== + +       int sem_wait(sem_t * sem); +       int sem_trywait(sem_t * sem); +       int sem_post(sem_t * sem); +       int sem_getvalue(sem_t * sem, int * sval); + +struct sem_t { + +   unsigned int count; +         - current semaphore count, also used as a futex +} + +sem_wait(sem_t *sem) +{ +  for (;;) { + +    if (atomic_decrement_if_positive(sem->count)) +      break; + +    futex_wait(&sem->count, 0) +  } +} + +sem_post(sem_t *sem) +{ +  n = atomic_increment(sem->count); +  // Pass the new value of sem->count +  futex_wake(&sem->count, n + 1); +} + +sem_trywait(sem_t *sem) +{ +  if (atomic_decrement_if_positive(sem->count)) { +    return 0; +  } else { +    return EAGAIN; +  } +} + +sem_getvalue(sem_t *sem, int *sval) +{ +  *sval = sem->count; +  read_barrier(); +} diff --git a/libpthread/nptl/Makefile b/libpthread/nptl/Makefile new file mode 100644 index 000000000..4c3cf941d --- /dev/null +++ b/libpthread/nptl/Makefile @@ -0,0 +1,592 @@ +# Copyright (C) 2002, 2003, 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 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. + +# +#	Sub-makefile for NPTL portion of the library. +# +subdir	:= nptl + +headers := pthread.h semaphore.h bits/semaphore.h + +extra-libs := libpthread +extra-libs-others := $(extra-libs) +install-lib-ldscripts := libpthread.so + +routines = alloca_cutoff forward libc-lowlevellock libc-cancellation +shared-only-routines = forward + +libpthread-routines = init vars events version \ +		      pthread_create pthread_exit pthread_detach \ +		      pthread_join pthread_tryjoin pthread_timedjoin \ +		      pthread_self pthread_equal pthread_yield \ +		      pthread_getconcurrency pthread_setconcurrency \ +		      pthread_getschedparam pthread_setschedparam \ +		      pthread_setschedprio \ +		      pthread_attr_init pthread_attr_destroy \ +		      pthread_attr_getdetachstate pthread_attr_setdetachstate \ +		      pthread_attr_getguardsize pthread_attr_setguardsize \ +		      pthread_attr_getschedparam pthread_attr_setschedparam \ +		      pthread_attr_getschedpolicy pthread_attr_setschedpolicy \ +		      pthread_attr_getinheritsched \ +		      pthread_attr_setinheritsched \ +		      pthread_attr_getscope pthread_attr_setscope \ +		      pthread_attr_getstackaddr pthread_attr_setstackaddr \ +		      pthread_attr_getstacksize pthread_attr_setstacksize \ +		      pthread_attr_getstack pthread_attr_setstack \ +		      pthread_getattr_np \ +		      pthread_mutex_init pthread_mutex_destroy \ +		      pthread_mutex_lock pthread_mutex_trylock \ +		      pthread_mutex_timedlock pthread_mutex_unlock \ +		      pthread_mutexattr_init pthread_mutexattr_destroy \ +		      pthread_mutexattr_getpshared \ +		      pthread_mutexattr_setpshared \ +		      pthread_mutexattr_gettype pthread_mutexattr_settype \ +		      pthread_rwlock_init pthread_rwlock_destroy \ +		      pthread_rwlock_rdlock pthread_rwlock_timedrdlock \ +		      pthread_rwlock_wrlock pthread_rwlock_timedwrlock \ +		      pthread_rwlock_tryrdlock pthread_rwlock_trywrlock \ +		      pthread_rwlock_unlock \ +		      pthread_rwlockattr_init pthread_rwlockattr_destroy \ +		      pthread_rwlockattr_getpshared \ +		      pthread_rwlockattr_setpshared \ +		      pthread_rwlockattr_getkind_np \ +		      pthread_rwlockattr_setkind_np \ +		      pthread_cond_init pthread_cond_destroy \ +		      pthread_cond_wait pthread_cond_timedwait \ +		      pthread_cond_signal pthread_cond_broadcast \ +		      old_pthread_cond_init old_pthread_cond_destroy \ +		      old_pthread_cond_wait old_pthread_cond_timedwait \ +		      old_pthread_cond_signal old_pthread_cond_broadcast \ +		      pthread_condattr_init pthread_condattr_destroy \ +		      pthread_condattr_getpshared pthread_condattr_setpshared \ +		      pthread_condattr_getclock pthread_condattr_setclock \ +		      pthread_spin_init pthread_spin_destroy \ +		      pthread_spin_lock pthread_spin_trylock \ +		      pthread_spin_unlock \ +		      pthread_barrier_init pthread_barrier_destroy \ +		      pthread_barrier_wait \ +		      pthread_barrierattr_init pthread_barrierattr_destroy \ +		      pthread_barrierattr_getpshared \ +		      pthread_barrierattr_setpshared \ +		      pthread_key_create pthread_key_delete \ +		      pthread_getspecific pthread_setspecific \ +		      pthread_sigmask pthread_kill \ +		      pthread_cancel pthread_testcancel \ +		      pthread_setcancelstate pthread_setcanceltype \ +		      pthread_once \ +		      old_pthread_atfork pthread_atfork \ +		      pthread_getcpuclockid \ +		      pthread_clock_gettime pthread_clock_settime \ +		      sem_init sem_destroy \ +		      sem_open sem_close sem_unlink \ +		      sem_getvalue \ +		      sem_wait sem_trywait sem_timedwait sem_post \ +		      cleanup cleanup_defer cleanup_compat \ +		      cleanup_defer_compat unwind \ +		      pt-longjmp pt-cleanup\ +		      cancellation \ +		      lowlevellock \ +		      pt-vfork \ +		      ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \ +		      ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg ptw-send \ +		      ptw-sendmsg ptw-sendto ptw-fsync ptw-lseek ptw-llseek \ +		      ptw-msync ptw-nanosleep ptw-open ptw-open64 ptw-pause \ +		      ptw-pread ptw-pread64 ptw-pwrite ptw-pwrite64 \ +		      ptw-tcdrain ptw-wait ptw-waitpid ptw-msgrcv ptw-msgsnd \ +		      ptw-sigwait \ +		      pt-raise pt-system \ +		      flockfile ftrylockfile funlockfile \ +		      sigaction \ +		      herrno res pt-allocrtsig \ +		      pthread_kill_other_threads \ +		      pthread_getaffinity pthread_setaffinity \ +		      pthread_attr_getaffinity pthread_attr_setaffinity \ +		      cleanup_routine unwind-forcedunwind +#		      pthread_setuid pthread_seteuid pthread_setreuid \ +#		      pthread_setresuid \ +#		      pthread_setgid pthread_setegid pthread_setregid \ +#		      pthread_setresgid + +libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind +libpthread-static-only-routines = pthread_atfork + +CFLAGS-pthread_atfork.c = -DNOT_IN_libc + +# Since cancellation handling is in large parts handled using exceptions +# we have to compile some files with exception handling enabled, some +# even with asynchronous unwind tables. + +# init.c contains sigcancel_handler(). +CFLAGS-init.c = -fexceptions -fasynchronous-unwind-tables +# The unwind code itself, +CFLAGS-unwind.c = -fexceptions +CFLAGS-unwind-forcedunwind.c = -fexceptions -fasynchronous-unwind-tables + +# The following three functions must be async-cancel safe. +CFLAGS-pthread_cancel.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_setcancelstate.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_setcanceltype.c = -fexceptions -fasynchronous-unwind-tables + +# These are internal functions which similar functionality as setcancelstate +# and setcanceltype. +CFLAGS-cancellation.c = -fasynchronous-unwind-tables +CFLAGS-libc-cancellation.c = -fasynchronous-unwind-tables + +# Calling pthread_exit() must cause the registered cancel handlers to +# be executed.  Therefore exceptions have to be thrown through this +# function. +CFLAGS-pthread_exit.c = -fexceptions + +# Among others, __pthread_unwind is forwarded.  This function must handle +# exceptions. +CFLAGS-forward.c = -fexceptions + +# The following are cancellation points.  Some of the functions can +# block and therefore temporarily enable asynchronous cancellation. +# Those must be compiled asynchronous unwind tables. +CFLAGS-pthread_testcancel.c = -fexceptions +CFLAGS-pthread_join.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \ +			-fasynchronous-unwind-tables +CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables + +# These are the function wrappers we have to duplicate here. +CFLAGS-fcntl.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-lockf.c = -fexceptions +CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sigwait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgrcv.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgsnd.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-tcdrain.c = -fexceptions -fasynchronous-unwind-tables + +CFLAGS-pt-system.c = -fexceptions + +# Don't generate deps for calls with no sources.  See sysdeps/unix/Makefile. +omit-deps = $(unix-syscalls:%=ptw-%) + + +tests = tst-attr1 tst-attr2 tst-attr3 \ +	tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ +	tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \ +	tst-spin1 tst-spin2 tst-spin3 \ +	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ +	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ +	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ +	tst-cond20 tst-cond21 \ +	tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \ +	tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \ +	tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \ +	tst-once1 tst-once2 tst-once3 tst-once4 \ +	tst-key1 tst-key2 tst-key3 tst-key4 \ +	tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ +	tst-sem8 tst-sem9 \ +	tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \ +	tst-align tst-align2 \ +	tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ +	tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \ +	tst-raise1 \ +	tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 \ +	tst-detach1 \ +	tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \ +	tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 \ +	tst-tls1 tst-tls2 \ +	tst-fork1 tst-fork2 tst-fork3 tst-fork4 \ +	tst-atfork1 \ +	tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \ +	tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \ +	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \ +	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \ +	tst-cancel21 tst-cancel22 tst-cancel23 \ +	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \ +	tst-flock1 tst-flock2 \ +	tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ +	tst-signal6 \ +	tst-exec1 tst-exec2 tst-exec3 tst-exec4 \ +	tst-exit1 tst-exit2 tst-exit3 \ +	tst-stdio1 tst-stdio2 \ +	tst-stack1 tst-stack2 tst-stack3 \ +	tst-unload \ +	tst-dlsym1 \ +	tst-sysconf \ +	tst-locale1 tst-locale2 \ +	tst-umask1 \ +	tst-popen1 \ +	tst-clock1 \ +	tst-context1 \ +	tst-sched1 \ +	tst-backtrace1 \ +	tst-oddstacklimit \ +	tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \ +	tst-getpid1 tst-getpid2 +xtests = tst-setuid1 tst-setuid1-static + +# Files which must not be linked with libpthread. +tests-nolibpthread = tst-unload + +# This sets the stack resource limit to 1023kb, which is not a multiple +# of the page size since every architecture's page size is > 1k. +tst-oddstacklimit-ENV = ; ulimit -s 1023; + +distribute = eintr.c tst-cleanup4aux.c + +gen-as-const-headers = pthread-errnos.sym + +LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst + + +include ../Makeconfig + +ifeq ($(have-forced-unwind),yes) +tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ +	 tst-cancelx6 tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 \ +	 tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 \ +	 tst-cancelx16 tst-cancelx17 tst-cancelx18 tst-cancelx20 tst-cancelx21 \ +	 tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \ +	 tst-oncex3 tst-oncex4 +endif +ifeq ($(build-shared),yes) +tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 +tests-nolibpthread += tst-fini1 +ifeq ($(have-z-execstack),yes) +tests += tst-execstack +endif +endif + +modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ +		tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ +		tst-tls5modd tst-tls5mode tst-tls5modf \ +		tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod +extra-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o +test-extras += $(modules-names) +test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) + +tst-atfork2mod.so-no-z-defs = yes +tst-tls3mod.so-no-z-defs = yes +tst-tls5mod.so-no-z-defs = yes +tst-tls5moda.so-no-z-defs = yes +tst-tls5modb.so-no-z-defs = yes +tst-tls5modc.so-no-z-defs = yes +tst-tls5modd.so-no-z-defs = yes +tst-tls5mode.so-no-z-defs = yes +tst-tls5modf.so-no-z-defs = yes + +$(test-modules): $(objpfx)%.so: $(objpfx)%.os $(common-objpfx)shlib.lds +	$(build-module) + +ifeq ($(build-shared),yes) +# Build all the modules even when not actually running test programs. +tests: $(test-modules) +endif + +ifeq ($(build-shared),yes) + +# Set the `multidir' variable by grabbing the variable from the compiler. +# We do it once and save the result in a generated makefile. +-include $(objpfx)multidir.mk +$(objpfx)multidir.mk: $(common-objpfx)config.make +	$(make-target-directory) +	dir=`$(CC) $(CFLAGS) $(CPPFLAGS) -print-multi-directory`; \ +	echo "multidir := $$dir" > $@T +	mv -f $@T $@ + +crti-objs := crti.o +crtn-objs := crtn.o +ifneq (,$(patsubst .,,$(multidir))) +generated-dirs := $(firstword $(subst /, , $(multidir))) +crti-objs += $(multidir)/crti.o +crtn-objs += $(multidir)/crtn.o +omit-deps += $(multidir)/crti $(multidir)/crtn +$(objpfx)$(multidir): +	mkdir $@ +endif +extra-objs += $(crti-objs) $(crtn-objs) +omit-deps += crti crtn + +CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions $(fno-unit-at-a-time) +endif + +CFLAGS-flockfile.c = -D_IO_MTSAFE_IO +CFLAGS-ftrylockfile.c = -D_IO_MTSAFE_IO +CFLAGS-funlockfile.c = -D_IO_MTSAFE_IO + +link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \ +		    $(common-objpfx)libc.a + +ifeq ($(build-static),yes) +tests-static += tst-locale1 tst-locale2 +xtests-static += tst-setuid1-static +endif +# These tests are linked with libc before libpthread +tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x + +include ../Rules + +ifeq (yes,$(build-shared)) +# Make sure these things are built in the `make lib' pass so they can be used +# to run programs during the `make others' pass. +lib-noranlib: $(addprefix $(objpfx),$(extra-objs)) + +# What we install as libpthread.so for programs to link against is in fact a +# link script.  It contains references for the various libraries we need. +# The libpthread.so object is not complete since some functions are only +# defined in libpthread_nonshared.a. +# We need to use absolute paths since otherwise local copies (if they exist) +# of the files are taken by the linker. +install: $(inst_libdir)/libpthread.so + +$(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \ +			      $(objpfx)libpthread.so$(libpthread.so-version) \ +			      $(inst_libdir)/$(patsubst %,$(libtype.oS),\ +							$(libprefix)pthread) \ +			      $(+force) +	(echo '/* GNU ld script';\ +	 echo '   Use the shared library, but some functions are only in';\ +	 echo '   the static library, so try that secondarily.  */';\ +	 cat $<; \ +	 echo 'GROUP ( $(slibdir)/libpthread.so$(libpthread.so-version)' \ +	      '$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)pthread)'\ +	      ')' \ +	) > $@.new +	mv -f $@.new $@ +endif + + +# 'pthread_self' is a simple memory or register load.  Setting up the +# stack frame is more work than the actual operation.  Disable the +# frame creation entirely.  This will help applications which call the +# function frequently to get a thread-specific handle. +CFLAGS-pthread_self.os += -fomit-frame-pointer + +# Run the cancellation and cleanup tests also for the modern, exception-based +# implementation.  For this we have to pass the -fexceptions parameter. +CFLAGS-tst-cancelx2.c += -fexceptions +CFLAGS-tst-cancelx3.c += -fexceptions +CFLAGS-tst-cancelx4.c += -fexceptions +CFLAGS-tst-cancelx5.c += -fexceptions +CFLAGS-tst-cancelx6.c += -fexceptions +CFLAGS-tst-cancelx7.c += -fexceptions +CFLAGS-tst-cancelx8.c += -fexceptions +CFLAGS-tst-cancelx9.c += -fexceptions +CFLAGS-tst-cancelx10.c += -fexceptions +CFLAGS-tst-cancelx11.c += -fexceptions +CFLAGS-tst-cancelx12.c += -fexceptions +CFLAGS-tst-cancelx13.c += -fexceptions +CFLAGS-tst-cancelx14.c += -fexceptions +CFLAGS-tst-cancelx15.c += -fexceptions +CFLAGS-tst-cancelx16.c += -fexceptions +CFLAGS-tst-cancelx17.c += -fexceptions +CFLAGS-tst-cancelx18.c += -fexceptions +CFLAGS-tst-cancelx20.c += -fexceptions -fasynchronous-unwind-tables +CFLAGS-tst-cancelx21.c += -fexceptions -fasynchronous-unwind-tables +CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables +CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables +CFLAGS-tst-cleanupx2.c += -fexceptions +CFLAGS-tst-cleanupx3.c += -fexceptions +CFLAGS-tst-cleanupx4.c += -fexceptions +CFLAGS-tst-oncex3.c += -fexceptions +CFLAGS-tst-oncex4.c += -fexceptions +CFLAGS-tst-align.c += $(stack-align-test-flags) + +tst-cancel7-ARGS = --command "$(built-program-cmd)" +tst-cancelx7-ARGS = $(tst-cancel7-ARGS) +tst-umask1-ARGS = $(objpfx)tst-umask1.temp + +$(objpfx)tst-atfork2: $(libdl) $(shared-thread-library) +LDFLAGS-tst-atfork2 = -rdynamic +tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace +$(objpfx)tst-atfork2mod.so: $(shared-thread-library) + +tests: $(objpfx)tst-stack3-mem +tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace +$(objpfx)tst-stack3-mem: $(objpfx)tst-stack3.out +	$(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@ +generated += tst-stack3-mem tst-stack3.mtrace + +$(objpfx)tst-cleanup4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library) +$(objpfx)tst-cleanupx4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library) + +$(objpfx)tst-tls3: $(libdl) $(shared-thread-library) +LDFLAGS-tst-tls3 = -rdynamic +$(objpfx)tst-tls3.out: $(objpfx)tst-tls3mod.so +$(objpfx)tst-tls3mod.so: $(shared-thread-library) + +$(objpfx)tst-tls4: $(libdl) $(shared-thread-library) +$(objpfx)tst-tls4.out: $(objpfx)tst-tls4moda.so $(objpfx)tst-tls4modb.so + +$(objpfx)tst-tls5: $(objpfx)tst-tls5mod.so $(shared-thread-library) +LDFLAGS-tst-tls5mod.so = -Wl,-soname,tst-tls5mod.so + +ifeq ($(build-shared),yes) +tests: $(objpfx)tst-tls6.out +$(objpfx)tst-tls6.out: tst-tls6.sh $(objpfx)tst-tls5 \ +		       $(objpfx)tst-tls5moda.so $(objpfx)tst-tls5modb.so \ +		       $(objpfx)tst-tls5modc.so $(objpfx)tst-tls5modd.so \ +		       $(objpfx)tst-tls5mode.so $(objpfx)tst-tls5modf.so +	$(SHELL) -e tst-tls6.sh $(common-objpfx) $(elf-objpfx) \ +		    $(rtld-installed-name) +endif + +$(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library) + +$(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so + +ifeq (yes,$(build-shared)) +$(objpfx)tst-cond11: $(common-objpfx)rt/librt.so +$(objpfx)tst-cond19: $(common-objpfx)rt/librt.so +$(objpfx)tst-cancel17: $(common-objpfx)rt/librt.so +$(objpfx)tst-cancelx17: $(common-objpfx)rt/librt.so +$(objpfx)tst-cancel18: $(common-objpfx)rt/librt.so +$(objpfx)tst-cancelx18: $(common-objpfx)rt/librt.so +$(objpfx)tst-clock2: $(common-objpfx)rt/librt.so +$(objpfx)tst-rwlock14: $(common-objpfx)rt/librt.so +$(objpfx)tst-_res1mod2.so: $(objpfx)tst-_res1mod1.so +LDFLAGS-tst-_res1mod1.so = -Wl,-soname,tst-_res1mod1.so +LDFLAGS-tst-_res1mod2.so = -Wl,-soname,tst-_res1mod2.so +$(objpfx)tst-_res1: $(objpfx)tst-_res1mod2.so $(shared-thread-library) +else +$(objpfx)tst-cond11: $(common-objpfx)rt/librt.a +$(objpfx)tst-cond19: $(common-objpfx)rt/librt.a +$(objpfx)tst-cancel17: $(common-objpfx)rt/librt.a +$(objpfx)tst-cancelx17: $(common-objpfx)rt/librt.a +$(objpfx)tst-cancel18: $(common-objpfx)rt/librt.a +$(objpfx)tst-cancelx18: $(common-objpfx)rt/librt.a +$(objpfx)tst-clock2: $(common-objpfx)rt/librt.a +$(objpfx)tst-rwlock14: $(common-objpfx)rt/librt.a +endif + +extra-B-pthread.so = -B$(common-objpfx)nptl/ +$(objpfx)libpthread.so: $(addprefix $(objpfx),$(crti-objs) $(crtn-objs)) +$(objpfx)libpthread.so: +preinit += $(addprefix $(objpfx),$(crti-objs)) +$(objpfx)libpthread.so: +postinit += $(addprefix $(objpfx),$(crtn-objs)) + +# Depend on libc.so so a DT_NEEDED is generated in the shared objects. +# This ensures they will load libc.so for needed symbols if loaded by +# a statically-linked program that hasn't already loaded it. +# Depend on ld.so too to get proper versions of ld.so symbols. +$(objpfx)libpthread.so: $(common-objpfx)libc.so \ +			$(common-objpfx)libc_nonshared.a \ +			$(if $(filter yes,$(elf)), $(elfobjdir)/ld.so) + +# Make sure we link with the thread library. +ifeq ($(build-shared),yes) +$(addprefix $(objpfx), \ +  $(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \ +    $(tests-nolibpthread), \ +    $(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \ +				       $(objpfx)libpthread_nonshared.a +$(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so +# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so, +# since otherwise libpthread.so comes before libc.so when linking. +$(addprefix $(objpfx), $(tests-reverse)): \ +  $(objpfx)../libc.so $(objpfx)libpthread.so \ +  $(objpfx)libpthread_nonshared.a +$(objpfx)../libc.so: $(common-objpfx)libc.so ; +$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a + +$(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so +else +$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a +endif + +ifeq ($(build-shared),yes) +vpath pt-initfini.c $(full_config_sysdirs) + +$(objpfx)pt-initfini.s: pt-initfini.c +	$(compile.c) -S $(CFLAGS-pt-initfini.s) -finhibit-size-directive \ +		$(patsubst -f%,-fno-%,$(exceptions)) -o $@ + +$(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0 +	$(make-test-out) 2>&1 | cmp - tst-cleanup0.expect >& $@ + +# We only have one kind of startup code files.  Static binaries and +# shared libraries are build using the PIC version. +$(objpfx)crti.S: $(objpfx)pt-initfini.s +	sed -n -e '1,/@HEADER_ENDS/p' \ +	       -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \ +	       -e '/@TRAILER_BEGINS/,$$p' $< > $@ +$(objpfx)crtn.S: $(objpfx)pt-initfini.s +	sed -n -e '1,/@HEADER_ENDS/p' \ +	       -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \ +	       -e '/@TRAILER_BEGINS/,$$p' $< > $@ + +$(objpfx)defs.h: $(objpfx)pt-initfini.s +	sed -n -e '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \ +		$(AWK) -f ../csu/defs.awk > $@ + +$(objpfx)crti.o: $(objpfx)crti.S $(objpfx)defs.h +	$(compile.S) -g0 $(ASFLAGS-.os) -o $@ + +$(objpfx)crtn.o: $(objpfx)crtn.S $(objpfx)defs.h +	$(compile.S) -g0 $(ASFLAGS-.os) -o $@ + +ifneq ($(multidir),.) +$(objpfx)$(multidir)/crti.o: $(objpfx)crti.o $(objpfx)$(multidir)/ +	ln -f $< $@ + +$(objpfx)$(multidir)/crtn.o: $(objpfx)crtn.o $(objpfx)$(multidir)/ +	ln -f $< $@ +endif + +generated += crti.S crtn.S defs.h pt-initfini.s  libpthread_nonshared.a \ +	     multidir.mk tst-atfork2.mtrace tst-cancel-wrappers.out \ +	     tst-tls6.out + +generated += $(objpfx)tst-atfork2.mtrace \ +	     $(addsuffix .so,$(strip $(modules-names))) + +$(objpfx)version.d: $(objpfx)banner.h +$(objpfx)version.os: $(objpfx)banner.h +$(objpfx)banner.h: Banner +	sed 's/\(.*\)/"\1\\n"/' $< > $@ +generated += banner.h +# Give libpthread.so an entry point and make it directly runnable itself. +LDFLAGS-pthread.so += -e __nptl_main +endif + +ifeq (no,$(cross-compiling)) +ifeq (yes,$(build-shared)) +tests: $(objpfx)tst-cancel-wrappers.out +$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh +	$(SHELL) $< $(common-objpfx)libc_pic.a \ +		    $(common-objpfx)libc.a \ +		    $(objpfx)libpthread_pic.a \ +		    $(objpfx)libpthread.a > $@ +endif +endif + +tst-exec4-ARGS = $(built-program-cmd) + +$(objpfx)tst-execstack: $(libdl) +$(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so +LDFLAGS-tst-execstack = -Wl,-z,noexecstack + +$(objpfx)tst-fini1mod.so: $(shared-thread-library) + +# The tests here better do not run in parallel +ifneq ($(filter %tests,$(MAKECMDGOALS)),) +.NOTPARALLEL: +endif diff --git a/libpthread/nptl/TODO b/libpthread/nptl/TODO new file mode 100644 index 000000000..a4a1055f4 --- /dev/null +++ b/libpthread/nptl/TODO @@ -0,0 +1,12 @@ +- we should probably extend pthread_mutexattr_t with a field to create a +  single linked list of all instances.  This requires changing the +  pthread_mutexattr_* functions. + + +- a new attribute for mutexes: number of times we spin before calling +sys_futex + + + +- test with threaded process terminating and semadj (?) being applied +  only after all threads are gone diff --git a/libpthread/nptl/TODO-kernel b/libpthread/nptl/TODO-kernel new file mode 100644 index 000000000..ad6d2a4b5 --- /dev/null +++ b/libpthread/nptl/TODO-kernel @@ -0,0 +1,20 @@ +- setuid/setgid must effect process +  + test syscalls (getuid) afterwards +  + test core file content + +  + use UID/GID in access(2), chmod(2), chown(2), link(2) + +- nice level is process property + +- rlimit should be process-wide and SIGXCPU should be sent if all threads +  together exceed the limit + +- getrusage() must return resource utilization for the process + + + +The following are possible optimizations and in no way required: + + +- the scheduler should be thread group-aware, i.e., it has to give time to +  the thread group not proportional to the number of threads. diff --git a/libpthread/nptl/TODO-testing b/libpthread/nptl/TODO-testing new file mode 100644 index 000000000..e076e5624 --- /dev/null +++ b/libpthread/nptl/TODO-testing @@ -0,0 +1,20 @@ +pthread_attr_setguardsize + +  test effectiveness + +pthread_attr_[sg]etschedparam + +  what to test? + +pthread_attr_[sg]etstack + +  some more tests needed + +pthread_getcpuclockid + +  check that value is reset -> rt subdir + +pthread_getschedparam +pthread_setschedparam + +  what to test? diff --git a/libpthread/nptl/Versions b/libpthread/nptl/Versions new file mode 100644 index 000000000..79bf190c3 --- /dev/null +++ b/libpthread/nptl/Versions @@ -0,0 +1,240 @@ +libc { +  GLIBC_2.0 { +    pthread_attr_destroy; pthread_attr_init; +    pthread_attr_getdetachstate; pthread_attr_setdetachstate; +    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_condattr_destroy; pthread_condattr_init; +    pthread_cond_broadcast; pthread_cond_destroy; +    pthread_cond_init; pthread_cond_signal; pthread_cond_wait; +    pthread_cond_timedwait; +    pthread_equal; pthread_exit; +    pthread_getschedparam; pthread_setschedparam; +    pthread_mutex_destroy; pthread_mutex_init; +    pthread_mutex_lock; pthread_mutex_unlock; +    pthread_self; +    pthread_setcancelstate; pthread_setcanceltype; +  } +  GLIBC_2.1 { +    pthread_attr_init; +  } +  GLIBC_2.3.2 { +    # Changed pthread_cond_t. +    pthread_cond_init; pthread_cond_destroy; +    pthread_cond_wait; pthread_cond_signal; +    pthread_cond_broadcast; pthread_cond_timedwait; +  } +  GLIBC_PRIVATE { +    # Internal libc interface to libpthread +    __libc_dl_error_tsd; +  } +} + +libpthread { +  GLIBC_2.0 { +    pthread_create; pthread_join; pthread_self; pthread_equal; +    pthread_exit; pthread_detach; + +    pthread_getschedparam; pthread_setschedparam; + +    pthread_attr_init; pthread_attr_destroy; +    pthread_attr_getdetachstate; pthread_attr_setdetachstate; +    pthread_attr_getschedparam; pthread_attr_setschedparam; +    pthread_attr_getschedpolicy; pthread_attr_setschedpolicy; +    pthread_attr_getinheritsched; pthread_attr_setinheritsched; +    pthread_attr_getscope; pthread_attr_setscope; + +    pthread_mutex_init; pthread_mutex_destroy; +    pthread_mutex_lock; pthread_mutex_trylock; pthread_mutex_unlock; + +    pthread_mutexattr_init; pthread_mutexattr_destroy; + +    pthread_cond_init; pthread_cond_destroy; +    pthread_cond_wait; pthread_cond_timedwait; +    pthread_cond_signal; pthread_cond_broadcast; + +    pthread_condattr_destroy; pthread_condattr_init; + +    pthread_cancel; pthread_testcancel; +    pthread_setcancelstate; pthread_setcanceltype; + +    pthread_sigmask; pthread_kill; + +    pthread_key_create; pthread_key_delete; +    pthread_getspecific; pthread_setspecific; + +    pthread_once; + +    pthread_atfork; + +    flockfile; funlockfile; ftrylockfile; + +    # Non-standard POSIX1.x functions. +    pthread_mutexattr_getkind_np; pthread_mutexattr_setkind_np; + +    # Protected names for functions used in other shared objects. +    __pthread_mutex_init; __pthread_mutex_destroy; +    __pthread_mutex_lock; __pthread_mutex_trylock; __pthread_mutex_unlock; +    __pthread_mutexattr_init; __pthread_mutexattr_destroy; +    __pthread_mutexattr_settype; +    __pthread_key_create; __pthread_getspecific; __pthread_setspecific; +    __pthread_once; __pthread_atfork; +    _IO_flockfile; _IO_ftrylockfile; _IO_funlockfile; + +    # Hidden entry point (through macros). +    #_pthread_cleanup_pop; _pthread_cleanup_pop_restore; _pthread_cleanup_push; +    #_pthread_cleanup_push_defer; + +    # Semaphores. +    sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait; + +    # Special fork handling. +    fork; __fork; vfork; + +    # Cancellation points. +    close; __close; fcntl; __fcntl; read; __read; write; __write; accept; +    connect; __connect; recv; recvfrom; recvmsg; send; __send; sendmsg; sendto; +    fsync; lseek; __lseek; msync; nanosleep; open; __open; pause; tcdrain; +    system; wait; __wait; waitpid; + +    # Hidden entry point (through macros). +    _pthread_cleanup_push; _pthread_cleanup_pop; +    _pthread_cleanup_push_defer; _pthread_cleanup_pop_restore; + +    pthread_kill_other_threads_np; + +    # The error functions. +    __errno_location; __h_errno_location; + +    # Functions which previously have been overwritten. +    sigwait; sigaction; __sigaction; _exit; _Exit; longjmp; siglongjmp; +    raise; +  } + +  GLIBC_2.1 { +    pthread_create; +    pthread_attr_init; + +    pthread_attr_getguardsize; pthread_attr_setguardsize; +    pthread_attr_getstackaddr; pthread_attr_setstackaddr; +    pthread_attr_getstacksize; pthread_attr_setstacksize; + +    pthread_mutexattr_gettype; pthread_mutexattr_settype; + +    pthread_rwlock_init; pthread_rwlock_destroy; +    pthread_rwlock_rdlock; pthread_rwlock_wrlock; pthread_rwlock_unlock; +    pthread_rwlock_tryrdlock; pthread_rwlock_trywrlock; + +    pthread_rwlockattr_init; pthread_rwlockattr_destroy; +    pthread_rwlockattr_getpshared; pthread_rwlockattr_setpshared; +    pthread_rwlockattr_getkind_np; pthread_rwlockattr_setkind_np; + +    pthread_getconcurrency; pthread_setconcurrency; + +    # Semaphores. +    sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait; + +    __libc_current_sigrtmin; __libc_current_sigrtmax; +    __libc_allocate_rtsig; +  } + +  GLIBC_2.1.1 { +    sem_close; sem_open; sem_unlink; +  } + +  GLIBC_2.1.2 { +    __vfork; +  } + +  GLIBC_2.2 { +    pthread_mutexattr_getpshared; pthread_mutexattr_setpshared; + +    pthread_condattr_getpshared; pthread_condattr_setpshared; + +    # New functions from IEEE Std. 1003.1-2001. +    pthread_mutex_timedlock; + +    pthread_rwlock_timedrdlock; pthread_rwlock_timedwrlock; + +    pthread_attr_getstack; pthread_attr_setstack; + +    pthread_spin_destroy; pthread_spin_init; pthread_spin_lock; +    pthread_spin_trylock; pthread_spin_unlock; + +    pthread_barrier_init; pthread_barrier_destroy; pthread_barrier_wait; +    pthread_barrierattr_destroy; pthread_barrierattr_init; +    pthread_barrierattr_setpshared; + +    sem_timedwait; + +    pthread_yield; + +    pthread_getcpuclockid; + +    # Cancellation points. +    lseek64; open64; __open64; pread; pread64; __pread64; pwrite; pwrite64; +    __pwrite64; + +    # Names used internally. +    __pthread_rwlock_init; __pthread_rwlock_destroy; +    __pthread_rwlock_rdlock; __pthread_rwlock_tryrdlock; +    __pthread_rwlock_wrlock; __pthread_rwlock_trywrlock; +    __pthread_rwlock_unlock; + +    __res_state; +  } + +  GLIBC_2.2.3 { +    # Extensions. +    pthread_getattr_np; +  } + +  GLIBC_2.2.6 { +    # Cancellation wrapper +    __nanosleep; +  } + +  GLIBC_2.3.2 { +    # Changed pthread_cond_t. +    pthread_cond_init; pthread_cond_destroy; +    pthread_cond_wait; pthread_cond_timedwait; +    pthread_cond_signal; pthread_cond_broadcast; +  } + +  GLIBC_2.3.3 { +    # 1003.1-2001 function accidentally left out in 2.2. +    pthread_barrierattr_getpshared; + +    # Unix CS option. +    pthread_condattr_getclock; pthread_condattr_setclock; + +    # Proposed API extensions. +    pthread_tryjoin_np; pthread_timedjoin_np; + +    # New cancellation cleanup handling. +    __pthread_register_cancel; __pthread_unregister_cancel; +    __pthread_register_cancel_defer; __pthread_unregister_cancel_restore; +    __pthread_unwind_next; +    __pthread_cleanup_routine; + +    # affinity interfaces without size parameter +    pthread_getaffinity_np; pthread_setaffinity_np; +    pthread_attr_getaffinity_np; pthread_attr_setaffinity_np; +  } + +  GLIBC_2.3.4 { +    # New affinity interfaces. +    pthread_getaffinity_np; pthread_setaffinity_np; +    pthread_attr_getaffinity_np; pthread_attr_setaffinity_np; + +    pthread_setschedprio; +  } + +  GLIBC_PRIVATE { +    __pthread_initialize_minimal; +    __pthread_clock_gettime; __pthread_clock_settime; +    __pthread_unwind; +  } +} diff --git a/libpthread/nptl/alloca_cutoff.c b/libpthread/nptl/alloca_cutoff.c new file mode 100644 index 000000000..ba26ceba3 --- /dev/null +++ b/libpthread/nptl/alloca_cutoff.c @@ -0,0 +1,36 @@ +/* Determine whether block of given size can be allocated on the stack or not. +   Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the 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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <alloca.h> +#include <stdlib.h> +#include <sys/param.h> +#include <pthreadP.h> + + +int +__libc_alloca_cutoff (size_t size) +{ +  return size <= (MIN (__MAX_ALLOCA_CUTOFF, +		       THREAD_GETMEM (THREAD_SELF, stackblock_size) / 4 +		       /* The main thread, before the thread library is +			  initialized, has zero in the stackblock_size +			  element.  Since it is the main thread we can +			  assume the maximum available stack space.  */ +		       ?: __MAX_ALLOCA_CUTOFF * 4)); +} diff --git a/libpthread/nptl/allocatestack.c b/libpthread/nptl/allocatestack.c new file mode 100644 index 000000000..fcb6c6e47 --- /dev/null +++ b/libpthread/nptl/allocatestack.c @@ -0,0 +1,947 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/param.h> +#include <dl-sysdep.h> +#include <tls.h> +#include <lowlevellock.h> + + +#ifndef NEED_SEPARATE_REGISTER_STACK + +/* Most architectures have exactly one stack pointer.  Some have more.  */ +# define STACK_VARIABLES void *stackaddr + +/* How to pass the values to the 'create_thread' function.  */ +# define STACK_VARIABLES_ARGS stackaddr + +/* How to declare function which gets there parameters.  */ +# define STACK_VARIABLES_PARMS void *stackaddr + +/* How to declare allocate_stack.  */ +# define ALLOCATE_STACK_PARMS void **stack + +/* This is how the function is called.  We do it this way to allow +   other variants of the function to have more parameters.  */ +# define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr) + +#else + +/* We need two stacks.  The kernel will place them but we have to tell +   the kernel about the size of the reserved address space.  */ +# define STACK_VARIABLES void *stackaddr; size_t stacksize + +/* How to pass the values to the 'create_thread' function.  */ +# define STACK_VARIABLES_ARGS stackaddr, stacksize + +/* How to declare function which gets there parameters.  */ +# define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize + +/* How to declare allocate_stack.  */ +# define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize + +/* This is how the function is called.  We do it this way to allow +   other variants of the function to have more parameters.  */ +# define ALLOCATE_STACK(attr, pd) \ +  allocate_stack (attr, pd, &stackaddr, &stacksize) + +#endif + + +/* Default alignment of stack.  */ +#ifndef STACK_ALIGN +# define STACK_ALIGN __alignof__ (long double) +#endif + +/* Default value for minimal stack size after allocating thread +   descriptor and guard.  */ +#ifndef MINIMAL_REST_STACK +# define MINIMAL_REST_STACK	4096 +#endif + + +/* Let the architecture add some flags to the mmap() call used to +   allocate stacks.  */ +#ifndef ARCH_MAP_FLAGS +# define ARCH_MAP_FLAGS 0 +#endif + +/* This yields the pointer that TLS support code calls the thread pointer.  */ +#if TLS_TCB_AT_TP +# define TLS_TPADJ(pd) (pd) +#elif TLS_DTV_AT_TP +# define TLS_TPADJ(pd) ((struct pthread *)((char *) (pd) + TLS_PRE_TCB_SIZE)) +#endif + +/* Cache handling for not-yet free stacks.  */ + +/* Maximum size in kB of cache.  */ +static size_t stack_cache_maxsize = 40 * 1024 * 1024; /* 40MiBi by default.  */ +static size_t stack_cache_actsize; + +/* Mutex protecting this variable.  */ +static lll_lock_t stack_cache_lock = LLL_LOCK_INITIALIZER; + +/* List of queued stack frames.  */ +static LIST_HEAD (stack_cache); + +/* List of the stacks in use.  */ +static LIST_HEAD (stack_used); + +/* List of the threads with user provided stacks in use.  No need to +   initialize this, since it's done in __pthread_initialize_minimal.  */ +list_t __stack_user __attribute__ ((nocommon)); +hidden_data_def (__stack_user) + +#if COLORING_INCREMENT != 0 +/* Number of threads created.  */ +static unsigned int nptl_ncreated; +#endif + + +/* Check whether the stack is still used or not.  */ +#define FREE_P(descr) ((descr)->tid <= 0) + + +/* We create a double linked list of all cache entries.  Double linked +   because this allows removing entries from the end.  */ + + +/* Get a stack frame from the cache.  We have to match by size since +   some blocks might be too small or far too large.  */ +static struct pthread * +get_cached_stack (size_t *sizep, void **memp) +{ +  size_t size = *sizep; +  struct pthread *result = NULL; +  list_t *entry; + +  lll_lock (stack_cache_lock); + +  /* Search the cache for a matching entry.  We search for the +     smallest stack which has at least the required size.  Note that +     in normal situations the size of all allocated stacks is the +     same.  As the very least there are only a few different sizes. +     Therefore this loop will exit early most of the time with an +     exact match.  */ +  list_for_each (entry, &stack_cache) +    { +      struct pthread *curr; + +      curr = list_entry (entry, struct pthread, list); +      if (FREE_P (curr) && curr->stackblock_size >= size) +	{ +	  if (curr->stackblock_size == size) +	    { +	      result = curr; +	      break; +	    } + +	  if (result == NULL +	      || result->stackblock_size > curr->stackblock_size) +	    result = curr; +	} +    } + +  if (__builtin_expect (result == NULL, 0) +      /* Make sure the size difference is not too excessive.  In that +	 case we do not use the block.  */ +      || __builtin_expect (result->stackblock_size > 4 * size, 0)) +    { +      /* Release the lock.  */ +      lll_unlock (stack_cache_lock); + +      return NULL; +    } + +  /* Dequeue the entry.  */ +  list_del (&result->list); + +  /* And add to the list of stacks in use.  */ +  list_add (&result->list, &stack_used); + +  /* And decrease the cache size.  */ +  stack_cache_actsize -= result->stackblock_size; + +  /* Release the lock early.  */ +  lll_unlock (stack_cache_lock); + +  /* Report size and location of the stack to the caller.  */ +  *sizep = result->stackblock_size; +  *memp = result->stackblock; + +  /* Cancellation handling is back to the default.  */ +  result->cancelhandling = 0; +  result->cleanup = NULL; + +  /* No pending event.  */ +  result->nextevent = NULL; + +  /* Clear the DTV.  */ +  dtv_t *dtv = GET_DTV (TLS_TPADJ (result)); +  memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); + +  /* Re-initialize the TLS.  */ +  _dl_allocate_tls_init (TLS_TPADJ (result)); + +  return result; +} + + +/* Add a stack frame which is not used anymore to the stack.  Must be +   called with the cache lock held.  */ +static inline void +__attribute ((always_inline)) +queue_stack (struct pthread *stack) +{ +  /* We unconditionally add the stack to the list.  The memory may +     still be in use but it will not be reused until the kernel marks +     the stack as not used anymore.  */ +  list_add (&stack->list, &stack_cache); + +  stack_cache_actsize += stack->stackblock_size; +  if (__builtin_expect (stack_cache_actsize > stack_cache_maxsize, 0)) +    { +      /* We reduce the size of the cache.  Remove the last entries +	 until the size is below the limit.  */ +      list_t *entry; +      list_t *prev; + +      /* Search from the end of the list.  */ +      list_for_each_prev_safe (entry, prev, &stack_cache) +	{ +	  struct pthread *curr; + +	  curr = list_entry (entry, struct pthread, list); +	  if (FREE_P (curr)) +	    { +	      /* Unlink the block.  */ +	      list_del (entry); + +	      /* Account for the freed memory.  */ +	      stack_cache_actsize -= curr->stackblock_size; + +	      /* Free the memory associated with the ELF TLS.  */ +	      _dl_deallocate_tls (TLS_TPADJ (curr), false); + +	      /* Remove this block.  This should never fail.  If it +		 does something is really wrong.  */ +	      if (munmap (curr->stackblock, curr->stackblock_size) != 0) +		abort (); + +	      /* Maybe we have freed enough.  */ +	      if (stack_cache_actsize <= stack_cache_maxsize) +		break; +	    } +	} +    } +} + + +static int +internal_function +change_stack_perm (struct pthread *pd +#ifdef NEED_SEPARATE_REGISTER_STACK +		   , size_t pagemask +#endif +		   ) +{ +#ifdef NEED_SEPARATE_REGISTER_STACK +  void *stack = (pd->stackblock +		 + (((((pd->stackblock_size - pd->guardsize) / 2) +		      & pagemask) + pd->guardsize) & pagemask)); +  size_t len = pd->stackblock + pd->stackblock_size - stack; +#else +  void *stack = pd->stackblock + pd->guardsize; +  size_t len = pd->stackblock_size - pd->guardsize; +#endif +  if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) +    return errno; + +  return 0; +} + + +static int +allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, +		ALLOCATE_STACK_PARMS) +{ +  struct pthread *pd; +  size_t size; +  size_t pagesize_m1 = __getpagesize () - 1; +  void *stacktop; + +  assert (attr != NULL); +  assert (powerof2 (pagesize_m1 + 1)); +  assert (TCB_ALIGNMENT >= STACK_ALIGN); + +  /* Get the stack size from the attribute if it is set.  Otherwise we +     use the default we determined at start time.  */ +  size = attr->stacksize ?: __default_stacksize; + +  /* Get memory for the stack.  */ +  if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0)) +    { +      uintptr_t adj; + +      /* If the user also specified the size of the stack make sure it +	 is large enough.  */ +      if (attr->stacksize != 0 +	  && attr->stacksize < (__static_tls_size + MINIMAL_REST_STACK)) +	return EINVAL; + +      /* Adjust stack size for alignment of the TLS block.  */ +#if TLS_TCB_AT_TP +      adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE) +	    & __static_tls_align_m1; +      assert (size > adj + TLS_TCB_SIZE); +#elif TLS_DTV_AT_TP +      adj = ((uintptr_t) attr->stackaddr - __static_tls_size) +	    & __static_tls_align_m1; +      assert (size > adj); +#endif + +      /* The user provided some memory.  Let's hope it matches the +	 size...  We do not allocate guard pages if the user provided +	 the stack.  It is the user's responsibility to do this if it +	 is wanted.  */ +#if TLS_TCB_AT_TP +      pd = (struct pthread *) ((uintptr_t) attr->stackaddr +			       - TLS_TCB_SIZE - adj); +#elif TLS_DTV_AT_TP +      pd = (struct pthread *) (((uintptr_t) attr->stackaddr +			        - __static_tls_size - adj) +			       - TLS_PRE_TCB_SIZE); +#endif + +      /* The user provided stack memory needs to be cleared.  */ +      memset (pd, '\0', sizeof (struct pthread)); + +      /* The first TSD block is included in the TCB.  */ +      pd->specific[0] = pd->specific_1stblock; + +      /* Remember the stack-related values.  */ +      pd->stackblock = (char *) attr->stackaddr - size; +      pd->stackblock_size = size; + +      /* This is a user-provided stack.  It will not be queued in the +	 stack cache nor will the memory (except the TLS memory) be freed.  */ +      pd->user_stack = true; + +      /* This is at least the second thread.  */ +      pd->header.multiple_threads = 1; +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +      __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; +#endif + +#ifdef NEED_DL_SYSINFO +      /* Copy the sysinfo value from the parent.  */ +      THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO; +#endif + +      /* The process ID is also the same as that of the caller.  */ +      pd->pid = THREAD_GETMEM (THREAD_SELF, pid); + +      /* Allocate the DTV for this thread.  */ +      if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL) +	{ +	  /* Something went wrong.  */ +	  assert (errno == ENOMEM); +	  return EAGAIN; +	} + + +      /* Prepare to modify global data.  */ +      lll_lock (stack_cache_lock); + +      /* And add to the list of stacks in use.  */ +      list_add (&pd->list, &__stack_user); + +      lll_unlock (stack_cache_lock); +    } +  else +    { +      /* Allocate some anonymous memory.  If possible use the cache.  */ +      size_t guardsize; +      size_t reqsize; +      void *mem; +      const int prot = (PROT_READ | PROT_WRITE +			| ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0)); + +#if COLORING_INCREMENT != 0 +      /* Add one more page for stack coloring.  Don't do it for stacks +	 with 16 times pagesize or larger.  This might just cause +	 unnecessary misalignment.  */ +      if (size <= 16 * pagesize_m1) +	size += pagesize_m1 + 1; +#endif + +      /* Adjust the stack size for alignment.  */ +      size &= ~__static_tls_align_m1; +      assert (size != 0); + +      /* Make sure the size of the stack is enough for the guard and +	 eventually the thread descriptor.  */ +      guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1; +      if (__builtin_expect (size < (guardsize + __static_tls_size +				    + MINIMAL_REST_STACK + pagesize_m1 + 1), +			    0)) +	/* The stack is too small (or the guard too large).  */ +	return EINVAL; + +      /* Try to get a stack from the cache.  */ +      reqsize = size; +      pd = get_cached_stack (&size, &mem); +      if (pd == NULL) +	{ +	  /* To avoid aliasing effects on a larger scale than pages we +	     adjust the allocated stack size if necessary.  This way +	     allocations directly following each other will not have +	     aliasing problems.  */ +#if MULTI_PAGE_ALIASING != 0 +	  if ((size % MULTI_PAGE_ALIASING) == 0) +	    size += pagesize_m1 + 1; +#endif + +	  mem = mmap (NULL, size, prot, +		      MAP_PRIVATE | MAP_ANONYMOUS | ARCH_MAP_FLAGS, -1, 0); + +	  if (__builtin_expect (mem == MAP_FAILED, 0)) +	    { +#ifdef ARCH_RETRY_MMAP +	      mem = ARCH_RETRY_MMAP (size); +	      if (__builtin_expect (mem == MAP_FAILED, 0)) +#endif +		return errno; +	    } + +	  /* SIZE is guaranteed to be greater than zero. +	     So we can never get a null pointer back from mmap.  */ +	  assert (mem != NULL); + +#if COLORING_INCREMENT != 0 +	  /* Atomically increment NCREATED.  */ +	  unsigned int ncreated = atomic_increment_val (&nptl_ncreated); + +	  /* We chose the offset for coloring by incrementing it for +	     every new thread by a fixed amount.  The offset used +	     module the page size.  Even if coloring would be better +	     relative to higher alignment values it makes no sense to +	     do it since the mmap() interface does not allow us to +	     specify any alignment for the returned memory block.  */ +	  size_t coloring = (ncreated * COLORING_INCREMENT) & pagesize_m1; + +	  /* Make sure the coloring offsets does not disturb the alignment +	     of the TCB and static TLS block.  */ +	  if (__builtin_expect ((coloring & __static_tls_align_m1) != 0, 0)) +	    coloring = (((coloring + __static_tls_align_m1) +			 & ~(__static_tls_align_m1)) +			& ~pagesize_m1); +#else +	  /* Unless specified we do not make any adjustments.  */ +# define coloring 0 +#endif + +	  /* Place the thread descriptor at the end of the stack.  */ +#if TLS_TCB_AT_TP +	  pd = (struct pthread *) ((char *) mem + size - coloring) - 1; +#elif TLS_DTV_AT_TP +	  pd = (struct pthread *) ((((uintptr_t) mem + size - coloring +				    - __static_tls_size) +				    & ~__static_tls_align_m1) +				   - TLS_PRE_TCB_SIZE); +#endif + +	  /* Remember the stack-related values.  */ +	  pd->stackblock = mem; +	  pd->stackblock_size = size; + +	  /* We allocated the first block thread-specific data array. +	     This address will not change for the lifetime of this +	     descriptor.  */ +	  pd->specific[0] = pd->specific_1stblock; + +	  /* This is at least the second thread.  */ +	  pd->header.multiple_threads = 1; +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +	  __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; +#endif + +#ifdef NEED_DL_SYSINFO +	  /* Copy the sysinfo value from the parent.  */ +	  THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO; +#endif + +	  /* The process ID is also the same as that of the caller.  */ +	  pd->pid = THREAD_GETMEM (THREAD_SELF, pid); + +	  /* Allocate the DTV for this thread.  */ +	  if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL) +	    { +	      /* Something went wrong.  */ +	      assert (errno == ENOMEM); + +	      /* Free the stack memory we just allocated.  */ +	      (void) munmap (mem, size); + +	      return EAGAIN; +	    } + + +	  /* Prepare to modify global data.  */ +	  lll_lock (stack_cache_lock); + +	  /* And add to the list of stacks in use.  */ +	  list_add (&pd->list, &stack_used); + +	  lll_unlock (stack_cache_lock); + + +	  /* There might have been a race.  Another thread might have +	     caused the stacks to get exec permission while this new +	     stack was prepared.  Detect if this was possible and +	     change the permission if necessary.  */ +	  if (__builtin_expect ((GL(dl_stack_flags) & PF_X) != 0 +				&& (prot & PROT_EXEC) == 0, 0)) +	    { +	      int err = change_stack_perm (pd +#ifdef NEED_SEPARATE_REGISTER_STACK +					   , ~pagesize_m1 +#endif +					   ); +	      if (err != 0) +		{ +		  /* Free the stack memory we just allocated.  */ +		  (void) munmap (mem, size); + +		  return err; +		} +	    } + + +	  /* Note that all of the stack and the thread descriptor is +	     zeroed.  This means we do not have to initialize fields +	     with initial value zero.  This is specifically true for +	     the 'tid' field which is always set back to zero once the +	     stack is not used anymore and for the 'guardsize' field +	     which will be read next.  */ +	} + +      /* Create or resize the guard area if necessary.  */ +      if (__builtin_expect (guardsize > pd->guardsize, 0)) +	{ +#ifdef NEED_SEPARATE_REGISTER_STACK +	  char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1); +#else +	  char *guard = mem; +#endif +	  if (mprotect (guard, guardsize, PROT_NONE) != 0) +	    { +	      int err; +	    mprot_error: +	      err = errno; + +	      lll_lock (stack_cache_lock); + +	      /* Remove the thread from the list.  */ +	      list_del (&pd->list); + +	      lll_unlock (stack_cache_lock); + +	      /* Get rid of the TLS block we allocated.  */ +	      _dl_deallocate_tls (TLS_TPADJ (pd), false); + +	      /* Free the stack memory regardless of whether the size +		 of the cache is over the limit or not.  If this piece +		 of memory caused problems we better do not use it +		 anymore.  Uh, and we ignore possible errors.  There +		 is nothing we could do.  */ +	      (void) munmap (mem, size); + +	      return err; +	    } + +	  pd->guardsize = guardsize; +	} +      else if (__builtin_expect (pd->guardsize - guardsize > size - reqsize, +				 0)) +	{ +	  /* The old guard area is too large.  */ + +#ifdef NEED_SEPARATE_REGISTER_STACK +	  char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1); +	  char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1); + +	  if (oldguard < guard +	      && mprotect (oldguard, guard - oldguard, prot) != 0) +	    goto mprot_error; + +	  if (mprotect (guard + guardsize, +			oldguard + pd->guardsize - guard - guardsize, +			prot) != 0) +	    goto mprot_error; +#else +	  if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize, +			prot) != 0) +	    goto mprot_error; +#endif + +	  pd->guardsize = guardsize; +	} +      /* The pthread_getattr_np() calls need to get passed the size +	 requested in the attribute, regardless of how large the +	 actually used guardsize is.  */ +      pd->reported_guardsize = guardsize; +    } + +  /* Initialize the lock.  We have to do this unconditionally since the +     stillborn thread could be canceled while the lock is taken.  */ +  pd->lock = LLL_LOCK_INITIALIZER; + +  /* We place the thread descriptor at the end of the stack.  */ +  *pdp = pd; + +#if TLS_TCB_AT_TP +  /* The stack begins before the TCB and the static TLS block.  */ +  stacktop = ((char *) (pd + 1) - __static_tls_size); +#elif TLS_DTV_AT_TP +  stacktop = (char *) (pd - 1); +#endif + +#ifdef NEED_SEPARATE_REGISTER_STACK +  *stack = pd->stackblock; +  *stacksize = stacktop - *stack; +#else +  *stack = stacktop; +#endif + +  return 0; +} + + +void +internal_function +__deallocate_stack (struct pthread *pd) +{ +  lll_lock (stack_cache_lock); + +  /* Remove the thread from the list of threads with user defined +     stacks.  */ +  list_del (&pd->list); + +  /* Not much to do.  Just free the mmap()ed memory.  Note that we do +     not reset the 'used' flag in the 'tid' field.  This is done by +     the kernel.  If no thread has been created yet this field is +     still zero.  */ +  if (__builtin_expect (! pd->user_stack, 1)) +    (void) queue_stack (pd); +  else +    /* Free the memory associated with the ELF TLS.  */ +    _dl_deallocate_tls (TLS_TPADJ (pd), false); + +  lll_unlock (stack_cache_lock); +} + + +int +internal_function +__make_stacks_executable (void **stack_endp) +{ +  /* First the main thread's stack.  */ +  int err = _dl_make_stack_executable (stack_endp); +  if (err != 0) +    return err; + +#ifdef NEED_SEPARATE_REGISTER_STACK +  const size_t pagemask = ~(__getpagesize () - 1); +#endif + +  lll_lock (stack_cache_lock); + +  list_t *runp; +  list_for_each (runp, &stack_used) +    { +      err = change_stack_perm (list_entry (runp, struct pthread, list) +#ifdef NEED_SEPARATE_REGISTER_STACK +			       , pagemask +#endif +			       ); +      if (err != 0) +	break; +    } + +  /* Also change the permission for the currently unused stacks.  This +     might be wasted time but better spend it here than adding a check +     in the fast path.  */ +  if (err == 0) +    list_for_each (runp, &stack_cache) +      { +	err = change_stack_perm (list_entry (runp, struct pthread, list) +#ifdef NEED_SEPARATE_REGISTER_STACK +				 , pagemask +#endif +				 ); +	if (err != 0) +	  break; +      } + +  lll_unlock (stack_cache_lock); + +  return err; +} + + +/* In case of a fork() call the memory allocation in the child will be +   the same but only one thread is running.  All stacks except that of +   the one running thread are not used anymore.  We have to recycle +   them.  */ +void +__reclaim_stacks (void) +{ +  struct pthread *self = (struct pthread *) THREAD_SELF; + +  /* No locking necessary.  The caller is the only stack in use.  */ + +  /* Mark all stacks except the still running one as free.  */ +  list_t *runp; +  list_for_each (runp, &stack_used) +    { +      struct pthread *curp; + +      curp = list_entry (runp, struct pthread, list); +      if (curp != self) +	{ +	  /* This marks the stack as free.  */ +	  curp->tid = 0; + +	  /* The PID field must be initialized for the new process.  */ +	  curp->pid = self->pid; + +	  /* Account for the size of the stack.  */ +	  stack_cache_actsize += curp->stackblock_size; +	} +    } + +  /* Add the stack of all running threads to the cache.  */ +  list_splice (&stack_used, &stack_cache); + +  /* Remove the entry for the current thread to from the cache list +     and add it to the list of running threads.  Which of the two +     lists is decided by the user_stack flag.  */ +  list_del (&self->list); + +  /* Re-initialize the lists for all the threads.  */ +  INIT_LIST_HEAD (&stack_used); +  INIT_LIST_HEAD (&__stack_user); + +  if (__builtin_expect (THREAD_GETMEM (self, user_stack), 0)) +    list_add (&self->list, &__stack_user); +  else +    list_add (&self->list, &stack_used); + +  /* There is one thread running.  */ +  __nptl_nthreads = 1; + +  /* Initialize the lock.  */ +  stack_cache_lock = LLL_LOCK_INITIALIZER; +} + + +#if HP_TIMING_AVAIL +# undef __find_thread_by_id +/* Find a thread given the thread ID.  */ +attribute_hidden +struct pthread * +__find_thread_by_id (pid_t tid) +{ +  struct pthread *result = NULL; + +  lll_lock (stack_cache_lock); + +  /* Iterate over the list with system-allocated threads first.  */ +  list_t *runp; +  list_for_each (runp, &stack_used) +    { +      struct pthread *curp; + +      curp = list_entry (runp, struct pthread, list); + +      if (curp->tid == tid) +	{ +	  result = curp; +	  goto out; +	} +    } + +  /* Now the list with threads using user-allocated stacks.  */ +  list_for_each (runp, &__stack_user) +    { +      struct pthread *curp; + +      curp = list_entry (runp, struct pthread, list); + +      if (curp->tid == tid) +	{ +	  result = curp; +	  goto out; +	} +    } + + out: +  lll_unlock (stack_cache_lock); + +  return result; +} +#endif + +int +attribute_hidden +__nptl_setxid (struct xid_command *cmdp) +{ +  int result; +  lll_lock (stack_cache_lock); + +  __xidcmd = cmdp; +  cmdp->cntr = 0; + +  INTERNAL_SYSCALL_DECL (err); + +  struct pthread *self = THREAD_SELF; + +  /* Iterate over the list with system-allocated threads first.  */ +  list_t *runp; +  list_for_each (runp, &stack_used) +    { +      struct pthread *t = list_entry (runp, struct pthread, list); +      if (t != self) +	{ +	  int val; +#if __ASSUME_TGKILL +	  val = INTERNAL_SYSCALL (tgkill, err, 3, +				  THREAD_GETMEM (THREAD_SELF, pid), +				  t->tid, SIGSETXID); +#else +# ifdef __NR_tgkill +	  val = INTERNAL_SYSCALL (tgkill, err, 3, +				  THREAD_GETMEM (THREAD_SELF, pid), +				  t->tid, SIGSETXID); +	  if (INTERNAL_SYSCALL_ERROR_P (val, err) +	      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif +	    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID); +#endif + +	  if (!INTERNAL_SYSCALL_ERROR_P (val, err)) +	    atomic_increment (&cmdp->cntr); +	} +    } + +  /* Now the list with threads using user-allocated stacks.  */ +  list_for_each (runp, &__stack_user) +    { +      struct pthread *t = list_entry (runp, struct pthread, list); +      if (t != self) +	{ +	  int val; +#if __ASSUME_TGKILL +	  val = INTERNAL_SYSCALL (tgkill, err, 3, +				  THREAD_GETMEM (THREAD_SELF, pid), +				  t->tid, SIGSETXID); +#else +# ifdef __NR_tgkill +	  val = INTERNAL_SYSCALL (tgkill, err, 3, +				  THREAD_GETMEM (THREAD_SELF, pid), +				  t->tid, SIGSETXID); +	  if (INTERNAL_SYSCALL_ERROR_P (val, err) +	      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif +	    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID); +#endif + +	  if (!INTERNAL_SYSCALL_ERROR_P (val, err)) +	    atomic_increment (&cmdp->cntr); +	} +    } + +  int cur = cmdp->cntr; +  while (cur != 0) +    { +      lll_futex_wait (&cmdp->cntr, cur); +      cur = cmdp->cntr; +    } + +  /* This must be last, otherwise the current thread might not have +     permissions to send SIGSETXID syscall to the other threads.  */ +  result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, err, 3, +				 cmdp->id[0], cmdp->id[1], cmdp->id[2]); +  if (INTERNAL_SYSCALL_ERROR_P (result, err)) +    { +      __set_errno (INTERNAL_SYSCALL_ERRNO (result, err)); +      result = -1; +    } + +  lll_unlock (stack_cache_lock); +  return result; +} + +static inline void __attribute__((always_inline)) +init_one_static_tls (struct pthread *curp, struct link_map *map) +{ +  dtv_t *dtv = GET_DTV (TLS_TPADJ (curp)); +# if TLS_TCB_AT_TP +  void *dest = (char *) curp - map->l_tls_offset; +# elif TLS_DTV_AT_TP +  void *dest = (char *) curp + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + +  /* Fill in the DTV slot so that a later LD/GD access will find it.  */ +  dtv[map->l_tls_modid].pointer.val = dest; +  dtv[map->l_tls_modid].pointer.is_static = true; + +  /* Initialize the memory.  */ +  memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), +	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size); +} + +void +attribute_hidden +__pthread_init_static_tls (struct link_map *map) +{ +  lll_lock (stack_cache_lock); + +  /* Iterate over the list with system-allocated threads first.  */ +  list_t *runp; +  list_for_each (runp, &stack_used) +    init_one_static_tls (list_entry (runp, struct pthread, list), map); + +  /* Now the list with threads using user-allocated stacks.  */ +  list_for_each (runp, &__stack_user) +    init_one_static_tls (list_entry (runp, struct pthread, list), map); + +  lll_unlock (stack_cache_lock); +} diff --git a/libpthread/nptl/cancellation.c b/libpthread/nptl/cancellation.c new file mode 100644 index 000000000..1d28d383f --- /dev/null +++ b/libpthread/nptl/cancellation.c @@ -0,0 +1,90 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdlib.h> +#include "pthreadP.h" + + +/* The next two functions are similar to pthread_setcanceltype() but +   more specialized for the use in the cancelable functions like write(). +   They do not need to check parameters etc.  */ +int +attribute_hidden +__pthread_enable_asynccancel (void) +{ +  struct pthread *self = THREAD_SELF; +  int oldval = THREAD_GETMEM (self, cancelhandling); + +  while (1) +    { +      int newval = oldval | CANCELTYPE_BITMASK; + +      if (newval == oldval) +	break; + +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	{ +	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) +	    { +	      THREAD_SETMEM (self, result, PTHREAD_CANCELED); +	      __do_cancel (); +	    } + +	  break; +	} + +      /* Prepare the next round.  */ +      oldval = curval; +    } + +  return oldval; +} + + +void +internal_function attribute_hidden +__pthread_disable_asynccancel (int oldtype) +{ +  /* If asynchronous cancellation was enabled before we do not have +     anything to do.  */ +  if (oldtype & CANCELTYPE_BITMASK) +    return; + +  struct pthread *self = THREAD_SELF; +  int oldval = THREAD_GETMEM (self, cancelhandling); + +  while (1) +    { +      int newval = oldval & ~CANCELTYPE_BITMASK; + +      if (newval == oldval) +	break; + +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	break; + +      /* Prepare the next round.  */ +      oldval = curval; +    } +} diff --git a/libpthread/nptl/cleanup.c b/libpthread/nptl/cleanup.c new file mode 100644 index 000000000..af828c49f --- /dev/null +++ b/libpthread/nptl/cleanup.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +__cleanup_fct_attribute +__pthread_register_cancel (__pthread_unwind_buf_t *buf) +{ +  struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; +  struct pthread *self = THREAD_SELF; + +  /* Store old info.  */ +  ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); +  ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); + +  /* Store the new cleanup handler info.  */ +  THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); +} +hidden_def (__pthread_register_cancel) + + +void +__cleanup_fct_attribute +__pthread_unregister_cancel (__pthread_unwind_buf_t *buf) +{ +  struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + +  THREAD_SETMEM (THREAD_SELF, cleanup_jmp_buf, ibuf->priv.data.prev); +} +hidden_def (__pthread_unregister_cancel) diff --git a/libpthread/nptl/cleanup_compat.c b/libpthread/nptl/cleanup_compat.c new file mode 100644 index 000000000..a25b397f9 --- /dev/null +++ b/libpthread/nptl/cleanup_compat.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +_pthread_cleanup_push (buffer, routine, arg) +     struct _pthread_cleanup_buffer *buffer; +     void (*routine) (void *); +     void *arg; +{ +  struct pthread *self = THREAD_SELF; + +  buffer->__routine = routine; +  buffer->__arg = arg; +  buffer->__prev = THREAD_GETMEM (self, cleanup); + +  THREAD_SETMEM (self, cleanup, buffer); +} +strong_alias (_pthread_cleanup_push, __pthread_cleanup_push) + + +void +_pthread_cleanup_pop (buffer, execute) +     struct _pthread_cleanup_buffer *buffer; +     int execute; +{ +  struct pthread *self __attribute ((unused)) = THREAD_SELF; + +  THREAD_SETMEM (self, cleanup, buffer->__prev); + +  /* If necessary call the cleanup routine after we removed the +     current cleanup block from the list.  */ +  if (execute) +    buffer->__routine (buffer->__arg); +} +strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop) diff --git a/libpthread/nptl/cleanup_defer.c b/libpthread/nptl/cleanup_defer.c new file mode 100644 index 000000000..498d9557d --- /dev/null +++ b/libpthread/nptl/cleanup_defer.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +__cleanup_fct_attribute +__pthread_register_cancel_defer (__pthread_unwind_buf_t *buf) +{ +  struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; +  struct pthread *self = THREAD_SELF; + +  /* Store old info.  */ +  ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); +  ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); + +  int cancelhandling = THREAD_GETMEM (self, cancelhandling); + +  /* Disable asynchronous cancellation for now.  */ +  if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0)) +    while (1) +      { +	int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, +						cancelhandling +						& ~CANCELTYPE_BITMASK, +						cancelhandling); +	if (__builtin_expect (curval == cancelhandling, 1)) +	  /* Successfully replaced the value.  */ +	  break; + +	/* Prepare for the next round.  */ +	cancelhandling = curval; +      } + +  ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK +				? PTHREAD_CANCEL_ASYNCHRONOUS +				: PTHREAD_CANCEL_DEFERRED); + +  /* Store the new cleanup handler info.  */ +  THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); +} + + +void +__cleanup_fct_attribute +__pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf) +{ +  struct pthread *self = THREAD_SELF; +  struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + +  THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev); + +  int cancelhandling; +  if (ibuf->priv.data.canceltype != PTHREAD_CANCEL_DEFERRED +      && ((cancelhandling = THREAD_GETMEM (self, cancelhandling)) +	  & CANCELTYPE_BITMASK) == 0) +    { +      while (1) +	{ +	  int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, +						  cancelhandling +						  | CANCELTYPE_BITMASK, +						  cancelhandling); +	  if (__builtin_expect (curval == cancelhandling, 1)) +	    /* Successfully replaced the value.  */ +	    break; + +	  /* Prepare for the next round.  */ +	  cancelhandling = curval; +	} + +      CANCELLATION_P (self); +    } +} diff --git a/libpthread/nptl/cleanup_defer_compat.c b/libpthread/nptl/cleanup_defer_compat.c new file mode 100644 index 000000000..a0ed6da88 --- /dev/null +++ b/libpthread/nptl/cleanup_defer_compat.c @@ -0,0 +1,98 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +void +_pthread_cleanup_push_defer (buffer, routine, arg) +     struct _pthread_cleanup_buffer *buffer; +     void (*routine) (void *); +     void *arg; +{ +  struct pthread *self = THREAD_SELF; + +  buffer->__routine = routine; +  buffer->__arg = arg; +  buffer->__prev = THREAD_GETMEM (self, cleanup); + +  int cancelhandling = THREAD_GETMEM (self, cancelhandling); + +  /* Disable asynchronous cancellation for now.  */ +  if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0)) +    while (1) +      { +	int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, +						cancelhandling +						& ~CANCELTYPE_BITMASK, +						cancelhandling); +	if (__builtin_expect (curval == cancelhandling, 1)) +	  /* Successfully replaced the value.  */ +	  break; + +	/* Prepare for the next round.  */ +	cancelhandling = curval; +      } + +  buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK +			  ? PTHREAD_CANCEL_ASYNCHRONOUS +			  : PTHREAD_CANCEL_DEFERRED); + +  THREAD_SETMEM (self, cleanup, buffer); +} +strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer) + + +void +_pthread_cleanup_pop_restore (buffer, execute) +     struct _pthread_cleanup_buffer *buffer; +     int execute; +{ +  struct pthread *self = THREAD_SELF; + +  THREAD_SETMEM (self, cleanup, buffer->__prev); + +  int cancelhandling; +  if (__builtin_expect (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED, 0) +      && ((cancelhandling = THREAD_GETMEM (self, cancelhandling)) +	  & CANCELTYPE_BITMASK) == 0) +    { +      while (1) +	{ +	  int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, +						  cancelhandling +						  | CANCELTYPE_BITMASK, +						  cancelhandling); +	  if (__builtin_expect (curval == cancelhandling, 1)) +	    /* Successfully replaced the value.  */ +	    break; + +	  /* Prepare for the next round.  */ +	  cancelhandling = curval; +	} + +      CANCELLATION_P (self); +    } + +  /* If necessary call the cleanup routine after we removed the +     current cleanup block from the list.  */ +  if (execute) +    buffer->__routine (buffer->__arg); +} +strong_alias (_pthread_cleanup_pop_restore, __pthread_cleanup_pop_restore) diff --git a/libpthread/nptl/cleanup_routine.c b/libpthread/nptl/cleanup_routine.c new file mode 100644 index 000000000..cbf231834 --- /dev/null +++ b/libpthread/nptl/cleanup_routine.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthread.h> + + +void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *f) +{ +  if (f->__do_it) +    f->__cancel_routine (f->__cancel_arg); +} diff --git a/libpthread/nptl/cond-perf.c b/libpthread/nptl/cond-perf.c new file mode 100644 index 000000000..e37914e6b --- /dev/null +++ b/libpthread/nptl/cond-perf.c @@ -0,0 +1,103 @@ +#include <pthread.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <atomic.h> + +static pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER; + +static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER; + +static bool last_round; +static int ntogo; +static bool alldone; + + +static void * +cons (void *arg) +{ +  pthread_mutex_lock (&mut1); + +  do +    { +      if (atomic_decrement_and_test (&ntogo)) +	{ +	  pthread_mutex_lock (&mut2); +	  alldone = true; +	  pthread_cond_signal (&cond2); +	  pthread_mutex_unlock (&mut2); +	} + +      pthread_cond_wait (&cond1, &mut1); +    } +  while (! last_round); + +  pthread_mutex_unlock (&mut1); + +  return NULL; +} + + +int +main (int argc, char *argv[]) +{ +  int opt; +  int err; +  int nthreads = 10; +  int nrounds = 100; +  bool keeplock = false; + +  while ((opt = getopt (argc, argv, "n:r:k")) != -1) +    switch (opt) +      { +      case 'n': +	nthreads = atol (optarg); +	break; +      case 'r': +	nrounds = atol (optarg); +	break; +      case 'k': +	keeplock = true; +	break; +      } + +  ntogo = nthreads; + +  pthread_t th[nthreads]; +  int i; +  for (i = 0; __builtin_expect (i < nthreads, 1); ++i) +    if (__builtin_expect ((err = pthread_create (&th[i], NULL, cons, (void *) (long) i)) != 0, 0)) +      printf ("pthread_create: %s\n", strerror (err)); + +  for (i = 0; __builtin_expect (i < nrounds, 1); ++i) +    { +      pthread_mutex_lock (&mut2); +      while (! alldone) +	pthread_cond_wait (&cond2, &mut2); +      pthread_mutex_unlock (&mut2); + +      pthread_mutex_lock (&mut1); +      if (! keeplock) +	pthread_mutex_unlock (&mut1); + +      ntogo = nthreads; +      alldone = false; +      if (i + 1 >= nrounds) +	last_round = true; + +      pthread_cond_broadcast (&cond1); + +      if (keeplock) +	pthread_mutex_unlock (&mut1); +    } + +  for (i = 0; i < nthreads; ++i) +    if ((err = pthread_join (th[i], NULL)) != 0) +      printf ("pthread_create: %s\n", strerror (err)); + +  return 0; +} diff --git a/libpthread/nptl/descr.h b/libpthread/nptl/descr.h new file mode 100644 index 000000000..454bb2a54 --- /dev/null +++ b/libpthread/nptl/descr.h @@ -0,0 +1,260 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _DESCR_H +#define _DESCR_H	1 + +#include <limits.h> +#include <sched.h> +#include <setjmp.h> +#include <stdbool.h> +#include <sys/types.h> +#include <hp-timing.h> +#include <list.h> +#include <lowlevellock.h> +#include <pthreaddef.h> +#include <dl-sysdep.h> +#include "../nptl_db/thread_db.h" +#include <tls.h> +#ifdef HAVE_FORCED_UNWIND +# include <unwind.h> +#endif +#define __need_res_state +#include <resolv.h> + +#ifndef TCB_ALIGNMENT +# define TCB_ALIGNMENT	sizeof (double) +#endif + + +/* We keep thread specific data in a special data structure, a two-level +   array.  The top-level array contains pointers to dynamically allocated +   arrays of a certain number of data pointers.  So we can implement a +   sparse array.  Each dynamic second-level array has +        PTHREAD_KEY_2NDLEVEL_SIZE +   entries.  This value shouldn't be too large.  */ +#define PTHREAD_KEY_2NDLEVEL_SIZE       32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE +   keys in each subarray.  */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ +  ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ +   / PTHREAD_KEY_2NDLEVEL_SIZE) + + + + +/* Internal version of the buffer to store cancellation handler +   information.  */ +struct pthread_unwind_buf +{ +  struct +  { +    __jmp_buf jmp_buf; +    int mask_was_saved; +  } cancel_jmp_buf[1]; + +  union +  { +    /* This is the placeholder of the public version.  */ +    void *pad[4]; + +    struct +    { +      /* Pointer to the previous cleanup buffer.  */ +      struct pthread_unwind_buf *prev; + +      /* Backward compatibility: state of the old-style cleanup +	 handler at the time of the previous new-style cleanup handler +	 installment.  */ +      struct _pthread_cleanup_buffer *cleanup; + +      /* Cancellation type before the push call.  */ +      int canceltype; +    } data; +  } priv; +}; + + +/* Opcodes and data types for communication with the signal handler to +   change user/group IDs.  */ +struct xid_command +{ +  int syscall_no; +  long id[3]; +  volatile int cntr; +}; + + +/* Thread descriptor data structure.  */ +struct pthread +{ +  union +  { +#if !TLS_DTV_AT_TP +    /* This overlaps the TCB as used for TLS without threads (see tls.h).  */ +    tcbhead_t header; +#else +    struct +    { +      int multiple_threads; +    } header; +#endif + +    /* This extra padding has no special purpose, and this structure layout +       is private and subject to change without affecting the official ABI. +       We just have it here in case it might be convenient for some +       implementation-specific instrumentation hack or suchlike.  */ +    void *__padding[16]; +  }; + +  /* This descriptor's link on the `stack_used' or `__stack_user' list.  */ +  list_t list; + +  /* Thread ID - which is also a 'is this thread descriptor (and +     therefore stack) used' flag.  */ +  pid_t tid; + +  /* Process ID - thread group ID in kernel speak.  */ +  pid_t pid; + +  /* List of cleanup buffers.  */ +  struct _pthread_cleanup_buffer *cleanup; + +  /* Unwind information.  */ +  struct pthread_unwind_buf *cleanup_jmp_buf; +#define HAVE_CLEANUP_JMP_BUF + +  /* Flags determining processing of cancellation.  */ +  int cancelhandling; +  /* Bit set if cancellation is disabled.  */ +#define CANCELSTATE_BIT		0 +#define CANCELSTATE_BITMASK	0x01 +  /* Bit set if asynchronous cancellation mode is selected.  */ +#define CANCELTYPE_BIT		1 +#define CANCELTYPE_BITMASK	0x02 +  /* Bit set if canceling has been initiated.  */ +#define CANCELING_BIT		2 +#define CANCELING_BITMASK	0x04 +  /* Bit set if canceled.  */ +#define CANCELED_BIT		3 +#define CANCELED_BITMASK	0x08 +  /* Bit set if thread is exiting.  */ +#define EXITING_BIT		4 +#define EXITING_BITMASK		0x10 +  /* Bit set if thread terminated and TCB is freed.  */ +#define TERMINATED_BIT		5 +#define TERMINATED_BITMASK	0x20 +  /* Mask for the rest.  Helps the compiler to optimize.  */ +#define CANCEL_RESTMASK		0xffffffc0 + +#define CANCEL_ENABLED_AND_CANCELED(value) \ +  (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK	      \ +	       | CANCEL_RESTMASK | TERMINATED_BITMASK)) == CANCELED_BITMASK) +#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \ +  (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK    \ +	       | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK))     \ +   == (CANCELTYPE_BITMASK | CANCELED_BITMASK)) + +  /* We allocate one block of references here.  This should be enough +     to avoid allocating any memory dynamically for most applications.  */ +  struct pthread_key_data +  { +    /* Sequence number.  We use uintptr_t to not require padding on +       32- and 64-bit machines.  On 64-bit machines it helps to avoid +       wrapping, too.  */ +    uintptr_t seq; + +    /* Data pointer.  */ +    void *data; +  } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE]; + +  /* Flag which is set when specific data is set.  */ +  bool specific_used; + +  /* Two-level array for the thread-specific data.  */ +  struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE]; + +  /* True if events must be reported.  */ +  bool report_events; + +  /* True if the user provided the stack.  */ +  bool user_stack; + +  /* True if thread must stop at startup time.  */ +  bool stopped_start; + +  /* Lock to synchronize access to the descriptor.  */ +  lll_lock_t lock; + +#if HP_TIMING_AVAIL +  /* Offset of the CPU clock at start thread start time.  */ +  hp_timing_t cpuclock_offset; +#endif + +  /* If the thread waits to join another one the ID of the latter is +     stored here. + +     In case a thread is detached this field contains a pointer of the +     TCB if the thread itself.  This is something which cannot happen +     in normal operation.  */ +  struct pthread *joinid; +  /* Check whether a thread is detached.  */ +#define IS_DETACHED(pd) ((pd)->joinid == (pd)) + +  /* Flags.  Including those copied from the thread attribute.  */ +  int flags; + +  /* The result of the thread function.  */ +  void *result; + +  /* Scheduling parameters for the new thread.  */ +  struct sched_param schedparam; +  int schedpolicy; + +  /* Start position of the code to be executed and the argument passed +     to the function.  */ +  void *(*start_routine) (void *); +  void *arg; + +  /* Debug state.  */ +  td_eventbuf_t eventbuf; +  /* Next descriptor with a pending event.  */ +  struct pthread *nextevent; + +#ifdef HAVE_FORCED_UNWIND +  /* Machine-specific unwind info.  */ +  struct _Unwind_Exception exc; +#endif + +  /* If nonzero pointer to area allocated for the stack and its +     size.  */ +  void *stackblock; +  size_t stackblock_size; +  /* Size of the included guard area.  */ +  size_t guardsize; +  /* This is what the user specified and what we will report.  */ +  size_t reported_guardsize; + +  /* Resolver state.  */ +  struct __res_state res; +} __attribute ((aligned (TCB_ALIGNMENT))); + + +#endif	/* descr.h */ diff --git a/libpthread/nptl/eintr.c b/libpthread/nptl/eintr.c new file mode 100644 index 000000000..933c5d81b --- /dev/null +++ b/libpthread/nptl/eintr.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthread.h> +#include <signal.h> +#include <unistd.h> + + +static int the_sig; + + +static void +eintr_handler (int sig) +{ +  if (sig != the_sig) +    { +      write (STDOUT_FILENO, "eintr_handler: signal number wrong\n", 35); +      _exit (1); +    } +  write (STDOUT_FILENO, ".", 1); +} + + +static void * +eintr_source (void *arg) +{ +  struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000 }; + +  if (arg == NULL) +    { +      sigset_t ss; +      sigemptyset (&ss); +      sigaddset (&ss, the_sig); +      pthread_sigmask (SIG_BLOCK, &ss, NULL); +    } + +  while (1) +    { +      if (arg != NULL) +	pthread_kill (*(pthread_t *) arg, the_sig); +      else +	kill (getpid (), the_sig); + +      nanosleep (&ts, NULL); +    } + +  /* NOTREACHED */ +  return NULL; +} + + +static void +setup_eintr (int sig, pthread_t *thp) +{ +  struct sigaction sa; +  sigemptyset (&sa.sa_mask); +  sa.sa_flags = 0; +  sa.sa_handler = eintr_handler; +  if (sigaction (sig, &sa, NULL) != 0) +    { +      puts ("setup_eintr: sigaction failed"); +      exit (1); +    } +  the_sig = sig; + +  /* Create the thread which will fire off the signals.  */ +  pthread_t th; +  if (pthread_create (&th, NULL, eintr_source, thp) != 0) +    { +      puts ("setup_eintr: pthread_create failed"); +      exit (1); +    } +} diff --git a/libpthread/nptl/events.c b/libpthread/nptl/events.c new file mode 100644 index 000000000..df97e54f6 --- /dev/null +++ b/libpthread/nptl/events.c @@ -0,0 +1,34 @@ +/* Event functions used while debugging. +   Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* The functions contained here do nothing, they just return.  */ + +#include "pthreadP.h" + +void +__nptl_create_event (void) +{ +} +hidden_def (__nptl_create_event) + +void +__nptl_death_event (void) +{ +} +hidden_def (__nptl_death_event) diff --git a/libpthread/nptl/forward.c b/libpthread/nptl/forward.c new file mode 100644 index 000000000..e5f93d475 --- /dev/null +++ b/libpthread/nptl/forward.c @@ -0,0 +1,203 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <dlfcn.h> +#include <pthreadP.h> +#include <signal.h> +#include <stdlib.h> + +#include <shlib-compat.h> +#include <atomic.h> +#include <sysdep.h> + + +/* Pointers to the libc functions.  */ +struct pthread_functions __libc_pthread_functions attribute_hidden; + + +#define FORWARD2(name, rettype, decl, params, defaction) \ +rettype									      \ +name decl								      \ +{									      \ +  if (__libc_pthread_functions.ptr_##name == NULL)			      \ +    defaction;								      \ +									      \ +  return __libc_pthread_functions.ptr_##name params;			      \ +} + +#define FORWARD(name, decl, params, defretval) \ +  FORWARD2 (name, int, decl, params, return defretval) + + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_1) +FORWARD (__pthread_attr_init_2_0, (pthread_attr_t *attr), (attr), 0) +compat_symbol (libc, __pthread_attr_init_2_0, pthread_attr_init, GLIBC_2_0); +#endif + +FORWARD (__pthread_attr_init_2_1, (pthread_attr_t *attr), (attr), 0) +versioned_symbol (libc, __pthread_attr_init_2_1, pthread_attr_init, GLIBC_2_1); + +FORWARD (pthread_attr_getdetachstate, +	 (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), +	 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), +	 (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, +	 (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), +	 (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, +	 (const pthread_attr_t *attr, struct sched_param *param), +	 (attr, param), 0) +FORWARD (pthread_attr_setschedparam, +	 (pthread_attr_t *attr, const struct sched_param *param), +	 (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, +	 (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), +	 (attr, policy), 0) + +FORWARD (pthread_attr_getscope, +	 (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), +	 (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2) +FORWARD2 (__pthread_cond_broadcast_2_0, int attribute_compat_text_section, +	  (pthread_cond_2_0_t *cond), (cond), return 0) +compat_symbol (libc, __pthread_cond_broadcast_2_0, pthread_cond_broadcast, +	       GLIBC_2_0); +#endif +FORWARD (__pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) +versioned_symbol (libc, __pthread_cond_broadcast, pthread_cond_broadcast, +		  GLIBC_2_3_2); + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2) +FORWARD2 (__pthread_cond_destroy_2_0, int attribute_compat_text_section, +	  (pthread_cond_2_0_t *cond), (cond), return 0) +compat_symbol (libc, __pthread_cond_destroy_2_0, pthread_cond_destroy, +	       GLIBC_2_0); +#endif +FORWARD (__pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) +versioned_symbol (libc, __pthread_cond_destroy, pthread_cond_destroy, +		  GLIBC_2_3_2); + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2) +FORWARD2 (__pthread_cond_init_2_0, int attribute_compat_text_section, +	  (pthread_cond_2_0_t *cond, const pthread_condattr_t *cond_attr), +	  (cond, cond_attr), return 0) +compat_symbol (libc, __pthread_cond_init_2_0, pthread_cond_init, GLIBC_2_0); +#endif +FORWARD (__pthread_cond_init, +	 (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), +	 (cond, cond_attr), 0) +versioned_symbol (libc, __pthread_cond_init, pthread_cond_init, GLIBC_2_3_2); + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2) +FORWARD2 (__pthread_cond_signal_2_0, int attribute_compat_text_section, +	  (pthread_cond_2_0_t *cond), (cond), return 0) +compat_symbol (libc, __pthread_cond_signal_2_0, pthread_cond_signal, +	       GLIBC_2_0); +#endif +FORWARD (__pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) +versioned_symbol (libc, __pthread_cond_signal, pthread_cond_signal, +		  GLIBC_2_3_2); + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2) +FORWARD2 (__pthread_cond_wait_2_0, int attribute_compat_text_section, +	  (pthread_cond_2_0_t *cond, pthread_mutex_t *mutex), (cond, mutex), +	  return 0) +compat_symbol (libc, __pthread_cond_wait_2_0, pthread_cond_wait, +	       GLIBC_2_0); +#endif +FORWARD (__pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), +	 (cond, mutex), 0) +versioned_symbol (libc, __pthread_cond_wait, pthread_cond_wait, +		  GLIBC_2_3_2); + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2) +FORWARD2 (__pthread_cond_timedwait_2_0, int attribute_compat_text_section, +	  (pthread_cond_2_0_t *cond, pthread_mutex_t *mutex, +	   const struct timespec *abstime), (cond, mutex, abstime), +	  return 0) +compat_symbol (libc, __pthread_cond_timedwait_2_0, pthread_cond_timedwait, +	       GLIBC_2_0); +#endif +FORWARD (__pthread_cond_timedwait, +	 (pthread_cond_t *cond, pthread_mutex_t *mutex, +	  const struct timespec *abstime), (cond, mutex, abstime), 0) +versioned_symbol (libc, __pthread_cond_timedwait, pthread_cond_timedwait, +		  GLIBC_2_3_2); + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), +	 (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn.  */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit); + + +FORWARD (pthread_getschedparam, +	 (pthread_t target_thread, int *policy, struct sched_param *param), +	 (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, +	 (pthread_t target_thread, int policy, +	  const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, +	 (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), +	 (mutex, mutexattr), 0) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) + + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), +	 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +#define return /* value is void */ +FORWARD2(__pthread_unwind, +	 void attribute_hidden __attribute ((noreturn)) __cleanup_fct_attribute +	 attribute_compat_text_section, +	 (__pthread_unwind_buf_t *buf), (buf), { +		       /* We cannot call abort() here.  */ +		       INTERNAL_SYSCALL_DECL (err); +		       INTERNAL_SYSCALL (kill, err, 1, SIGKILL); +		     }) +#undef return diff --git a/libpthread/nptl/herrno.c b/libpthread/nptl/herrno.c new file mode 100644 index 000000000..6e8339d43 --- /dev/null +++ b/libpthread/nptl/herrno.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1996,97,98,2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <features.h> +#include <netdb.h> +#undef h_errno + +#include <tls.h> + +/* We need to have the error status variable of the resolver +   accessible in the libc.  */ +extern __thread int h_errno; + + +/* When threaded, h_errno may be a per-thread variable.  */ +int * +__h_errno_location (void) +{ +  return &h_errno; +} diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c new file mode 100644 index 000000000..86745af8d --- /dev/null +++ b/libpthread/nptl/init.c @@ -0,0 +1,345 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <limits.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/param.h> +#include <sys/resource.h> +#include <pthreadP.h> +#include <atomic.h> +#include <ldsodefs.h> +#include <tls.h> +#include <fork.h> +#include <version.h> +#include <shlib-compat.h> +#include <smp.h> +#include <lowlevellock.h> + + +#ifndef __NR_set_tid_address +/* XXX For the time being...  Once we can rely on the kernel headers +   having the definition remove these lines.  */ +#if defined __s390__ +# define __NR_set_tid_address	252 +#elif defined __ia64__ +# define __NR_set_tid_address	1233 +#elif defined __i386__ +# define __NR_set_tid_address	258 +#elif defined __x86_64__ +# define __NR_set_tid_address	218 +#elif defined __powerpc__ +# define __NR_set_tid_address	232 +#elif defined __sparc__ +# define __NR_set_tid_address	166 +#else +# error "define __NR_set_tid_address" +#endif +#endif + + +/* Size and alignment of static TLS block.  */ +size_t __static_tls_size; +size_t __static_tls_align_m1; + +/* Version of the library, used in libthread_db to detect mismatches.  */ +static const char nptl_version[] __attribute_used__ = VERSION; + + +#if defined USE_TLS && !defined SHARED +extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); +#endif + + +#ifdef SHARED +static const struct pthread_functions pthread_functions = +  { +    .ptr_pthread_attr_destroy = __pthread_attr_destroy, +# if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +    .ptr___pthread_attr_init_2_0 = __pthread_attr_init_2_0, +# endif +    .ptr___pthread_attr_init_2_1 = __pthread_attr_init_2_1, +    .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate, +    .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate, +    .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched, +    .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched, +    .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam, +    .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam, +    .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy, +    .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy, +    .ptr_pthread_attr_getscope = __pthread_attr_getscope, +    .ptr_pthread_attr_setscope = __pthread_attr_setscope, +    .ptr_pthread_condattr_destroy = __pthread_condattr_destroy, +    .ptr_pthread_condattr_init = __pthread_condattr_init, +    .ptr___pthread_cond_broadcast = __pthread_cond_broadcast, +    .ptr___pthread_cond_destroy = __pthread_cond_destroy, +    .ptr___pthread_cond_init = __pthread_cond_init, +    .ptr___pthread_cond_signal = __pthread_cond_signal, +    .ptr___pthread_cond_wait = __pthread_cond_wait, +    .ptr___pthread_cond_timedwait = __pthread_cond_timedwait, +# if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +    .ptr___pthread_cond_broadcast_2_0 = __pthread_cond_broadcast_2_0, +    .ptr___pthread_cond_destroy_2_0 = __pthread_cond_destroy_2_0, +    .ptr___pthread_cond_init_2_0 = __pthread_cond_init_2_0, +    .ptr___pthread_cond_signal_2_0 = __pthread_cond_signal_2_0, +    .ptr___pthread_cond_wait_2_0 = __pthread_cond_wait_2_0, +    .ptr___pthread_cond_timedwait_2_0 = __pthread_cond_timedwait_2_0, +# endif +    .ptr_pthread_equal = __pthread_equal, +    .ptr___pthread_exit = __pthread_exit, +    .ptr_pthread_getschedparam = __pthread_getschedparam, +    .ptr_pthread_setschedparam = __pthread_setschedparam, +    .ptr_pthread_mutex_destroy = INTUSE(__pthread_mutex_destroy), +    .ptr_pthread_mutex_init = INTUSE(__pthread_mutex_init), +    .ptr_pthread_mutex_lock = INTUSE(__pthread_mutex_lock), +    .ptr_pthread_mutex_unlock = INTUSE(__pthread_mutex_unlock), +    .ptr_pthread_self = __pthread_self, +    .ptr_pthread_setcancelstate = __pthread_setcancelstate, +    .ptr_pthread_setcanceltype = __pthread_setcanceltype, +    .ptr___pthread_cleanup_upto = __pthread_cleanup_upto, +    .ptr___pthread_once = __pthread_once_internal, +    .ptr___pthread_rwlock_rdlock = __pthread_rwlock_rdlock_internal, +    .ptr___pthread_rwlock_wrlock = __pthread_rwlock_wrlock_internal, +    .ptr___pthread_rwlock_unlock = __pthread_rwlock_unlock_internal, +    .ptr___pthread_key_create = __pthread_key_create_internal, +    .ptr___pthread_getspecific = __pthread_getspecific_internal, +    .ptr___pthread_setspecific = __pthread_setspecific_internal, +    .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer, +    .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore, +    .ptr_nthreads = &__nptl_nthreads, +    .ptr___pthread_unwind = &__pthread_unwind, +    .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd, +    .ptr__nptl_setxid = __nptl_setxid +  }; +# define ptr_pthread_functions &pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + + +/* For asynchronous cancellation we use a signal.  This is the handler.  */ +static void +sigcancel_handler (int sig, siginfo_t *si, void *ctx) +{ +  /* Safety check.  It would be possible to call this function for +     other signals and send a signal from another process.  This is not +     correct and might even be a security problem.  Try to catch as +     many incorrect invocations as possible.  */ +  if (sig != SIGCANCEL +#ifdef __ASSUME_CORRECT_SI_PID +      /* Kernels before 2.5.75 stored the thread ID and not the process +	 ID in si_pid so we skip this test.  */ +      || si->si_pid != THREAD_GETMEM (THREAD_SELF, pid) +#endif +      || si->si_code != SI_TKILL) +    return; + +  struct pthread *self = THREAD_SELF; + +  int oldval = THREAD_GETMEM (self, cancelhandling); +  while (1) +    { +      /* We are canceled now.  When canceled by another thread this flag +	 is already set but if the signal is directly send (internally or +	 from another process) is has to be done here.  */ +      int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; + +      if (oldval == newval || (oldval & EXITING_BITMASK) != 0) +	/* Already canceled or exiting.  */ +	break; + +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (curval == oldval) +	{ +	  /* Set the return value.  */ +	  THREAD_SETMEM (self, result, PTHREAD_CANCELED); + +	  /* Make sure asynchronous cancellation is still enabled.  */ +	  if ((newval & CANCELTYPE_BITMASK) != 0) +	    /* Run the registered destructors and terminate the thread.  */ +	    __do_cancel (); + +	  break; +	} + +      oldval = curval; +    } +} + + +struct xid_command *__xidcmd attribute_hidden; + +/* For asynchronous cancellation we use a signal.  This is the handler.  */ +static void +sighandler_setxid (int sig, siginfo_t *si, void *ctx) +{ +  /* Safety check.  It would be possible to call this function for +     other signals and send a signal from another process.  This is not +     correct and might even be a security problem.  Try to catch as +     many incorrect invocations as possible.  */ +  if (sig != SIGSETXID +#ifdef __ASSUME_CORRECT_SI_PID +      /* Kernels before 2.5.75 stored the thread ID and not the process +	 ID in si_pid so we skip this test.  */ +      || si->si_pid != THREAD_GETMEM (THREAD_SELF, pid) +#endif +      || si->si_code != SI_TKILL) +    return; + +  INTERNAL_SYSCALL_DECL (err); +  INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0], +			__xidcmd->id[1], __xidcmd->id[2]); + +  if (atomic_decrement_val (&__xidcmd->cntr) == 0) +    lll_futex_wake (&__xidcmd->cntr, 1); +} + + +/* When using __thread for this, we do it in libc so as not +   to give libpthread its own TLS segment just for this.  */ +extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); + + +void +__pthread_initialize_minimal_internal (void) +{ +#ifndef SHARED +  /* Unlike in the dynamically linked case the dynamic linker has not +     taken care of initializing the TLS data structures.  */ +  __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN); + +  /* We must prevent gcc from being clever and move any of the +     following code ahead of the __libc_setup_tls call.  This function +     will initialize the thread register which is subsequently +     used.  */ +  __asm __volatile (""); +#endif + +  /* Minimal initialization of the thread descriptor.  */ +  struct pthread *pd = THREAD_SELF; +  INTERNAL_SYSCALL_DECL (err); +  pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid); +  THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]); +  THREAD_SETMEM (pd, user_stack, true); +  if (LLL_LOCK_INITIALIZER != 0) +    THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER); +#if HP_TIMING_AVAIL +  THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset)); +#endif + +  /* Set initial thread's stack block from 0 up to __libc_stack_end. +     It will be bigger than it actually is, but for unwind.c/pt-longjmp.c +     purposes this is good enough.  */ +  THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end); + +  /* Initialize the list of all running threads with the main thread.  */ +  INIT_LIST_HEAD (&__stack_user); +  list_add (&pd->list, &__stack_user); + + +  /* Install the cancellation signal handler.  If for some reason we +     cannot install the handler we do not abort.  Maybe we should, but +     it is only asynchronous cancellation which is affected.  */ +  struct sigaction sa; +  sa.sa_sigaction = sigcancel_handler; +  sa.sa_flags = SA_SIGINFO; +  __sigemptyset (&sa.sa_mask); + +  (void) __libc_sigaction (SIGCANCEL, &sa, NULL); + +  /* Install the handle to change the threads' uid/gid.  */ +  sa.sa_sigaction = sighandler_setxid; +  sa.sa_flags = SA_SIGINFO | SA_RESTART; + +  (void) __libc_sigaction (SIGSETXID, &sa, NULL); + +  /* The parent process might have left the signals blocked.  Just in +     case, unblock it.  We reuse the signal mask in the sigaction +     structure.  It is already cleared.  */ +  __sigaddset (&sa.sa_mask, SIGCANCEL); +  __sigaddset (&sa.sa_mask, SIGSETXID); +  (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &sa.sa_mask, +			   NULL, _NSIG / 8); + + +  /* Determine the default allowed stack size.  This is the size used +     in case the user does not specify one.  */ +  struct rlimit limit; +  if (getrlimit (RLIMIT_STACK, &limit) != 0 +      || limit.rlim_cur == RLIM_INFINITY) +    /* The system limit is not usable.  Use an architecture-specific +       default.  */ +    __default_stacksize = ARCH_STACK_DEFAULT_SIZE; +  else if (limit.rlim_cur < PTHREAD_STACK_MIN) +    /* The system limit is unusably small. +       Use the minimal size acceptable.  */ +    __default_stacksize = PTHREAD_STACK_MIN; +  else +    { +      /* Round the resource limit up to page size.  */ +      const uintptr_t pagesz = __sysconf (_SC_PAGESIZE); +      __default_stacksize = (limit.rlim_cur + pagesz - 1) & -pagesz; +    } + +  /* Get the size of the static and alignment requirements for the TLS +     block.  */ +  size_t static_tls_align; +  _dl_get_tls_static_info (&__static_tls_size, &static_tls_align); + +  /* Make sure the size takes all the alignments into account.  */ +  if (STACK_ALIGN > static_tls_align) +    static_tls_align = STACK_ALIGN; +  __static_tls_align_m1 = static_tls_align - 1; + +  __static_tls_size = roundup (__static_tls_size, static_tls_align); + +#ifdef SHARED +  /* Transfer the old value from the dynamic linker's internal location.  */ +  *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); +  GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; + +  /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock, +     keep the lock count from the ld.so implementation.  */ +  GL(dl_rtld_lock_recursive) = (void *) INTUSE (__pthread_mutex_lock); +  GL(dl_rtld_unlock_recursive) = (void *) INTUSE (__pthread_mutex_unlock); +  unsigned int rtld_lock_count = GL(dl_load_lock).mutex.__data.__count; +  GL(dl_load_lock).mutex.__data.__count = 0; +  while (rtld_lock_count-- > 0) +    INTUSE (__pthread_mutex_lock) (&GL(dl_load_lock).mutex); + +  GL(dl_make_stack_executable_hook) = &__make_stacks_executable; +#endif + +  GL(dl_init_static_tls) = &__pthread_init_static_tls; + +  /* Register the fork generation counter with the libc.  */ +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +  __libc_multiple_threads_ptr = +#endif +    __libc_pthread_init (&__fork_generation, __reclaim_stacks, +			 ptr_pthread_functions); + +  /* Determine whether the machine is SMP or not.  */ +  __is_smp = is_smp_system (); +} +strong_alias (__pthread_initialize_minimal_internal, +	      __pthread_initialize_minimal) diff --git a/libpthread/nptl/libc-cancellation.c b/libpthread/nptl/libc-cancellation.c new file mode 100644 index 000000000..c9237e095 --- /dev/null +++ b/libpthread/nptl/libc-cancellation.c @@ -0,0 +1,116 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdlib.h> +#include "pthreadP.h" +#include "atomic.h" +#include <bits/libc-lock.h> + + +#ifndef NOT_IN_libc + +/* The next two functions are similar to pthread_setcanceltype() but +   more specialized for the use in the cancelable functions like write(). +   They do not need to check parameters etc.  */ +int +attribute_hidden +__libc_enable_asynccancel (void) +{ +  struct pthread *self = THREAD_SELF; +  int oldval = THREAD_GETMEM (self, cancelhandling); + +  while (1) +    { +      int newval = oldval | CANCELTYPE_BITMASK; + +      if (__builtin_expect ((oldval & CANCELED_BITMASK) != 0, 0)) +	{ +	  /* If we are already exiting or if PTHREAD_CANCEL_DISABLED, +	     stop right here.  */ +	  if ((oldval & (EXITING_BITMASK | CANCELSTATE_BITMASK)) != 0) +	    break; + +	  int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, +						  newval, oldval); +	  if (__builtin_expect (curval != oldval, 0)) +	    { +	      /* Somebody else modified the word, try again.  */ +	      oldval = curval; +	      continue; +	    } + +	  THREAD_SETMEM (self, result, PTHREAD_CANCELED); + +	  __do_cancel (); + +	  /* NOTREACHED */ +	} + +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	break; + +      /* Prepare the next round.  */ +      oldval = curval; +    } + +  return oldval; +} + + +void +internal_function attribute_hidden +__libc_disable_asynccancel (int oldtype) +{ +  /* If asynchronous cancellation was enabled before we do not have +     anything to do.  */ +  if (oldtype & CANCELTYPE_BITMASK) +    return; + +  struct pthread *self = THREAD_SELF; +  int oldval = THREAD_GETMEM (self, cancelhandling); + +  while (1) +    { +      int newval = oldval & ~CANCELTYPE_BITMASK; + +      if (newval == oldval) +	break; + +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	break; + +      /* Prepare the next round.  */ +      oldval = curval; +    } +} + + +void +__libc_cleanup_routine (struct __pthread_cleanup_frame *f) +{ +  if (f->__do_it) +    f->__cancel_routine (f->__cancel_arg); +} + +#endif diff --git a/libpthread/nptl/old_pthread_atfork.c b/libpthread/nptl/old_pthread_atfork.c new file mode 100644 index 000000000..768e6876c --- /dev/null +++ b/libpthread/nptl/old_pthread_atfork.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <shlib-compat.h> + +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3) +# define __pthread_atfork __dyn_pthread_atfork +# include "pthread_atfork.c" +# undef __pthread_atfork +compat_symbol (libpthread, __dyn_pthread_atfork, pthread_atfork, GLIBC_2_0); +#endif diff --git a/libpthread/nptl/old_pthread_cond_broadcast.c b/libpthread/nptl/old_pthread_cond_broadcast.c new file mode 100644 index 000000000..3852943fa --- /dev/null +++ b/libpthread/nptl/old_pthread_cond_broadcast.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <atomic.h> +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__pthread_cond_broadcast_2_0 (cond) +     pthread_cond_2_0_t *cond; +{ +  if (cond->cond == NULL) +    { +      pthread_cond_t *newcond; + +#if LLL_MUTEX_LOCK_INITIALIZER == 0 +      newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1); +      if (newcond == NULL) +	return ENOMEM; +#else +      newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); +      if (newcond == NULL) +	return ENOMEM; + +      /* Initialize the condvar.  */ +      (void) pthread_cond_init (newcond, NULL); +#endif + +      if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL)) +	/* Somebody else just initialized the condvar.  */ +	free (newcond); +    } + +  return __pthread_cond_broadcast (cond->cond); +} +compat_symbol (libpthread, __pthread_cond_broadcast_2_0, +	       pthread_cond_broadcast, GLIBC_2_0); +#endif diff --git a/libpthread/nptl/old_pthread_cond_destroy.c b/libpthread/nptl/old_pthread_cond_destroy.c new file mode 100644 index 000000000..f6dba1188 --- /dev/null +++ b/libpthread/nptl/old_pthread_cond_destroy.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> +#include "pthreadP.h" +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__pthread_cond_destroy_2_0 (cond) +     pthread_cond_2_0_t *cond; +{ +  /* Free the memory which was eventually allocated.  */ +  free (cond->cond); + +  return 0; +} +compat_symbol (libpthread, __pthread_cond_destroy_2_0, pthread_cond_destroy, +	       GLIBC_2_0); +#endif diff --git a/libpthread/nptl/old_pthread_cond_init.c b/libpthread/nptl/old_pthread_cond_init.c new file mode 100644 index 000000000..47e68b000 --- /dev/null +++ b/libpthread/nptl/old_pthread_cond_init.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__pthread_cond_init_2_0 (cond, cond_attr) +     pthread_cond_2_0_t *cond; +     const pthread_condattr_t *cond_attr; +{ +  struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr; + +  /* The type of the first argument is actually that of the old, too +     small pthread_cond_t.  We use only the first word of it, as a +     pointer.  */ +  cond->cond = NULL; + +  /* We can't support PSHARED condvars in the old pthread_cond_* +     functions and neither clocks other than CLOCK_REALTIME.  */ +  if (icond_attr != NULL && icond_attr->value) +    return EINVAL; + +  return 0; +} +compat_symbol (libpthread, __pthread_cond_init_2_0, pthread_cond_init, +	       GLIBC_2_0); +#endif diff --git a/libpthread/nptl/old_pthread_cond_signal.c b/libpthread/nptl/old_pthread_cond_signal.c new file mode 100644 index 000000000..65beb0b9d --- /dev/null +++ b/libpthread/nptl/old_pthread_cond_signal.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <atomic.h> +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__pthread_cond_signal_2_0 (cond) +     pthread_cond_2_0_t *cond; +{ +  if (cond->cond == NULL) +    { +      pthread_cond_t *newcond; + +#if LLL_MUTEX_LOCK_INITIALIZER == 0 +      newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1); +      if (newcond == NULL) +	return ENOMEM; +#else +      newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); +      if (newcond == NULL) +	return ENOMEM; + +      /* Initialize the condvar.  */ +      (void) pthread_cond_init (newcond, NULL); +#endif + +      if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL)) +	/* Somebody else just initialized the condvar.  */ +	free (newcond); +    } + +  return __pthread_cond_signal (cond->cond); +} +compat_symbol (libpthread, __pthread_cond_signal_2_0, pthread_cond_signal, +	       GLIBC_2_0); +#endif diff --git a/libpthread/nptl/old_pthread_cond_timedwait.c b/libpthread/nptl/old_pthread_cond_timedwait.c new file mode 100644 index 000000000..27c10938d --- /dev/null +++ b/libpthread/nptl/old_pthread_cond_timedwait.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <atomic.h> +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__pthread_cond_timedwait_2_0 (cond, mutex, abstime) +     pthread_cond_2_0_t *cond; +     pthread_mutex_t *mutex; +     const struct timespec *abstime; +{ +  if (cond->cond == NULL) +    { +      pthread_cond_t *newcond; + +#if LLL_MUTEX_LOCK_INITIALIZER == 0 +      newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1); +      if (newcond == NULL) +	return ENOMEM; +#else +      newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); +      if (newcond == NULL) +	return ENOMEM; + +      /* Initialize the condvar.  */ +      (void) pthread_cond_init (newcond, NULL); +#endif + +      if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL)) +	/* Somebody else just initialized the condvar.  */ +	free (newcond); +    } + +  return __pthread_cond_timedwait (cond->cond, mutex, abstime); +} +compat_symbol (libpthread, __pthread_cond_timedwait_2_0, +	       pthread_cond_timedwait, GLIBC_2_0); +#endif diff --git a/libpthread/nptl/old_pthread_cond_wait.c b/libpthread/nptl/old_pthread_cond_wait.c new file mode 100644 index 000000000..0a503a1cd --- /dev/null +++ b/libpthread/nptl/old_pthread_cond_wait.c @@ -0,0 +1,59 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <atomic.h> +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__pthread_cond_wait_2_0 (cond, mutex) +     pthread_cond_2_0_t *cond; +     pthread_mutex_t *mutex; +{ +  if (cond->cond == NULL) +    { +      pthread_cond_t *newcond; + +#if LLL_MUTEX_LOCK_INITIALIZER == 0 +      newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1); +      if (newcond == NULL) +	return ENOMEM; +#else +      newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); +      if (newcond == NULL) +	return ENOMEM; + +      /* Initialize the condvar.  */ +      (void) pthread_cond_init (newcond, NULL); +#endif + +      if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL)) +	/* Somebody else just initialized the condvar.  */ +	free (newcond); +    } + +  return __pthread_cond_wait (cond->cond, mutex); +} +compat_symbol (libpthread, __pthread_cond_wait_2_0, pthread_cond_wait, +	       GLIBC_2_0); +#endif diff --git a/libpthread/nptl/perf.c b/libpthread/nptl/perf.c new file mode 100644 index 000000000..5b920d719 --- /dev/null +++ b/libpthread/nptl/perf.c @@ -0,0 +1,755 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#define _GNU_SOURCE	1 +#include <argp.h> +#include <error.h> +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <limits.h> +#include <pthread.h> +#include <signal.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/param.h> +#include <sys/types.h> + +#ifndef MAX_THREADS +# define MAX_THREADS		100000 +#endif +#ifndef DEFAULT_THREADS +# define DEFAULT_THREADS	50 +#endif + + +#define OPT_TO_THREAD		300 +#define OPT_TO_PROCESS		301 +#define OPT_SYNC_SIGNAL		302 +#define OPT_SYNC_JOIN		303 +#define OPT_TOPLEVEL		304 + + +static const struct argp_option options[] = +  { +    { NULL, 0, NULL, 0, "\ +This is a test for threads so we allow ther user to selection the number of \ +threads which are used at any one time.  Independently the total number of \ +rounds can be selected.  This is the total number of threads which will have \ +run when the process terminates:" }, +    { "threads", 't', "NUMBER", 0, "Number of threads used at once" }, +    { "starts", 's', "NUMBER", 0, "Total number of working threads" }, +    { "toplevel", OPT_TOPLEVEL, "NUMBER", 0, +      "Number of toplevel threads which start the other threads; this \ +implies --sync-join" }, + +    { NULL, 0, NULL, 0, "\ +Each thread can do one of two things: sleep or do work.  The latter is 100% \ +CPU bound.  The work load is the probability a thread does work.  All values \ +from zero to 100 (inclusive) are valid.  How often each thread repeats this \ +can be determined by the number of rounds.  The work cost determines how long \ +each work session (not sleeping) takes.  If it is zero a thread would \ +effectively nothing.  By setting the number of rounds to zero the thread \ +does no work at all and pure thread creation times can be measured." }, +    { "workload", 'w', "PERCENT", 0, "Percentage of time spent working" }, +    { "workcost", 'c', "NUMBER", 0, +      "Factor in the cost of each round of working" }, +    { "rounds", 'r', "NUMBER", 0, "Number of rounds each thread runs" }, + +    { NULL, 0, NULL, 0, "\ +There are a number of different methods how thread creation can be \ +synchronized.  Synchronization is necessary since the number of concurrently \ +running threads is limited." }, +    { "sync-signal", OPT_SYNC_SIGNAL, NULL, 0, +      "Synchronize using a signal (default)" }, +    { "sync-join", OPT_SYNC_JOIN, NULL, 0, "Synchronize using pthread_join" }, + +    { NULL, 0, NULL, 0, "\ +One parameter for each threads execution is the size of the stack.  If this \ +parameter is not used the system's default stack size is used.  If many \ +threads are used the stack size should be chosen quite small." }, +    { "stacksize", 'S', "BYTES", 0, "Size of threads stack" }, +    { "guardsize", 'g', "BYTES", 0, +      "Size of stack guard area; must fit into the stack" }, + +    { NULL, 0, NULL, 0, "Signal options:" }, +    { "to-thread", OPT_TO_THREAD, NULL, 0, "Send signal to main thread" }, +    { "to-process", OPT_TO_PROCESS, NULL, 0, +      "Send signal to process (default)" }, + +    { NULL, 0, NULL, 0, "Administrative options:" }, +    { "progress", 'p', NULL, 0, "Show signs of progress" }, +    { "timing", 'T', NULL, 0, +      "Measure time from startup to the last thread finishing" }, +    { NULL, 0, NULL, 0, NULL } +  }; + +/* Prototype for option handler.  */ +static error_t parse_opt (int key, char *arg, struct argp_state *state); + +/* Data structure to communicate with argp functions.  */ +static struct argp argp = +{ +  options, parse_opt +}; + + +static unsigned long int threads = DEFAULT_THREADS; +static unsigned long int workload = 75; +static unsigned long int workcost = 20; +static unsigned long int rounds = 10; +static long int starts = 5000; +static unsigned long int stacksize; +static long int guardsize = -1; +static bool progress; +static bool timing; +static bool to_thread; +static unsigned long int toplevel = 1; + + +static long int running; +static pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER; + +static pid_t pid; +static pthread_t tmain; + +static clockid_t cl; +static struct timespec start_time; + + +static pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER; +unsigned int sum; + +static enum +  { +    sync_signal, +    sync_join +  } +sync_method; + + +/* We use 64bit values for the times.  */ +typedef unsigned long long int hp_timing_t; + + +/* Attributes for all created threads.  */ +static pthread_attr_t attr; + + +static void * +work (void *arg) +{ +  unsigned long int i; +  unsigned int state = (unsigned long int) arg; + +  for (i = 0; i < rounds; ++i) +    { +      /* Determine what to do.  */ +      unsigned int rnum; + +      /* Uniform distribution.  */ +      do +	rnum = rand_r (&state); +      while (rnum >= UINT_MAX - (UINT_MAX % 100)); + +      rnum %= 100; + +      if (rnum < workload) +	{ +	  int j; +	  int a[4] = { i, rnum, i + rnum, rnum - i }; + +	  if (progress) +	    write (STDERR_FILENO, "c", 1); + +	  for (j = 0; j < workcost; ++j) +	    { +	      a[0] += a[3] >> 12; +	      a[1] += a[2] >> 20; +	      a[2] += a[1] ^ 0x3423423; +	      a[3] += a[0] - a[1]; +	    } + +	  pthread_mutex_lock (&sum_mutex); +	  sum += a[0] + a[1] + a[2] + a[3]; +	  pthread_mutex_unlock (&sum_mutex); +	} +      else +	{ +	  /* Just sleep.  */ +	  struct timespec tv; + +	  tv.tv_sec = 0; +	  tv.tv_nsec = 10000000; + +	  if (progress) +	    write (STDERR_FILENO, "w", 1); + +	  nanosleep (&tv, NULL); +	} +    } + +  return NULL; +} + + +static void * +thread_function (void *arg) +{ +  work (arg); + +  pthread_mutex_lock (&running_mutex); +  if (--running <= 0 && starts <= 0) +    { +      /* We are done.  */ +      if (progress) +	write (STDERR_FILENO, "\n", 1); + +      if (timing) +	{ +	  struct timespec end_time; + +	  if (clock_gettime (cl, &end_time) == 0) +	    { +	      end_time.tv_sec -= start_time.tv_sec; +	      end_time.tv_nsec -= start_time.tv_nsec; +	      if (end_time.tv_nsec < 0) +		{ +		  end_time.tv_nsec += 1000000000; +		  --end_time.tv_sec; +		} + +	      printf ("\nRuntime: %lu.%09lu seconds\n", +		      (unsigned long int) end_time.tv_sec, +		      (unsigned long int) end_time.tv_nsec); +	    } +	} + +      printf ("Result: %08x\n", sum); + +      exit (0); +    } +  pthread_mutex_unlock (&running_mutex); + +  if (sync_method == sync_signal) +    { +      if (to_thread) +	/* This code sends a signal to the main thread.  */ +	pthread_kill (tmain, SIGUSR1); +      else +	/* Use this code to test sending a signal to the process.  */ +	kill (pid, SIGUSR1); +    } + +  if (progress) +    write (STDERR_FILENO, "f", 1); + +  return NULL; +} + + +struct start_info +{ +  unsigned int starts; +  unsigned int threads; +}; + + +static void * +start_threads (void *arg) +{ +  struct start_info *si = arg; +  unsigned int starts = si->starts; +  pthread_t ths[si->threads]; +  unsigned int state = starts; +  unsigned int n; +  unsigned int i = 0; +  int err; + +  if (progress) +    write (STDERR_FILENO, "T", 1); + +  memset (ths, '\0', sizeof (pthread_t) * si->threads); + +  while (starts-- > 0) +    { +      if (ths[i] != 0) +	{ +	  /* Wait for the threads in the order they were created.  */ +	  err = pthread_join (ths[i], NULL); +	  if (err != 0) +	    error (EXIT_FAILURE, err, "cannot join thread"); + +	  if (progress) +	    write (STDERR_FILENO, "f", 1); +	} + +      err = pthread_create (&ths[i], &attr, work, +			    (void *) (long) (rand_r (&state) + starts + i)); + +      if (err != 0) +	error (EXIT_FAILURE, err, "cannot start thread"); + +      if (progress) +	write (STDERR_FILENO, "t", 1); + +      if (++i == si->threads) +	i = 0; +    } + +  n = i; +  do +    { +      if (ths[i] != 0) +	{ +	  err = pthread_join (ths[i], NULL); +	  if (err != 0) +	    error (EXIT_FAILURE, err, "cannot join thread"); + +	  if (progress) +	    write (STDERR_FILENO, "f", 1); +	} + +      if (++i == si->threads) +	i = 0; +    } +  while (i != n); + +  if (progress) +    write (STDERR_FILENO, "F", 1); + +  return NULL; +} + + +int +main (int argc, char *argv[]) +{ +  int remaining; +  sigset_t ss; +  pthread_t th; +  pthread_t *ths = NULL; +  int empty = 0; +  int last; +  bool cont = true; + +  /* Parse and process arguments.  */ +  argp_parse (&argp, argc, argv, 0, &remaining, NULL); + +  if (sync_method == sync_join) +    { +      ths = (pthread_t *) calloc (threads, sizeof (pthread_t)); +      if (ths == NULL) +	error (EXIT_FAILURE, errno, +	       "cannot allocate memory for thread descriptor array"); + +      last = threads; +    } +  else +    { +      ths = &th; +      last = 1; +    } + +  if (toplevel > threads) +    { +      printf ("resetting number of toplevel threads to %lu to not surpass number to concurrent threads\n", +	      threads); +      toplevel = threads; +    } + +  if (timing) +    { +      if (clock_getcpuclockid (0, &cl) != 0 +	  || clock_gettime (cl, &start_time) != 0) +	timing = false; +    } + +  /* We need this later.  */ +  pid = getpid (); +  tmain = pthread_self (); + +  /* We use signal SIGUSR1 for communication between the threads and +     the main thread.  We only want sychronous notification.  */ +  if (sync_method == sync_signal) +    { +      sigemptyset (&ss); +      sigaddset (&ss, SIGUSR1); +      if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0) +	error (EXIT_FAILURE, errno, "cannot set signal mask"); +    } + +  /* Create the thread attributes.  */ +  pthread_attr_init (&attr); + +  /* If the user provided a stack size use it.  */ +  if (stacksize != 0 +      && pthread_attr_setstacksize (&attr, stacksize) != 0) +    puts ("could not set stack size; will use default"); +  /* And stack guard size.  */ +  if (guardsize != -1 +      && pthread_attr_setguardsize (&attr, guardsize) != 0) +    puts ("invalid stack guard size; will use default"); + +  /* All threads are created detached if we are not using pthread_join +     to synchronize.  */ +  if (sync_method != sync_join) +    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + +  if (sync_method == sync_signal) +    { +      while (1) +	{ +	  int err; +	  bool do_wait = false; + +	  pthread_mutex_lock (&running_mutex); +	  if (starts-- < 0) +	    cont = false; +	  else +	    do_wait = ++running >= threads && starts > 0; + +	  pthread_mutex_unlock (&running_mutex); + +	  if (! cont) +	    break; + +	  if (progress) +	    write (STDERR_FILENO, "t", 1); + +	  err = pthread_create (&ths[empty], &attr, thread_function, +				(void *) starts); +	  if (err != 0) +	    error (EXIT_FAILURE, err, "cannot start thread %lu", starts); + +	  if (++empty == last) +	    empty = 0; + +	  if (do_wait) +	    sigwaitinfo (&ss, NULL); +	} + +      /* Do nothing anymore.  On of the threads will terminate the program.  */ +      sigfillset (&ss); +      sigdelset (&ss, SIGINT); +      while (1) +	sigsuspend (&ss); +    } +  else +    { +      pthread_t ths[toplevel]; +      struct start_info si[toplevel]; +      unsigned int i; + +      for (i = 0; i < toplevel; ++i) +	{ +	  unsigned int child_starts = starts / (toplevel - i); +	  unsigned int child_threads = threads / (toplevel - i); +	  int err; + +	  si[i].starts = child_starts; +	  si[i].threads = child_threads; + +	  err = pthread_create (&ths[i], &attr, start_threads, &si[i]); +	  if (err != 0) +	    error (EXIT_FAILURE, err, "cannot start thread"); + +	  starts -= child_starts; +	  threads -= child_threads; +	} + +      for (i = 0; i < toplevel; ++i) +	{ +	  int err = pthread_join (ths[i], NULL); + +	  if (err != 0) +	    error (EXIT_FAILURE, err, "cannot join thread"); +	} + +      /* We are done.  */ +      if (progress) +	write (STDERR_FILENO, "\n", 1); + +      if (timing) +	{ +	  struct timespec end_time; + +	  if (clock_gettime (cl, &end_time) == 0) +	    { +	      end_time.tv_sec -= start_time.tv_sec; +	      end_time.tv_nsec -= start_time.tv_nsec; +	      if (end_time.tv_nsec < 0) +		{ +		  end_time.tv_nsec += 1000000000; +		  --end_time.tv_sec; +		} + +	      printf ("\nRuntime: %lu.%09lu seconds\n", +		      (unsigned long int) end_time.tv_sec, +		      (unsigned long int) end_time.tv_nsec); +	    } +	} + +      printf ("Result: %08x\n", sum); + +      exit (0); +    } + +  /* NOTREACHED */ +  return 0; +} + + +/* Handle program arguments.  */ +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ +  unsigned long int num; +  long int snum; + +  switch (key) +    { +    case 't': +      num = strtoul (arg, NULL, 0); +      if (num <= MAX_THREADS) +	threads = num; +      else +	printf ("\ +number of threads limited to %u; recompile with a higher limit if necessary", +		MAX_THREADS); +      break; + +    case 'w': +      num = strtoul (arg, NULL, 0); +      if (num <= 100) +	workload = num; +      else +	puts ("workload must be between 0 and 100 percent"); +      break; + +    case 'c': +      workcost = strtoul (arg, NULL, 0); +      break; + +    case 'r': +      rounds = strtoul (arg, NULL, 0); +      break; + +    case 's': +      starts = strtoul (arg, NULL, 0); +      break; + +    case 'S': +      num = strtoul (arg, NULL, 0); +      if (num >= PTHREAD_STACK_MIN) +	stacksize = num; +      else +	printf ("minimum stack size is %d\n", PTHREAD_STACK_MIN); +      break; + +    case 'g': +      snum = strtol (arg, NULL, 0); +      if (snum < 0) +	printf ("invalid guard size %s\n", arg); +      else +	guardsize = snum; +      break; + +    case 'p': +      progress = true; +      break; + +    case 'T': +      timing = true; +      break; + +    case OPT_TO_THREAD: +      to_thread = true; +      break; + +    case OPT_TO_PROCESS: +      to_thread = false; +      break; + +    case OPT_SYNC_SIGNAL: +      sync_method = sync_signal; +      break; + +    case OPT_SYNC_JOIN: +      sync_method = sync_join; +      break; + +    case OPT_TOPLEVEL: +      num = strtoul (arg, NULL, 0); +      if (num < MAX_THREADS) +	toplevel = num; +      else +	printf ("\ +number of threads limited to %u; recompile with a higher limit if necessary", +		MAX_THREADS); +      sync_method = sync_join; +      break; + +    default: +      return ARGP_ERR_UNKNOWN; +    } + +  return 0; +} + + +static hp_timing_t +get_clockfreq (void) +{ +  /* We read the information from the /proc filesystem.  It contains at +     least one line like +	cpu MHz         : 497.840237 +     or also +	cpu MHz         : 497.841 +     We search for this line and convert the number in an integer.  */ +  static hp_timing_t result; +  int fd; + +  /* If this function was called before, we know the result.  */ +  if (result != 0) +    return result; + +  fd = open ("/proc/cpuinfo", O_RDONLY); +  if (__builtin_expect (fd != -1, 1)) +    { +      /* XXX AFAIK the /proc filesystem can generate "files" only up +         to a size of 4096 bytes.  */ +      char buf[4096]; +      ssize_t n; + +      n = read (fd, buf, sizeof buf); +      if (__builtin_expect (n, 1) > 0) +	{ +	  char *mhz = memmem (buf, n, "cpu MHz", 7); + +	  if (__builtin_expect (mhz != NULL, 1)) +	    { +	      char *endp = buf + n; +	      int seen_decpoint = 0; +	      int ndigits = 0; + +	      /* Search for the beginning of the string.  */ +	      while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') +		++mhz; + +	      while (mhz < endp && *mhz != '\n') +		{ +		  if (*mhz >= '0' && *mhz <= '9') +		    { +		      result *= 10; +		      result += *mhz - '0'; +		      if (seen_decpoint) +			++ndigits; +		    } +		  else if (*mhz == '.') +		    seen_decpoint = 1; + +		  ++mhz; +		} + +	      /* Compensate for missing digits at the end.  */ +	      while (ndigits++ < 6) +		result *= 10; +	    } +	} + +      close (fd); +    } + +  return result; +} + + +int +clock_getcpuclockid (pid_t pid, clockid_t *clock_id) +{ +  /* We don't allow any process ID but our own.  */ +  if (pid != 0 && pid != getpid ()) +    return EPERM; + +#ifdef CLOCK_PROCESS_CPUTIME_ID +  /* Store the number.  */ +  *clock_id = CLOCK_PROCESS_CPUTIME_ID; + +  return 0; +#else +  /* We don't have a timer for that.  */ +  return ENOENT; +#endif +} + + +#ifdef i386 +#define HP_TIMING_NOW(Var)	__asm__ __volatile__ ("rdtsc" : "=A" (Var)) +#elif defined __ia64__ +#define HP_TIMING_NOW(Var)	__asm__ __volatile__ ("mov %0=ar.itc" : "=r" (Var) : : "memory") +#else +#error "HP_TIMING_NOW missing" +#endif + +/* Get current value of CLOCK and store it in TP.  */ +int +clock_gettime (clockid_t clock_id, struct timespec *tp) +{ +  int retval = -1; + +  switch (clock_id) +    { +    case CLOCK_PROCESS_CPUTIME_ID: +      { + +	static hp_timing_t freq; +	hp_timing_t tsc; + +	/* Get the current counter.  */ +	HP_TIMING_NOW (tsc); + +	if (freq == 0) +	  { +	    freq = get_clockfreq (); +	    if (freq == 0) +	      return EINVAL; +	  } + +	/* Compute the seconds.  */ +	tp->tv_sec = tsc / freq; + +	/* And the nanoseconds.  This computation should be stable until +	   we get machines with about 16GHz frequency.  */ +	tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; + +	retval = 0; +      } +    break; + +    default: +      errno = EINVAL; +      break; +    } + +  return retval; +} diff --git a/libpthread/nptl/pt-allocrtsig.c b/libpthread/nptl/pt-allocrtsig.c new file mode 100644 index 000000000..347bf139a --- /dev/null +++ b/libpthread/nptl/pt-allocrtsig.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <signal.h> + + +/* These are defined in libc.  We want to have only one definition +   so we "forward" the calls.  */ +extern int __libc_current_sigrtmin_private (void); +extern int __libc_current_sigrtmax_private (void); +extern int __libc_allocate_rtsig_private (int high); + + +/* We reserve __SIGRTMIN for use as the cancellation signal and +   __SIGRTMIN+1 to handle setuid et.al.  These signals are used +   internally.  */ +int +__libc_current_sigrtmin (void) +{ +  return __libc_current_sigrtmin_private (); +} + + +int +__libc_current_sigrtmax (void) +{ +  return __libc_current_sigrtmax_private (); +} + + +int +__libc_allocate_rtsig (int high) +{ +  return __libc_allocate_rtsig_private (high); +} diff --git a/libpthread/nptl/pt-cleanup.c b/libpthread/nptl/pt-cleanup.c new file mode 100644 index 000000000..96836a14a --- /dev/null +++ b/libpthread/nptl/pt-cleanup.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdlib.h> +#include "pthreadP.h" +#include "jmpbuf-unwind.h" + +void +__pthread_cleanup_upto (__jmp_buf target, char *targetframe) +{ +  struct pthread *self = THREAD_SELF; +  struct _pthread_cleanup_buffer *cbuf; + +  /* Adjust all pointers used in comparisons, so that top of thread's +     stack is at the top of address space.  Without that, things break +     if stack is allocated above the main stack.  */ +  uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size; +  uintptr_t targetframe_adj = (uintptr_t) targetframe - adj; + +  for (cbuf = THREAD_GETMEM (self, cleanup); +       cbuf != NULL && _JMPBUF_UNWINDS_ADJ (target, cbuf, adj); +       cbuf = cbuf->__prev) +    { +#if _STACK_GROWS_DOWN +      if ((uintptr_t) cbuf - adj <= targetframe_adj) +        { +          cbuf = NULL; +          break; +        } +#elif _STACK_GROWS_UP +      if ((uintptr_t) cbuf - adj >= targetframe_adj) +        { +          cbuf = NULL; +          break; +        } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + +      /* Call the cleanup code.  */ +      cbuf->__routine (cbuf->__arg); +    } + +  THREAD_SETMEM (self, cleanup, cbuf); +} +hidden_def (__pthread_cleanup_upto) + diff --git a/libpthread/nptl/pt-system.c b/libpthread/nptl/pt-system.c new file mode 100644 index 000000000..b3b45ab93 --- /dev/null +++ b/libpthread/nptl/pt-system.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include "pthreadP.h" + + +int +system (const char *line) +{ +  return __libc_system (line); +} + +/* __libc_system in libc.so handles cancellation.  */ +LIBC_CANCEL_HANDLED (); diff --git a/libpthread/nptl/pthread-errnos.sym b/libpthread/nptl/pthread-errnos.sym new file mode 100644 index 000000000..2bb4d0d3c --- /dev/null +++ b/libpthread/nptl/pthread-errnos.sym @@ -0,0 +1,12 @@ +#include <errno.h> + +-- These errno codes are used by some assembly code. + +EAGAIN		EAGAIN +EBUSY		EBUSY +EDEADLK		EDEADLK +EINTR		EINTR +EINVAL		EINVAL +ENOSYS		ENOSYS +ETIMEDOUT	ETIMEDOUT +EWOULDBLOCK	EWOULDBLOCK diff --git a/libpthread/nptl/pthreadP.h b/libpthread/nptl/pthreadP.h new file mode 100644 index 000000000..24168146f --- /dev/null +++ b/libpthread/nptl/pthreadP.h @@ -0,0 +1,466 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _PTHREADP_H +#define _PTHREADP_H	1 + +#include <pthread.h> +#include <setjmp.h> +#include <stdbool.h> +#include <sys/syscall.h> +#include "descr.h" +#include <tls.h> +#include <lowlevellock.h> +#include <stackinfo.h> +#include <internaltypes.h> +#include <pthread-functions.h> +#include <atomic.h> + + +/* Atomic operations on TLS memory.  */ +#ifndef THREAD_ATOMIC_CMPXCHG_VAL +# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, new, old) \ +  atomic_compare_and_exchange_val_acq (&(descr)->member, new, old) +#endif + +#ifndef THREAD_ATOMIC_BIT_SET +# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ +  atomic_bit_set (&(descr)->member, bit) +#endif + + +/* Adaptive mutex definitions.  */ +#ifndef MAX_ADAPTIVE_COUNT +# define MAX_ADAPTIVE_COUNT 100 +#endif + + +/* Internal variables.  */ + + +/* Default stack size.  */ +extern size_t __default_stacksize attribute_hidden; + +/* Size and alignment of static TLS block.  */ +extern size_t __static_tls_size attribute_hidden; +extern size_t __static_tls_align_m1 attribute_hidden; + +/* Flag whether the machine is SMP or not.  */ +extern int __is_smp attribute_hidden; + +/* Thread descriptor handling.  */ +extern list_t __stack_user; +hidden_proto (__stack_user) + +/* Attribute handling.  */ +extern struct pthread_attr *__attr_list attribute_hidden; +extern lll_lock_t __attr_list_lock attribute_hidden; + +/* First available RT signal.  */ +extern int __current_sigrtmin attribute_hidden; +/* Last available RT signal.  */ +extern int __current_sigrtmax attribute_hidden; + +/* Concurrency handling.  */ +extern int __concurrency_level attribute_hidden; + +/* Thread-local data key handling.  */ +extern struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX]; +hidden_proto (__pthread_keys) + +/* Number of threads running.  */ +extern unsigned int __nptl_nthreads attribute_hidden; + +/* The library can run in debugging mode where it performs a lot more +   tests.  */ +extern int __pthread_debug attribute_hidden; +/** For now disable debugging support.  */ +#if 0 +# define DEBUGGING_P __builtin_expect (__pthread_debug, 0) +# define INVALID_TD_P(pd) (DEBUGGING_P && __find_in_stack_list (pd) == NULL) +# define INVALID_NOT_TERMINATED_TD_P(pd) INVALID_TD_P (pd) +#else +# define DEBUGGING_P 0 +/* Simplified test.  This will not catch all invalid descriptors but +   is better than nothing.  And if the test triggers the thread +   descriptor is guaranteed to be invalid.  */ +# define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0) +# define INVALID_NOT_TERMINATED_TD_P(pd) __builtin_expect ((pd)->tid < 0, 0) +#endif + + +/* Cancellation test.  */ +#define CANCELLATION_P(self) \ +  do {									      \ +    int cancelhandling = THREAD_GETMEM (self, cancelhandling);		      \ +    if (CANCEL_ENABLED_AND_CANCELED (cancelhandling))			      \ +      {									      \ +	THREAD_SETMEM (self, result, PTHREAD_CANCELED);			      \ +	__do_cancel ();							      \ +      }									      \ +  } while (0) + + +extern void __pthread_unwind (__pthread_unwind_buf_t *__buf) +     __cleanup_fct_attribute __attribute ((__noreturn__)) +#if !defined SHARED && !defined IS_IN_libpthread +     weak_function +#endif +     ; +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) +     __cleanup_fct_attribute __attribute ((__noreturn__)) +#ifndef SHARED +     weak_function +#endif +     ; +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) +     __cleanup_fct_attribute; +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) +     __cleanup_fct_attribute; +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (__pthread_unwind) +hidden_proto (__pthread_unwind_next) +hidden_proto (__pthread_register_cancel) +hidden_proto (__pthread_unregister_cancel) +# ifdef SHARED +extern void attribute_hidden pthread_cancel_init (void); +# endif +#endif + + +/* Called when a thread reacts on a cancellation request.  */ +static inline void +__attribute ((noreturn, always_inline)) +__do_cancel (void) +{ +  struct pthread *self = THREAD_SELF; + +  /* Make sure we get no more cancellations.  */ +  THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT); + +  __pthread_unwind ((__pthread_unwind_buf_t *) +		    THREAD_GETMEM (self, cleanup_jmp_buf)); +} + + +/* Set cancellation mode to asynchronous.  */ +#define CANCEL_ASYNC() \ +  __pthread_enable_asynccancel () +/* Reset to previous cancellation mode.  */ +#define CANCEL_RESET(oldtype) \ +  __pthread_disable_asynccancel (oldtype) + +#if !defined NOT_IN_libc +/* Same as CANCEL_ASYNC, but for use in libc.so.  */ +# define LIBC_CANCEL_ASYNC() \ +  __libc_enable_asynccancel () +/* Same as CANCEL_RESET, but for use in libc.so.  */ +# define LIBC_CANCEL_RESET(oldtype) \ +  __libc_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ +  __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \ +  __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel") +#elif defined NOT_IN_libc && defined IS_IN_libpthread +# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC () +# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val) +# define LIBC_CANCEL_HANDLED() \ +  __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \ +  __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel") +#elif defined NOT_IN_libc && defined IS_IN_librt +# define LIBC_CANCEL_ASYNC() \ +  __librt_enable_asynccancel () +# define LIBC_CANCEL_RESET(val) \ +  __librt_disable_asynccancel (val) +# define LIBC_CANCEL_HANDLED() \ +  __asm (".globl " __SYMBOL_PREFIX "__librt_enable_asynccancel"); \ +  __asm (".globl " __SYMBOL_PREFIX "__librt_disable_asynccancel") +#else +# define LIBC_CANCEL_ASYNC()	0 /* Just a dummy value.  */ +# define LIBC_CANCEL_RESET(val)	((void)(val)) /* Nothing, but evaluate it.  */ +# define LIBC_CANCEL_HANDLED()	/* Nothing.  */ +#endif + +/* The signal used for asynchronous cancelation.  */ +#define SIGCANCEL	__SIGRTMIN + + +/* Signal needed for the kernel-supported POSIX timer implementation. +   We can reuse the cancellation signal since we can distinguish +   cancellation from timer expirations.  */ +#define SIGTIMER	SIGCANCEL + + +/* Signal used to implement the setuid et.al. functions.  */ +#define SIGSETXID	(__SIGRTMIN + 1) + +/* Used to communicate with signal handler.  */ +extern struct xid_command *__xidcmd attribute_hidden; + + +/* Internal prototypes.  */ + +/* Thread list handling.  */ +extern struct pthread *__find_in_stack_list (struct pthread *pd) +     attribute_hidden internal_function; + +/* Deallocate a thread's stack after optionally making sure the thread +   descriptor is still valid.  */ +extern void __free_tcb (struct pthread *pd) attribute_hidden internal_function; + +/* Free allocated stack.  */ +extern void __deallocate_stack (struct pthread *pd) +     attribute_hidden internal_function; + +/* Mark all the stacks except for the current one as available.  This +   function also re-initializes the lock for the stack cache.  */ +extern void __reclaim_stacks (void) attribute_hidden; + +/* Make all threads's stacks executable.  */ +extern int __make_stacks_executable (void **stack_endp) +     internal_function attribute_hidden; + +/* longjmp handling.  */ +extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe); +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (__pthread_cleanup_upto) +#endif + + +/* Functions with versioned interfaces.  */ +extern int __pthread_create_2_1 (pthread_t *newthread, +				 const pthread_attr_t *attr, +				 void *(*start_routine) (void *), void *arg); +extern int __pthread_create_2_0 (pthread_t *newthread, +				 const pthread_attr_t *attr, +				 void *(*start_routine) (void *), void *arg); +extern int __pthread_attr_init_2_1 (pthread_attr_t *attr); +extern int __pthread_attr_init_2_0 (pthread_attr_t *attr); + + +/* Event handlers for libthread_db interface.  */ +extern void __nptl_create_event (void); +extern void __nptl_death_event (void); +hidden_proto (__nptl_create_event) +hidden_proto (__nptl_death_event) + +/* Register the generation counter in the libpthread with the libc.  */ +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +extern void __libc_pthread_init (unsigned long int *ptr, +				 void (*reclaim) (void), +				 const struct pthread_functions *functions) +     internal_function; +#else +extern int *__libc_pthread_init (unsigned long int *ptr, +				 void (*reclaim) (void), +				 const struct pthread_functions *functions) +     internal_function; + +/* Variable set to a nonzero value if more than one thread runs or ran.  */ +extern int __pthread_multiple_threads attribute_hidden; +/* Pointer to the corresponding variable in libc.  */ +extern int *__libc_multiple_threads_ptr attribute_hidden; +#endif + +/* Find a thread given its TID.  */ +extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden +#ifdef SHARED +; +#else +weak_function; +#define __find_thread_by_id(tid) \ +  (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL) +#endif + +extern void __pthread_init_static_tls (struct link_map *) attribute_hidden; + + +/* Namespace save aliases.  */ +extern int __pthread_getschedparam (pthread_t thread_id, int *policy, +				    struct sched_param *param); +extern int __pthread_setschedparam (pthread_t thread_id, int policy, +				    const struct sched_param *param); +extern int __pthread_setcancelstate (int state, int *oldstate); +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, +				 __const pthread_mutexattr_t *__mutexattr); +extern int __pthread_mutex_init_internal (pthread_mutex_t *__mutex, +					  __const pthread_mutexattr_t *__mutexattr) +     attribute_hidden; +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int __pthread_mutex_destroy_internal (pthread_mutex_t *__mutex) +     attribute_hidden; +extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex); +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_lock_internal (pthread_mutex_t *__mutex) +     attribute_hidden; +extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex) +     attribute_hidden internal_function; +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock_internal (pthread_mutex_t *__mutex) +     attribute_hidden; +extern int __pthread_mutex_unlock_usercnt (pthread_mutex_t *__mutex, +					   int __decr) +     attribute_hidden internal_function; +extern int __pthread_mutexattr_init (pthread_mutexattr_t *attr); +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *attr); +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind); +extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, +					  int *detachstate); +extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, +					  int detachstate); +extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr, +					   int *inherit); +extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit); +extern int __pthread_attr_getschedparam (const pthread_attr_t *attr, +					 struct sched_param *param); +extern int __pthread_attr_setschedparam (pthread_attr_t *attr, +					 const struct sched_param *param); +extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr, +					  int *policy); +extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy); +extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope); +extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope); +extern int __pthread_attr_getstackaddr (__const pthread_attr_t *__restrict +					__attr, void **__restrict __stackaddr); +extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr, +					void *__stackaddr); +extern int __pthread_attr_getstacksize (__const pthread_attr_t *__restrict +					__attr, +					size_t *__restrict __stacksize); +extern int __pthread_attr_setstacksize (pthread_attr_t *__attr, +					size_t __stacksize); +extern int __pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, +				    void **__restrict __stackaddr, +				    size_t *__restrict __stacksize); +extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, +				    size_t __stacksize); +extern int __pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, +				  __const pthread_rwlockattr_t *__restrict +				  __attr); +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_rdlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_wrlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_unlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_cond_broadcast (pthread_cond_t *cond); +extern int __pthread_cond_destroy (pthread_cond_t *cond); +extern int __pthread_cond_init (pthread_cond_t *cond, +				const pthread_condattr_t *cond_attr); +extern int __pthread_cond_signal (pthread_cond_t *cond); +extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int __pthread_cond_timedwait (pthread_cond_t *cond, +				     pthread_mutex_t *mutex, +				     const struct timespec *abstime); +extern int __pthread_condattr_destroy (pthread_condattr_t *attr); +extern int __pthread_condattr_init (pthread_condattr_t *attr); +extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *)); +extern int __pthread_key_create_internal (pthread_key_t *key, +					  void (*destr) (void *)); +extern void *__pthread_getspecific (pthread_key_t key); +extern void *__pthread_getspecific_internal (pthread_key_t key); +extern int __pthread_setspecific (pthread_key_t key, const void *value); +extern int __pthread_setspecific_internal (pthread_key_t key, +					   const void *value); +extern int __pthread_once (pthread_once_t *once_control, +			   void (*init_routine) (void)); +extern int __pthread_once_internal (pthread_once_t *once_control, +				    void (*init_routine) (void)); +extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void), +			     void (*child) (void)); +extern pthread_t __pthread_self (void); +extern int __pthread_equal (pthread_t thread1, pthread_t thread2); +extern int __pthread_kill (pthread_t threadid, int signo); +extern void __pthread_exit (void *value); +extern int __pthread_setcanceltype (int type, int *oldtype); +extern int __pthread_enable_asynccancel (void) attribute_hidden; +extern void __pthread_disable_asynccancel (int oldtype) +     internal_function attribute_hidden; + +extern int __pthread_cond_broadcast_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_destroy_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_init_2_0 (pthread_cond_2_0_t *cond, +				    const pthread_condattr_t *cond_attr); +extern int __pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_timedwait_2_0 (pthread_cond_2_0_t *cond, +					 pthread_mutex_t *mutex, +					 const struct timespec *abstime); +extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond, +				    pthread_mutex_t *mutex); + +extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize, +				     cpu_set_t *cpuset); + +/* The two functions are in libc.so and not exported.  */ +extern int __libc_enable_asynccancel (void) attribute_hidden; +extern void __libc_disable_asynccancel (int oldtype) +     internal_function attribute_hidden; + + +/* The two functions are in librt.so and not exported.  */ +extern int __librt_enable_asynccancel (void) attribute_hidden; +extern void __librt_disable_asynccancel (int oldtype) +     internal_function attribute_hidden; + +#ifdef IS_IN_libpthread +/* Special versions which use non-exported functions.  */ +extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, +				    void (*routine) (void *), void *arg) +     attribute_hidden; +# undef pthread_cleanup_push +# define pthread_cleanup_push(routine,arg) \ +  { struct _pthread_cleanup_buffer _buffer;				      \ +    __pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, +				   int execute) attribute_hidden; +# undef pthread_cleanup_pop +# define pthread_cleanup_pop(execute) \ +    __pthread_cleanup_pop (&_buffer, (execute)); } +#endif + +extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, +					  void (*routine) (void *), void *arg); +extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, +					   int execute); + +/* Old cleanup interfaces, still used in libc.so.  */ +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, +                                   void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, +                                  int execute); +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, +                                         void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, +                                          int execute); + +extern void __nptl_deallocate_tsd (void) attribute_hidden; + +extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden; + +#ifdef SHARED +# define PTHREAD_STATIC_FN_REQUIRE(name) +#else +# define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name); +#endif + +#endif	/* pthreadP.h */ diff --git a/libpthread/nptl/pthread_atfork.c b/libpthread/nptl/pthread_atfork.c new file mode 100644 index 000000000..6437d6490 --- /dev/null +++ b/libpthread/nptl/pthread_atfork.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   In addition to the permissions in the GNU Lesser General Public +   License, the Free Software Foundation gives you unlimited +   permission to link the compiled version of this file with other +   programs, and to distribute those programs without any restriction +   coming from the use of this file. (The GNU Lesser General Public +   License restrictions do apply in other respects; for example, they +   cover modification of the file, and distribution when not linked +   into another program.) + +   Note that people who make modified versions of this file are not +   obligated to grant this special exception for their modified +   versions; it is their choice whether to do so. The GNU Lesser +   General Public License gives permission to release a modified +   version without this exception; this exception also makes it +   possible to release a modified version which carries forward this +   exception. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" +#include <fork.h> + +/* This is defined by newer gcc version unique for each module.  */ +extern void *__dso_handle __attribute__ ((__weak__)); + + +/* Hide the symbol so that no definition but the one locally in the +   executable or DSO is used.  */ +int +#ifndef __pthread_atfork +/* Don't mark the compatibility function as hidden.  */ +attribute_hidden +#endif +__pthread_atfork (prepare, parent, child) +     void (*prepare) (void); +     void (*parent) (void); +     void (*child) (void); +{ +  return __register_atfork (prepare, parent, child, +			    &__dso_handle == NULL ? NULL : __dso_handle); +} +#ifndef __pthread_atfork +extern int pthread_atfork (void (*prepare) (void), void (*parent) (void), +			   void (*child) (void)) attribute_hidden; +strong_alias (__pthread_atfork, pthread_atfork) +#endif diff --git a/libpthread/nptl/pthread_attr_destroy.c b/libpthread/nptl/pthread_attr_destroy.c new file mode 100644 index 000000000..b8d9a20d3 --- /dev/null +++ b/libpthread/nptl/pthread_attr_destroy.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include "pthreadP.h" +#include <shlib-compat.h> + +int +__pthread_attr_destroy (attr) +     pthread_attr_t *attr; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +  /* In old struct pthread_attr, neither next nor cpuset are +     present.  */ +  if (__builtin_expect ((iattr->flags & ATTR_FLAG_OLDATTR), 0) == 0) +#endif +    /* The affinity CPU set might be allocated dynamically.  */ +    free (iattr->cpuset); + +  return 0; +} +strong_alias (__pthread_attr_destroy, pthread_attr_destroy) diff --git a/libpthread/nptl/pthread_attr_getdetachstate.c b/libpthread/nptl/pthread_attr_getdetachstate.c new file mode 100644 index 000000000..502cfa4f1 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getdetachstate.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getdetachstate (attr, detachstate) +     const pthread_attr_t *attr; +     int *detachstate; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  *detachstate = (iattr->flags & ATTR_FLAG_DETACHSTATE +		  ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + +  return 0; +} +strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate) diff --git a/libpthread/nptl/pthread_attr_getguardsize.c b/libpthread/nptl/pthread_attr_getguardsize.c new file mode 100644 index 000000000..e1d0ed624 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getguardsize.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +pthread_attr_getguardsize (attr, guardsize) +     const pthread_attr_t *attr; +     size_t *guardsize; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  *guardsize = iattr->guardsize; + +  return 0; +} diff --git a/libpthread/nptl/pthread_attr_getinheritsched.c b/libpthread/nptl/pthread_attr_getinheritsched.c new file mode 100644 index 000000000..f47bf7147 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getinheritsched.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getinheritsched (attr, inherit) +     const pthread_attr_t *attr; +     int *inherit; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Store the current values.  */ +  *inherit = (iattr->flags & ATTR_FLAG_NOTINHERITSCHED +	      ? PTHREAD_EXPLICIT_SCHED : PTHREAD_INHERIT_SCHED); + +  return 0; +} +strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched) diff --git a/libpthread/nptl/pthread_attr_getschedparam.c b/libpthread/nptl/pthread_attr_getschedparam.c new file mode 100644 index 000000000..0ff0c0c4f --- /dev/null +++ b/libpthread/nptl/pthread_attr_getschedparam.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <string.h> +#include "pthreadP.h" + + +int +__pthread_attr_getschedparam (attr, param) +     const pthread_attr_t *attr; +     struct sched_param *param; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Copy the current values.  */ +  memcpy (param, &iattr->schedparam, sizeof (struct sched_param)); + +  return 0; +} +strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam) diff --git a/libpthread/nptl/pthread_attr_getschedpolicy.c b/libpthread/nptl/pthread_attr_getschedpolicy.c new file mode 100644 index 000000000..8364f3be0 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getschedpolicy.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getschedpolicy (attr, policy) +     const pthread_attr_t *attr; +     int *policy; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Store the current values.  */ +  *policy = iattr->schedpolicy; + +  return 0; +} +strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy) diff --git a/libpthread/nptl/pthread_attr_getscope.c b/libpthread/nptl/pthread_attr_getscope.c new file mode 100644 index 000000000..b6aa5a213 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getscope.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getscope (attr, scope) +     const pthread_attr_t *attr; +     int *scope; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Store the current values.  */ +  *scope = (iattr->flags & ATTR_FLAG_SCOPEPROCESS +	      ? PTHREAD_SCOPE_PROCESS : PTHREAD_SCOPE_SYSTEM); + +  return 0; +} +strong_alias (__pthread_attr_getscope, pthread_attr_getscope) diff --git a/libpthread/nptl/pthread_attr_getstack.c b/libpthread/nptl/pthread_attr_getstack.c new file mode 100644 index 000000000..1db135e5c --- /dev/null +++ b/libpthread/nptl/pthread_attr_getstack.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getstack (attr, stackaddr, stacksize) +     const pthread_attr_t *attr; +     void **stackaddr; +     size_t *stacksize; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Store the result.  */ +  *stackaddr = (char *) iattr->stackaddr - iattr->stacksize; +  *stacksize = iattr->stacksize; + +  return 0; +} +strong_alias (__pthread_attr_getstack, pthread_attr_getstack) diff --git a/libpthread/nptl/pthread_attr_getstackaddr.c b/libpthread/nptl/pthread_attr_getstackaddr.c new file mode 100644 index 000000000..7656600dd --- /dev/null +++ b/libpthread/nptl/pthread_attr_getstackaddr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_getstackaddr (attr, stackaddr) +     const pthread_attr_t *attr; +     void **stackaddr; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Some code assumes this function to work even if no stack address +     has been set.  Let them figure it out for themselves what the +     value means.  Simply store the result.  */ +  *stackaddr = iattr->stackaddr; + +  return 0; +} +strong_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) + +link_warning (pthread_attr_getstackaddr, +              "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'") diff --git a/libpthread/nptl/pthread_attr_getstacksize.c b/libpthread/nptl/pthread_attr_getstacksize.c new file mode 100644 index 000000000..d4ff54f38 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getstacksize.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getstacksize (attr, stacksize) +     const pthread_attr_t *attr; +     size_t *stacksize; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* If the user has not set a stack size we return what the system +     will use as the default.  */ +  *stacksize = iattr->stacksize ?: __default_stacksize; + +  return 0; +} +strong_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) diff --git a/libpthread/nptl/pthread_attr_init.c b/libpthread/nptl/pthread_attr_init.c new file mode 100644 index 000000000..c84b33f31 --- /dev/null +++ b/libpthread/nptl/pthread_attr_init.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include "pthreadP.h" + +#include <shlib-compat.h> + + +struct pthread_attr *__attr_list; +lll_lock_t __attr_list_lock = LLL_LOCK_INITIALIZER; + + +int +__pthread_attr_init_2_1 (attr) +     pthread_attr_t *attr; +{ +  struct pthread_attr *iattr; + +  /* Many elements are initialized to zero so let us do it all at +     once.  This also takes care of clearing the bytes which are not +     internally used.  */ +  memset (attr, '\0', __SIZEOF_PTHREAD_ATTR_T); + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Default guard size specified by the standard.  */ +  iattr->guardsize = __getpagesize (); + +  return 0; +} +versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init, +		  GLIBC_2_1); + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +int +__pthread_attr_init_2_0 (attr) +     pthread_attr_t *attr; +{ +  /* This code is specific to the old LinuxThread code which has a too +     small pthread_attr_t definition.  The struct looked like +     this:  */ +  struct old_attr +  { +    int detachstate; +    int schedpolicy; +    struct sched_param schedparam; +    int inheritsched; +    int scope; +  }; +  struct pthread_attr *iattr; + +  /* Many elements are initialized to zero so let us do it all at +     once.  This also takes care of clearing the bytes which are not +     internally used.  */ +  memset (attr, '\0', sizeof (struct old_attr)); + +  iattr = (struct pthread_attr *) attr; +  iattr->flags |= ATTR_FLAG_OLDATTR; + +  /* We cannot enqueue the attribute because that member is not in the +     old attribute structure.  */ +  return 0; +} +compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init, +	       GLIBC_2_0); +#endif diff --git a/libpthread/nptl/pthread_attr_setdetachstate.c b/libpthread/nptl/pthread_attr_setdetachstate.c new file mode 100644 index 000000000..a0e6c2017 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setdetachstate.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_setdetachstate (attr, detachstate) +     pthread_attr_t *attr; +     int detachstate; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid values.  */ +  if (detachstate != PTHREAD_CREATE_DETACHED +      && __builtin_expect (detachstate != PTHREAD_CREATE_JOINABLE, 0)) +    return EINVAL; + +  /* Set the flag.  It is nonzero if threads are created detached.  */ +  if (detachstate == PTHREAD_CREATE_DETACHED) +    iattr->flags |= ATTR_FLAG_DETACHSTATE; +  else +    iattr->flags &= ~ATTR_FLAG_DETACHSTATE; + +  return 0; +} +strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate) diff --git a/libpthread/nptl/pthread_attr_setguardsize.c b/libpthread/nptl/pthread_attr_setguardsize.c new file mode 100644 index 000000000..4c674f4df --- /dev/null +++ b/libpthread/nptl/pthread_attr_setguardsize.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include "pthreadP.h" + + +int +pthread_attr_setguardsize (attr, guardsize) +     pthread_attr_t *attr; +     size_t guardsize; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Note that we don't round the value here.  The standard requires +     that subsequent pthread_attr_getguardsize calls return the value +     set by the user.  */ +  iattr->guardsize = guardsize; + +  return 0; +} diff --git a/libpthread/nptl/pthread_attr_setinheritsched.c b/libpthread/nptl/pthread_attr_setinheritsched.c new file mode 100644 index 000000000..8a77eeb65 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setinheritsched.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_setinheritsched (attr, inherit) +     pthread_attr_t *attr; +     int inherit; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid values.  */ +  if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) +    return EINVAL; + +  /* Store the new values.  */ +  if (inherit != PTHREAD_INHERIT_SCHED) +    iattr->flags |= ATTR_FLAG_NOTINHERITSCHED; +  else +    iattr->flags &= ~ATTR_FLAG_NOTINHERITSCHED; + +  return 0; +} +strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched) diff --git a/libpthread/nptl/pthread_attr_setschedparam.c b/libpthread/nptl/pthread_attr_setschedparam.c new file mode 100644 index 000000000..976ad1387 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setschedparam.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include "pthreadP.h" + + +int +__pthread_attr_setschedparam (attr, param) +     pthread_attr_t *attr; +     const struct sched_param *param; +{ +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  struct pthread_attr *iattr = (struct pthread_attr *) attr; + +  /* Copy the new values.  */ +  memcpy (&iattr->schedparam, param, sizeof (struct sched_param)); + +  /* Remember we set the value.  */ +  iattr->flags |= ATTR_FLAG_SCHED_SET; + +  return 0; +} +strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam) diff --git a/libpthread/nptl/pthread_attr_setschedpolicy.c b/libpthread/nptl/pthread_attr_setschedpolicy.c new file mode 100644 index 000000000..b9710d57a --- /dev/null +++ b/libpthread/nptl/pthread_attr_setschedpolicy.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_setschedpolicy (attr, policy) +     pthread_attr_t *attr; +     int policy; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid values.  */ +  if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) +    return EINVAL; + +  /* Store the new values.  */ +  iattr->schedpolicy = policy; + +  /* Remember we set the value.  */ +  iattr->flags |= ATTR_FLAG_POLICY_SET; + +  return 0; +} +strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy) diff --git a/libpthread/nptl/pthread_attr_setscope.c b/libpthread/nptl/pthread_attr_setscope.c new file mode 100644 index 000000000..8b3e1612e --- /dev/null +++ b/libpthread/nptl/pthread_attr_setscope.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_setscope (attr, scope) +     pthread_attr_t *attr; +     int scope; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid values.  */ +  switch (scope) +    { +    case PTHREAD_SCOPE_SYSTEM: +      iattr->flags &= ~ATTR_FLAG_SCOPEPROCESS; +      break; + +    case PTHREAD_SCOPE_PROCESS: +      return ENOTSUP; + +    default: +      return EINVAL; +    } + +  return 0; +} +strong_alias (__pthread_attr_setscope, pthread_attr_setscope) diff --git a/libpthread/nptl/pthread_attr_setstack.c b/libpthread/nptl/pthread_attr_setstack.c new file mode 100644 index 000000000..622e4a225 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setstack.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include "pthreadP.h" + + +int +__pthread_attr_setstack (attr, stackaddr, stacksize) +     pthread_attr_t *attr; +     void *stackaddr; +     size_t stacksize; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid sizes.  */ +  if (stacksize < PTHREAD_STACK_MIN) +    return EINVAL; + +#ifdef EXTRA_PARAM_CHECKS +  EXTRA_PARAM_CHECKS; +#endif + +  iattr->stacksize = stacksize; +  iattr->stackaddr = (char *) stackaddr + stacksize; +  iattr->flags |= ATTR_FLAG_STACKADDR; + +  return 0; +} + +#if PTHREAD_STACK_MIN == 16384 +strong_alias (__pthread_attr_setstack, pthread_attr_setstack) +#else +# include <shlib-compat.h> +versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack, +		  GLIBC_2_3_3); + +# if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3) + +int +__old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, +			     size_t stacksize) +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid sizes.  */ +  if (stacksize < 16384) +    return EINVAL; + +# ifdef EXTRA_PARAM_CHECKS +  EXTRA_PARAM_CHECKS; +# endif + +  iattr->stacksize = stacksize; +  iattr->stackaddr = (char *) stackaddr + stacksize; +  iattr->flags |= ATTR_FLAG_STACKADDR; + +  return 0; +} + +compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack, +	       GLIBC_2_2); +# endif + +#endif diff --git a/libpthread/nptl/pthread_attr_setstackaddr.c b/libpthread/nptl/pthread_attr_setstackaddr.c new file mode 100644 index 000000000..0d7a7c0eb --- /dev/null +++ b/libpthread/nptl/pthread_attr_setstackaddr.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_setstackaddr (attr, stackaddr) +     pthread_attr_t *attr; +     void *stackaddr; +{ +  struct pthread_attr *iattr; + +#ifdef EXTRA_PARAM_CHECKS +  EXTRA_PARAM_CHECKS; +#endif + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  iattr->stackaddr = stackaddr; +  iattr->flags |= ATTR_FLAG_STACKADDR; + +  return 0; +} +strong_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +link_warning (pthread_attr_setstackaddr, +              "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'") diff --git a/libpthread/nptl/pthread_attr_setstacksize.c b/libpthread/nptl/pthread_attr_setstacksize.c new file mode 100644 index 000000000..f84a9f68e --- /dev/null +++ b/libpthread/nptl/pthread_attr_setstacksize.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include "pthreadP.h" + + +int +__pthread_attr_setstacksize (attr, stacksize) +     pthread_attr_t *attr; +     size_t stacksize; +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid sizes.  */ +  if (stacksize < PTHREAD_STACK_MIN) +    return EINVAL; + +  iattr->stacksize = stacksize; + +  return 0; +} + +#if PTHREAD_STACK_MIN == 16384 +strong_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) +#else +# include <shlib-compat.h> +versioned_symbol (libpthread, __pthread_attr_setstacksize, +		  pthread_attr_setstacksize, GLIBC_2_3_3); + +# if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3) + +int +__old_pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize) +{ +  struct pthread_attr *iattr; + +  assert (sizeof (*attr) >= sizeof (struct pthread_attr)); +  iattr = (struct pthread_attr *) attr; + +  /* Catch invalid sizes.  */ +  if (stacksize < 16384) +    return EINVAL; + +  iattr->stacksize = stacksize; + +  return 0; +} + +compat_symbol (libpthread, __old_pthread_attr_setstacksize, +	       pthread_attr_setstacksize, GLIBC_2_1); +# endif + +#endif diff --git a/libpthread/nptl/pthread_barrier_destroy.c b/libpthread/nptl/pthread_barrier_destroy.c new file mode 100644 index 000000000..492b29485 --- /dev/null +++ b/libpthread/nptl/pthread_barrier_destroy.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +pthread_barrier_destroy (barrier) +     pthread_barrier_t *barrier; +{ +  struct pthread_barrier *ibarrier; +  int result = EBUSY; + +  ibarrier = (struct pthread_barrier *) barrier; + +  lll_lock (ibarrier->lock); + +  if (__builtin_expect (ibarrier->left == ibarrier->init_count, 1)) +    /* The barrier is not used anymore.  */ +    result = 0; +  else +    /* Still used, return with an error.  */ +    lll_unlock (ibarrier->lock); + +  return result; +} diff --git a/libpthread/nptl/pthread_barrier_init.c b/libpthread/nptl/pthread_barrier_init.c new file mode 100644 index 000000000..19e82fa38 --- /dev/null +++ b/libpthread/nptl/pthread_barrier_init.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +pthread_barrier_init (barrier, attr, count) +     pthread_barrier_t *barrier; +     const pthread_barrierattr_t *attr; +     unsigned int count; +{ +  struct pthread_barrier *ibarrier; + +  if (__builtin_expect (count == 0, 0)) +    return EINVAL; + +  if (attr != NULL) +    { +      struct pthread_barrierattr *iattr; + +      iattr = (struct pthread_barrierattr *) attr; + +      if (iattr->pshared != PTHREAD_PROCESS_PRIVATE +	  && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0)) +	/* Invalid attribute.  */ +	return EINVAL; +    } + +  ibarrier = (struct pthread_barrier *) barrier; + +  /* Initialize the individual fields.  */ +  ibarrier->lock = LLL_LOCK_INITIALIZER; +  ibarrier->left = count; +  ibarrier->init_count = count; +  ibarrier->curr_event = 0; + +  return 0; +} diff --git a/libpthread/nptl/pthread_barrierattr_destroy.c b/libpthread/nptl/pthread_barrierattr_destroy.c new file mode 100644 index 000000000..f947daf38 --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_destroy.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_destroy (attr) +     pthread_barrierattr_t *attr; +{ +  /* Nothing to do.  */ + +  return 0; +} diff --git a/libpthread/nptl/pthread_barrierattr_getpshared.c b/libpthread/nptl/pthread_barrierattr_getpshared.c new file mode 100644 index 000000000..246c8882e --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_getpshared (attr, pshared) +     const pthread_barrierattr_t *attr; +     int *pshared; +{ +  *pshared = ((const struct pthread_barrierattr *) attr)->pshared; + +  return 0; +} diff --git a/libpthread/nptl/pthread_barrierattr_init.c b/libpthread/nptl/pthread_barrierattr_init.c new file mode 100644 index 000000000..a0be9528b --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_init.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_init (attr) +     pthread_barrierattr_t *attr; +{ +  ((struct pthread_barrierattr *) attr)->pshared = PTHREAD_PROCESS_PRIVATE; + +  return 0; +} diff --git a/libpthread/nptl/pthread_barrierattr_setpshared.c b/libpthread/nptl/pthread_barrierattr_setpshared.c new file mode 100644 index 000000000..b69f23ef1 --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_setpshared.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + + +int +pthread_barrierattr_setpshared (attr, pshared) +     pthread_barrierattr_t *attr; +     int pshared; +{ +  struct pthread_barrierattr *iattr; + +  if (pshared != PTHREAD_PROCESS_PRIVATE +      && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) +    return EINVAL; + +  iattr = (struct pthread_barrierattr *) attr; + +  iattr->pshared = pshared; + +  return 0; +} diff --git a/libpthread/nptl/pthread_cancel.c b/libpthread/nptl/pthread_cancel.c new file mode 100644 index 000000000..a13af56b3 --- /dev/null +++ b/libpthread/nptl/pthread_cancel.c @@ -0,0 +1,104 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <signal.h> +#include "pthreadP.h" +#include "atomic.h" +#include <sysdep.h> +#include <kernel-features.h> + + +int +pthread_cancel (th) +     pthread_t th; +{ +  volatile struct pthread *pd = (volatile struct pthread *) th; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +#ifdef SHARED +  pthread_cancel_init (); +#endif +  int result = 0; +  int oldval; +  int newval; +  do +    { +      oldval = pd->cancelhandling; +      newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; + +      /* Avoid doing unnecessary work.  The atomic operation can +	 potentially be expensive if the bug has to be locked and +	 remote cache lines have to be invalidated.  */ +      if (oldval == newval) +	break; + +      /* If the cancellation is handled asynchronously just send a +	 signal.  We avoid this if possible since it's more +	 expensive.  */ +      if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) +	{ +	  /* Mark the cancellation as "in progress".  */ +	  atomic_bit_set (&pd->cancelhandling, CANCELING_BIT); + +	  /* The cancellation handler will take care of marking the +	     thread as canceled.  */ +	  INTERNAL_SYSCALL_DECL (err); + +	  /* One comment: The PID field in the TCB can temporarily be +	     changed (in fork).  But this must not affect this code +	     here.  Since this function would have to be called while +	     the thread is executing fork, it would have to happen in +	     a signal handler.  But this is no allowed, pthread_cancel +	     is not guaranteed to be async-safe.  */ +	  int val; +#if __ASSUME_TGKILL +	  val = INTERNAL_SYSCALL (tgkill, err, 3, +				  THREAD_GETMEM (THREAD_SELF, pid), pd->tid, +				  SIGCANCEL); +#else +# ifdef __NR_tgkill +	  val = INTERNAL_SYSCALL (tgkill, err, 3, +				  THREAD_GETMEM (THREAD_SELF, pid), pd->tid, +				  SIGCANCEL); +	  if (INTERNAL_SYSCALL_ERROR_P (val, err) +	      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif +	    val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCANCEL); +#endif + +	  if (INTERNAL_SYSCALL_ERROR_P (val, err)) +	    result = INTERNAL_SYSCALL_ERRNO (val, err); + +	  break; +	} +    } +  /* Mark the thread as canceled.  This has to be done +     atomically since other bits could be modified as well.  */ +  while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval, +					       oldval)); + +  return result; +} + +PTHREAD_STATIC_FN_REQUIRE (pthread_create) diff --git a/libpthread/nptl/pthread_clock_gettime.c b/libpthread/nptl/pthread_clock_gettime.c new file mode 100644 index 000000000..a71174c9c --- /dev/null +++ b/libpthread/nptl/pthread_clock_gettime.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2001, 2002, 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 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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <libc-internal.h> +#include "pthreadP.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, +			 struct timespec *tp) +{ +  hp_timing_t tsc; + +  /* Get the current counter.  */ +  HP_TIMING_NOW (tsc); + +  /* This is the ID of the thread we are looking for.  */ +  pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + +  /* Compute the offset since the start time of the process.  */ +  if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) +    /* Our own clock.  */ +    tsc -= THREAD_GETMEM (THREAD_SELF, cpuclock_offset); +  else +    { +      /* This is more complicated.  We have to locate the thread based +	 on the ID.  This means walking the list of existing +	 threads.  */ +      struct pthread *thread = __find_thread_by_id (tid); +      if (thread == NULL) +	{ +	  __set_errno (EINVAL); +	  return -1; +	} + +      /* There is a race here.  The thread might terminate and the stack +	 become unusable.  But this is the user's problem.  */ +      tsc -= thread->cpuclock_offset; +    } + +  /* Compute the seconds.  */ +  tp->tv_sec = tsc / freq; + +  /* And the nanoseconds.  This computation should be stable until +     we get machines with about 16GHz frequency.  */ +  tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq; + +  return 0; +} +#endif diff --git a/libpthread/nptl/pthread_clock_settime.c b/libpthread/nptl/pthread_clock_settime.c new file mode 100644 index 000000000..61002a8f7 --- /dev/null +++ b/libpthread/nptl/pthread_clock_settime.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2001, 2002, 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 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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <libc-internal.h> +#include "pthreadP.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) +{ +  /* This is the ID of the thread we are looking for.  */ +  pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + +  /* Compute the offset since the start time of the process.  */ +  if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) +    /* Our own clock.  */ +    THREAD_SETMEM (THREAD_SELF, cpuclock_offset, offset); +  else +    { +      /* This is more complicated.  We have to locate the thread based +	 on the ID.  This means walking the list of existing +	 threads.  */ +      struct pthread *thread = __find_thread_by_id (tid); +      if (thread == NULL) +	{ +	  __set_errno (EINVAL); +	  return -1; +	} + +      /* There is a race here.  The thread might terminate and the stack +	 become unusable.  But this is the user's problem.  */ +      thread->cpuclock_offset = offset; +    } + +  return 0; +} +#endif diff --git a/libpthread/nptl/pthread_cond_destroy.c b/libpthread/nptl/pthread_cond_destroy.c new file mode 100644 index 000000000..0208d18ce --- /dev/null +++ b/libpthread/nptl/pthread_cond_destroy.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <shlib-compat.h> +#include "pthreadP.h" + + +int +__pthread_cond_destroy (cond) +     pthread_cond_t *cond; +{ +  /* Make sure we are alone.  */ +  lll_mutex_lock (cond->__data.__lock); + +  if (cond->__data.__total_seq > cond->__data.__wakeup_seq) +    { +      /* If there are still some waiters which have not been +	 woken up, this is an application bug.  */ +      lll_mutex_unlock (cond->__data.__lock); +      return EBUSY; +    } + +  /* Tell pthread_cond_*wait that this condvar is being destroyed.  */ +  cond->__data.__total_seq = -1ULL; + +  /* If there are waiters which have been already signalled or +     broadcasted, but still are using the pthread_cond_t structure, +     pthread_cond_destroy needs to wait for them.  */ +  unsigned int nwaiters = cond->__data.__nwaiters; +  while (nwaiters >= (1 << COND_CLOCK_BITS)) +    { +      lll_mutex_unlock (cond->__data.__lock); + +      lll_futex_wait (&cond->__data.__nwaiters, nwaiters); + +      lll_mutex_lock (cond->__data.__lock); + +      nwaiters = cond->__data.__nwaiters; +    } + +  return 0; +} +versioned_symbol (libpthread, __pthread_cond_destroy, +		  pthread_cond_destroy, GLIBC_2_3_2); diff --git a/libpthread/nptl/pthread_cond_init.c b/libpthread/nptl/pthread_cond_init.c new file mode 100644 index 000000000..5e2e6704a --- /dev/null +++ b/libpthread/nptl/pthread_cond_init.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <shlib-compat.h> +#include "pthreadP.h" + + +int +__pthread_cond_init (cond, cond_attr) +     pthread_cond_t *cond; +     const pthread_condattr_t *cond_attr; +{ +  struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr; + +  cond->__data.__lock = LLL_MUTEX_LOCK_INITIALIZER; +  cond->__data.__futex = 0; +  cond->__data.__nwaiters = (icond_attr != NULL +			     && ((icond_attr->value & (COND_CLOCK_BITS << 1)) +				 >> 1)); +  cond->__data.__total_seq = 0; +  cond->__data.__wakeup_seq = 0; +  cond->__data.__woken_seq = 0; +  cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0 +			  ? NULL : (void *) ~0l); +  cond->__data.__broadcast_seq = 0; + +  return 0; +} +versioned_symbol (libpthread, __pthread_cond_init, +		  pthread_cond_init, GLIBC_2_3_2); diff --git a/libpthread/nptl/pthread_condattr_destroy.c b/libpthread/nptl/pthread_condattr_destroy.c new file mode 100644 index 000000000..e6d069e40 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_destroy.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +__pthread_condattr_destroy (attr) +     pthread_condattr_t *attr; +{ +  /* Nothing to be done.  */ +  return 0; +} +strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy) diff --git a/libpthread/nptl/pthread_condattr_getclock.c b/libpthread/nptl/pthread_condattr_getclock.c new file mode 100644 index 000000000..84de918a5 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_getclock.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_condattr_getclock (attr, clock_id) +     const pthread_condattr_t *attr; +     clockid_t *clock_id; +{ +  *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1) +	       & ((1 << COND_CLOCK_BITS) - 1)); +  return 0; +} diff --git a/libpthread/nptl/pthread_condattr_getpshared.c b/libpthread/nptl/pthread_condattr_getpshared.c new file mode 100644 index 000000000..b44eac94e --- /dev/null +++ b/libpthread/nptl/pthread_condattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_condattr_getpshared (attr, pshared) +     const pthread_condattr_t *attr; +     int *pshared; +{ +  *pshared = ((const struct pthread_condattr *) attr)->value & 1; + +  return 0; +} diff --git a/libpthread/nptl/pthread_condattr_init.c b/libpthread/nptl/pthread_condattr_init.c new file mode 100644 index 000000000..738deb489 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_init.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <string.h> +#include "pthreadP.h" + + +int +__pthread_condattr_init (attr) +     pthread_condattr_t *attr; +{ +  memset (attr, '\0', sizeof (*attr)); + +  return 0; +} +strong_alias (__pthread_condattr_init, pthread_condattr_init) diff --git a/libpthread/nptl/pthread_condattr_setclock.c b/libpthread/nptl/pthread_condattr_setclock.c new file mode 100644 index 000000000..04e246b74 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_setclock.c @@ -0,0 +1,72 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <time.h> +#include <sysdep.h> +#include "pthreadP.h" +#include <kernel-features.h> + + +int +pthread_condattr_setclock (attr, clock_id) +     pthread_condattr_t *attr; +     clockid_t clock_id; +{ +  /* Only a few clocks are allowed.  CLOCK_REALTIME is always allowed. +     CLOCK_MONOTONIC only if the kernel has the necessary support.  */ +  if (clock_id == CLOCK_MONOTONIC) +    { +#ifndef __ASSUME_POSIX_TIMERS +# ifdef __NR_clock_getres +      /* Check whether the clock is available.  */ +      static int avail; + +      if (avail == 0) +	{ +	  struct timespec ts; + +	  INTERNAL_SYSCALL_DECL (err); +	  int val; +	  val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); +	  avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1; +	} + +      if (avail < 0) +# endif +	/* Not available.  */ +	return EINVAL; +#endif +    } +  else if (clock_id != CLOCK_REALTIME) +    /* If more clocks are allowed some day the storing of the clock ID +       in the pthread_cond_t structure needs to be adjusted.  */ +    return EINVAL; + +  /* Make sure the value fits in the bits we reserved.  */ +  assert (clock_id < (1 << COND_CLOCK_BITS)); + +  int *valuep = &((struct pthread_condattr *) attr)->value; + +  *valuep = (*valuep & ~(1 << (COND_CLOCK_BITS + 1)) & ~1) | (clock_id << 1); + +  return 0; +} diff --git a/libpthread/nptl/pthread_condattr_setpshared.c b/libpthread/nptl/pthread_condattr_setpshared.c new file mode 100644 index 000000000..f00858780 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_setpshared.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <pthreadP.h> + +int +pthread_condattr_setpshared (attr, pshared) +     pthread_condattr_t *attr; +     int pshared; +{ +  if (pshared != PTHREAD_PROCESS_PRIVATE +      && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) +    return EINVAL; + +  int *valuep = &((struct pthread_condattr *) attr)->value; + +  *valuep = (*valuep & ~1) | (pshared != PTHREAD_PROCESS_PRIVATE); + +  return 0; +} diff --git a/libpthread/nptl/pthread_create.c b/libpthread/nptl/pthread_create.c new file mode 100644 index 000000000..18f1c034c --- /dev/null +++ b/libpthread/nptl/pthread_create.c @@ -0,0 +1,520 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include "pthreadP.h" +#include <hp-timing.h> +#include <ldsodefs.h> +#include <atomic.h> +#include <libc-internal.h> +#include <resolv.h> + +#include <shlib-compat.h> + + +/* Local function to start thread and handle cleanup.  */ +static int start_thread (void *arg); + + +/* Nozero if debugging mode is enabled.  */ +int __pthread_debug; + +/* Globally enabled events.  */ +static td_thr_events_t __nptl_threads_events; + +/* Pointer to descriptor with the last event.  */ +static struct pthread *__nptl_last_event; + +/* Number of threads running.  */ +unsigned int __nptl_nthreads = 1; + + +/* Code to allocate and deallocate a stack.  */ +#include "allocatestack.c" + +/* Code to create the thread.  */ +#include "createthread.c" + + +struct pthread * +internal_function +__find_in_stack_list (pd) +     struct pthread *pd; +{ +  list_t *entry; +  struct pthread *result = NULL; + +  lll_lock (stack_cache_lock); + +  list_for_each (entry, &stack_used) +    { +      struct pthread *curp; + +      curp = list_entry (entry, struct pthread, list); +      if (curp == pd) +	{ +	  result = curp; +	  break; +	} +    } + +  if (result == NULL) +    list_for_each (entry, &__stack_user) +      { +	struct pthread *curp; + +	curp = list_entry (entry, struct pthread, list); +	if (curp == pd) +	  { +	    result = curp; +	    break; +	  } +      } + +  lll_unlock (stack_cache_lock); + +  return result; +} + + +/* Deallocate POSIX thread-local-storage.  */ +void +attribute_hidden +__nptl_deallocate_tsd (void) +{ +  struct pthread *self = THREAD_SELF; + +  /* Maybe no data was ever allocated.  This happens often so we have +     a flag for this.  */ +  if (THREAD_GETMEM (self, specific_used)) +    { +      size_t round; +      size_t cnt; + +      round = 0; +      do +	{ +	  size_t idx; + +	  /* So far no new nonzero data entry.  */ +	  THREAD_SETMEM (self, specific_used, false); + +	  for (cnt = idx = 0; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) +	    { +	      struct pthread_key_data *level2; + +	      level2 = THREAD_GETMEM_NC (self, specific, cnt); + +	      if (level2 != NULL) +		{ +		  size_t inner; + +		  for (inner = 0; inner < PTHREAD_KEY_2NDLEVEL_SIZE; +		       ++inner, ++idx) +		    { +		      void *data = level2[inner].data; + +		      if (data != NULL) +			{ +			  /* Always clear the data.  */ +			  level2[inner].data = NULL; + +			  /* Make sure the data corresponds to a valid +			     key.  This test fails if the key was +			     deallocated and also if it was +			     re-allocated.  It is the user's +			     responsibility to free the memory in this +			     case.  */ +			  if (level2[inner].seq +			      == __pthread_keys[idx].seq +			      /* It is not necessary to register a destructor +				 function.  */ +			      && __pthread_keys[idx].destr != NULL) +			    /* Call the user-provided destructor.  */ +			    __pthread_keys[idx].destr (data); +			} +		    } +		} +	      else +		idx += PTHREAD_KEY_1STLEVEL_SIZE; +	    } + +	  if (THREAD_GETMEM (self, specific_used) == 0) +	    /* No data has been modified.  */ +	    goto just_free; +	} +      /* We only repeat the process a fixed number of times.  */ +      while (__builtin_expect (++round < PTHREAD_DESTRUCTOR_ITERATIONS, 0)); + +      /* Just clear the memory of the first block for reuse.  */ +      memset (&THREAD_SELF->specific_1stblock, '\0', +	      sizeof (self->specific_1stblock)); + +    just_free: +      /* Free the memory for the other blocks.  */ +      for (cnt = 1; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) +	{ +	  struct pthread_key_data *level2; + +	  level2 = THREAD_GETMEM_NC (self, specific, cnt); +	  if (level2 != NULL) +	    { +	      /* The first block is allocated as part of the thread +		 descriptor.  */ +	      free (level2); +	      THREAD_SETMEM_NC (self, specific, cnt, NULL); +	    } +	} + +      THREAD_SETMEM (self, specific_used, false); +    } +} + + +/* Deallocate a thread's stack after optionally making sure the thread +   descriptor is still valid.  */ +void +internal_function +__free_tcb (struct pthread *pd) +{ +  /* The thread is exiting now.  */ +  if (__builtin_expect (atomic_bit_test_set (&pd->cancelhandling, +					     TERMINATED_BIT) == 0, 1)) +    { +      /* Remove the descriptor from the list.  */ +      if (DEBUGGING_P && __find_in_stack_list (pd) == NULL) +	/* Something is really wrong.  The descriptor for a still +	   running thread is gone.  */ +	abort (); + +      /* Queue the stack memory block for reuse and exit the process.  The +	 kernel will signal via writing to the address returned by +	 QUEUE-STACK when the stack is available.  */ +      __deallocate_stack (pd); +    } +} + + +static int +start_thread (void *arg) +{ +  struct pthread *pd = (struct pthread *) arg; + +#if HP_TIMING_AVAIL +  /* Remember the time when the thread was started.  */ +  hp_timing_t now; +  HP_TIMING_NOW (now); +  THREAD_SETMEM (pd, cpuclock_offset, now); +#endif + +  /* Initialize resolver state pointer.  */ +  __resp = &pd->res; + +  /* This is where the try/finally block should be created.  For +     compilers without that support we do use setjmp.  */ +  struct pthread_unwind_buf unwind_buf; + +  /* No previous handlers.  */ +  unwind_buf.priv.data.prev = NULL; +  unwind_buf.priv.data.cleanup = NULL; + +  int not_first_call; +  not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); +  if (__builtin_expect (! not_first_call, 1)) +    { +      /* Store the new cleanup handler info.  */ +      THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf); + +      if (__builtin_expect (pd->stopped_start, 0)) +	{ +	  int oldtype = CANCEL_ASYNC (); + +	  /* Get the lock the parent locked to force synchronization.  */ +	  lll_lock (pd->lock); +	  /* And give it up right away.  */ +	  lll_unlock (pd->lock); + +	  CANCEL_RESET (oldtype); +	} + +      /* Run the code the user provided.  */ +#ifdef CALL_THREAD_FCT +      THREAD_SETMEM (pd, result, CALL_THREAD_FCT (pd)); +#else +      THREAD_SETMEM (pd, result, pd->start_routine (pd->arg)); +#endif +    } + +  /* Run the destructor for the thread-local data.  */ +  __nptl_deallocate_tsd (); + +  /* Clean up any state libc stored in thread-local variables.  */ +  __libc_thread_freeres (); + +  /* If this is the last thread we terminate the process now.  We +     do not notify the debugger, it might just irritate it if there +     is no thread left.  */ +  if (__builtin_expect (atomic_decrement_and_test (&__nptl_nthreads), 0)) +    /* This was the last thread.  */ +    exit (0); + +  /* Report the death of the thread if this is wanted.  */ +  if (__builtin_expect (pd->report_events, 0)) +    { +      /* See whether TD_DEATH is in any of the mask.  */ +      const int idx = __td_eventword (TD_DEATH); +      const uint32_t mask = __td_eventmask (TD_DEATH); + +      if ((mask & (__nptl_threads_events.event_bits[idx] +		   | pd->eventbuf.eventmask.event_bits[idx])) != 0) +	{ +	  /* Yep, we have to signal the death.  Add the descriptor to +	     the list but only if it is not already on it.  */ +	  if (pd->nextevent == NULL) +	    { +	      pd->eventbuf.eventnum = TD_DEATH; +	      pd->eventbuf.eventdata = pd; + +	      do +		pd->nextevent = __nptl_last_event; +	      while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event, +							   pd, pd->nextevent)); +	    } + +	  /* Now call the function to signal the event.  */ +	  __nptl_death_event (); +	} +    } + +  /* The thread is exiting now.  Don't set this bit until after we've hit +     the event-reporting breakpoint, so that td_thr_get_info on us while at +     the breakpoint reports TD_THR_RUN state rather than TD_THR_ZOMBIE.  */ +  atomic_bit_set (&pd->cancelhandling, EXITING_BIT); + +  /* If the thread is detached free the TCB.  */ +  if (IS_DETACHED (pd)) +    /* Free the TCB.  */ +    __free_tcb (pd); + +  /* We cannot call '_exit' here.  '_exit' will terminate the process. + +     The 'exit' implementation in the kernel will signal when the +     process is really dead since 'clone' got passed the CLONE_CLEARTID +     flag.  The 'tid' field in the TCB will be set to zero. + +     The exit code is zero since in case all threads exit by calling +     'pthread_exit' the exit status must be 0 (zero).  */ +  __exit_thread_inline (0); + +  /* NOTREACHED */ +  return 0; +} + + +/* Default thread attributes for the case when the user does not +   provide any.  */ +static const struct pthread_attr default_attr = +  { +    /* Just some value > 0 which gets rounded to the nearest page size.  */ +    .guardsize = 1, +  }; + + +int +__pthread_create_2_1 (newthread, attr, start_routine, arg) +     pthread_t *newthread; +     const pthread_attr_t *attr; +     void *(*start_routine) (void *); +     void *arg; +{ +  STACK_VARIABLES; + +  const struct pthread_attr *iattr = (struct pthread_attr *) attr; +  if (iattr == NULL) +    /* Is this the best idea?  On NUMA machines this could mean +       accessing far-away memory.  */ +    iattr = &default_attr; + +  struct pthread *pd; +  int err = ALLOCATE_STACK (iattr, &pd); +  if (__builtin_expect (err != 0, 0)) +    /* Something went wrong.  Maybe a parameter of the attributes is +       invalid or we could not allocate memory.  */ +    return err; + + +  /* Initialize the TCB.  All initializations with zero should be +     performed in 'get_cached_stack'.  This way we avoid doing this if +     the stack freshly allocated with 'mmap'.  */ + +#ifdef TLS_TCB_AT_TP +  /* Reference to the TCB itself.  */ +  pd->header.self = pd; + +  /* Self-reference for TLS.  */ +  pd->header.tcb = pd; +#endif + +  /* Store the address of the start routine and the parameter.  Since +     we do not start the function directly the stillborn thread will +     get the information from its thread descriptor.  */ +  pd->start_routine = start_routine; +  pd->arg = arg; + +  /* Copy the thread attribute flags.  */ +  struct pthread *self = THREAD_SELF; +  pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) +	       | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))); + +  /* Initialize the field for the ID of the thread which is waiting +     for us.  This is a self-reference in case the thread is created +     detached.  */ +  pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL; + +  /* The debug events are inherited from the parent.  */ +  pd->eventbuf = self->eventbuf; + + +  /* Copy the parent's scheduling parameters.  The flags will say what +     is valid and what is not.  */ +  pd->schedpolicy = self->schedpolicy; +  pd->schedparam = self->schedparam; + +  /* Determine scheduling parameters for the thread.  */ +  if (attr != NULL +      && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0) +      && (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0) +    { +      INTERNAL_SYSCALL_DECL (scerr); + +      /* Use the scheduling parameters the user provided.  */ +      if (iattr->flags & ATTR_FLAG_POLICY_SET) +	pd->schedpolicy = iattr->schedpolicy; +      else if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) +	{ +	  pd->schedpolicy = INTERNAL_SYSCALL (sched_getscheduler, scerr, 1, 0); +	  pd->flags |= ATTR_FLAG_POLICY_SET; +	} + +      if (iattr->flags & ATTR_FLAG_SCHED_SET) +	memcpy (&pd->schedparam, &iattr->schedparam, +		sizeof (struct sched_param)); +      else if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) +	{ +	  INTERNAL_SYSCALL (sched_getparam, scerr, 2, 0, &pd->schedparam); +	  pd->flags |= ATTR_FLAG_SCHED_SET; +	} + +      /* Check for valid priorities.  */ +      int minprio = INTERNAL_SYSCALL (sched_get_priority_min, scerr, 1, +				      iattr->schedpolicy); +      int maxprio = INTERNAL_SYSCALL (sched_get_priority_max, scerr, 1, +				      iattr->schedpolicy); +      if (pd->schedparam.sched_priority < minprio +	  || pd->schedparam.sched_priority > maxprio) +	{ +	  err = EINVAL; +	  goto errout; +	} +    } + +  /* Pass the descriptor to the caller.  */ +  *newthread = (pthread_t) pd; + +  /* Remember whether the thread is detached or not.  In case of an +     error we have to free the stacks of non-detached stillborn +     threads.  */ +  bool is_detached = IS_DETACHED (pd); + +  /* Start the thread.  */ +  err = create_thread (pd, iattr, STACK_VARIABLES_ARGS); +  if (err != 0) +    { +      /* Something went wrong.  Free the resources.  */ +      if (!is_detached) +	{ +	errout: +	  __deallocate_stack (pd); +	} +      return err; +    } + +  return 0; +} +versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1); + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +int +__pthread_create_2_0 (newthread, attr, start_routine, arg) +     pthread_t *newthread; +     const pthread_attr_t *attr; +     void *(*start_routine) (void *); +     void *arg; +{ +  /* The ATTR attribute is not really of type `pthread_attr_t *'.  It has +     the old size and access to the new members might crash the program. +     We convert the struct now.  */ +  struct pthread_attr new_attr; + +  if (attr != NULL) +    { +      struct pthread_attr *iattr = (struct pthread_attr *) attr; +      size_t ps = __getpagesize (); + +      /* Copy values from the user-provided attributes.  */ +      new_attr.schedparam = iattr->schedparam; +      new_attr.schedpolicy = iattr->schedpolicy; +      new_attr.flags = iattr->flags; + +      /* Fill in default values for the fields not present in the old +	 implementation.  */ +      new_attr.guardsize = ps; +      new_attr.stackaddr = NULL; +      new_attr.stacksize = 0; +      new_attr.cpuset = NULL; + +      /* We will pass this value on to the real implementation.  */ +      attr = (pthread_attr_t *) &new_attr; +    } + +  return __pthread_create_2_1 (newthread, attr, start_routine, arg); +} +compat_symbol (libpthread, __pthread_create_2_0, pthread_create, +	       GLIBC_2_0); +#endif + +/* Information for libthread_db.  */ + +#include "../nptl_db/db_info.c" + +/* If pthread_create is present, libgcc_eh.a and libsupc++.a expects some other POSIX thread +   functions to be present as well.  */ +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_lock) +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_unlock) + +PTHREAD_STATIC_FN_REQUIRE (pthread_once) +PTHREAD_STATIC_FN_REQUIRE (pthread_cancel) + +PTHREAD_STATIC_FN_REQUIRE (pthread_key_create) +PTHREAD_STATIC_FN_REQUIRE (pthread_setspecific) +PTHREAD_STATIC_FN_REQUIRE (pthread_getspecific) diff --git a/libpthread/nptl/pthread_detach.c b/libpthread/nptl/pthread_detach.c new file mode 100644 index 000000000..1f0c2fe7c --- /dev/null +++ b/libpthread/nptl/pthread_detach.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +pthread_detach (th) +     pthread_t th; +{ +  struct pthread *pd = (struct pthread *) th; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_NOT_TERMINATED_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  int result = 0; + +  /* Mark the thread as detached.  */ +  if (atomic_compare_and_exchange_bool_acq (&pd->joinid, pd, NULL)) +    { +      /* There are two possibilities here.  First, the thread might +	 already be detached.  In this case we return EINVAL. +	 Otherwise there might already be a waiter.  The standard does +	 not mention what happens in this case.  */ +      if (IS_DETACHED (pd)) +	result = EINVAL; +    } +  else +    /* Check whether the thread terminated meanwhile.  In this case we +       will just free the TCB.  */ +    if ((pd->cancelhandling & EXITING_BITMASK) != 0) +      /* Note that the code in __free_tcb makes sure each thread +	 control block is freed only once.  */ +      __free_tcb (pd); + +  return result; +} diff --git a/libpthread/nptl/pthread_equal.c b/libpthread/nptl/pthread_equal.c new file mode 100644 index 000000000..c9986096f --- /dev/null +++ b/libpthread/nptl/pthread_equal.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +__pthread_equal (thread1, thread2) +     pthread_t thread1; +     pthread_t thread2; +{ +  return thread1 == thread2; +} +strong_alias (__pthread_equal, pthread_equal) diff --git a/libpthread/nptl/pthread_exit.c b/libpthread/nptl/pthread_exit.c new file mode 100644 index 000000000..85d8fd456 --- /dev/null +++ b/libpthread/nptl/pthread_exit.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +__pthread_exit (value) +     void *value; +{ +  THREAD_SETMEM (THREAD_SELF, result, value); + +  __do_cancel (); +} +strong_alias (__pthread_exit, pthread_exit) diff --git a/libpthread/nptl/pthread_getattr_np.c b/libpthread/nptl/pthread_getattr_np.c new file mode 100644 index 000000000..ba720af6c --- /dev/null +++ b/libpthread/nptl/pthread_getattr_np.c @@ -0,0 +1,177 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <string.h> +#include <sys/resource.h> +#include "pthreadP.h" +#include <lowlevellock.h> +#include <ldsodefs.h> + + +int +pthread_getattr_np (thread_id, attr) +     pthread_t thread_id; +     pthread_attr_t *attr; +{ +  struct pthread *thread = (struct pthread *) thread_id; +  struct pthread_attr *iattr = (struct pthread_attr *) attr; +  int ret = 0; + +  /* We have to handle cancellation in the following code since we are +     locking another threads desriptor.  */ +  pthread_cleanup_push ((void (*) (void *)) lll_unlock_wake_cb, &thread->lock); + +  lll_lock (thread->lock); + +  /* The thread library is responsible for keeping the values in the +     thread desriptor up-to-date in case the user changes them.  */ +  memcpy (&iattr->schedparam, &thread->schedparam, +	  sizeof (struct sched_param)); +  iattr->schedpolicy = thread->schedpolicy; + +  /* Clear the flags work.  */ +  iattr->flags = thread->flags; + +  /* The thread might be detached by now.  */ +  if (IS_DETACHED (thread)) +    iattr->flags |= ATTR_FLAG_DETACHSTATE; + +  /* This is the guardsize after adjusting it.  */ +  iattr->guardsize = thread->reported_guardsize; + +  /* The sizes are subject to alignment.  */ +  if (__builtin_expect (thread->stackblock != NULL, 1)) +    { +      iattr->stacksize = thread->stackblock_size; +      iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize; +    } +  else +    { +      /* No stack information available.  This must be for the initial +	 thread.  Get the info in some magical way.  */ +      assert (abs (thread->pid) == thread->tid); + +      /* Stack size limit.  */ +      struct rlimit rl; + +      /* The safest way to get the top of the stack is to read +	 /proc/self/maps and locate the line into which +	 __libc_stack_end falls.  */ +      FILE *fp = fopen ("/proc/self/maps", "rc"); +      if (fp == NULL) +	ret = errno; +      /* We need the limit of the stack in any case.  */ +      else if (getrlimit (RLIMIT_STACK, &rl) != 0) +	ret = errno; +      else +	{ +	  /* We need no locking.  */ +	  __fsetlocking (fp, FSETLOCKING_BYCALLER); + +	  /* Until we found an entry (which should always be the case) +	     mark the result as a failure.  */ +	  ret = ENOENT; + +	  char *line = NULL; +	  size_t linelen = 0; +	  uintptr_t last_to = 0; + +	  while (! feof_unlocked (fp)) +	    { +	      if (__getdelim (&line, &linelen, '\n', fp) <= 0) +		break; + +	      uintptr_t from; +	      uintptr_t to; +	      if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) +		continue; +	      if (from <= (uintptr_t) __libc_stack_end +		  && (uintptr_t) __libc_stack_end < to) +		{ +		  /* Found the entry.  Now we have the info we need.  */ +		  iattr->stacksize = rl.rlim_cur; +		  iattr->stackaddr = (void *) to; + +		  /* The limit might be too high.  */ +		  if ((size_t) iattr->stacksize +		      > (size_t) iattr->stackaddr - last_to) +		    iattr->stacksize = (size_t) iattr->stackaddr - last_to; + +		  /* We succeed and no need to look further.  */ +		  ret = 0; +		  break; +		} +	      last_to = to; +	    } + +	  fclose (fp); +	  free (line); +	} +    } + +  iattr->flags |= ATTR_FLAG_STACKADDR; + +  if (ret == 0) +    { +      size_t size = 16; +      cpu_set_t *cpuset = NULL; + +      do +	{ +	  size <<= 1; + +	  void *newp = realloc (cpuset, size); +	  if (newp == NULL) +	    { +	      ret = ENOMEM; +	      break; +	    } +	  cpuset = (cpu_set_t *) newp; + +	  ret = __pthread_getaffinity_np (thread_id, size, cpuset); +	} +      /* Pick some ridiculous upper limit.  Is 8 million CPUs enough?  */ +      while (ret == EINVAL && size < 1024 * 1024); + +      if (ret == 0) +	{ +	  iattr->cpuset = cpuset; +	  iattr->cpusetsize = size; +	} +      else +	{ +	  free (cpuset); +	  if (ret == ENOSYS) +	    /* There is no such functionality.  */ +	    ret = 0; +	} +    } + +  lll_unlock (thread->lock); + +  pthread_cleanup_pop (0); + +  return ret; +} diff --git a/libpthread/nptl/pthread_getconcurrency.c b/libpthread/nptl/pthread_getconcurrency.c new file mode 100644 index 000000000..52c0c7cbe --- /dev/null +++ b/libpthread/nptl/pthread_getconcurrency.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_getconcurrency (void) +{ +  return __concurrency_level; +} diff --git a/libpthread/nptl/pthread_getschedparam.c b/libpthread/nptl/pthread_getschedparam.c new file mode 100644 index 000000000..434d86777 --- /dev/null +++ b/libpthread/nptl/pthread_getschedparam.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <string.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_getschedparam (threadid, policy, param) +     pthread_t threadid; +     int *policy; +     struct sched_param *param; +{ +  struct pthread *pd = (struct pthread *) threadid; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  int result = 0; + +  /* We have to handle cancellation in the following code since we are +     locking another threads descriptor.  */ +  pthread_cleanup_push ((void (*) (void *)) lll_unlock_wake_cb, &pd->lock); + +  lll_lock (pd->lock); + +  /* The library is responsible for maintaining the values at all +     times.  If the user uses a interface other than +     pthread_setschedparam to modify the scheduler setting it is not +     the library's problem.  In case the descriptor's values have +     not yet been retrieved do it now.  */ +  if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) +    { +      if (__sched_getparam (pd->tid, &pd->schedparam) != 0) +	result = 1; +      else +	pd->flags |= ATTR_FLAG_SCHED_SET; +    } + +  if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) +    { +      pd->schedpolicy = __sched_getscheduler (pd->tid); +      if (pd->schedpolicy == -1) +	result = 1; +      else +	pd->flags |= ATTR_FLAG_POLICY_SET; +    } + +  if (result == 0) +    { +      *policy = pd->schedpolicy; +      memcpy (param, &pd->schedparam, sizeof (struct sched_param)); +    } + +  lll_unlock (pd->lock); + +  pthread_cleanup_pop (0); + +  return result; +} +strong_alias (__pthread_getschedparam, pthread_getschedparam) diff --git a/libpthread/nptl/pthread_getspecific.c b/libpthread/nptl/pthread_getspecific.c new file mode 100644 index 000000000..afb4d26ff --- /dev/null +++ b/libpthread/nptl/pthread_getspecific.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void * +__pthread_getspecific (key) +     pthread_key_t key; +{ +  struct pthread_key_data *data; + +  /* Special case access to the first 2nd-level block.  This is the +     usual case.  */ +  if (__builtin_expect (key < PTHREAD_KEY_2NDLEVEL_SIZE, 1)) +    data = &THREAD_SELF->specific_1stblock[key]; +  else +    { +      /* Verify the key is sane.  */ +      if (key >= PTHREAD_KEYS_MAX) +	/* Not valid.  */ +	return NULL; + +      unsigned int idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; +      unsigned int idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + +      /* If the sequence number doesn't match or the key cannot be defined +	 for this thread since the second level array is not allocated +	 return NULL, too.  */ +      struct pthread_key_data *level2 = THREAD_GETMEM_NC (THREAD_SELF, +							  specific, idx1st); +      if (level2 == NULL) +	/* Not allocated, therefore no data.  */ +	return NULL; + +      /* There is data.  */ +      data = &level2[idx2nd]; +    } + +  void *result = data->data; +  if (result != NULL) +    { +      uintptr_t seq = data->seq; + +      if (__builtin_expect (seq != __pthread_keys[key].seq, 0)) +	result = data->data = NULL; +    } + +  return result; +} +strong_alias (__pthread_getspecific, pthread_getspecific) +strong_alias (__pthread_getspecific, __pthread_getspecific_internal) diff --git a/libpthread/nptl/pthread_join.c b/libpthread/nptl/pthread_join.c new file mode 100644 index 000000000..f94128dd9 --- /dev/null +++ b/libpthread/nptl/pthread_join.c @@ -0,0 +1,108 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> + +#include "atomic.h" +#include "pthreadP.h" + + +static void +cleanup (void *arg) +{ +  *(void **) arg = NULL; +} + + +int +pthread_join (threadid, thread_return) +     pthread_t threadid; +     void **thread_return; +{ +  struct pthread *self; +  struct pthread *pd = (struct pthread *) threadid; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_NOT_TERMINATED_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  /* Is the thread joinable?.  */ +  if (IS_DETACHED (pd)) +    /* We cannot wait for the thread.  */ +    return EINVAL; + +  self = THREAD_SELF; +  if (pd == self +      || (self->joinid == pd +	  && (pd->cancelhandling +	      & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK +		 | TERMINATED_BITMASK)) == 0)) +    /* This is a deadlock situation.  The threads are waiting for each +       other to finish.  Note that this is a "may" error.  To be 100% +       sure we catch this error we would have to lock the data +       structures but it is not necessary.  In the unlikely case that +       two threads are really caught in this situation they will +       deadlock.  It is the programmer's problem to figure this +       out.  */ +    return EDEADLK; + +  /* Wait for the thread to finish.  If it is already locked something +     is wrong.  There can only be one waiter.  */ +  if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid, +							      self, +							      NULL), 0)) +    /* There is already somebody waiting for the thread.  */ +    return EINVAL; + + +  /* During the wait we change to asynchronous cancellation.  If we +     are cancelled the thread we are waiting for must be marked as +     un-wait-ed for again.  */ +  pthread_cleanup_push (cleanup, &pd->joinid); + +  /* Switch to asynchronous cancellation.  */ +  int oldtype = CANCEL_ASYNC (); + + +  /* Wait for the child.  */ +  lll_wait_tid (pd->tid); + + +  /* Restore cancellation mode.  */ +  CANCEL_RESET (oldtype); + +  /* Remove the handler.  */ +  pthread_cleanup_pop (0); + + +  /* We mark the thread as terminated and as joined.  */ +  pd->tid = -1; + +  /* Store the return value if the caller is interested.  */ +  if (thread_return != NULL) +    *thread_return = pd->result; + + +  /* Free the TCB.  */ +  __free_tcb (pd); + +  return 0; +} diff --git a/libpthread/nptl/pthread_key_create.c b/libpthread/nptl/pthread_key_create.c new file mode 100644 index 000000000..cf35bc877 --- /dev/null +++ b/libpthread/nptl/pthread_key_create.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + + +/* Internal mutex for __pthread_keys table handling.  */ +lll_lock_t __pthread_keys_lock = LLL_LOCK_INITIALIZER; + +int +__pthread_key_create (key, destr) +     pthread_key_t *key; +     void (*destr) (void *); +{ +  int result = EAGAIN; +  size_t cnt; + +  lll_lock (__pthread_keys_lock); + +  /* Find a slot in __pthread_kyes which is unused.  */ +  for (cnt = 0; cnt < PTHREAD_KEYS_MAX; ++cnt) +    if (KEY_UNUSED (__pthread_keys[cnt].seq) +	&& KEY_USABLE (__pthread_keys[cnt].seq)) +      { +	/* We found an unused slot.  */ +	++__pthread_keys[cnt].seq; + +	/* Remember the destructor.  */ +	__pthread_keys[cnt].destr = destr; + +	/* Return the key to the caller.  */ +	*key = cnt; + +	/* The call succeeded.  */ +	result = 0; + +	/* We found a key and can stop now.  */ +	break; +      } + +  lll_unlock (__pthread_keys_lock); + +  return result; +} +strong_alias (__pthread_key_create, pthread_key_create) +strong_alias (__pthread_key_create, __pthread_key_create_internal) diff --git a/libpthread/nptl/pthread_key_delete.c b/libpthread/nptl/pthread_key_delete.c new file mode 100644 index 000000000..ae7d7c459 --- /dev/null +++ b/libpthread/nptl/pthread_key_delete.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +pthread_key_delete (key) +     pthread_key_t key; +{ +  int result = EINVAL; + +  if (__builtin_expect (key < PTHREAD_KEYS_MAX, 1)) +    { +      unsigned int seq = __pthread_keys[key].seq; + +      if (__builtin_expect (! KEY_UNUSED (seq), 1) +	  && ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[key].seq, +						     seq + 1, seq)) +	/* We deleted a valid key.  */ +	result = 0; +    } + +  return result; +} diff --git a/libpthread/nptl/pthread_kill_other_threads.c b/libpthread/nptl/pthread_kill_other_threads.c new file mode 100644 index 000000000..a4464233a --- /dev/null +++ b/libpthread/nptl/pthread_kill_other_threads.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <shlib-compat.h> + + +#ifdef SHARED +/* This function does not serve a useful purpose in the thread library +   implementation anymore.  It used to be necessary when then kernel +   could not shut down "processes" but this is not the case anymore. + +   We could theoretically provide an equivalent implementation but +   this is not necessary since the kernel already does a much better +   job than we ever could.  */ +void +__pthread_kill_other_threads_np (void) +{ +} +compat_symbol (libpthread, __pthread_kill_other_threads_np, +	       pthread_kill_other_threads_np, GLIBC_2_0); +#endif diff --git a/libpthread/nptl/pthread_mutex_destroy.c b/libpthread/nptl/pthread_mutex_destroy.c new file mode 100644 index 000000000..91ccfb0d2 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_destroy.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_mutex_destroy (mutex) +     pthread_mutex_t *mutex; +{ +  if (mutex->__data.__nusers != 0) +    return EBUSY; + +  return 0; +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) +INTDEF(__pthread_mutex_destroy) diff --git a/libpthread/nptl/pthread_mutex_init.c b/libpthread/nptl/pthread_mutex_init.c new file mode 100644 index 000000000..074941daf --- /dev/null +++ b/libpthread/nptl/pthread_mutex_init.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <string.h> +#include "pthreadP.h" + + +static const struct pthread_mutexattr default_attr = +  { +    /* Default is a normal mutex, not shared between processes.  */ +    .mutexkind = PTHREAD_MUTEX_NORMAL +  }; + + +int +__pthread_mutex_init (mutex, mutexattr) +     pthread_mutex_t *mutex; +     const pthread_mutexattr_t *mutexattr; +{ +  const struct pthread_mutexattr *imutexattr; + +  assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T); + +  imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr; + +  /* Clear the whole variable.  */ +  memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T); + +  /* Copy the values from the attribute.  */ +  mutex->__data.__kind = imutexattr->mutexkind & ~0x80000000; + +  /* Default values: mutex not used yet.  */ +  // mutex->__count = 0;	already done by memset +  // mutex->__owner = 0;	already done by memset +  // mutex->__nusers = 0;	already done by memset +  // mutex->__spins = 0;	already done by memset + +  return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) +INTDEF(__pthread_mutex_init) diff --git a/libpthread/nptl/pthread_mutex_lock.c b/libpthread/nptl/pthread_mutex_lock.c new file mode 100644 index 000000000..ee39f2082 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_lock.c @@ -0,0 +1,119 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +#ifndef LLL_MUTEX_LOCK +# define LLL_MUTEX_LOCK(mutex) lll_mutex_lock (mutex) +# define LLL_MUTEX_TRYLOCK(mutex) lll_mutex_trylock (mutex) +#endif + + +int +__pthread_mutex_lock (mutex) +     pthread_mutex_t *mutex; +{ +  assert (sizeof (mutex->__size) >= sizeof (mutex->__data)); + +  pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + +  switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP)) +    { +      /* Recursive mutex.  */ +    case PTHREAD_MUTEX_RECURSIVE_NP: +      /* Check whether we already hold the mutex.  */ +      if (mutex->__data.__owner == id) +	{ +	  /* Just bump the counter.  */ +	  if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) +	    /* Overflow of the counter.  */ +	    return EAGAIN; + +	  ++mutex->__data.__count; + +	  return 0; +	} + +      /* We have to get the mutex.  */ +      LLL_MUTEX_LOCK (mutex->__data.__lock); + +      mutex->__data.__count = 1; +      break; + +      /* Error checking mutex.  */ +    case PTHREAD_MUTEX_ERRORCHECK_NP: +      /* Check whether we already hold the mutex.  */ +      if (mutex->__data.__owner == id) +	return EDEADLK; + +      /* FALLTHROUGH */ + +    default: +      /* Correct code cannot set any other type.  */ +    case PTHREAD_MUTEX_TIMED_NP: +    simple: +      /* Normal mutex.  */ +      LLL_MUTEX_LOCK (mutex->__data.__lock); +      break; + +    case PTHREAD_MUTEX_ADAPTIVE_NP: +      if (! __is_smp) +	goto simple; + +      if (LLL_MUTEX_TRYLOCK (mutex->__data.__lock) != 0) +	{ +	  int cnt = 0; +	  int max_cnt = MIN (MAX_ADAPTIVE_COUNT, +			     mutex->__data.__spins * 2 + 10); +	  do +	    { +	      if (cnt++ >= max_cnt) +		{ +		  LLL_MUTEX_LOCK (mutex->__data.__lock); +		  break; +		} + +#ifdef BUSY_WAIT_NOP +	      BUSY_WAIT_NOP; +#endif +	    } +	  while (LLL_MUTEX_TRYLOCK (mutex->__data.__lock) != 0); + +	  mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; +	} +      break; +    } + +  /* Record the ownership.  */ +  assert (mutex->__data.__owner == 0); +  mutex->__data.__owner = id; +#ifndef NO_INCR +  ++mutex->__data.__nusers; +#endif + +  return 0; +} +#ifndef __pthread_mutex_lock +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) +strong_alias (__pthread_mutex_lock, __pthread_mutex_lock_internal) +#endif diff --git a/libpthread/nptl/pthread_mutex_timedlock.c b/libpthread/nptl/pthread_mutex_timedlock.c new file mode 100644 index 000000000..1cd2c7e60 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_timedlock.c @@ -0,0 +1,118 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +pthread_mutex_timedlock (mutex, abstime) +     pthread_mutex_t *mutex; +     const struct timespec *abstime; +{ +  pid_t id = THREAD_GETMEM (THREAD_SELF, tid); +  int result = 0; + +  /* We must not check ABSTIME here.  If the thread does not block +     abstime must not be checked for a valid value.  */ + +  switch (mutex->__data.__kind) +    { +      /* Recursive mutex.  */ +    case PTHREAD_MUTEX_RECURSIVE_NP: +      /* Check whether we already hold the mutex.  */ +      if (mutex->__data.__owner == id) +	{ +	  /* Just bump the counter.  */ +	  if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) +	    /* Overflow of the counter.  */ +	    return EAGAIN; + +	  ++mutex->__data.__count; + +	  goto out; +	} +      else +	{ +	  /* We have to get the mutex.  */ +	  result = lll_mutex_timedlock (mutex->__data.__lock, abstime); + +	  if (result != 0) +	    goto out; + +	  /* Only locked once so far.  */ +	  mutex->__data.__count = 1; +	} +      break; + +      /* Error checking mutex.  */ +    case PTHREAD_MUTEX_ERRORCHECK_NP: +      /* Check whether we already hold the mutex.  */ +      if (mutex->__data.__owner == id) +	return EDEADLK; + +      /* FALLTHROUGH */ + +    default: +      /* Correct code cannot set any other type.  */ +    case PTHREAD_MUTEX_TIMED_NP: +    simple: +      /* Normal mutex.  */ +      result = lll_mutex_timedlock (mutex->__data.__lock, abstime); +      break; + +    case PTHREAD_MUTEX_ADAPTIVE_NP: +      if (! __is_smp) +	goto simple; + +      if (lll_mutex_trylock (mutex->__data.__lock) != 0) +	{ +	  int cnt = 0; +	  int max_cnt = MIN (MAX_ADAPTIVE_COUNT, +			     mutex->__data.__spins * 2 + 10); +	  do +	    { +	      if (cnt++ >= max_cnt) +		{ +		  result = lll_mutex_timedlock (mutex->__data.__lock, abstime); +		  break; +		} + +#ifdef BUSY_WAIT_NOP +	      BUSY_WAIT_NOP; +#endif +	    } +	  while (lll_mutex_trylock (mutex->__data.__lock) != 0); + +	  mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; +	} +      break; +    } + +  if (result == 0) +    { +      /* Record the ownership.  */ +      mutex->__data.__owner = id; +      ++mutex->__data.__nusers; +    } + + out: +  return result; +} diff --git a/libpthread/nptl/pthread_mutex_trylock.c b/libpthread/nptl/pthread_mutex_trylock.c new file mode 100644 index 000000000..7008af3d9 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_trylock.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_mutex_trylock (mutex) +     pthread_mutex_t *mutex; +{ +  pid_t id; + +  switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP)) +    { +      /* Recursive mutex.  */ +    case PTHREAD_MUTEX_RECURSIVE_NP: +      id = THREAD_GETMEM (THREAD_SELF, tid); +      /* Check whether we already hold the mutex.  */ +      if (mutex->__data.__owner == id) +	{ +	  /* Just bump the counter.  */ +	  if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) +	    /* Overflow of the counter.  */ +	    return EAGAIN; + +	  ++mutex->__data.__count; +	  return 0; +	} + +      if (lll_mutex_trylock (mutex->__data.__lock) == 0) +	{ +	  /* Record the ownership.  */ +	  mutex->__data.__owner = id; +	  mutex->__data.__count = 1; +	  ++mutex->__data.__nusers; +	  return 0; +	} +      break; + +    case PTHREAD_MUTEX_ERRORCHECK_NP: +      /* Error checking mutex.  We do not check for deadlocks.  */ +    default: +      /* Correct code cannot set any other type.  */ +    case PTHREAD_MUTEX_TIMED_NP: +    case PTHREAD_MUTEX_ADAPTIVE_NP: +      /* Normal mutex.  */ +      if (lll_mutex_trylock (mutex->__data.__lock) == 0) +	{ +	  /* Record the ownership.  */ +	  mutex->__data.__owner = THREAD_GETMEM (THREAD_SELF, tid); +	  ++mutex->__data.__nusers; + +	  return 0; +	} +    } + +  return EBUSY; +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) diff --git a/libpthread/nptl/pthread_mutex_unlock.c b/libpthread/nptl/pthread_mutex_unlock.c new file mode 100644 index 000000000..32bc2a4bc --- /dev/null +++ b/libpthread/nptl/pthread_mutex_unlock.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +internal_function attribute_hidden +__pthread_mutex_unlock_usercnt (mutex, decr) +     pthread_mutex_t *mutex; +     int decr; +{ +  switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP)) +    { +    case PTHREAD_MUTEX_RECURSIVE_NP: +      /* Recursive mutex.  */ +      if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) +	return EPERM; + +      if (--mutex->__data.__count != 0) +	/* We still hold the mutex.  */ +	return 0; +      break; + +    case PTHREAD_MUTEX_ERRORCHECK_NP: +      /* Error checking mutex.  */ +      if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid) +	  || ! lll_mutex_islocked (mutex->__data.__lock)) +	return EPERM; +      break; + +    default: +      /* Correct code cannot set any other type.  */ +    case PTHREAD_MUTEX_TIMED_NP: +    case PTHREAD_MUTEX_ADAPTIVE_NP: +      /* Normal mutex.  Nothing special to do.  */ +      break; +    } + +  /* Always reset the owner field.  */ +  mutex->__data.__owner = 0; +  if (decr) +    /* One less user.  */ +    --mutex->__data.__nusers; + +  /* Unlock.  */ +  lll_mutex_unlock (mutex->__data.__lock); + +  return 0; +} + + +int +__pthread_mutex_unlock (mutex) +     pthread_mutex_t *mutex; +{ +  return __pthread_mutex_unlock_usercnt (mutex, 1); +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) +strong_alias (__pthread_mutex_unlock, __pthread_mutex_unlock_internal) diff --git a/libpthread/nptl/pthread_mutexattr_destroy.c b/libpthread/nptl/pthread_mutexattr_destroy.c new file mode 100644 index 000000000..eab27d351 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_destroy.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthreadP.h> + + +int +__pthread_mutexattr_destroy (attr) +     pthread_mutexattr_t *attr; +{ +  return 0; +} +strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy) diff --git a/libpthread/nptl/pthread_mutexattr_getpshared.c b/libpthread/nptl/pthread_mutexattr_getpshared.c new file mode 100644 index 000000000..4bd4ea18d --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_getpshared.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthreadP.h> + + +int +pthread_mutexattr_getpshared (attr, pshared) +     const pthread_mutexattr_t *attr; +     int *pshared; +{ +  const struct pthread_mutexattr *iattr; + +  iattr = (const struct pthread_mutexattr *) attr; + +  /* We use bit 31 to signal whether the mutex is going to be +     process-shared or not.  */ +  *pshared = ((iattr->mutexkind & 0x80000000) != 0 +	      ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE); + +  return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_gettype.c b/libpthread/nptl/pthread_mutexattr_gettype.c new file mode 100644 index 000000000..5c32b2c6f --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_gettype.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthreadP.h> + + +int +pthread_mutexattr_gettype (attr, kind) +     const pthread_mutexattr_t *attr; +     int *kind; +{ +  const struct pthread_mutexattr *iattr; + +  iattr = (const struct pthread_mutexattr *) attr; + +  /* We use bit 31 to signal whether the mutex is going to be +     process-shared or not.  */ +  *kind = iattr->mutexkind & ~0x80000000; + +  return 0; +} +weak_alias (pthread_mutexattr_gettype, pthread_mutexattr_getkind_np) diff --git a/libpthread/nptl/pthread_mutexattr_init.c b/libpthread/nptl/pthread_mutexattr_init.c new file mode 100644 index 000000000..ee026c654 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_init.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <string.h> +#include <pthreadP.h> + + +int +__pthread_mutexattr_init (attr) +     pthread_mutexattr_t *attr; +{ +  if (sizeof (struct pthread_mutexattr) != sizeof (pthread_mutexattr_t)) +    memset (attr, '\0', sizeof (*attr)); + +  /* We use bit 31 to signal whether the mutex is going to be +     process-shared or not.  By default it is zero, i.e., the mutex is +     not process-shared.  */ +  ((struct pthread_mutexattr *) attr)->mutexkind = PTHREAD_MUTEX_NORMAL; + +  return 0; +} +strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init) diff --git a/libpthread/nptl/pthread_mutexattr_setpshared.c b/libpthread/nptl/pthread_mutexattr_setpshared.c new file mode 100644 index 000000000..5f2cf417e --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_setpshared.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutexattr_setpshared (attr, pshared) +     pthread_mutexattr_t *attr; +     int pshared; +{ +  struct pthread_mutexattr *iattr; + +  if (pshared != PTHREAD_PROCESS_PRIVATE +      && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) +    return EINVAL; + +  iattr = (struct pthread_mutexattr *) attr; + +  /* We use bit 31 to signal whether the mutex is going to be +     process-shared or not.  */ +  if (pshared == PTHREAD_PROCESS_PRIVATE) +    iattr->mutexkind &= ~0x80000000; +  else +    iattr->mutexkind |= 0x80000000; + +  return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_settype.c b/libpthread/nptl/pthread_mutexattr_settype.c new file mode 100644 index 000000000..c77fe79df --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_settype.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <pthreadP.h> + + +int +__pthread_mutexattr_settype (attr, kind) +     pthread_mutexattr_t *attr; +     int kind; +{ +  struct pthread_mutexattr *iattr; + +  if (kind < PTHREAD_MUTEX_NORMAL || kind > PTHREAD_MUTEX_ADAPTIVE_NP) +    return EINVAL; + +  iattr = (struct pthread_mutexattr *) attr; + +  /* We use bit 31 to signal whether the mutex is going to be +     process-shared or not.  */ +  iattr->mutexkind = (iattr->mutexkind & 0x80000000) | kind; + +  return 0; +} +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_setkind_np) +strong_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype) diff --git a/libpthread/nptl/pthread_rwlock_destroy.c b/libpthread/nptl/pthread_rwlock_destroy.c new file mode 100644 index 000000000..28fd24b55 --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_destroy.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +__pthread_rwlock_destroy (rwlock) +     pthread_rwlock_t *rwlock; +{ +  /* Nothing to be done.  For now.  */ +  return 0; +} +strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy) diff --git a/libpthread/nptl/pthread_rwlock_init.c b/libpthread/nptl/pthread_rwlock_init.c new file mode 100644 index 000000000..f664dd810 --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_init.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +static const struct pthread_rwlockattr default_attr = +  { +    .lockkind = PTHREAD_RWLOCK_DEFAULT_NP, +    .pshared = PTHREAD_PROCESS_PRIVATE +  }; + + +int +__pthread_rwlock_init (rwlock, attr) +     pthread_rwlock_t *rwlock; +     const pthread_rwlockattr_t *attr; +{ +  const struct pthread_rwlockattr *iattr; + +  iattr = ((const struct pthread_rwlockattr *) attr) ?: &default_attr; + +  rwlock->__data.__lock = 0; +  rwlock->__data.__flags +    = iattr->lockkind == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP; +  rwlock->__data.__nr_readers = 0; +  rwlock->__data.__writer = 0; +  rwlock->__data.__readers_wakeup = 0; +  rwlock->__data.__writer_wakeup = 0; +  rwlock->__data.__nr_readers_queued = 0; +  rwlock->__data.__nr_writers_queued = 0; + +  return 0; +} +strong_alias (__pthread_rwlock_init, pthread_rwlock_init) diff --git a/libpthread/nptl/pthread_rwlock_tryrdlock.c b/libpthread/nptl/pthread_rwlock_tryrdlock.c new file mode 100644 index 000000000..446af0596 --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_tryrdlock.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_rwlock_tryrdlock (rwlock) +     pthread_rwlock_t *rwlock; +{ +  int result = EBUSY; + +  lll_mutex_lock (rwlock->__data.__lock); + +  if (rwlock->__data.__writer == 0 +      && (rwlock->__data.__nr_writers_queued == 0 +	  || rwlock->__data.__flags == 0)) +    { +      if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0)) +	{ +	  --rwlock->__data.__nr_readers; +	  result = EAGAIN; +	} +      else +	result = 0; +    } + +  lll_mutex_unlock (rwlock->__data.__lock); + +  return result; +} +strong_alias (__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock) diff --git a/libpthread/nptl/pthread_rwlock_trywrlock.c b/libpthread/nptl/pthread_rwlock_trywrlock.c new file mode 100644 index 000000000..b754a1956 --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_trywrlock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_rwlock_trywrlock (rwlock) +     pthread_rwlock_t *rwlock; +{ +  int result = EBUSY; + +  lll_mutex_lock (rwlock->__data.__lock); + +  if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) +    { +      rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); +      result = 0; +    } + +  lll_mutex_unlock (rwlock->__data.__lock); + +  return result; +} +strong_alias (__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock) diff --git a/libpthread/nptl/pthread_rwlockattr_destroy.c b/libpthread/nptl/pthread_rwlockattr_destroy.c new file mode 100644 index 000000000..4f0c2c4fe --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_destroy.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_destroy (attr) +     pthread_rwlockattr_t *attr; +{ +  /* Nothing to do.  For now.  */ + +  return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_getkind_np.c b/libpthread/nptl/pthread_rwlockattr_getkind_np.c new file mode 100644 index 000000000..aad9468fd --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_getkind_np.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_getkind_np (attr, pref) +     const pthread_rwlockattr_t *attr; +     int *pref; +{ +  *pref = ((const struct pthread_rwlockattr *) attr)->lockkind; + +  return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_getpshared.c b/libpthread/nptl/pthread_rwlockattr_getpshared.c new file mode 100644 index 000000000..3a776835a --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_getpshared (attr, pshared) +     const pthread_rwlockattr_t *attr; +     int *pshared; +{ +  *pshared = ((const struct pthread_rwlockattr *) attr)->pshared; + +  return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_init.c b/libpthread/nptl/pthread_rwlockattr_init.c new file mode 100644 index 000000000..b29953455 --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_init.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_init (attr) +     pthread_rwlockattr_t *attr; +{ +  struct pthread_rwlockattr *iattr; + +  iattr = (struct pthread_rwlockattr *) attr; + +  iattr->lockkind = PTHREAD_RWLOCK_DEFAULT_NP; +  iattr->pshared = PTHREAD_PROCESS_PRIVATE; + +  return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_setkind_np.c b/libpthread/nptl/pthread_rwlockattr_setkind_np.c new file mode 100644 index 000000000..0311f1b50 --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_setkind_np.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + + +int +pthread_rwlockattr_setkind_np (attr, pref) +     pthread_rwlockattr_t *attr; +     int pref; +{ +  struct pthread_rwlockattr *iattr; + +  if (pref != PTHREAD_RWLOCK_PREFER_READER_NP +      && pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP +      && __builtin_expect  (pref != PTHREAD_RWLOCK_PREFER_WRITER_NP, 0)) +    return EINVAL; + +  iattr = (struct pthread_rwlockattr *) attr; + +  iattr->lockkind = pref; + +  return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_setpshared.c b/libpthread/nptl/pthread_rwlockattr_setpshared.c new file mode 100644 index 000000000..9438d2931 --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_setpshared.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + + +int +pthread_rwlockattr_setpshared (attr, pshared) +     pthread_rwlockattr_t *attr; +     int pshared; +{ +  struct pthread_rwlockattr *iattr; + +  if (pshared != PTHREAD_PROCESS_SHARED +      && __builtin_expect (pshared != PTHREAD_PROCESS_PRIVATE, 0)) +    return EINVAL; + +  iattr = (struct pthread_rwlockattr *) attr; + +  iattr->pshared = pshared; + +  return 0; +} diff --git a/libpthread/nptl/pthread_self.c b/libpthread/nptl/pthread_self.c new file mode 100644 index 000000000..f0e3b3f98 --- /dev/null +++ b/libpthread/nptl/pthread_self.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" +#include <tls.h> + + +pthread_t +__pthread_self (void) +{ +  return (pthread_t) THREAD_SELF; +} +strong_alias (__pthread_self, pthread_self) diff --git a/libpthread/nptl/pthread_setcancelstate.c b/libpthread/nptl/pthread_setcancelstate.c new file mode 100644 index 000000000..a452c2ec4 --- /dev/null +++ b/libpthread/nptl/pthread_setcancelstate.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +__pthread_setcancelstate (state, oldstate) +     int state; +     int *oldstate; +{ +  volatile struct pthread *self; + +  if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) +    return EINVAL; + +  self = THREAD_SELF; + +  int oldval = THREAD_GETMEM (self, cancelhandling); +  while (1) +    { +      int newval = (state == PTHREAD_CANCEL_DISABLE +		    ? oldval | CANCELSTATE_BITMASK +		    : oldval & ~CANCELSTATE_BITMASK); + +      /* Store the old value.  */ +      if (oldstate != NULL) +	*oldstate = ((oldval & CANCELSTATE_BITMASK) +		     ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE); + +      /* Avoid doing unnecessary work.  The atomic operation can +	 potentially be expensive if the memory has to be locked and +	 remote cache lines have to be invalidated.  */ +      if (oldval == newval) +	break; + +      /* Update the cancel handling word.  This has to be done +	 atomically since other bits could be modified as well.  */ +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	{ +	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) +	    __do_cancel (); + +	  break; +	} + +      /* Prepare for the next round.  */ +      oldval = curval; +    } + +  return 0; +} +strong_alias (__pthread_setcancelstate, pthread_setcancelstate) diff --git a/libpthread/nptl/pthread_setcanceltype.c b/libpthread/nptl/pthread_setcanceltype.c new file mode 100644 index 000000000..bbe87ba64 --- /dev/null +++ b/libpthread/nptl/pthread_setcanceltype.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +__pthread_setcanceltype (type, oldtype) +     int type; +     int *oldtype; +{ +  volatile struct pthread *self; + +  if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) +    return EINVAL; + +  self = THREAD_SELF; + +  int oldval = THREAD_GETMEM (self, cancelhandling); +  while (1) +    { +      int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS +		    ? oldval | CANCELTYPE_BITMASK +		    : oldval & ~CANCELTYPE_BITMASK); + +      /* Store the old value.  */ +      if (oldtype != NULL) +	*oldtype = ((oldval & CANCELTYPE_BITMASK) +		    ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED); + +      /* Avoid doing unnecessary work.  The atomic operation can +	 potentially be expensive if the memory has to be locked and +	 remote cache lines have to be invalidated.  */ +      if (oldval == newval) +	break; + +      /* Update the cancel handling word.  This has to be done +	 atomically since other bits could be modified as well.  */ +      int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, +					      oldval); +      if (__builtin_expect (curval == oldval, 1)) +	{ +	  if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) +	    { +	      THREAD_SETMEM (self, result, PTHREAD_CANCELED); +	      __do_cancel (); +	    } + +	  break; +	} + +      /* Prepare for the next round.  */ +      oldval = curval; +    } + +  return 0; +} +strong_alias (__pthread_setcanceltype, pthread_setcanceltype) diff --git a/libpthread/nptl/pthread_setconcurrency.c b/libpthread/nptl/pthread_setconcurrency.c new file mode 100644 index 000000000..8cf150713 --- /dev/null +++ b/libpthread/nptl/pthread_setconcurrency.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + + +/* Global definition.  Needed in pthread_getconcurrency as well.  */ +int __concurrency_level; + + +int +pthread_setconcurrency (level) +     int level; +{ +  if (level < 0) +    return EINVAL; + +  __concurrency_level = level; + +  /* XXX For ports which actually need to handle the concurrency level +     some more code is probably needed here.  */ + +  return 0; +} diff --git a/libpthread/nptl/pthread_setegid.c b/libpthread/nptl/pthread_setegid.c new file mode 100644 index 000000000..9252dfac7 --- /dev/null +++ b/libpthread/nptl/pthread_setegid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define setegid pthread_setegid_np +#include <setegid.c> diff --git a/libpthread/nptl/pthread_seteuid.c b/libpthread/nptl/pthread_seteuid.c new file mode 100644 index 000000000..47bb69802 --- /dev/null +++ b/libpthread/nptl/pthread_seteuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define seteuid pthread_seteuid_np +#include <seteuid.c> diff --git a/libpthread/nptl/pthread_setgid.c b/libpthread/nptl/pthread_setgid.c new file mode 100644 index 000000000..b06bffbf3 --- /dev/null +++ b/libpthread/nptl/pthread_setgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setgid pthread_setgid_np +#include <setgid.c> diff --git a/libpthread/nptl/pthread_setregid.c b/libpthread/nptl/pthread_setregid.c new file mode 100644 index 000000000..7461d2b7f --- /dev/null +++ b/libpthread/nptl/pthread_setregid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setregid pthread_setregid_np +#include <setregid.c> diff --git a/libpthread/nptl/pthread_setresgid.c b/libpthread/nptl/pthread_setresgid.c new file mode 100644 index 000000000..369fae267 --- /dev/null +++ b/libpthread/nptl/pthread_setresgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresgid pthread_setresgid_np +#include <setresgid.c> diff --git a/libpthread/nptl/pthread_setresuid.c b/libpthread/nptl/pthread_setresuid.c new file mode 100644 index 000000000..ac57c0fa8 --- /dev/null +++ b/libpthread/nptl/pthread_setresuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresuid pthread_setresuid_np +#include <setresuid.c> diff --git a/libpthread/nptl/pthread_setreuid.c b/libpthread/nptl/pthread_setreuid.c new file mode 100644 index 000000000..aa804ab01 --- /dev/null +++ b/libpthread/nptl/pthread_setreuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setreuid pthread_setreuid_np +#include <setreuid.c> diff --git a/libpthread/nptl/pthread_setschedparam.c b/libpthread/nptl/pthread_setschedparam.c new file mode 100644 index 000000000..5889cc98a --- /dev/null +++ b/libpthread/nptl/pthread_setschedparam.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <sched.h> +#include <string.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_setschedparam (threadid, policy, param) +     pthread_t threadid; +     int policy; +     const struct sched_param *param; +{ +  struct pthread *pd = (struct pthread *) threadid; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  int result = 0; + +  /* We have to handle cancellation in the following code since we are +     locking another threads desriptor.  */ +  pthread_cleanup_push ((void (*) (void *)) lll_unlock_wake_cb, &pd->lock); + +  lll_lock (pd->lock); + +  /* Try to set the scheduler information.  */ +  if (__builtin_expect (__sched_setscheduler (pd->tid, policy, +					      param) == -1, 0)) +    result = errno; +  else +    { +      /* We succeeded changing the kernel information.  Reflect this +	 change in the thread descriptor.  */ +      pd->schedpolicy = policy; +      memcpy (&pd->schedparam, param, sizeof (struct sched_param)); +      pd->flags |= ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET; +    } + +  lll_unlock (pd->lock); + +  pthread_cleanup_pop (0); + +  return result; +} +strong_alias (__pthread_setschedparam, pthread_setschedparam) diff --git a/libpthread/nptl/pthread_setschedprio.c b/libpthread/nptl/pthread_setschedprio.c new file mode 100644 index 000000000..063f5232f --- /dev/null +++ b/libpthread/nptl/pthread_setschedprio.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <sched.h> +#include <string.h> +#include <sched.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +pthread_setschedprio (threadid, prio) +     pthread_t threadid; +     int prio; +{ +  struct pthread *pd = (struct pthread *) threadid; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  int result = 0; +  struct sched_param param; +  param.sched_priority = prio; + +  /* We have to handle cancellation in the following code since we are +     locking another threads desriptor.  */ +  pthread_cleanup_push ((void (*) (void *)) lll_unlock_wake_cb, &pd->lock); + +  lll_lock (pd->lock); + +  /* Try to set the scheduler information.  */ +  if (__builtin_expect (sched_setparam (pd->tid, ¶m) == -1, 0)) +    result = errno; +  else +    { +      /* We succeeded changing the kernel information.  Reflect this +	 change in the thread descriptor.  */ +      memcpy (&pd->schedparam, ¶m, sizeof (struct sched_param)); +      pd->flags |= ATTR_FLAG_SCHED_SET; +    } + +  lll_unlock (pd->lock); + +  pthread_cleanup_pop (0); + +  return result; +} diff --git a/libpthread/nptl/pthread_setspecific.c b/libpthread/nptl/pthread_setspecific.c new file mode 100644 index 000000000..b6e66b5f2 --- /dev/null +++ b/libpthread/nptl/pthread_setspecific.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" + + +int +__pthread_setspecific (key, value) +     pthread_key_t key; +     const void *value; +{ +  struct pthread *self; +  unsigned int idx1st; +  unsigned int idx2nd; +  struct pthread_key_data *level2; +  unsigned int seq; + +  self = THREAD_SELF; + +  /* Special case access to the first 2nd-level block.  This is the +     usual case.  */ +  if (__builtin_expect (key < PTHREAD_KEY_2NDLEVEL_SIZE, 1)) +    { +      /* Verify the key is sane.  */ +      if (KEY_UNUSED ((seq = __pthread_keys[key].seq))) +	/* Not valid.  */ +	return EINVAL; + +      level2 = &self->specific_1stblock[key]; + +      /* Remember that we stored at least one set of data.  */ +      if (value != NULL) +	THREAD_SETMEM (self, specific_used, true); +    } +  else +    { +      if (KEY_UNUSED ((seq = __pthread_keys[key].seq)) +	  || key >= PTHREAD_KEYS_MAX) +	/* Not valid.  */ +	return EINVAL; + +      idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; +      idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + +      /* This is the second level array.  Allocate it if necessary.  */ +      level2 = THREAD_GETMEM_NC (self, specific, idx1st); +      if (level2 == NULL) +	{ +	  if (value == NULL) +	    /* We don't have to do anything.  The value would in any case +	       be NULL.  We can save the memory allocation.  */ +	    return 0; + +	  level2 +	    = (struct pthread_key_data *) calloc (PTHREAD_KEY_2NDLEVEL_SIZE, +						  sizeof (*level2)); +	  if (level2 == NULL) +	    return ENOMEM; + +	  THREAD_SETMEM_NC (self, specific, idx1st, level2); +	} + +      /* Pointer to the right array element.  */ +      level2 = &level2[idx2nd]; + +      /* Remember that we stored at least one set of data.  */ +      THREAD_SETMEM (self, specific_used, true); +    } + +  /* Store the data and the sequence number so that we can recognize +     stale data.  */ +  level2->seq = seq; +  level2->data = (void *) value; + +  return 0; +} +strong_alias (__pthread_setspecific, pthread_setspecific) +strong_alias (__pthread_setspecific, __pthread_setspecific_internal) diff --git a/libpthread/nptl/pthread_setuid.c b/libpthread/nptl/pthread_setuid.c new file mode 100644 index 000000000..ff949c850 --- /dev/null +++ b/libpthread/nptl/pthread_setuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setuid pthread_setuid_np +#include <setuid.c> diff --git a/libpthread/nptl/pthread_testcancel.c b/libpthread/nptl/pthread_testcancel.c new file mode 100644 index 000000000..e9b17b493 --- /dev/null +++ b/libpthread/nptl/pthread_testcancel.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +pthread_testcancel (void) +{ +  CANCELLATION_P (THREAD_SELF); +} diff --git a/libpthread/nptl/pthread_timedjoin.c b/libpthread/nptl/pthread_timedjoin.c new file mode 100644 index 000000000..1cc07213c --- /dev/null +++ b/libpthread/nptl/pthread_timedjoin.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> +#include "atomic.h" +#include "pthreadP.h" + + +static void +cleanup (void *arg) +{ +  *(void **) arg = NULL; +} + + +int +pthread_timedjoin_np (threadid, thread_return, abstime) +     pthread_t threadid; +     void **thread_return; +     const struct timespec *abstime; +{ +  struct pthread *self; +  struct pthread *pd = (struct pthread *) threadid; +  int result; + +  /* Make sure the descriptor is valid.  */ +  if (INVALID_NOT_TERMINATED_TD_P (pd)) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  /* Is the thread joinable?.  */ +  if (IS_DETACHED (pd)) +    /* We cannot wait for the thread.  */ +    return EINVAL; + +  self = THREAD_SELF; +  if (pd == self || self->joinid == pd) +    /* This is a deadlock situation.  The threads are waiting for each +       other to finish.  Note that this is a "may" error.  To be 100% +       sure we catch this error we would have to lock the data +       structures but it is not necessary.  In the unlikely case that +       two threads are really caught in this situation they will +       deadlock.  It is the programmer's problem to figure this +       out.  */ +    return EDEADLK; + +  /* Wait for the thread to finish.  If it is already locked something +     is wrong.  There can only be one waiter.  */ +  if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid, +							      self, NULL), 0)) +    /* There is already somebody waiting for the thread.  */ +    return EINVAL; + + +  /* During the wait we change to asynchronous cancellation.  If we +     are cancelled the thread we are waiting for must be marked as +     un-wait-ed for again.  */ +  pthread_cleanup_push (cleanup, &pd->joinid); + +  /* Switch to asynchronous cancellation.  */ +  int oldtype = CANCEL_ASYNC (); + + +  /* Wait for the child.  */ +  result = lll_timedwait_tid (pd->tid, abstime); + + +  /* Restore cancellation mode.  */ +  CANCEL_RESET (oldtype); + +  /* Remove the handler.  */ +  pthread_cleanup_pop (0); + + +  /* We might have timed out.  */ +  if (result == 0) +    { +      /* Store the return value if the caller is interested.  */ +      if (thread_return != NULL) +	*thread_return = pd->result; + + +      /* Free the TCB.  */ +      __free_tcb (pd); +    } +  else +    pd->joinid = NULL; + +  return result; +} diff --git a/libpthread/nptl/pthread_tryjoin.c b/libpthread/nptl/pthread_tryjoin.c new file mode 100644 index 000000000..904cb5280 --- /dev/null +++ b/libpthread/nptl/pthread_tryjoin.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <stdlib.h> + +#include "atomic.h" +#include "pthreadP.h" + + +int +pthread_tryjoin_np (threadid, thread_return) +     pthread_t threadid; +     void **thread_return; +{ +  struct pthread *self; +  struct pthread *pd = (struct pthread *) threadid; + +  /* Make sure the descriptor is valid.  */ +  if (DEBUGGING_P && __find_in_stack_list (pd) == NULL) +    /* Not a valid thread handle.  */ +    return ESRCH; + +  /* Is the thread joinable?.  */ +  if (IS_DETACHED (pd)) +    /* We cannot wait for the thread.  */ +    return EINVAL; + +  self = THREAD_SELF; +  if (pd == self || self->joinid == pd) +    /* This is a deadlock situation.  The threads are waiting for each +       other to finish.  Note that this is a "may" error.  To be 100% +       sure we catch this error we would have to lock the data +       structures but it is not necessary.  In the unlikely case that +       two threads are really caught in this situation they will +       deadlock.  It is the programmer's problem to figure this +       out.  */ +    return EDEADLK; + +  /* Return right away if the thread hasn't terminated yet.  */ +  if (pd->tid != 0) +    return EBUSY; + +  /* Wait for the thread to finish.  If it is already locked something +     is wrong.  There can only be one waiter.  */ +  if (atomic_compare_and_exchange_bool_acq (&pd->joinid, self, NULL)) +    /* There is already somebody waiting for the thread.  */ +    return EINVAL; + +  /* Store the return value if the caller is interested.  */ +  if (thread_return != NULL) +    *thread_return = pd->result; + + +  /* Free the TCB.  */ +  __free_tcb (pd); + +  return 0; +} diff --git a/libpthread/nptl/res.c b/libpthread/nptl/res.c new file mode 100644 index 000000000..ba4f81d06 --- /dev/null +++ b/libpthread/nptl/res.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002, 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <features.h> +#include <resolv.h> +#include <tls.h> + +struct __res_state * +__res_state (void) +{ +  return __resp; +} diff --git a/libpthread/nptl/sem_close.c b/libpthread/nptl/sem_close.c new file mode 100644 index 000000000..279522d08 --- /dev/null +++ b/libpthread/nptl/sem_close.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <search.h> +#include <sys/mman.h> +#include "semaphoreP.h" + + +/* Global variables to parametrize the walk function.  This works +   since we always have to use locks.  And we have to use the twalk +   function since the entries are not sorted wrt the mapping +   address.  */ +static sem_t *the_sem; +static struct inuse_sem *rec; + +static void +walker (const void *inodep, const VISIT which, const int depth) +{ +  struct inuse_sem *nodep = *(struct inuse_sem **) inodep; + +  if (nodep->sem == the_sem) +    rec = nodep; +} + + +int +sem_close (sem) +     sem_t *sem; +{ +  int result = 0; + +  /* Get the lock.  */ +  lll_lock (__sem_mappings_lock); + +  /* Locate the entry for the mapping the caller provided.  */ +  rec = NULL; +  the_sem = sem; +  twalk (__sem_mappings, walker); +  if  (rec != NULL) +    { +      /* Check the reference counter.  If it is going to be zero, free +	 all the resources.  */ +      if (--rec->refcnt == 0) +	{ +	  /* Remove the record from the tree.  */ +	  (void) tdelete (rec, &__sem_mappings, __sem_search); + +	  result = munmap (rec->sem, sizeof (sem_t)); + +	  free (rec); +	} +    } +  else +    { +      /* This is no valid semaphore.  */ +      result = -1; +      __set_errno (EINVAL); +    } + +  /* Release the lock.  */ +  lll_unlock (__sem_mappings_lock); + +  return result; +} diff --git a/libpthread/nptl/sem_destroy.c b/libpthread/nptl/sem_destroy.c new file mode 100644 index 000000000..1c823dc51 --- /dev/null +++ b/libpthread/nptl/sem_destroy.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <semaphore.h> +#include <shlib-compat.h> +#include "semaphoreP.h" + + +int +__new_sem_destroy (sem) +     sem_t *sem; +{ +  /* XXX Check for valid parameter.  */ + +  /* Nothing to do.  */ +  return 0; +} +versioned_symbol (libpthread, __new_sem_destroy, sem_destroy, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_destroy, __old_sem_destroy) +compat_symbol (libpthread, __old_sem_destroy, sem_destroy, GLIBC_2_0); +#endif diff --git a/libpthread/nptl/sem_getvalue.c b/libpthread/nptl/sem_getvalue.c new file mode 100644 index 000000000..6bc7ea82b --- /dev/null +++ b/libpthread/nptl/sem_getvalue.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <semaphore.h> +#include <shlib-compat.h> +#include "semaphoreP.h" + + +int +__new_sem_getvalue (sem, sval) +     sem_t *sem; +     int *sval; +{ +  struct sem *isem = (struct sem *) sem; + +  /* XXX Check for valid SEM parameter.  */ + +  *sval = isem->count; + +  return 0; +} +versioned_symbol (libpthread, __new_sem_getvalue, sem_getvalue, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_getvalue, __old_sem_getvalue) +compat_symbol (libpthread, __old_sem_getvalue, sem_getvalue, GLIBC_2_0); +#endif diff --git a/libpthread/nptl/sem_init.c b/libpthread/nptl/sem_init.c new file mode 100644 index 000000000..8709911ac --- /dev/null +++ b/libpthread/nptl/sem_init.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <semaphore.h> +#include <lowlevellock.h> +#include <shlib-compat.h> +#include "semaphoreP.h" + + +int +__new_sem_init (sem, pshared, value) +     sem_t *sem; +     int pshared; +     unsigned int value; +{ +  /* Parameter sanity check.  */ +  if (__builtin_expect (value > SEM_VALUE_MAX, 0)) +    { +      __set_errno (EINVAL); +      return -1; +    } + +  /* Map to the internal type.  */ +  struct sem *isem = (struct sem *) sem; + +  /* Use the value the user provided.  */ +  isem->count = value; + +  /* We can completely ignore the PSHARED parameter since inter-process +     use needs no special preparation.  */ + +  return 0; +} +versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_init, __old_sem_init) +compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0); +#endif diff --git a/libpthread/nptl/sem_open.c b/libpthread/nptl/sem_open.c new file mode 100644 index 000000000..a4b2f5b3a --- /dev/null +++ b/libpthread/nptl/sem_open.c @@ -0,0 +1,404 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <fcntl.h> +#include <mntent.h> +#include <paths.h> +#include <pthread.h> +#include <search.h> +#include <semaphore.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/statfs.h> +#include <linux_fsinfo.h> +#include "semaphoreP.h" + + + +/* Information about the mount point.  */ +struct mountpoint_info mountpoint attribute_hidden; + +/* This is the default mount point.  */ +static const char defaultmount[] = "/dev/shm"; +/* This is the default directory.  */ +static const char defaultdir[] = "/dev/shm/sem."; + +/* Protect the `mountpoint' variable above.  */ +pthread_once_t __namedsem_once attribute_hidden = PTHREAD_ONCE_INIT; + + +/* Determine where the shmfs is mounted (if at all).  */ +void +attribute_hidden +__where_is_shmfs (void) +{ +  char buf[512]; +  struct statfs f; +  struct mntent resmem; +  struct mntent *mp; +  FILE *fp; + +  /* The canonical place is /dev/shm.  This is at least what the +     documentation tells everybody to do.  */ +  if (__statfs (defaultmount, &f) == 0 && f.f_type == SHMFS_SUPER_MAGIC) +    { +      /* It is in the normal place.  */ +      mountpoint.dir = (char *) defaultdir; +      mountpoint.dirlen = sizeof (defaultdir) - 1; + +      return; +    } + +  /* OK, do it the hard way.  Look through the /proc/mounts file and if +     this does not exist through /etc/fstab to find the mount point.  */ +  fp = __setmntent ("/proc/mounts", "r"); +  if (__builtin_expect (fp == NULL, 0)) +    { +      fp = __setmntent (_PATH_MNTTAB, "r"); +      if (__builtin_expect (fp == NULL, 0)) +	/* There is nothing we can do.  Blind guesses are not helpful.  */ +	return; +    } + +  /* Now read the entries.  */ +  while ((mp = __getmntent_r (fp, &resmem, buf, sizeof buf)) != NULL) +    /* The original name is "shm" but this got changed in early Linux +       2.4.x to "tmpfs".  */ +    if (strcmp (mp->mnt_type, "tmpfs") == 0 +	|| strcmp (mp->mnt_type, "shm") == 0) +      { +	/* Found it.  There might be more than one place where the +           filesystem is mounted but one is enough for us.  */ +	size_t namelen; + +	/* First make sure this really is the correct entry.  At least +	   some versions of the kernel give wrong information because +	   of the implicit mount of the shmfs for SysV IPC.  */ +	if (__statfs (mp->mnt_dir, &f) != 0 || f.f_type != SHMFS_SUPER_MAGIC) +	  continue; + +	namelen = strlen (mp->mnt_dir); + +	if (namelen == 0) +	  /* Hum, maybe some crippled entry.  Keep on searching.  */ +	  continue; + +	mountpoint.dir = (char *) malloc (namelen + 4 + 2); +	if (mountpoint.dir != NULL) +	  { +	    char *cp = __mempcpy (mountpoint.dir, mp->mnt_dir, namelen); +	    if (cp[-1] != '/') +	      *cp++ = '/'; +	    cp = stpcpy (cp, "sem."); +	    mountpoint.dirlen = cp - mountpoint.dir; +	  } + +	break; +      } + +  /* Close the stream.  */ +  __endmntent (fp); +} + + +/* Comparison function for search of existing mapping.  */ +int +attribute_hidden +__sem_search (const void *a, const void *b) +{ +  const struct inuse_sem *as = (const struct inuse_sem *) a; +  const struct inuse_sem *bs = (const struct inuse_sem *) b; + +  if (as->ino != bs->ino) +    /* Cannot return the difference the type is larger than int.  */ +    return as->ino < bs->ino ? -1 : (as->ino == bs->ino ? 0 : 1); + +  if (as->dev != bs->dev) +    /* Cannot return the difference the type is larger than int.  */ +    return as->dev < bs->dev ? -1 : (as->dev == bs->dev ? 0 : 1); + +  return strcmp (as->name, bs->name); +} + + +/* The search tree for existing mappings.  */ +void *__sem_mappings attribute_hidden; + +/* Lock to protect the search tree.  */ +lll_lock_t __sem_mappings_lock = LLL_LOCK_INITIALIZER; + + +/* Search for existing mapping and if possible add the one provided.  */ +static sem_t * +check_add_mapping (const char *name, size_t namelen, int fd, sem_t *existing) +{ +  sem_t *result = SEM_FAILED; + +  /* Get the information about the file.  */ +  struct stat64 st; +  if (__fxstat64 (_STAT_VER, fd, &st) == 0) +    { +      /* Get the lock.  */ +      lll_lock (__sem_mappings_lock); + +      /* Search for an existing mapping given the information we have.  */ +      struct inuse_sem *fake; +      fake = (struct inuse_sem *) alloca (sizeof (*fake) + namelen); +      memcpy (fake->name, name, namelen); +      fake->dev = st.st_dev; +      fake->ino = st.st_ino; + +      struct inuse_sem **foundp = tfind (fake, &__sem_mappings, __sem_search); +      if (foundp != NULL) +	{ +	  /* There is already a mapping.  Use it.  */ +	  result = (*foundp)->sem; +	  ++(*foundp)->refcnt; +	} +      else +	{ +	  /* We haven't found a mapping.  Install ione.  */ +	  struct inuse_sem *newp; + +	  newp = (struct inuse_sem *) malloc (sizeof (*newp) + namelen); +	  if (newp != NULL) +	    { +	      /* If the caller hasn't provided any map it now.  */ +	      if (existing == SEM_FAILED) +		existing = (sem_t *) mmap (NULL, sizeof (sem_t), +					   PROT_READ | PROT_WRITE, MAP_SHARED, +					   fd, 0); + +	      newp->dev = st.st_dev; +	      newp->ino = st.st_ino; +	      newp->refcnt = 1; +	      newp->sem = existing; +	      memcpy (newp->name, name, namelen); + +	      /* Insert the new value.  */ +	      if (existing != MAP_FAILED +		  && tsearch (newp, &__sem_mappings, __sem_search) != NULL) +		/* Successful.  */ +		result = existing; +	      else +		/* Something went wrong while inserting the new +		   value.  We fail completely.  */ +		free (newp); +	    } +	} + +      /* Release the lock.  */ +      lll_unlock (__sem_mappings_lock); +    } + +  if (result != existing && existing != SEM_FAILED && existing != MAP_FAILED) +    { +      /* Do not disturb errno.  */ +      INTERNAL_SYSCALL_DECL (err); +      INTERNAL_SYSCALL (munmap, err, 2, existing, sizeof (sem_t)); +    } + +  return result; +} + + +sem_t * +sem_open (const char *name, int oflag, ...) +{ +  char *finalname; +  sem_t *result = SEM_FAILED; +  int fd; + +  /* Determine where the shmfs is mounted.  */ +  INTUSE(__pthread_once) (&__namedsem_once, __where_is_shmfs); + +  /* If we don't know the mount points there is nothing we can do.  Ever.  */ +  if (mountpoint.dir == NULL) +    { +      __set_errno (ENOSYS); +      return SEM_FAILED; +    } + +  /* Construct the filename.  */ +  while (name[0] == '/') +    ++name; + +  if (name[0] == '\0') +    { +      /* The name "/" is not supported.  */ +      __set_errno (EINVAL); +      return SEM_FAILED; +    } +  size_t namelen = strlen (name) + 1; + +  /* Create the name of the final file.  */ +  finalname = (char *) alloca (mountpoint.dirlen + namelen); +  __mempcpy (__mempcpy (finalname, mountpoint.dir, mountpoint.dirlen), +	     name, namelen); + +  /* If the semaphore object has to exist simply open it.  */ +  if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0) +    { +    try_again: +      fd = __libc_open (finalname, +			(oflag & ~(O_CREAT|O_ACCMODE)) | O_NOFOLLOW | O_RDWR); + +      if (fd == -1) +	{ +	  /* If we are supposed to create the file try this next.  */ +	  if ((oflag & O_CREAT) != 0 && errno == ENOENT) +	    goto try_create; + +	  /* Return.  errno is already set.  */ +	} +      else +	/* Check whether we already have this semaphore mapped and +	   create one if necessary.  */ +	result = check_add_mapping (name, namelen, fd, SEM_FAILED); +    } +  else +    { +      /* We have to open a temporary file first since it must have the +	 correct form before we can start using it.  */ +      char *tmpfname; +      mode_t mode; +      unsigned int value; +      va_list ap; + +    try_create: +      va_start (ap, oflag); + +      mode = va_arg (ap, mode_t); +      value = va_arg (ap, unsigned int); + +      va_end (ap); + +      if (value > SEM_VALUE_MAX) +	{ +	  __set_errno (EINVAL); +	  return SEM_FAILED; +	} + +      /* Create the initial file content.  */ +      sem_t initsem; + +      struct sem *iinitsem = (struct sem *) &initsem; +      iinitsem->count = value; + +      /* Initialize the remaining bytes as well.  */ +      memset ((char *) &initsem + sizeof (struct sem), '\0', +	      sizeof (sem_t) - sizeof (struct sem)); + +      tmpfname = (char *) alloca (mountpoint.dirlen + 6 + 1); +      char *xxxxxx = __mempcpy (tmpfname, mountpoint.dir, mountpoint.dirlen); + +      int retries = 0; +#define NRETRIES 50 +      while (1) +	{ +	  /* Add the suffix for mktemp.  */ +	  strcpy (xxxxxx, "XXXXXX"); + +	  /* We really want to use mktemp here.  We cannot use mkstemp +	     since the file must be opened with a specific mode.  The +	     mode cannot later be set since then we cannot apply the +	     file create mask.  */ +	  if (mktemp (tmpfname) == NULL) +	    return SEM_FAILED; + +	  /* Open the file.  Make sure we do not overwrite anything.  */ +	  fd = __libc_open (tmpfname, O_RDWR | O_CREAT | O_EXCL, mode); +	  if (fd == -1) +	    { +	      if (errno == EEXIST) +		{ +		  if (++retries < NRETRIES) +		    continue; + +		  __set_errno (EAGAIN); +		} + +	      return SEM_FAILED; +	    } + +	  /* We got a file.  */ +	  break; +	} + +      if (TEMP_FAILURE_RETRY (__libc_write (fd, &initsem, sizeof (sem_t))) +	  == sizeof (sem_t) +	  /* Map the sem_t structure from the file.  */ +	  && (result = (sem_t *) mmap (NULL, sizeof (sem_t), +				       PROT_READ | PROT_WRITE, MAP_SHARED, +				       fd, 0)) != MAP_FAILED) +	{ +	  /* Create the file.  Don't overwrite an existing file.  */ +	  if (link (tmpfname, finalname) != 0) +	    { +	      /* Undo the mapping.  */ +	      (void) munmap (result, sizeof (sem_t)); + +	      /* Reinitialize 'result'.  */ +	      result = SEM_FAILED; + +	      /* This failed.  If O_EXCL is not set and the problem was +		 that the file exists, try again.  */ +	      if ((oflag & O_EXCL) == 0 && errno == EEXIST) +		{ +		  /* Remove the file.  */ +		  (void) unlink (tmpfname); + +		  /* Close the file.  */ +		  (void) __libc_close (fd); + +		  goto try_again; +		} +	    } +	  else +	    /* Insert the mapping into the search tree.  This also +	       determines whether another thread sneaked by and already +	       added such a mapping despite the fact that we created it.  */ +	    result = check_add_mapping (name, namelen, fd, result); +	} + +      /* Now remove the temporary name.  This should never fail.  If +	 it fails we leak a file name.  Better fix the kernel.  */ +      (void) unlink (tmpfname); +    } + +  /* Map the mmap error to the error we need.  */ +  if (MAP_FAILED != (void *) SEM_FAILED && result == MAP_FAILED) +    result = SEM_FAILED; + +  /* We don't need the file descriptor anymore.  */ +  if (fd != -1) +    { +      /* Do not disturb errno.  */ +      INTERNAL_SYSCALL_DECL (err); +      INTERNAL_SYSCALL (close, err, 1, fd); +    } + +  return result; +} diff --git a/libpthread/nptl/sem_unlink.c b/libpthread/nptl/sem_unlink.c new file mode 100644 index 000000000..17074774d --- /dev/null +++ b/libpthread/nptl/sem_unlink.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <semaphore.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "semaphoreP.h" + + +int +sem_unlink (name) +     const char *name; +{ +  char *fname; +  size_t namelen; + +  /* Determine where the shmfs is mounted.  */ +  INTUSE(__pthread_once) (&__namedsem_once, __where_is_shmfs); + +  /* If we don't know the mount points there is nothing we can do.  Ever.  */ +  if (mountpoint.dir == NULL) +    { +      __set_errno (ENOSYS); +      return -1; +    } + +  /* Construct the filename.  */ +  while (name[0] == '/') +    ++name; + +  if (name[0] == '\0') +    { +      /* The name "/" is not supported.  */ +      __set_errno (ENOENT); +      return -1; +    } +  namelen = strlen (name); + +  /* Create the name of the file.  */ +  fname = (char *) alloca (mountpoint.dirlen + namelen + 1); +  __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen), +	     name, namelen + 1); + +  /* Now try removing it.  */ +  int ret = unlink (fname); +  if (ret < 0 && errno == EPERM) +    __set_errno (EACCES); +  return ret; +} diff --git a/libpthread/nptl/semaphore.h b/libpthread/nptl/semaphore.h new file mode 100644 index 000000000..4f13725b3 --- /dev/null +++ b/libpthread/nptl/semaphore.h @@ -0,0 +1,79 @@ +/* Copyright (C) 2002, 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 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 _SEMAPHORE_H +#define _SEMAPHORE_H	1 + +#include <features.h> +#include <sys/types.h> +#ifdef __USE_XOPEN2K +# define __need_timespec +# include <time.h> +#endif + +/* Get the definition for sem_t.  */ +#include <bits/semaphore.h> + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE.  If PSHARED then share it +   with other processes.  */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) +     __THROW; +/* Free resources associated with semaphore object SEM.  */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG.  */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM.  */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME.  */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + +   This function is a cancellation point and therefore not marked with +   __THROW.  */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + +   This function is a cancellation point and therefore not marked with +   __THROW.  */ +extern int sem_timedwait (sem_t *__restrict __sem, +			  __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted.  */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM.  */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL.  */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) +     __THROW; + + +__END_DECLS + +#endif	/* semaphore.h */ diff --git a/libpthread/nptl/semaphoreP.h b/libpthread/nptl/semaphoreP.h new file mode 100644 index 000000000..d14ea92c7 --- /dev/null +++ b/libpthread/nptl/semaphoreP.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <semaphore.h> +#include "pthreadP.h" + + +/* Mount point of the shared memory filesystem.  */ +struct mountpoint_info +{ +  char *dir; +  size_t dirlen; +}; + +/* Keeping track of currently used mappings.  */ +struct inuse_sem +{ +  dev_t dev; +  ino_t ino; +  int refcnt; +  sem_t *sem; +  char name[0]; +}; + + +/* Variables used in multiple interfaces.  */ +extern struct mountpoint_info mountpoint attribute_hidden; + +extern pthread_once_t __namedsem_once attribute_hidden; + +/* The search tree for existing mappings.  */ +extern void *__sem_mappings attribute_hidden; + +/* Lock to protect the search tree.  */ +extern lll_lock_t __sem_mappings_lock; + + +/* Initializer for mountpoint.  */ +extern void __where_is_shmfs (void) attribute_hidden; + +/* Comparison function for search in tree with existing mappings.  */ +extern int __sem_search (const void *a, const void *b) attribute_hidden; + + +/* Prototypes of functions with multiple interfaces.  */ +extern int __new_sem_init (sem_t *sem, int pshared, unsigned int value); +extern int __new_sem_destroy (sem_t *sem); +extern int __new_sem_post (sem_t *sem); +extern int __new_sem_wait (sem_t *sem); +extern int __new_sem_trywait (sem_t *sem); +extern int __new_sem_getvalue (sem_t *sem, int *sval); diff --git a/libpthread/nptl/sockperf.c b/libpthread/nptl/sockperf.c new file mode 100644 index 000000000..d29a6ee26 --- /dev/null +++ b/libpthread/nptl/sockperf.c @@ -0,0 +1,594 @@ +#define _GNU_SOURCE +#include <argp.h> +#include <complex.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <gd.h> +#include <inttypes.h> +#include <pthread.h> +#include <signal.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/param.h> +#include <sys/poll.h> +#include <sys/socket.h> +#include <sys/un.h> + + +#define size_x 320 +#define size_y 240 + + +#define PATH "/tmp/s.sockperf" + + +struct thread_param +{ +  unsigned int from; +  unsigned int to; +  unsigned int nserv; +}; + +struct coord +{ +  unsigned int x; +  unsigned int y; +  complex double z; +}; + + +/* We use 64bit values for the times.  */ +typedef unsigned long long int hp_timing_t; + + +static unsigned int nclients = 2; +static unsigned int nservers = 2; + +static bool timing; +static int points; + + +static complex double top_left = -0.7 + 0.2i; +static complex double bottom_right = -0.5 - 0.0i; + + +static int colors[256]; +static gdImagePtr image; +static pthread_mutex_t image_lock; + +static int sock; + + +static void * +client (void *arg) +{ +  struct thread_param *param = arg; +  unsigned int cnt; +  unsigned int nserv = param->nserv; +  int clisock[nserv]; +  struct pollfd servpoll[nserv]; +  struct sockaddr_un servaddr; +  socklen_t servlen; +  struct coord c; + +  bool new_coord (void) +    { +      if (cnt >= param->to) +	return false; + +      unsigned int row = cnt / size_x; +      unsigned int col = cnt % size_x; + +      c.x = col; +      c.y = row; +      c.z = (top_left +	     + ((col +		 * (creal (bottom_right) - creal (top_left))) / size_x) +	     + (_Complex_I * (row * (cimag (bottom_right) - cimag (top_left))) +		/ size_y)); + +      ++cnt; + +      return true; +    } + + +  for (cnt = 0; cnt < nserv; ++cnt) +    { +      servpoll[cnt].fd = socket (AF_UNIX, SOCK_STREAM, 0); +      if (clisock < 0) +	{ +	  puts ("cannot create socket in client"); +	  return NULL; +	} + +      memset (&servaddr, '\0', sizeof (servaddr)); +      servaddr.sun_family = AF_UNIX; +      strncpy (servaddr.sun_path, PATH, sizeof (servaddr.sun_path)); +      servlen = offsetof (struct sockaddr_un, sun_path) + strlen (PATH) + 1; + + +      int err; +      while (1) +	{ +	  err = TEMP_FAILURE_RETRY (connect (servpoll[cnt].fd, &servaddr, +					     servlen)); +	  if (err != -1 || errno != ECONNREFUSED) +	    break; + +	  pthread_yield (); +	} + +      if (err == -1) +	{ +	  printf ("cannot connect: %m (%d)\n", errno); +	  exit (1); +	} + +      servpoll[cnt].events = POLLOUT; +      servpoll[cnt].revents = 0; +    } + +  cnt = param->from; + +  new_coord (); +  bool z_valid = true; + +  while (1) +    { +      int i; +      int n = poll (servpoll, nserv, -1); +      if (n == -1) +	{ +	  puts ("poll returned error"); +	  break; +	} + +      bool cont = false; +      for (i = 0; i < nserv && n > 0; ++i) +	if (servpoll[i].revents != 0) +	  { +	    if (servpoll[i].revents == POLLIN) +	      { +		unsigned int vals[3]; +		if (TEMP_FAILURE_RETRY (read (servpoll[i].fd, &vals, +					      sizeof (vals))) +		    != sizeof (vals)) +		  { +		    puts ("read error in client"); +		    return NULL; +		  } + +		pthread_mutex_lock (&image_lock); + +		gdImageSetPixel (image, vals[0], vals[1], vals[2]); +		++points; + +		pthread_mutex_unlock (&image_lock); + +		servpoll[i].events = POLLOUT; +	      } +	    else +	      { +		if (servpoll[i].revents != POLLOUT) +		  printf ("revents: %hd != POLLOUT ???\n", +			  servpoll[i].revents); + +		if (z_valid) +		  { +		    if (TEMP_FAILURE_RETRY (write (servpoll[i].fd, &c, +						   sizeof (c))) != sizeof (c)) +		      { +			puts ("write error in client"); +			return NULL; +		      } +		    cont = true; +		    servpoll[i].events = POLLIN; + +		    z_valid = new_coord (); +		    if (! z_valid) +		      /* No more to do.  Clear the event fields.  */ +		      for (i = 0; i < nserv; ++i) +			if (servpoll[i].events == POLLOUT) +			  servpoll[i].events = servpoll[i].revents = 0; +		  } +		else +		  servpoll[i].events = servpoll[i].revents = 0; +	      } + +	    --n; +	  } +	else if (servpoll[i].events != 0) +	  cont = true; + +      if (! cont && ! z_valid) +	break; +    } + +  c.x = 0xffffffff; +  c.y = 0xffffffff; +  for (cnt = 0; cnt < nserv; ++cnt) +    { +      TEMP_FAILURE_RETRY (write (servpoll[cnt].fd, &c, sizeof (c))); +      close (servpoll[cnt].fd); +    } + +  return NULL; +} + + +static void * +server (void *arg) +{ +  struct sockaddr_un cliaddr; +  socklen_t clilen; +  int clisock = TEMP_FAILURE_RETRY (accept (sock, &cliaddr, &clilen)); + +  if (clisock == -1) +    { +      puts ("accept failed"); +      return NULL; +    } + +  while (1) +    { +      struct coord c; + +      if (TEMP_FAILURE_RETRY (read (clisock, &c, sizeof (c))) != sizeof (c)) +	{ +	  printf ("server read failed: %m (%d)\n", errno); +	  break; +	} + +      if (c.x == 0xffffffff && c.y == 0xffffffff) +	break; + +      unsigned int rnds = 0; +      complex double z = c.z; +      while (cabs (z) < 4.0) +	{ +	  z = z * z - 1; +	  if (++rnds == 255) +	    break; +	} + +      unsigned int vals[3] = { c.x, c.y, rnds }; +      if (TEMP_FAILURE_RETRY (write (clisock, vals, sizeof (vals))) +	  != sizeof (vals)) +	{ +	  puts ("server write error"); +	  return NULL; +	} +    } + +  close (clisock); + +  return NULL; +} + + +static const char *outfilename = "test.png"; + + +static const struct argp_option options[] = +  { +    { "clients", 'c', "NUMBER", 0, "Number of client threads" }, +    { "servers", 's', "NUMBER", 0, "Number of server threads per client" }, +    { "timing", 'T', NULL, 0, +      "Measure time from startup to the last thread finishing" }, +    { NULL, 0, NULL, 0, NULL } +  }; + +/* Prototype for option handler.  */ +static error_t parse_opt (int key, char *arg, struct argp_state *state); + +/* Data structure to communicate with argp functions.  */ +static struct argp argp = +{ +  options, parse_opt +}; + + +int +main (int argc, char *argv[]) +{ +  int cnt; +  FILE *outfile; +  struct sockaddr_un servaddr; +  socklen_t servlen; +  int remaining; + +  /* Parse and process arguments.  */ +  argp_parse (&argp, argc, argv, 0, &remaining, NULL); + + +  pthread_t servth[nservers * nclients]; +  pthread_t clntth[nclients]; +  struct thread_param clntparam[nclients]; + + +  image = gdImageCreate (size_x, size_y); +  if (image == NULL) +    { +      puts ("gdImageCreate failed"); +      return 1; +    } + +  for (cnt = 0; cnt < 255; ++cnt) +    colors[cnt] = gdImageColorAllocate (image, 256 - cnt, 256 - cnt, +					256 - cnt); +  /* Black.  */ +  colors[cnt] = gdImageColorAllocate (image, 0, 0, 0); + + +  sock = socket (AF_UNIX, SOCK_STREAM, 0); +  if (sock < 0) +    error (EXIT_FAILURE, errno, "cannot create socket"); + +  memset (&servaddr, '\0', sizeof (servaddr)); +  servaddr.sun_family = AF_UNIX; +  strncpy (servaddr.sun_path, PATH, sizeof (servaddr.sun_path)); +  servlen = offsetof (struct sockaddr_un, sun_path) + strlen (PATH) + 1; + +  if (bind (sock, &servaddr, servlen) == -1) +    error (EXIT_FAILURE, errno, "bind failed"); + +  listen (sock, SOMAXCONN); + +  pthread_mutex_init (&image_lock, NULL); + + +  struct sigaction sa; +  sa.sa_handler = SIG_IGN; +  sigemptyset (&sa.sa_mask); +  sa.sa_flags = 0; + +  clockid_t cl; +  struct timespec start_time; +  if (timing) +    { +      if (clock_getcpuclockid (0, &cl) != 0 +	  || clock_gettime (cl, &start_time) != 0) +	timing = false; +    } + +  /* Start the servers.  */ +  for (cnt = 0; cnt < nservers * nclients; ++cnt) +    { +      if (pthread_create (&servth[cnt], NULL, server, NULL) != 0) +	{ +	  puts ("pthread_create for server failed"); +	  exit (1); +	} +    } + +  for (cnt = 0; cnt < nclients; ++cnt) +    { +      clntparam[cnt].from = cnt * (size_x * size_y) / nclients; +      clntparam[cnt].to = MIN ((cnt + 1) * (size_x * size_y) / nclients, +			       size_x * size_y); +      clntparam[cnt].nserv = nservers; + +      if (pthread_create (&clntth[cnt], NULL, client, &clntparam[cnt]) != 0) +	{ +	  puts ("pthread_create for client failed"); +	  exit (1); +	} +    } + + +  /* Wait for the clients.  */ +  for (cnt = 0; cnt < nclients; ++cnt) +    if (pthread_join (clntth[cnt], NULL) != 0) +      { +	puts ("client pthread_join failed"); +	exit (1); +      } + +  /* Wait for the servers.  */ +  for (cnt = 0; cnt < nclients * nservers; ++cnt) +    if (pthread_join (servth[cnt], NULL) != 0) +      { +	puts ("server pthread_join failed"); +	exit (1); +      } + + +  if (timing) +    { +      struct timespec end_time; + +      if (clock_gettime (cl, &end_time) == 0) +	{ +	  end_time.tv_sec -= start_time.tv_sec; +	  end_time.tv_nsec -= start_time.tv_nsec; +	  if (end_time.tv_nsec < 0) +	    { +	      end_time.tv_nsec += 1000000000; +	      --end_time.tv_sec; +	    } + +	  printf ("\nRuntime: %lu.%09lu seconds\n%d points computed\n", +		  (unsigned long int) end_time.tv_sec, +		  (unsigned long int) end_time.tv_nsec, +		  points); +	} +    } + + +  outfile = fopen (outfilename, "w"); +  if (outfile == NULL) +    error (EXIT_FAILURE, errno, "cannot open output file '%s'", outfilename); + +  gdImagePng (image, outfile); + +  fclose (outfile); + +  unlink (PATH); + +  return 0; +} + + +/* Handle program arguments.  */ +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ +  switch (key) +    { +    case 'c': +      nclients = strtoul (arg, NULL, 0); +      break; + +    case 's': +      nservers = strtoul (arg, NULL, 0); +      break; + +    case 'T': +      timing = true; +      break; + +    default: +      return ARGP_ERR_UNKNOWN; +    } + +  return 0; +} + + +static hp_timing_t +get_clockfreq (void) +{ +  /* We read the information from the /proc filesystem.  It contains at +     least one line like +	cpu MHz         : 497.840237 +     or also +	cpu MHz         : 497.841 +     We search for this line and convert the number in an integer.  */ +  static hp_timing_t result; +  int fd; + +  /* If this function was called before, we know the result.  */ +  if (result != 0) +    return result; + +  fd = open ("/proc/cpuinfo", O_RDONLY); +  if (__builtin_expect (fd != -1, 1)) +    { +      /* XXX AFAIK the /proc filesystem can generate "files" only up +         to a size of 4096 bytes.  */ +      char buf[4096]; +      ssize_t n; + +      n = read (fd, buf, sizeof buf); +      if (__builtin_expect (n, 1) > 0) +	{ +	  char *mhz = memmem (buf, n, "cpu MHz", 7); + +	  if (__builtin_expect (mhz != NULL, 1)) +	    { +	      char *endp = buf + n; +	      int seen_decpoint = 0; +	      int ndigits = 0; + +	      /* Search for the beginning of the string.  */ +	      while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') +		++mhz; + +	      while (mhz < endp && *mhz != '\n') +		{ +		  if (*mhz >= '0' && *mhz <= '9') +		    { +		      result *= 10; +		      result += *mhz - '0'; +		      if (seen_decpoint) +			++ndigits; +		    } +		  else if (*mhz == '.') +		    seen_decpoint = 1; + +		  ++mhz; +		} + +	      /* Compensate for missing digits at the end.  */ +	      while (ndigits++ < 6) +		result *= 10; +	    } +	} + +      close (fd); +    } + +  return result; +} + + +int +clock_getcpuclockid (pid_t pid, clockid_t *clock_id) +{ +  /* We don't allow any process ID but our own.  */ +  if (pid != 0 && pid != getpid ()) +    return EPERM; + +#ifdef CLOCK_PROCESS_CPUTIME_ID +  /* Store the number.  */ +  *clock_id = CLOCK_PROCESS_CPUTIME_ID; + +  return 0; +#else +  /* We don't have a timer for that.  */ +  return ENOENT; +#endif +} + + +#define HP_TIMING_NOW(Var)	__asm__ __volatile__ ("rdtsc" : "=A" (Var)) + +/* Get current value of CLOCK and store it in TP.  */ +int +clock_gettime (clockid_t clock_id, struct timespec *tp) +{ +  int retval = -1; + +  switch (clock_id) +    { +    case CLOCK_PROCESS_CPUTIME_ID: +      { + +	static hp_timing_t freq; +	hp_timing_t tsc; + +	/* Get the current counter.  */ +	HP_TIMING_NOW (tsc); + +	if (freq == 0) +	  { +	    freq = get_clockfreq (); +	    if (freq == 0) +	      return EINVAL; +	  } + +	/* Compute the seconds.  */ +	tp->tv_sec = tsc / freq; + +	/* And the nanoseconds.  This computation should be stable until +	   we get machines with about 16GHz frequency.  */ +	tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; + +	retval = 0; +      } +    break; + +    default: +      errno = EINVAL; +      break; +    } + +  return retval; +} diff --git a/libpthread/nptl/sysdeps/alpha/Makefile b/libpthread/nptl/sysdeps/alpha/Makefile new file mode 100644 index 000000000..88c106bbb --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/Makefile @@ -0,0 +1,21 @@ +# 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 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. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c b/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c new file mode 100644 index 000000000..ba2e419d6 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c @@ -0,0 +1,89 @@ +/* Special .init and .fini section support for Alpha.  NPTL 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 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.  */ + +/* This file is compiled into assembly code which is then munged by a sed +   script into two files: crti.s and crtn.s. + +   * crti.s puts a function prologue at the beginning of the .init and .fini +   sections and defines global symbols for those addresses, so they can be +   called as functions. + +   * crtn.s puts the corresponding function epilogues in the .init and .fini +   sections. + +   This differs from what would be generated by the generic code in that +   we save and restore the GP within the function.  In order for linker +   relaxation to work, the value in the GP register on exit from a function +   must be valid for the function entry point.  Normally, a function is +   contained within one object file and this is not an issue, provided +   that the function reloads the gp after making any function calls. +   However, _init and _fini are constructed from pieces of many object +   files, all of which may have different GP values.  So we must reload +   the GP value from crti.o in crtn.o.  */ + +__asm__ ("						\n\ +#include \"defs.h\"					\n\ +							\n\ +/*@HEADER_ENDS*/					\n\ +							\n\ +/*@_init_PROLOG_BEGINS*/				\n\ +	.section .init, \"ax\", @progbits		\n\ +	.globl	_init					\n\ +	.type	_init,@function				\n\ +	.usepv	_init,std				\n\ +_init:							\n\ +	ldgp	$29, 0($27)				\n\ +	subq	$30, 16, $30				\n\ +	stq	$26, 0($30)				\n\ +	stq	$29, 8($30)				\n\ +	bsr	$26, __pthread_initialize_minimal_internal !samegp \n\ +	.align 3					\n\ +/*@_init_PROLOG_ENDS*/					\n\ +							\n\ +/*@_init_EPILOG_BEGINS*/				\n\ +	.section .init, \"ax\", @progbits		\n\ +	ldq	$26, 0($30)				\n\ +	ldq	$29, 8($30)				\n\ +	addq	$30, 16, $30				\n\ +	ret						\n\ +/*@_init_EPILOG_ENDS*/					\n\ +							\n\ +/*@_fini_PROLOG_BEGINS*/				\n\ +	.section .fini, \"ax\", @progbits		\n\ +	.globl	_fini					\n\ +	.type	_fini,@function				\n\ +	.usepv	_fini,std				\n\ +_fini:							\n\ +	ldgp	$29, 0($27)				\n\ +	subq	$30, 16, $30				\n\ +	stq	$26, 0($30)				\n\ +	stq	$29, 8($30)				\n\ +	.align 3					\n\ +/*@_fini_PROLOG_ENDS*/					\n\ +							\n\ +/*@_fini_EPILOG_BEGINS*/				\n\ +	.section .fini, \"ax\", @progbits		\n\ +	ldq	$26, 0($30)				\n\ +	ldq	$29, 8($30)				\n\ +	addq	$30, 16, $30				\n\ +	ret						\n\ +/*@_fini_EPILOG_ENDS*/					\n\ +							\n\ +/*@TRAILER_BEGINS*/					\n\ +"); diff --git a/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h new file mode 100644 index 000000000..5cef8b1cf --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S b/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S new file mode 100644 index 000000000..ce6cd41a4 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Richard Henderson  <rth@twiddle.net>, 2003. + +   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.  */ + + +	.text +	.align	4 + +	.globl	pthread_spin_lock +	.ent	pthread_spin_lock +pthread_spin_lock: +	.frame	$sp, 0, $26, 0 +	.prologue 0 + +0:	ldl_l	$1, 0($16) +	lda	$2, 1 +	lda	$0, 0 +	bne	$1, 1f + +	stl_c	$2, 0($16) +	beq	$2, 1f +	mb +	ret + +1:	ldl	$1, 0($16) +	bne	$1, 1b +	unop +	br	0b + +	.end	pthread_spin_lock diff --git a/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S new file mode 100644 index 000000000..0948da698 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Richard Henderson  <rth@twiddle.net>, 2003. + +   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.  */ + + +#define _ERRNO_H 1 +#include <bits/errno.h> + +	.text +	.align	4 + +	.globl	pthread_spin_trylock +	.ent	pthread_spin_trylock +pthread_spin_trylock: +	.frame	$sp, 0, $26, 0 +	.prologue 0 + +0:	ldl_l	$1, 0($16) +	lda	$2, 1 +	lda	$0, EBUSY +	bne	$1, 1f + +	stl_c	$2, 0($16) +	beq	$2, 2f +	mb +	lda	$0, 0 + +1:	ret +2:	br	0b + +	.end	pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/alpha/pthreaddef.h b/libpthread/nptl/sysdeps/alpha/pthreaddef.h new file mode 100644 index 000000000..26c4daf7b --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/pthreaddef.h @@ -0,0 +1,38 @@ +/* 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 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.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  The ABI requires 16.  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	4096 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME	__builtin_frame_address (0) + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym b/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym new file mode 100644 index 000000000..c21a79104 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym @@ -0,0 +1,14 @@ +#include <sysdep.h> +#include <tls.h> + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +-- # define __builtin_thread_pointer()  ((void *) 0) +-- # define thread_offsetof(mem)     ((void *) &THREAD_SELF->mem - (void *) 0) +-- Ho hum, this doesn't work in gcc4, so Know Things about THREAD_SELF +#define thread_offsetof(mem)	(long)(offsetof(struct pthread, mem) - sizeof(struct pthread)) + +MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads) +PID_OFFSET			thread_offsetof (pid) +TID_OFFSET			thread_offsetof (tid) diff --git a/libpthread/nptl/sysdeps/alpha/tls.h b/libpthread/nptl/sysdeps/alpha/tls.h new file mode 100644 index 000000000..fa3c832a6 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/tls.h @@ -0,0 +1,129 @@ +/* Definition for thread-local data handling.  NPTL/Alpha 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 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 _TLS_H +#define _TLS_H	1 + +# include <dl-sysdep.h> + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools.  */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available.  */ +# define USE_TLS	1 + +#ifndef __ASSEMBLER__ + +/* Get system call information.  */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks.  */ +# define TLS_DTV_AT_TP	1 + +/* Get the thread descriptor definition.  */ +# include <nptl/descr.h> + +typedef struct +{ +  dtv_t *dtv; +  void *private; +} tcbhead_t; + +/* This is the size of the initial TCB.  */ +# define TLS_INIT_TCB_SIZE	sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN	16 + +/* This is the size of the TCB.  */ +# define TLS_TCB_SIZE		sizeof (tcbhead_t) + +/* This is the size we need before TCB.  */ +# define TLS_PRE_TCB_SIZE	sizeof (struct pthread) + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN		16 + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(tcbp, dtvp) \ +  (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(dtv) \ +  (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(tcbp) \ +  (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer.  This might need +   special attention since 'errno' is not yet available and if the +   operation can cause a failure 'errno' must not be touched.  */ +# define TLS_INIT_TP(tcbp, secondcall) \ +  (__builtin_set_thread_pointer ((void *)(tcbp)), NULL) + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +  (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread.  */ +# define THREAD_SELF \ + ((struct pthread *)__builtin_thread_pointer () - 1) + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF \ +  REGISTER (64, 64, 32 * 8, -sizeof (struct pthread)) + +/* Access to data in the thread descriptor is easy.  */ +#define THREAD_GETMEM(descr, member) \ +  descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ +  descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ +  descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ +  descr->member[idx] = (value) + +#endif /* __ASSEMBLER__ */ + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/i386/Makefile b/libpthread/nptl/sysdeps/i386/Makefile new file mode 100644 index 000000000..2f0d88f30 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) 2002, 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 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. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif + +ifeq ($(subdir),nptl) +CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align2.c += -mpreferred-stack-boundary=4 +endif diff --git a/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S new file mode 100644 index 000000000..e30072c3d --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthread-errnos.h> + + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +	.globl	pthread_spin_trylock +	.type	pthread_spin_trylock,@function +	.align	16 +pthread_spin_trylock: +	movl	4(%esp), %edx +	movl	$1, %eax +	xorl	%ecx, %ecx +	LOCK +	cmpxchgl %ecx, (%edx) +	movl	$EBUSY, %eax +#ifdef HAVE_CMOV +	cmovel	%ecx, %eax +#else +	jne	0f +	movl	%ecx, %eax +0: +#endif +	ret +	.size	pthread_spin_trylock,.-pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S new file mode 100644 index 000000000..ffe3d456b --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "../i486/pthread_spin_trylock.S" diff --git a/libpthread/nptl/sysdeps/i386/i686/Makefile b/libpthread/nptl/sysdeps/i386/i686/Makefile new file mode 100644 index 000000000..137c0a2f0 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/Makefile @@ -0,0 +1,32 @@ +# Copyright (C) 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),nptl) +# It turns out that stack coloring is in general not good on P4s.  Some +# applications will benefit.  We will probably have a configuration option +# at some point.  Enabling coloring can be done with +# +#   -DCOLORING_INCREMENT=128 +# +# What is useful is to avoid the 64k aliasing problem which reliably +# happens if all stacks use sizes which are a multiple of 64k.  Tell +# the stack allocator to disturb this by allocation one more page if +# necessary. +CFLAGS-pthread_create.c += -DMULTI_PAGE_ALIASING=65536 +endif diff --git a/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S new file mode 100644 index 000000000..a5d861f92 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#define HAVE_CMOV	1 +#include "../i486/pthread_spin_trylock.S" diff --git a/libpthread/nptl/sysdeps/i386/i686/tls.h b/libpthread/nptl/sysdeps/i386/i686/tls.h new file mode 100644 index 000000000..4025ed8d2 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/tls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _TLS_H + +/* Additional definitions for <tls.h> on i686 and up.  */ + + +/* Macros to load from and store into segment registers.  We can use +   the 32-bit instructions.  */ +#define TLS_GET_GS() \ +  ({ int __seg; __asm ("movl %%gs, %0" : "=q" (__seg)); __seg; }) +#define TLS_SET_GS(val) \ +  __asm ("movl %0, %%gs" :: "q" (val)) + + +/* Get the full set of definitions.  */ +#include "../tls.h" + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h new file mode 100644 index 000000000..5cef8b1cf --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_init.c b/libpthread/nptl/sysdeps/i386/pthread_spin_init.c new file mode 100644 index 000000000..0a47981aa --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +/* Not needed.  pthread_spin_init is an alias for pthread_spin_unlock.  */ diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c b/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c new file mode 100644 index 000000000..b41174e5f --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002,2003,2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + +#ifndef LOCK_PREFIX +# ifdef UP +#  define LOCK_PREFIX	/* nothing */ +# else +#  define LOCK_PREFIX	"lock;" +# endif +#endif + + +int +pthread_spin_lock (lock) +     pthread_spinlock_t *lock; +{ +  asm ("\n" +       "1:\t" LOCK_PREFIX "decl %0\n\t" +       "jne 2f\n\t" +       ".subsection 1\n\t" +       ".align 16\n" +       "2:\trep; nop\n\t" +       "cmpl $0, %0\n\t" +       "jg 1b\n\t" +       "jmp 2b\n\t" +       ".previous" +       : "=m" (*lock) +       : "m" (*lock)); + +  return 0; +} diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S new file mode 100644 index 000000000..d94f1e7b8 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +	.globl	pthread_spin_unlock +	.type	pthread_spin_unlock,@function +	.align	16 +pthread_spin_unlock: +	movl	4(%esp), %eax +	movl	$1, (%eax) +	xorl	%eax, %eax +	ret +	.size	pthread_spin_unlock,.-pthread_spin_unlock + +	/* The implementation of pthread_spin_init is identical.  */ +	.globl	pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/libpthread/nptl/sysdeps/i386/pthreaddef.h b/libpthread/nptl/sysdeps/i386/pthreaddef.h new file mode 100644 index 000000000..43b771c6d --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthreaddef.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  SSE requires 16 +   bytes.  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	2048 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME	__builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  while (1) {								      \ +    if (__builtin_constant_p (val) && (val) == 0)			      \ +      asm volatile ("xorl %%ebx, %%ebx; int $0x80" :: "a" (__NR_exit));	      \ +    else								      \ +      asm volatile ("movl %1, %%ebx; int $0x80"				      \ +		    :: "a" (__NR_exit), "r" (val));			      \ +  } diff --git a/libpthread/nptl/sysdeps/i386/tcb-offsets.sym b/libpthread/nptl/sysdeps/i386/tcb-offsets.sym new file mode 100644 index 000000000..4e0444ba3 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/tcb-offsets.sym @@ -0,0 +1,13 @@ +#include <sysdep.h> +#include <tls.h> + +RESULT			offsetof (struct pthread, result) +TID			offsetof (struct pthread, tid) +PID			offsetof (struct pthread, pid) +CANCELHANDLING		offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF		offsetof (struct pthread, cleanup_jmp_buf) +MULTIPLE_THREADS_OFFSET	offsetof (tcbhead_t, multiple_threads) +SYSINFO_OFFSET		offsetof (tcbhead_t, sysinfo) +CLEANUP			offsetof (struct pthread, cleanup) +CLEANUP_PREV		offsetof (struct _pthread_cleanup_buffer, __prev) +MUTEX_FUTEX		offsetof (pthread_mutex_t, __data.__lock) diff --git a/libpthread/nptl/sysdeps/i386/tls.h b/libpthread/nptl/sysdeps/i386/tls.h new file mode 100644 index 000000000..06def42a5 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/tls.h @@ -0,0 +1,419 @@ +/* Definition for thread-local data handling.  nptl/i386 version. +   Copyright (C) 2002, 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 +   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 _TLS_H +#define _TLS_H	1 + +#include <dl-sysdep.h> +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <list.h> + + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + + +typedef struct +{ +  void *tcb;		/* Pointer to the TCB.  Not necessarily the +			   thread descriptor used by libpthread.  */ +  dtv_t *dtv; +  void *self;		/* Pointer to the thread descriptor.  */ +  int multiple_threads; +  uintptr_t sysinfo; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + + +/* We require TLS support in the tools.  */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available.  */ +#define USE_TLS	1 + +/* Alignment requirement for the stack.  For IA-32 this is governed by +   the SSE memory functions.  */ +#define STACK_ALIGN	16 + +#ifndef __ASSEMBLER__ +/* Get system call information.  */ +# include <sysdep.h> + +/* The old way: using LDT.  */ + +/* Structure passed to `modify_ldt', 'set_thread_area', and 'clone' calls.  */ +struct user_desc +{ +  unsigned int entry_number; +  unsigned long int base_addr; +  unsigned int limit; +  unsigned int seg_32bit:1; +  unsigned int contents:2; +  unsigned int read_exec_only:1; +  unsigned int limit_in_pages:1; +  unsigned int seg_not_present:1; +  unsigned int useable:1; +  unsigned int empty:25; +}; + +/* Initializing bit fields is slow.  We speed it up by using a union.  */ +union user_desc_init +{ +  struct user_desc desc; +  unsigned int vals[4]; +}; + + +/* Get the thread descriptor definition.  */ +# include <nptl/descr.h> + +/* This is the size of the initial TCB.  */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB.  */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the +   thread pointer points to is unspecified.  Allocate the TCB there.  */ +# define TLS_TCB_AT_TP	1 + + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(descr, dtvp) \ +  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(dtvp) \ +  ({ struct pthread *__pd;						      \ +     THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(descr) \ +  (((tcbhead_t *) (descr))->dtv) + +#define THREAD_SELF_SYSINFO	THREAD_GETMEM (THREAD_SELF, header.sysinfo) +#define THREAD_SYSINFO(pd)	((pd)->header.sysinfo) + +/* Macros to load from and store into segment registers.  */ +# ifndef TLS_GET_GS +#  define TLS_GET_GS() \ +  ({ int __seg; __asm ("movw %%gs, %w0" : "=q" (__seg)); __seg & 0xffff; }) +# endif +# ifndef TLS_SET_GS +#  define TLS_SET_GS(val) \ +  __asm ("movw %w0, %%gs" :: "q" (val)) +# endif + + +# ifndef __NR_set_thread_area +#  define __NR_set_thread_area 243 +# endif +# ifndef TLS_FLAG_WRITABLE +#  define TLS_FLAG_WRITABLE		0x00000001 +# endif + +// XXX Enable for the real world. +#if 0 +# ifndef __ASSUME_SET_THREAD_AREA +#  error "we need set_thread_area" +# endif +#endif + +# ifdef __PIC__ +#  define TLS_EBX_ARG "r" +#  define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +#  define TLS_EBX_ARG "b" +#  define TLS_LOAD_EBX +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ +  _head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +#ifndef LOCK_PREFIX +# ifdef UP +#  define LOCK_PREFIX  /* nothing */ +# else +#  define LOCK_PREFIX "lock;" +# endif +#endif + +/* Code to initially initialize the thread pointer.  This might need +   special attention since 'errno' is not yet available and if the +   operation can cause a failure 'errno' must not be touched.  */ +# define TLS_INIT_TP(thrdescr, secondcall) \ +  ({ void *_thrdescr = (thrdescr);					      \ +     tcbhead_t *_head = _thrdescr;					      \ +     union user_desc_init _segdescr;					      \ +     int _result;							      \ +									      \ +     _head->tcb = _thrdescr;						      \ +     /* For now the thread descriptor is at the same address.  */	      \ +     _head->self = _thrdescr;						      \ +     /* New syscall handling support.  */				      \ +     INIT_SYSINFO;							      \ +									      \ +     /* The 'entry_number' field.  Let the kernel pick a value.  */	      \ +     if (secondcall)							      \ +       _segdescr.vals[0] = TLS_GET_GS () >> 3;				      \ +     else								      \ +       _segdescr.vals[0] = -1;						      \ +     /* The 'base_addr' field.  Pointer to the TCB.  */			      \ +     _segdescr.vals[1] = (unsigned long int) _thrdescr;			      \ +     /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */	      \ +     _segdescr.vals[2] = 0xfffff;					      \ +     /* Collapsed value of the bitfield:				      \ +	  .seg_32bit = 1						      \ +	  .contents = 0							      \ +	  .read_exec_only = 0						      \ +	  .limit_in_pages = 1						      \ +	  .seg_not_present = 0						      \ +	  .useable = 1 */						      \ +     _segdescr.vals[3] = 0x51;						      \ +									      \ +     /* Install the TLS.  */						      \ +     asm volatile (TLS_LOAD_EBX						      \ +		   "int $0x80\n\t"					      \ +		   TLS_LOAD_EBX						      \ +		   : "=a" (_result), "=m" (_segdescr.desc.entry_number)	      \ +		   : "0" (__NR_set_thread_area),			      \ +		     TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc));    \ +									      \ +     if (_result == 0)							      \ +       /* We know the index in the GDT, now load the segment register.	      \ +	  The use of the GDT is described by the value 3 in the lower	      \ +	  three bits of the segment descriptor value.			      \ +									      \ +	  Note that we have to do this even if the numeric value of	      \ +	  the descriptor does not change.  Loading the segment register	      \ +	  causes the segment information from the GDT to be loaded	      \ +	  which is necessary since we have changed it.   */		      \ +       TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3);		      \ +									      \ +     _result == 0 ? NULL						      \ +     : "set_thread_area failed when setting up thread-local storage\n"; }) + + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +  ({ struct pthread *__pd;						      \ +     THREAD_GETMEM (__pd, header.dtv); }) + + +/* Return the thread descriptor for the current thread. + +   The contained asm must *not* be marked volatile since otherwise +   assignments like +        pthread_descr self = thread_self(); +   do not get optimized away.  */ +# define THREAD_SELF \ +  ({ struct pthread *__self;						      \ +     asm ("movl %%gs:%c1,%0" : "=r" (__self)				      \ +	  : "i" (offsetof (struct pthread, header.self)));		      \ +     __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF \ +  REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ +  REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */ + + +/* Read member of the thread descriptor directly.  */ +# define THREAD_GETMEM(descr, member) \ +  ({ __typeof (descr->member) __value;					      \ +     if (sizeof (__value) == 1)						      \ +       asm volatile ("movb %%gs:%P2,%b0"				      \ +		     : "=q" (__value)					      \ +		     : "0" (0), "i" (offsetof (struct pthread, member)));     \ +     else if (sizeof (__value) == 4)					      \ +       asm volatile ("movl %%gs:%P1,%0"					      \ +		     : "=r" (__value)					      \ +		     : "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       {								      \ +	 if (sizeof (__value) != 8)					      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile ("movl %%gs:%P1,%%eax\n\t"			      \ +		       "movl %%gs:%P2,%%edx"				      \ +		       : "=A" (__value)					      \ +		       : "i" (offsetof (struct pthread, member)),	      \ +			 "i" (offsetof (struct pthread, member) + 4));	      \ +       }								      \ +     __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */ +# define THREAD_GETMEM_NC(descr, member, idx) \ +  ({ __typeof (descr->member[0]) __value;				      \ +     if (sizeof (__value) == 1)						      \ +       asm volatile ("movb %%gs:%P2(%3),%b0"				      \ +		     : "=q" (__value)					      \ +		     : "0" (0), "i" (offsetof (struct pthread, member[0])),   \ +		     "r" (idx));					      \ +     else if (sizeof (__value) == 4)					      \ +       asm volatile ("movl %%gs:%P1(,%2,4),%0"				      \ +		     : "=r" (__value)					      \ +		     : "i" (offsetof (struct pthread, member[0])),	      \ +		       "r" (idx));					      \ +     else								      \ +       {								      \ +	 if (sizeof (__value) != 8)					      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile  ("movl %%gs:%P1(,%2,8),%%eax\n\t"		      \ +			"movl %%gs:4+%P1(,%2,8),%%edx"			      \ +			: "=&A" (__value)				      \ +			: "i" (offsetof (struct pthread, member[0])),	      \ +			  "r" (idx));					      \ +       }								      \ +     __value; }) + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */ +# define THREAD_SETMEM(descr, member, value) \ +  ({ if (sizeof (descr->member) == 1)					      \ +       asm volatile ("movb %b0,%%gs:%P1" :				      \ +		     : "iq" (value),					      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else if (sizeof (descr->member) == 4)				      \ +       asm volatile ("movl %0,%%gs:%P1" :				      \ +		     : "ir" (value),					      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       {								      \ +	 if (sizeof (descr->member) != 8)				      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile ("movl %%eax,%%gs:%P1\n\t"			      \ +		       "movl %%edx,%%gs:%P2" :				      \ +		       : "A" (value),					      \ +			 "i" (offsetof (struct pthread, member)),	      \ +			 "i" (offsetof (struct pthread, member) + 4));	      \ +       }}) + + +/* Set member of the thread descriptor directly.  */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ +  ({ if (sizeof (descr->member[0]) == 1)				      \ +       asm volatile ("movb %b0,%%gs:%P1(%2)" :				      \ +		     : "iq" (value),					      \ +		       "i" (offsetof (struct pthread, member)),		      \ +		       "r" (idx));					      \ +     else if (sizeof (descr->member[0]) == 4)				      \ +       asm volatile ("movl %0,%%gs:%P1(,%2,4)" :			      \ +		     : "ir" (value),					      \ +		       "i" (offsetof (struct pthread, member)),		      \ +		       "r" (idx));					      \ +     else								      \ +       {								      \ +	 if (sizeof (descr->member[0]) != 8)				      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t"			      \ +		       "movl %%edx,%%gs:4+%P1(,%2,8)" :			      \ +		       : "A" (value),					      \ +			 "i" (offsetof (struct pthread, member)),	      \ +			 "r" (idx));					      \ +       }}) + + +/* Atomic compare and exchange on TLS, returning old value.  */ +#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ +  ({ __typeof (descr->member) __ret;					      \ +     __typeof (oldval) __old = (oldval);				      \ +     if (sizeof (descr->member) == 4)					      \ +       asm volatile (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3"		      \ +		     : "=a" (__ret)					      \ +		     : "0" (__old), "r" (newval),			      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       /* Not necessary for other sizes in the moment.  */		      \ +       abort ();							      \ +     __ret; }) + + +/* Atomic set bit.  */ +#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ +  (void) ({ if (sizeof ((descr)->member) == 4)				      \ +	      asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0"		      \ +			    :: "i" (offsetof (struct pthread, member)),	      \ +			       "ir" (1 << (bit)));			      \ +	    else							      \ +	      /* Not necessary for other sizes in the moment.  */	      \ +	      abort (); }) + + +/* Call the user-provided thread function.  */ +#define CALL_THREAD_FCT(descr) \ +  ({ void *__res;							      \ +     int __ignore1, __ignore2;						      \ +     asm volatile ("pushl %%eax\n\t"					      \ +		   "pushl %%eax\n\t"					      \ +		   "pushl %%eax\n\t"					      \ +		   "pushl %%gs:%P4\n\t"					      \ +		   "call *%%gs:%P3\n\t"					      \ +		   "addl $16, %%esp"					      \ +		   : "=a" (__res), "=c" (__ignore1), "=d" (__ignore2)	      \ +		   : "i" (offsetof (struct pthread, start_routine)),	      \ +		     "i" (offsetof (struct pthread, arg)));		      \ +     __res; }) + + +#endif /* __ASSEMBLER__ */ + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/mips/Makefile b/libpthread/nptl/sysdeps/mips/Makefile new file mode 100644 index 000000000..d0c59a509 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/Makefile @@ -0,0 +1,25 @@ +# 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 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. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif + +ifeq ($(subdir),nptl) +libpthread-sysdep_routines += nptl-sysdep +endif diff --git a/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h new file mode 100644 index 000000000..67cc96966 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h @@ -0,0 +1,30 @@ +/* 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[0].__sp - (_adj)) + +/* We use the normal longjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/mips/nptl-sysdep.S b/libpthread/nptl/sysdeps/mips/nptl-sysdep.S new file mode 100644 index 000000000..3f5c2a364 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/nptl-sysdep.S @@ -0,0 +1,2 @@ +/* Pull in __syscall_error.  */ +#include <sysdep.S> diff --git a/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S b/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S new file mode 100644 index 000000000..d5f2a7234 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S @@ -0,0 +1,37 @@ +/* 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sys/asm.h> +#include <sysdep.h> +#include <sgidefs.h> + +ENTRY (pthread_spin_lock) +	.set	push +#if _MIPS_SIM == _ABIO32 +	.set	mips2 +#endif +1:	ll	a2, 0(a0) +	li	a1, 1 +	bnez	a2, 1b +	sc	a1, 0(a0) +	beqz	a1, 1b +	MIPS_SYNC +	.set	pop +	li	v0, 0 +	ret +PSEUDO_END (pthread_spin_lock) diff --git a/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S new file mode 100644 index 000000000..9c6e740f0 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S @@ -0,0 +1,41 @@ +/* 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sys/asm.h> +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <sgidefs.h> + +ENTRY (pthread_spin_trylock) +	.set	push +#if _MIPS_SIM == _ABIO32 +	.set	mips2 +#endif +	ll	a2, 0(a0) +	li	a1, 1 +	bnez	a2, 1f +	sc	a1, 0(a0) +	beqz	a1, 1f +	MIPS_SYNC +	.set	pop +	li	v0, 0 +	ret +1:	li	v0, EBUSY +	ret +PSEUDO_END (pthread_spin_trylock) diff --git a/libpthread/nptl/sysdeps/mips/pthreaddef.h b/libpthread/nptl/sysdeps/mips/pthreaddef.h new file mode 100644 index 000000000..e72b4bc58 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/pthreaddef.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 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 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.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	2048 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME	__builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here.  */ + +#define __exit_thread_inline(val) \ +  INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/mips/tcb-offsets.sym b/libpthread/nptl/sysdeps/mips/tcb-offsets.sym new file mode 100644 index 000000000..e0e71dc43 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/tcb-offsets.sym @@ -0,0 +1,11 @@ +#include <sysdep.h> +#include <tls.h> + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +#define thread_offsetof(mem)	(long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads) +PID_OFFSET			thread_offsetof (pid) +TID_OFFSET			thread_offsetof (tid) diff --git a/libpthread/nptl/sysdeps/mips/tls.h b/libpthread/nptl/sysdeps/mips/tls.h new file mode 100644 index 000000000..1cef16101 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/tls.h @@ -0,0 +1,161 @@ +/* Definition for thread-local data handling.  NPTL/MIPS 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 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 _TLS_H +#define _TLS_H	1 + +#include <dl-sysdep.h> + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + +/* Note: rd must be $v1 to be ABI-conformant.  */ +# define READ_THREAD_POINTER() \ +    ({ void *__result;							      \ +       asm volatile (".set\tpush\n\t.set\tmips32r2\n\t"			      \ +		     "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result));	      \ +       __result; }) + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> + +# define READ_THREAD_POINTER(rd) \ +	.set	push;							      \ +	.set	mips32r2;						      \ +	rdhwr	rd, $29;						      \ +	.set	pop +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools.  */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available.  */ +#define USE_TLS	1 + +#ifndef __ASSEMBLER__ + +/* Get system call information.  */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks.  */ +# define TLS_DTV_AT_TP	1 + +/* Get the thread descriptor definition.  */ +# include <nptl/descr.h> + +typedef struct +{ +  dtv_t *dtv; +  void *private; +} tcbhead_t; + +/* This is the size of the initial TCB.  Because our TCB is before the thread +   pointer, we don't need this.  */ +# define TLS_INIT_TCB_SIZE	0 + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN	__alignof__ (struct pthread) + +/* This is the size of the TCB.  Because our TCB is before the thread +   pointer, we don't need this.  */ +# define TLS_TCB_SIZE		0 + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN		__alignof__ (struct pthread) + +/* This is the size we need before TCB - actually, it includes the TCB.  */ +# define TLS_PRE_TCB_SIZE \ +  (sizeof (struct pthread)						      \ +   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The thread pointer (in hardware register $29) points to the end of +   the TCB + 0x7000, as for PowerPC.  The pthread_descr structure is +   immediately in front of the TCB.  */ +# define TLS_TCB_OFFSET	0x7000 + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(tcbp, dtvp) \ +  (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(dtv) \ +  (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(tcbp) \ +  (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer.  This might need +   special attention since 'errno' is not yet available and if the +   operation can cause a failure 'errno' must not be touched.  */ +# define TLS_INIT_TP(tcbp, secondcall) \ +  ({ INTERNAL_SYSCALL_DECL (err);					\ +     long result_var;							\ +     result_var = INTERNAL_SYSCALL (set_thread_area, err, 1,		\ +				    (char *) (tcbp) + TLS_TCB_OFFSET);	\ +     INTERNAL_SYSCALL_ERROR_P (result_var, err)				\ +       ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +  (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread.  */ +# define THREAD_SELF \ + ((struct pthread *) (READ_THREAD_POINTER ()			     \ +		      - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF \ +  CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Access to data in the thread descriptor is easy.  */ +# define THREAD_GETMEM(descr, member) \ +  descr->member +# define THREAD_GETMEM_NC(descr, member, idx) \ +  descr->member[idx] +# define THREAD_SETMEM(descr, member, value) \ +  descr->member = (value) +# define THREAD_SETMEM_NC(descr, member, idx, value) \ +  descr->member[idx] = (value) + +/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some +   different value to mean unset l_tls_offset.  */ +# define NO_TLS_OFFSET		-1 + +#endif /* __ASSEMBLER__ */ + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/powerpc/Makefile b/libpthread/nptl/sysdeps/powerpc/Makefile new file mode 100644 index 000000000..3af245600 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/Makefile @@ -0,0 +1,21 @@ +# 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 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. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h new file mode 100644 index 000000000..0b817160d --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_GPR1] - (_adj)) + +/* We use the normal lobngjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c b/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c new file mode 100644 index 000000000..e2293fda1 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + +int +pthread_spin_lock (lock) +     pthread_spinlock_t *lock; +{ +  unsigned int __tmp; + +  asm volatile ( +       "1:	lwarx	%0,0,%1\n" +       "	cmpwi	0,%0,0\n" +       "	bne-	2f\n" +       "	stwcx.	%2,0,%1\n" +       "	bne-	2f\n" +       "	isync\n" +       "	.subsection 1\n" +       "2:	lwzx	%0,0,%1\n" +       "	cmpwi	0,%0,0\n" +       "	bne	2b\n" +       "	b	1b\n" +       "	.previous" +       : "=&r" (__tmp) +       : "r" (lock), "r" (1) +       : "cr0", "memory"); +  return 0; +} diff --git a/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c new file mode 100644 index 000000000..d8e1dbcc8 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + +int +pthread_spin_trylock (lock) +     pthread_spinlock_t *lock; +{ +  unsigned int old; +  int err = EBUSY; + +  asm ("1:	lwarx	%0,0,%2\n" +       "	cmpwi	0,%0,0\n" +       "	bne	2f\n" +       "	stwcx.	%3,0,%2\n" +       "	bne-	1b\n" +       "	li	%1,0\n" +       "	isync\n" +       "2:	" +       : "=&r" (old), "=&r" (err) +       : "r" (lock), "r" (1), "1" (err) +       : "cr0", "memory"); + +  return err; +} diff --git a/libpthread/nptl/sysdeps/powerpc/pthreaddef.h b/libpthread/nptl/sysdeps/powerpc/pthreaddef.h new file mode 100644 index 000000000..342c15c67 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/pthreaddef.h @@ -0,0 +1,41 @@ +/* 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 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.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  The ABI requires 16 +   bytes (for both 32-bit and 64-bit PowerPC).  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	4096 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME	__builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym b/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym new file mode 100644 index 000000000..3962edbd5 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym @@ -0,0 +1,16 @@ +#include <sysdep.h> +#include <tls.h> + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +# undef __thread_register +# define __thread_register	((void *) 0) +# define thread_offsetof(mem)	((ptrdiff_t) THREAD_SELF + offsetof (struct pthread, mem)) + + +#if TLS_MULTIPLE_THREADS_IN_TCB +MULTIPLE_THREADS_OFFSET		thread_offsetof (header.multiple_threads) +#endif +PID				thread_offsetof (pid) +TID				thread_offsetof (tid) diff --git a/libpthread/nptl/sysdeps/powerpc/tls.h b/libpthread/nptl/sysdeps/powerpc/tls.h new file mode 100644 index 000000000..a7f69074e --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/tls.h @@ -0,0 +1,165 @@ +/* Definition for thread-local data handling.  NPTL/PowerPC 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 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 _TLS_H +#define _TLS_H	1 + +# include <dl-sysdep.h> + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools.  */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available.  */ +# define USE_TLS	1 + +#ifndef __ASSEMBLER__ + +/* Get system call information.  */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks.  */ +# define TLS_DTV_AT_TP	1 + +/* We use the multiple_threads field in the pthread struct */ +#define TLS_MULTIPLE_THREADS_IN_TCB	1 + +/* Get the thread descriptor definition.  */ +# include <nptl/descr.h> + +/* This layout is actually wholly private and not affected by the ABI. +   Nor does it overlap the pthread data structure, so we need nothing +   extra here at all.  */ +typedef struct +{ +  dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB.  */ +# define TLS_INIT_TCB_SIZE	0 + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN	__alignof__ (struct pthread) + +/* This is the size of the TCB.  */ +# define TLS_TCB_SIZE		0 + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN		__alignof__ (struct pthread) + +/* This is the size we need before TCB.  */ +# define TLS_PRE_TCB_SIZE \ +  (sizeof (struct pthread)						      \ +   + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +# ifndef __powerpc64__ +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r2"); +#  define PT_THREAD_POINTER PT_R2 +# else +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r13"); +#  define PT_THREAD_POINTER PT_R13 +# endif + +/* The following assumes that TP (R2 or R13) points to the end of the +   TCB + 0x7000 (per the ABI).  This implies that TCB address is +   TP - 0x7000.  As we define TLS_DTV_AT_TP we can +   assume that the pthread struct is allocated immediately ahead of the +   TCB.  This implies that the pthread_descr address is +   TP - (TLS_PRE_TCB_SIZE + 0x7000).  */ +# define TLS_TCB_OFFSET	0x7000 + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(tcbp, dtvp) \ +  ((tcbhead_t *) (tcbp))[-1].dtv = dtvp + 1 + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(tcbp)	(((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer.  This might need +   special attention since 'errno' is not yet available and if the +   operation can cause a failure 'errno' must not be touched.  */ +# define TLS_INIT_TP(tcbp, secondcall) \ +    (__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET, NULL) + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +     (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread.  */ +# define THREAD_SELF \ +    ((struct pthread *) (__thread_register \ +			 - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF							      \ +  REGISTER (32, 32, PT_THREAD_POINTER * 4,					      \ +	    - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)			      \ +  REGISTER (64, 64, PT_THREAD_POINTER * 8,					      \ +	    - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +/* Read member of the thread descriptor directly.  */ +# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */ +# define THREAD_GETMEM_NC(descr, member, idx) \ +    ((void)(descr), (THREAD_SELF)->member[idx]) + +/* Set member of the thread descriptor directly.  */ +# define THREAD_SETMEM(descr, member, value) \ +    ((void)(descr), (THREAD_SELF)->member = (value)) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ +    ((void)(descr), (THREAD_SELF)->member[idx] = (value)) + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some +   different value to mean unset l_tls_offset.  */ +# define NO_TLS_OFFSET		-1 + +#endif /* __ASSEMBLER__ */ + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h b/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 000000000..795caa713 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,568 @@ +/* libc-internal interface for mutex locks.  NPTL version. +   Copyright (C) 1996-2001, 2002, 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 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; 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_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include <pthread.h> +#define __need_NULL +#include <stddef.h> + + +/* Fortunately Linux now has a mean to do locking which is realtime +   safe without the aid of the thread library.  We also need no fancy +   options like error checking mutexes etc.  We only need simple +   locks, maybe recursive.  This can be easily and cheaply implemented +   using futexes.  We will use them everywhere except in ld.so since +   ld.so might be used on old kernels with a different libc.so.  */ +#ifdef _LIBC +# include <lowlevellock.h> +# include <tls.h> +# include <pthread-functions.h> +#endif + +/* Mutex type.  */ +#if defined _LIBC || defined _IO_MTSAFE_IO +# if (defined NOT_IN_libc && !defined IS_IN_libpthread) || !defined _LIBC +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# else +typedef int __libc_lock_t; +typedef struct { int lock; int cnt; void *owner; } __libc_lock_recursive_t; +# endif +typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data.  */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS.  The lock must be +   initialized with __libc_lock_init before it can be used (or define it +   with __libc_lock_define_initialized, below).  Use `extern' for CLASS to +   declare a lock defined in another module.  In public structure +   definitions you must use a pointer to the lock structure (i.e., NAME +   begins with a `*'), because its storage size will not be known outside +   of libc.  */ +#define __libc_lock_define(CLASS,NAME) \ +  CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ +  CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ +  CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ +  CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + +   For the C library we take a deeper look at the initializer.  For +   this implementation all fields are initialized to zero.  Therefore +   we don't initialize the variable which allows putting it into the +   BSS section.  (Except on PA-RISC and other odd architectures, where +   initialized locks must be set to one due to the lack of normal +   atomic operations.) */ + +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# if LLL_LOCK_INITIALIZER == 0 +#  define __libc_lock_define_initialized(CLASS,NAME) \ +  CLASS __libc_lock_t NAME; +# else +#  define __libc_lock_define_initialized(CLASS,NAME) \ +  CLASS __libc_lock_t NAME = LLL_LOCK_INITIALIZER; +# endif +#else +# if __LT_SPINLOCK_INIT == 0 +#  define __libc_lock_define_initialized(CLASS,NAME) \ +  CLASS __libc_lock_t NAME; +# else +#  define __libc_lock_define_initialized(CLASS,NAME) \ +  CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +# endif +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ +  CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage +   class CLASS.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# if LLL_LOCK_INITIALIZER == 0 +#  define __libc_lock_define_initialized_recursive(CLASS,NAME) \ +  CLASS __libc_lock_recursive_t NAME; +# else +#  define __libc_lock_define_initialized_recursive(CLASS,NAME) \ +  CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +# endif +# define _LIBC_LOCK_RECURSIVE_INITIALIZER \ +  { LLL_LOCK_INITIALIZER, 0, NULL } +#else +# define __libc_lock_define_initialized_recursive(CLASS,NAME) \ +  CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +# define _LIBC_LOCK_RECURSIVE_INITIALIZER \ +  {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} +#endif + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ +  CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ +  {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_initialize(NAME) \ +  (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER) + +/* If we check for a weakly referenced symbol and then perform a +   normal jump to it te code generated for some platforms in case of +   PIC is unnecessarily slow.  What would happen is that the function +   is first referenced as data and then it is called indirectly +   through the PLT.  We can make this a direct jump.  */ +#ifdef __PIC__ +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ +  (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ +                    _fn != NULL ? (*_fn) ARGS : ELSE; })) +#else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ +  (FUNC != NULL ? FUNC ARGS : ELSE) +#endif + +/* Call thread functions through the function pointer table.  */ +#if defined SHARED && !defined NOT_IN_libc +# define PTF(NAME) __libc_pthread_functions.ptr_##NAME +# define __libc_ptf_call(FUNC, ARGS, ELSE) \ +  (PTF(FUNC) != NULL ? PTF(FUNC) ARGS : ELSE) +#else +# define PTF(NAME) NAME +# define __libc_ptf_call(FUNC, ARGS, ELSE) \ +  __libc_maybe_call (FUNC, ARGS, ELSE) +#endif + + +/* Initialize the named lock variable, leaving it in a consistent, unlocked +   state.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_init(NAME) ((NAME) = LLL_LOCK_INITIALIZER, 0) +#else +# define __libc_lock_init(NAME) \ +  __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0) +#endif +#define __libc_rwlock_init(NAME) \ +  __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0) + +/* Same as last but this time we initialize a recursive mutex.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_init_recursive(NAME) \ +  ((NAME) = (__libc_lock_recursive_t) _LIBC_LOCK_RECURSIVE_INITIALIZER, 0) +#else +# define __libc_lock_init_recursive(NAME) \ +  do {									      \ +    if (__pthread_mutex_init != NULL)					      \ +      {									      \ +	pthread_mutexattr_t __attr;					      \ +	__pthread_mutexattr_init (&__attr);				      \ +	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP);    \ +	__pthread_mutex_init (&(NAME).mutex, &__attr);			      \ +	__pthread_mutexattr_destroy (&__attr);				      \ +      }									      \ +  } while (0) +#endif + +#define __rtld_lock_init_recursive(NAME) \ +  do {									      \ +    if (__pthread_mutex_init != NULL)					      \ +      {									      \ +	pthread_mutexattr_t __attr;					      \ +	__pthread_mutexattr_init (&__attr);				      \ +	__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP);    \ +	__pthread_mutex_init (&(NAME).mutex, &__attr);			      \ +	__pthread_mutexattr_destroy (&__attr);				      \ +      }									      \ +  } while (0) + +/* Finalize the named lock variable, which must be locked.  It cannot be +   used again until __libc_lock_init is called again on it.  This must be +   called on a lock variable before the containing storage is reused.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_fini(NAME) ((void) 0) +#else +# define __libc_lock_fini(NAME) \ +  __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) +#endif +#define __libc_rwlock_fini(NAME) \ +  __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0) + +/* Finalize recursive named lock.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_fini_recursive(NAME) ((void) 0) +#else +# define __libc_lock_fini_recursive(NAME) \ +  __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) +#endif + +/* Lock the named lock variable.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_lock(NAME) \ +  ({ lll_lock (NAME); 0; }) +#else +# define __libc_lock_lock(NAME) \ +  __libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0) +#endif +#define __libc_rwlock_rdlock(NAME) \ +  __libc_ptf_call (__pthread_rwlock_rdlock, (&(NAME)), 0) +#define __libc_rwlock_wrlock(NAME) \ +  __libc_ptf_call (__pthread_rwlock_wrlock, (&(NAME)), 0) + +/* Lock the recursive named lock variable.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_lock_recursive(NAME) \ +  do {									      \ +    void *self = THREAD_SELF;						      \ +    if ((NAME).owner != self)						      \ +      {									      \ +	lll_lock ((NAME).lock);						      \ +	(NAME).owner = self;						      \ +      }									      \ +    ++(NAME).cnt;							      \ +  } while (0) +#else +# define __libc_lock_lock_recursive(NAME) \ +  __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) +#endif + +/* Try to lock the named lock variable.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_trylock(NAME) \ +  lll_trylock (NAME) +#else +# define __libc_lock_trylock(NAME) \ +  __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) +#endif +#define __libc_rwlock_tryrdlock(NAME) \ +  __libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0) +#define __libc_rwlock_trywrlock(NAME) \ +  __libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0) + +/* Try to lock the recursive named lock variable.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_trylock_recursive(NAME) \ +  ({									      \ +    int result = 0;							      \ +    void *self = THREAD_SELF;						      \ +    if ((NAME).owner != self)						      \ +      {									      \ +	if (lll_trylock ((NAME).lock) == 0)				      \ +	  {								      \ +	    (NAME).owner = self;					      \ +	    (NAME).cnt = 1;						      \ +	  }								      \ +	else								      \ +	  result = EBUSY;						      \ +      }									      \ +    else								      \ +      ++(NAME).cnt;							      \ +    result;								      \ +  }) +#else +# define __libc_lock_trylock_recursive(NAME) \ +  __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) +#endif + +#define __rtld_lock_trylock_recursive(NAME) \ +  __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0) + +/* Unlock the named lock variable.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_unlock(NAME) \ +  lll_unlock (NAME) +#else +# define __libc_lock_unlock(NAME) \ +  __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) +#endif +#define __libc_rwlock_unlock(NAME) \ +  __libc_ptf_call (__pthread_rwlock_unlock, (&(NAME)), 0) + +/* Unlock the recursive named lock variable.  */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +/* We do no error checking here.  */ +# define __libc_lock_unlock_recursive(NAME) \ +  do {									      \ +    if (--(NAME).cnt == 0)						      \ +      {									      \ +	(NAME).owner = NULL;						      \ +	lll_unlock ((NAME).lock);					      \ +      }									      \ +  } while (0) +#else +# define __libc_lock_unlock_recursive(NAME) \ +  __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) +#endif + +#if defined _LIBC && defined SHARED +# define __rtld_lock_default_lock_recursive(lock) \ +  ++((pthread_mutex_t *)(lock))->__data.__count; + +# define __rtld_lock_default_unlock_recursive(lock) \ +  --((pthread_mutex_t *)(lock))->__data.__count; + +# define __rtld_lock_lock_recursive(NAME) \ +  GL(dl_rtld_lock_recursive) (&(NAME).mutex) + +# define __rtld_lock_unlock_recursive(NAME) \ +  GL(dl_rtld_unlock_recursive) (&(NAME).mutex) +#else +# define __rtld_lock_lock_recursive(NAME) \ +  __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) + +# define __rtld_lock_unlock_recursive(NAME) \ +  __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) +#endif + +/* Define once control variable.  */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization +   if it is zero.  */ +# define __libc_once_define(CLASS, NAME) \ +  CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ +  CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call.  */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ +  do {									      \ +    if (PTF(__pthread_once) != NULL)					      \ +      PTF(__pthread_once) (&(ONCE_CONTROL), INIT_FUNCTION);		      \ +    else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) {			      \ +      INIT_FUNCTION ();							      \ +      (ONCE_CONTROL) |= 2;						      \ +    }									      \ +  } while (0) + + +/* Note that for I/O cleanup handling we are using the old-style +   cancel handling.  It does not have to be integrated with C++ snce +   no C++ code is called in the middle.  The old-style handling is +   faster and the support is not going away.  */ +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, +                                   void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, +                                  int execute); +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, +                                         void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, +                                          int execute); + +/* Start critical region with cleanup.  */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ +  { struct _pthread_cleanup_buffer _buffer;				      \ +    int _avail;								      \ +    if (DOIT) {								      \ +      _avail = PTF(_pthread_cleanup_push_defer) != NULL;		      \ +      if (_avail) {							      \ +	PTF(_pthread_cleanup_push_defer) (&_buffer, FCT, ARG);		      \ +      } else {								      \ +	_buffer.__routine = (FCT);					      \ +	_buffer.__arg = (ARG);						      \ +      }									      \ +    } else {								      \ +      _avail = 0;							      \ +    } + +/* End critical region with cleanup.  */ +#define __libc_cleanup_region_end(DOIT) \ +    if (_avail) {							      \ +      PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT);		      \ +    } else if (DOIT)							      \ +      _buffer.__routine (_buffer.__arg);				      \ +  } + +/* Sometimes we have to exit the block in the middle.  */ +#define __libc_cleanup_end(DOIT) \ +    if (_avail) {							      \ +      PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT);		      \ +    } else if (DOIT)							      \ +      _buffer.__routine (_buffer.__arg) + + +/* Normal cleanup handling, based on C cleanup attribute.  */ +extern __inline void +__libc_cleanup_routine (struct __pthread_cleanup_frame *f) +{ +  if (f->__do_it) +    f->__cancel_routine (f->__cancel_arg); +} + +#define __libc_cleanup_push(fct, arg) \ +  do {									      \ +    struct __pthread_cleanup_frame __clframe				      \ +      __attribute__ ((__cleanup__ (__libc_cleanup_routine)))		      \ +      = { .__cancel_routine = (fct), .__cancel_arg = (arg),		      \ +          .__do_it = 1 }; + +#define __libc_cleanup_pop(execute) \ +    __clframe.__do_it = (execute);					      \ +  } while (0) + + +/* Create thread-specific key.  */ +#define __libc_key_create(KEY, DESTRUCTOR) \ +  __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1) + +/* Get thread-specific data.  */ +#define __libc_getspecific(KEY) \ +  __libc_ptf_call (__pthread_getspecific, (KEY), NULL) + +/* Set thread-specific data.  */ +#define __libc_setspecific(KEY, VALUE) \ +  __libc_ptf_call (__pthread_setspecific, (KEY, VALUE), 0) + + +/* Register handlers to execute before and after `fork'.  Note that the +   last parameter is NULL.  The handlers registered by the libc are +   never removed so this is OK.  */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ +  __register_atfork (PREPARE, PARENT, CHILD, NULL) +extern int __register_atfork (void (*__prepare) (void), +			      void (*__parent) (void), +			      void (*__child) (void), +			      void *__dso_handle); + +/* Functions that are used by this file and are internal to the GNU C +   library.  */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, +				 __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, +					int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, +				  __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, +				 void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, +				  __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, +			   void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), +			     void (*__parent) (void), +			     void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from +   single-threaded processes.  */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +#  if _LIBC +#   include <bp-sym.h> +#  else +#   define BP_SYM (sym) sym +#  endif +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +weak_extern (BP_SYM (pthread_setcancelstate)) +# else +#  pragma weak __pthread_mutex_init +#  pragma weak __pthread_mutex_destroy +#  pragma weak __pthread_mutex_lock +#  pragma weak __pthread_mutex_trylock +#  pragma weak __pthread_mutex_unlock +#  pragma weak __pthread_mutexattr_init +#  pragma weak __pthread_mutexattr_destroy +#  pragma weak __pthread_mutexattr_settype +#  pragma weak __pthread_rwlock_destroy +#  pragma weak __pthread_rwlock_rdlock +#  pragma weak __pthread_rwlock_tryrdlock +#  pragma weak __pthread_rwlock_wrlock +#  pragma weak __pthread_rwlock_trywrlock +#  pragma weak __pthread_rwlock_unlock +#  pragma weak __pthread_key_create +#  pragma weak __pthread_setspecific +#  pragma weak __pthread_getspecific +#  pragma weak __pthread_once +#  pragma weak __pthread_initialize +#  pragma weak __pthread_atfork +#  pragma weak _pthread_cleanup_push_defer +#  pragma weak _pthread_cleanup_pop_restore +#  pragma weak pthread_setcancelstate +# endif +#endif + +#endif	/* bits/libc-lock.h */ diff --git a/libpthread/nptl/sysdeps/pthread/bits/sigthread.h b/libpthread/nptl/sysdeps/pthread/bits/sigthread.h new file mode 100644 index 000000000..960bde18a --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/bits/sigthread.h @@ -0,0 +1,38 @@ +/* Signal handling function for threaded programs. +   Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; 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_SIGTHREAD_H +#define _BITS_SIGTHREAD_H	1 + +#if !defined _SIGNAL_H && !defined _PTHREAD_H +# error "Never include this file directly.  Use <pthread.h> instead" +#endif + +/* Functions for handling signals. */ + +/* Modify the signal mask for the calling thread.  The arguments have +   the same meaning as for sigprocmask(2). */ +extern int pthread_sigmask (int __how, +			    __const __sigset_t *__restrict __newmask, +			    __sigset_t *__restrict __oldmask)__THROW; + +/* Send signal SIGNO to the given thread. */ +extern int pthread_kill (pthread_t __threadid, int __signo) __THROW; + +#endif	/* bits/sigthread.h */ diff --git a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h new file mode 100644 index 000000000..cd64bc37e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h @@ -0,0 +1,105 @@ +/* Thread package specific definitions of stream lock type.  NPTL version. +   Copyright (C) 2000, 2001, 2002, 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 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_STDIO_LOCK_H +#define _BITS_STDIO_LOCK_H 1 + +#include <bits/libc-lock.h> +#include <lowlevellock.h> + + +/* The locking here is very inexpensive, even for inlining.  */ +#define _IO_lock_inexpensive	1 + +typedef struct { int lock; int cnt; void *owner; } _IO_lock_t; + +#define _IO_lock_initializer { LLL_LOCK_INITIALIZER, 0, NULL } + +#define _IO_lock_init(_name) \ +  ((_name) = (_IO_lock_t) _IO_lock_initializer , 0) + +#define _IO_lock_fini(_name) \ +  ((void) 0) + +#define _IO_lock_lock(_name) \ +  do {									      \ +    void *__self = THREAD_SELF;						      \ +    if ((_name).owner != __self)					      \ +      {									      \ +        lll_lock ((_name).lock);					      \ +        (_name).owner = __self;						      \ +      }									      \ +    ++(_name).cnt;							      \ +  } while (0) + +#define _IO_lock_trylock(_name) \ +  ({									      \ +    int __result = 0;							      \ +    void *__self = THREAD_SELF;						      \ +    if ((_name).owner != __self)					      \ +      {									      \ +        if (lll_trylock ((_name).lock) == 0)				      \ +          {								      \ +            (_name).owner = __self;					      \ +            (_name).cnt = 1;						      \ +          }								      \ +        else								      \ +          __result = EBUSY;						      \ +      }									      \ +    else								      \ +      ++(_name).cnt;							      \ +    __result;								      \ +  }) + +#define _IO_lock_unlock(_name) \ +  do {									      \ +    if (--(_name).cnt == 0)						      \ +      {									      \ +        (_name).owner = NULL;						      \ +        lll_unlock ((_name).lock);					      \ +      }									      \ +  } while (0) + + + +#define _IO_cleanup_region_start(_fct, _fp) \ +  __libc_cleanup_region_start (((_fp)->_flags & _IO_USER_LOCK) == 0, _fct, _fp) +#define _IO_cleanup_region_start_noarg(_fct) \ +  __libc_cleanup_region_start (1, _fct, NULL) +#define _IO_cleanup_region_end(_doit) \ +  __libc_cleanup_region_end (_doit) + +#if defined _LIBC && !defined NOT_IN_libc + +# ifdef __EXCEPTIONS +#  define _IO_acquire_lock(_fp) \ +  do {									      \ +    _IO_FILE *_IO_acquire_lock_file					      \ +	__attribute__((cleanup (_IO_acquire_lock_fct)))			      \ +	= (_fp);							      \ +    _IO_flockfile (_IO_acquire_lock_file); + +# else +#  define _IO_acquire_lock(_fp) _IO_acquire_lock_needs_exceptions_enabled +# endif +# define _IO_release_lock(_fp) ; } while (0) + +#endif + +#endif /* bits/stdio-lock.h */ diff --git a/libpthread/nptl/sysdeps/sh/Makefile b/libpthread/nptl/sysdeps/sh/Makefile new file mode 100644 index 000000000..81bddf688 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h new file mode 100644 index 000000000..cf6d25f04 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(jmpbuf, address, adj) \ +  ((uintptr_t) (address) - (adj) < (uintptr_t) (jmpbuf)[0].__regs[7] - (adj)) + +/* We use the normal lobngjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_init.c b/libpthread/nptl/sysdeps/sh/pthread_spin_init.c new file mode 100644 index 000000000..0a47981aa --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +/* Not needed.  pthread_spin_init is an alias for pthread_spin_unlock.  */ diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c new file mode 100644 index 000000000..e73264108 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c @@ -0,0 +1,35 @@ +/* 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + +int +pthread_spin_lock (lock) +     pthread_spinlock_t *lock; +{ +  unsigned int val; + +  do +    asm volatile ("tas.b @%1; movt %0" +		  : "=&r" (val) +		  : "r" (lock) +		  : "memory"); +  while (val == 0); + +  return 0; +} diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S new file mode 100644 index 000000000..18112ba23 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S @@ -0,0 +1,32 @@ +/* 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthread-errnos.h> + +	.globl	pthread_spin_trylock +	.type	pthread_spin_trylock,@function +	.align	5 +pthread_spin_trylock: +	tas.b	@r4 +	bf/s	1f +	mov	#EBUSY, r0 +	mov	#0, r0 +1: +	rts +	 nop +	.size	pthread_spin_trylock,.-pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S new file mode 100644 index 000000000..c77acaffe --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S @@ -0,0 +1,30 @@ +/* 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 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.  */ + +	.globl	pthread_spin_unlock +	.type	pthread_spin_unlock,@function +	.align	5 +pthread_spin_unlock: +	mov	#0,r0 +	rts +	 mov.l	r0,@r4 +	.size	pthread_spin_unlock,.-pthread_spin_unlock + +	/* The implementation of pthread_spin_init is identical.  */ +	.globl	pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/libpthread/nptl/sysdeps/sh/pthreaddef.h b/libpthread/nptl/sysdeps/sh/pthreaddef.h new file mode 100644 index 000000000..70c6a850b --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthreaddef.h @@ -0,0 +1,49 @@ +/* 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  */ +#define STACK_ALIGN		8 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	2048 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		8 + + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME	__builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  while (1) {								      \ +    if (__builtin_constant_p (val) && (val) == 0)			      \ +      asm volatile ("mov #0,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD  \ +		   :: "i" (__NR_exit));  \ +    else								      \ +      asm volatile ("mov %1,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD  \ +		    :: "i" (__NR_exit), "r" (val));			      \ +  } diff --git a/libpthread/nptl/sysdeps/sh/tcb-offsets.sym b/libpthread/nptl/sysdeps/sh/tcb-offsets.sym new file mode 100644 index 000000000..539789a81 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/tcb-offsets.sym @@ -0,0 +1,11 @@ +#include <sysdep.h> +#include <tls.h> + +RESULT			offsetof (struct pthread, result) +TID			offsetof (struct pthread, tid) +PID			offsetof (struct pthread, pid) +CANCELHANDLING		offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF		offsetof (struct pthread, cleanup_jmp_buf) +MULTIPLE_THREADS_OFFSET	offsetof (struct pthread, header.multiple_threads) +TLS_PRE_TCB_SIZE	sizeof (struct pthread) +MUTEX_FUTEX		offsetof (pthread_mutex_t, __data.__lock) diff --git a/libpthread/nptl/sysdeps/sh/tls.h b/libpthread/nptl/sysdeps/sh/tls.h new file mode 100644 index 000000000..e883bae99 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/tls.h @@ -0,0 +1,145 @@ +/* Definition for thread-local data handling.  NPTL/SH 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 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 _TLS_H +#define _TLS_H + +# include <dl-sysdep.h> + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + +typedef struct +{ +  dtv_t *dtv; +  void *private; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools.  */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available.  */ +# define USE_TLS	1 + +#ifndef __ASSEMBLER__ + +/* Get system call information.  */ +# include <sysdep.h> + +/* This is the size of the initial TCB.  */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB.  */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB.  */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TLS blocks start right after the TCB.  */ +# define TLS_DTV_AT_TP	1 + +/* Get the thread descriptor definition.  */ +# include <nptl/descr.h> + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(tcbp, dtvp) \ +  ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(dtv) \ +  ({ tcbhead_t *__tcbp;							      \ +     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));			      \ +     __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(tcbp) \ +  (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer.  This might need +   special attention since 'errno' is not yet available and if the +   operation can cause a failure 'errno' must not be touched.  */ +# define TLS_INIT_TP(tcbp, secondcall) \ +  ({ __asm __volatile ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +  ({ tcbhead_t *__tcbp;							      \ +     __asm __volatile ("stc gbr,%0" : "=r" (__tcbp));			      \ +     __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. +   The contained asm must *not* be marked volatile since otherwise +   assignments like +        struct pthread *self = thread_self(); +   do not get optimized away.  */ +# define THREAD_SELF \ +  ({ struct pthread *__self;						      \ +     __asm ("stc gbr,%0" : "=r" (__self));				      \ +     __self - 1;}) + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF \ +  REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread)) + +/* Read member of the thread descriptor directly.  */ +# define THREAD_GETMEM(descr, member) (descr->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */ +# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx]) + +/* Set member of the thread descriptor directly.  */ +# define THREAD_SETMEM(descr, member, value) \ +    descr->member = (value) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ +    descr->member[idx] = (value) + +#endif /* __ASSEMBLER__ */ + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/sparc/Makefile b/libpthread/nptl/sysdeps/sparc/Makefile new file mode 100644 index 000000000..81bddf688 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h new file mode 100644 index 000000000..5cef8b1cf --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c new file mode 100644 index 000000000..d3c6e3049 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ +  __asm __volatile +    ("1: ldstub [%0], %%g2\n" +     "   orcc   %%g2, 0x0, %%g0\n" +     "   bne,a  2f\n" +     "   ldub   [%0], %%g2\n" +     ".subsection 2\n" +     "2: orcc   %%g2, 0x0, %%g0\n" +     "   bne,a  2b\n" +     "   ldub   [%0], %%g2\n" +     "   b,a    1b\n" +     ".previous" +     : /* no outputs */ +     : "r" (lock) +     : "g2", "memory", "cc"); +  return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c new file mode 100644 index 000000000..bcc3158fd --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ +  int res; +  __asm __volatile ("ldstub [%1], %0" : "=r" (res) : "r" (lock) : "memory"); +  return res == 0 ? 0 : EBUSY; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h b/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h new file mode 100644 index 000000000..9908df9e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h @@ -0,0 +1,40 @@ +/* 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 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.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	2048 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME  (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c new file mode 100644 index 000000000..8880f535b --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ +  __asm __volatile +    ("1: ldstub  [%0], %%g2\n" +     "   brnz,pn %%g2, 2f\n" +     "    membar #StoreLoad | #StoreStore\n" +     ".subsection 2\n" +     "2: ldub    [%0], %%g2\n" +     "   brnz,pt %%g2, 2b\n" +     "    membar #LoadLoad\n" +     "   b,a,pt  %%xcc, 1b\n" +     ".previous" +     : /* no outputs */ +     : "r" (lock) +     : "g2", "memory"); +  return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c new file mode 100644 index 000000000..3b20a2180 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c @@ -0,0 +1 @@ +#include <sparc64/pthread_spin_trylock.c> diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c new file mode 100644 index 000000000..482cbe3d7 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c @@ -0,0 +1 @@ +#include <sparc64/pthread_spin_unlock.c> diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h new file mode 100644 index 000000000..77321aad3 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by David S. Miller <davem@davemloft.net>, 2005. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[0].uc_mcontext.mc_fp - (_adj)) + +/* We use the normal lobngjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c new file mode 100644 index 000000000..77171d9b9 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ +  __asm __volatile +    ("1: ldstub  [%0], %%g5\n" +     "   brnz,pn %%g5, 2f\n" +     "    membar #StoreLoad | #StoreStore\n" +     ".subsection 2\n" +     "2: ldub    [%0], %%g5\n" +     "   brnz,pt %%g5, 2b\n" +     "    membar #LoadLoad\n" +     "   b,a,pt  %%xcc, 1b\n" +     ".previous" +     : /* no outputs */ +     : "r" (lock) +     : "g5", "memory"); +  return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c new file mode 100644 index 000000000..2bda809da --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ +  int res; +  __asm __volatile +    ("ldstub [%1], %0\n" +     "membar #StoreLoad | #StoreStore" +     : "=r" (res) +     : "r" (lock) +     : "memory"); +  return res == 0 ? 0 : EBUSY; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c new file mode 100644 index 000000000..7037675a2 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c @@ -0,0 +1,30 @@ +/* pthread_spin_unlock -- unlock a spin lock.  Generic version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "pthreadP.h" +#include <atomic.h> + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ +  __asm __volatile ("membar #StoreStore | #LoadStore"); +  *lock = 0; +  return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h b/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h new file mode 100644 index 000000000..ec7651211 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h @@ -0,0 +1,40 @@ +/* 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 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.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	4096 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + + +/* Location of current stack frame.  */ +#define CURRENT_STACK_FRAME  (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__("%sp"); + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym b/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym new file mode 100644 index 000000000..237f975b2 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym @@ -0,0 +1,6 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET		offsetof (tcbhead_t, multiple_threads) +PID				offsetof (struct pthread, pid) +TID				offsetof (struct pthread, tid) diff --git a/libpthread/nptl/sysdeps/sparc/tls.h b/libpthread/nptl/sysdeps/sparc/tls.h new file mode 100644 index 000000000..8f54a0bb2 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/tls.h @@ -0,0 +1,129 @@ +/* Definitions for thread-local data handling.  NPTL/sparc 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 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 _TLS_H +#define _TLS_H + +#include <dl-sysdep.h> +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <list.h> + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + +typedef struct +{ +  void *tcb;		/* Pointer to the TCB.  Not necessary the +			   thread descriptor used by libpthread.  */ +  dtv_t *dtv; +  void *self; +  int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + +/* We require TLS support in the tools.  */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available.  */ +#define USE_TLS	1 + +#ifndef __ASSEMBLER__ +/* Get system call information.  */ +# include <sysdep.h> + +/* Get the thread descriptor definition.  */ +# include <nptl/descr.h> + +register struct pthread *__thread_self __asm__("%g7"); + +/* This is the size of the initial TCB.  */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB.  */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the +   thread pointer points to is unspecified.  Allocate the TCB there.  */ +# define TLS_TCB_AT_TP	1 + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(descr, dtvp) \ +  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(DTV) \ +  (((tcbhead_t *) __thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(descr) \ +  (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer.  */ +# define TLS_INIT_TP(descr, secondcall) \ +  (__thread_self = (__typeof (__thread_self)) (descr), NULL) + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +  (((tcbhead_t *) __thread_self)->dtv) + +/* Return the thread descriptor for the current thread.  */ +#define THREAD_SELF  __thread_self + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF_INCLUDE <sys/ucontext.h> +# define DB_THREAD_SELF \ +  REGISTER (32, 32, REG_G7 * 4, 0) REGISTER (64, 64, REG_G7 * 8, 0) + +/* Access to data in the thread descriptor is easy.  */ +#define THREAD_GETMEM(descr, member) \ +  descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ +  descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ +  descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ +  descr->member[idx] = (value) + +#endif /* !ASSEMBLER */ + +#endif	/* tls.h */ diff --git a/libpthread/nptl/sysdeps/x86_64/Makefile b/libpthread/nptl/sysdeps/x86_64/Makefile new file mode 100644 index 000000000..6e24a26cd --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/Makefile @@ -0,0 +1,28 @@ +# Copyright (C) 2002, 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 +# 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. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif + +ifeq ($(subdir),nptl) +# P4s have problems with 4M aliasing.  We disturb the allocation of stacks +# just enough so the subsequent allocations do not use stack address +# (mod 4M) == 0. +CFLAGS-pthread_create.c += -DMULTI_PAGE_ALIASING=65536 +endif diff --git a/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h new file mode 100644 index 000000000..345ed557c --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ +  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_RSP] - (_adj)) + +/* We use the normal lobngjmp for unwinding.  */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c b/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c new file mode 100644 index 000000000..55696204c --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include "../i386/pthread_spin_init.c" diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c b/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c new file mode 100644 index 000000000..7cf0e0ecc --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c @@ -0,0 +1 @@ +#include "../i386/pthread_spin_lock.c" diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S new file mode 100644 index 000000000..9b5133583 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S @@ -0,0 +1,40 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthread-errnos.h> + + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +	.globl	pthread_spin_trylock +	.type	pthread_spin_trylock,@function +	.align	16 +pthread_spin_trylock: +	movl	$1, %eax +	xorl	%ecx, %ecx +	LOCK +	cmpxchgl %ecx, (%rdi) +	movl	$EBUSY, %eax +	cmovel	%ecx, %eax +	retq +	.size	pthread_spin_trylock,.-pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S new file mode 100644 index 000000000..d3e13bde9 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S @@ -0,0 +1,31 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +	.globl	pthread_spin_unlock +	.type	pthread_spin_unlock,@function +	.align	16 +pthread_spin_unlock: +	movl	$1, (%rdi) +	xorl	%eax, %eax +	retq +	.size	pthread_spin_unlock,.-pthread_spin_unlock + +	/* The implementation of pthread_spin_init is identical.  */ +	.globl	pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/libpthread/nptl/sysdeps/x86_64/pthreaddef.h b/libpthread/nptl/sysdeps/x86_64/pthreaddef.h new file mode 100644 index 000000000..27896a445 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthreaddef.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +/* Default stack size.  */ +#define ARCH_STACK_DEFAULT_SIZE	(2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning.  SSE requires 16 +   bytes.  */ +#define STACK_ALIGN		16 + +/* Minimal stack size after allocating thread descriptor and guard size.  */ +#define MINIMAL_REST_STACK	2048 + +/* Alignment requirement for TCB.  */ +#define TCB_ALIGNMENT		16 + + +/* Location of current stack frame.  The frame pointer is not usable.  */ +#define CURRENT_STACK_FRAME \ +  ({ char *frame; asm ("movq %%rsp, %0" : "=r" (frame)); frame; }) + + +/* We prefer to have the stack allocated in the low 4GB since this +   allows faster context switches.  */ +#define ARCH_MAP_FLAGS MAP_32BIT + +/* If it is not possible to allocate memory there retry without that +   flag.  */ +#define ARCH_RETRY_MMAP(size) \ +  mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,			      \ +	MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) + + +/* XXX Until we have a better place keep the definitions here.  */ + +/* While there is no such syscall.  */ +#define __exit_thread_inline(val) \ +  asm volatile ("syscall" :: "a" (__NR_exit), "D" (val)) diff --git a/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym b/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym new file mode 100644 index 000000000..8118d2df8 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym @@ -0,0 +1,12 @@ +#include <sysdep.h> +#include <tls.h> + +RESULT			offsetof (struct pthread, result) +TID			offsetof (struct pthread, tid) +PID			offsetof (struct pthread, pid) +CANCELHANDLING		offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF		offsetof (struct pthread, cleanup_jmp_buf) +CLEANUP			offsetof (struct pthread, cleanup) +CLEANUP_PREV		offsetof (struct _pthread_cleanup_buffer, __prev) +MUTEX_FUTEX		offsetof (pthread_mutex_t, __data.__lock) +MULTIPLE_THREADS_OFFSET	offsetof (tcbhead_t, multiple_threads) diff --git a/libpthread/nptl/sysdeps/x86_64/tls.h b/libpthread/nptl/sysdeps/x86_64/tls.h new file mode 100644 index 000000000..12da9dc81 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/tls.h @@ -0,0 +1,323 @@ +/* Definition for thread-local data handling.  nptl/x86_64 version. +   Copyright (C) 2002, 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 +   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 _TLS_H +#define _TLS_H	1 + +#include <asm/prctl.h>	/* For ARCH_SET_FS.  */ +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> + + +/* Type for the dtv.  */ +typedef union dtv +{ +  size_t counter; +  struct +  { +    void *val; +    bool is_static; +  } pointer; +} dtv_t; + + +typedef struct +{ +  void *tcb;		/* Pointer to the TCB.  Not necessary the +			   thread descriptor used by libpthread.  */ +  dtv_t *dtv; +  void *self;		/* Pointer to the thread descriptor.  */ +  int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + + +/* We require TLS support in the tools.  */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available.  */ +#define USE_TLS	1 + +/* Alignment requirement for the stack.  */ +#define STACK_ALIGN	16 + + +#ifndef __ASSEMBLER__ +/* Get system call information.  */ +# include <sysdep.h> + + +/* Get the thread descriptor definition.  */ +# include <nptl/descr.h> + +#ifndef LOCK_PREFIX +# ifdef UP +#  define LOCK_PREFIX	/* nothing */ +# else +#  define LOCK_PREFIX	"lock;" +# endif +#endif + +/* This is the size of the initial TCB.  */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB.  */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB.  */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB.  */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the +   thread pointer points to is unspecified.  Allocate the TCB there.  */ +# define TLS_TCB_AT_TP	1 + + +/* Install the dtv pointer.  The pointer passed is to the element with +   index -1 which contain the length.  */ +# define INSTALL_DTV(descr, dtvp) \ +  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread.  */ +# define INSTALL_NEW_DTV(dtvp) \ +  ({ struct pthread *__pd;						      \ +     THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) + +/* Return dtv of given thread descriptor.  */ +# define GET_DTV(descr) \ +  (((tcbhead_t *) (descr))->dtv) + + +/* Macros to load from and store into segment registers.  */ +# define TLS_GET_FS() \ +  ({ int __seg; __asm ("movl %%fs, %0" : "=q" (__seg)); __seg; }) +# define TLS_SET_FS(val) \ +  __asm ("movl %0, %%fs" :: "q" (val)) + + +/* Code to initially initialize the thread pointer.  This might need +   special attention since 'errno' is not yet available and if the +   operation can cause a failure 'errno' must not be touched. + +   We have to make the syscall for both uses of the macro since the +   address might be (and probably is) different.  */ +# define TLS_INIT_TP(thrdescr, secondcall) \ +  ({ void *_thrdescr = (thrdescr);					      \ +     tcbhead_t *_head = _thrdescr;					      \ +     int _result;							      \ +									      \ +     _head->tcb = _thrdescr;						      \ +     /* For now the thread descriptor is at the same address.  */	      \ +     _head->self = _thrdescr;						      \ +									      \ +     /* It is a simple syscall to set the %fs value for the thread.  */	      \ +     asm volatile ("syscall"						      \ +		   : "=a" (_result)					      \ +		   : "0" ((unsigned long int) __NR_arch_prctl),		      \ +		     "D" ((unsigned long int) ARCH_SET_FS),		      \ +		     "S" (_thrdescr)					      \ +		   : "memory", "cc", "r11", "cx");			      \ +									      \ +    _result ? "cannot set %fs base address for thread-local storage" : 0;     \ +  }) + + +/* Return the address of the dtv for the current thread.  */ +# define THREAD_DTV() \ +  ({ struct pthread *__pd;						      \ +     THREAD_GETMEM (__pd, header.dtv); }) + + +/* Return the thread descriptor for the current thread. + +   The contained asm must *not* be marked volatile since otherwise +   assignments like +        pthread_descr self = thread_self(); +   do not get optimized away.  */ +# define THREAD_SELF \ +  ({ struct pthread *__self;						      \ +     asm ("movq %%fs:%c1,%q0" : "=r" (__self)				      \ +	  : "i" (offsetof (struct pthread, header.self)));	 	      \ +     __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF.  */ +# define DB_THREAD_SELF_INCLUDE  <sys/reg.h> /* For the FS constant.  */ +# define DB_THREAD_SELF CONST_THREAD_AREA (64, FS) + +/* Read member of the thread descriptor directly.  */ +# define THREAD_GETMEM(descr, member) \ +  ({ __typeof (descr->member) __value;					      \ +     if (sizeof (__value) == 1)						      \ +       asm volatile ("movb %%fs:%P2,%b0"				      \ +		     : "=q" (__value)					      \ +		     : "0" (0), "i" (offsetof (struct pthread, member)));     \ +     else if (sizeof (__value) == 4)					      \ +       asm volatile ("movl %%fs:%P1,%0"					      \ +		     : "=r" (__value)					      \ +		     : "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       {								      \ +	 if (sizeof (__value) != 8)					      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile ("movq %%fs:%P1,%q0"				      \ +		       : "=r" (__value)					      \ +		       : "i" (offsetof (struct pthread, member)));	      \ +       }								      \ +     __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant.  */ +# define THREAD_GETMEM_NC(descr, member, idx) \ +  ({ __typeof (descr->member[0]) __value;				      \ +     if (sizeof (__value) == 1)						      \ +       asm volatile ("movb %%fs:%P2(%q3),%b0"				      \ +		     : "=q" (__value)					      \ +		     : "0" (0), "i" (offsetof (struct pthread, member[0])),   \ +		       "r" (idx));					      \ +     else if (sizeof (__value) == 4)					      \ +       asm volatile ("movl %%fs:%P1(,%q2,4),%0"				      \ +		     : "=r" (__value)					      \ +		     : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ +     else								      \ +       {								      \ +	 if (sizeof (__value) != 8)					      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile ("movq %%fs:%P1(,%q2,8),%q0"			      \ +		       : "=r" (__value)					      \ +		       : "i" (offsetof (struct pthread, member[0])),	      \ +			 "r" (idx));					      \ +       }								      \ +     __value; }) + + +/* Loading addresses of objects on x86-64 needs to be treated special +   when generating PIC code.  */ +#ifdef __pic__ +# define IMM_MODE "nr" +#else +# define IMM_MODE "ir" +#endif + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */ +# define THREAD_SETMEM(descr, member, value) \ +  ({ if (sizeof (descr->member) == 1)					      \ +       asm volatile ("movb %b0,%%fs:%P1" :				      \ +		     : "iq" (value),					      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else if (sizeof (descr->member) == 4)				      \ +       asm volatile ("movl %0,%%fs:%P1" :				      \ +		     : IMM_MODE (value),				      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       {								      \ +	 if (sizeof (descr->member) != 8)				      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile ("movq %q0,%%fs:%P1" :				      \ +		       : IMM_MODE ((unsigned long int) value),		      \ +			 "i" (offsetof (struct pthread, member)));	      \ +       }}) + + +/* Set member of the thread descriptor directly.  */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ +  ({ if (sizeof (descr->member[0]) == 1)				      \ +       asm volatile ("movb %b0,%%fs:%P1(%q2)" :				      \ +		     : "iq" (value),					      \ +		       "i" (offsetof (struct pthread, member[0])),	      \ +		       "r" (idx));					      \ +     else if (sizeof (descr->member[0]) == 4)				      \ +       asm volatile ("movl %0,%%fs:%P1(,%q2,4)" :			      \ +		     : IMM_MODE (value),				      \ +		       "i" (offsetof (struct pthread, member[0])),	      \ +		       "r" (idx));					      \ +     else								      \ +       {								      \ +	 if (sizeof (descr->member[0]) != 8)				      \ +	   /* There should not be any value with a size other than 1,	      \ +	      4 or 8.  */						      \ +	   abort ();							      \ +									      \ +	 asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" :			      \ +		       : IMM_MODE ((unsigned long int) value),		      \ +			 "i" (offsetof (struct pthread, member[0])),	      \ +			 "r" (idx));					      \ +       }}) + + +/* Atomic compare and exchange on TLS, returning old value.  */ +#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ +  ({ __typeof (descr->member) __ret;					      \ +     __typeof (oldval) __old = (oldval);				      \ +     if (sizeof (descr->member) == 4)					      \ +       asm volatile (LOCK_PREFIX "cmpxchgl %2, %%fs:%P3"		      \ +		     : "=a" (__ret)					      \ +		     : "0" (__old), "r" (newval),			      \ +		       "i" (offsetof (struct pthread, member)));	      \ +     else								      \ +       /* Not necessary for other sizes in the moment.  */		      \ +       abort ();							      \ +     __ret; }) + + +/* Atomic set bit.  */ +#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ +  (void) ({ if (sizeof ((descr)->member) == 4)				      \ +	      asm volatile (LOCK_PREFIX "orl %1, %%fs:%P0"		      \ +			    :: "i" (offsetof (struct pthread, member)),	      \ +			       "ir" (1 << (bit)));			      \ +	    else							      \ +	      /* Not necessary for other sizes in the moment.  */	      \ +	      abort (); }) + + +#define CALL_THREAD_FCT(descr) \ +  ({ void *__res;							      \ +     asm volatile ("movq %%fs:%P2, %%rdi\n\t"				      \ +		   "callq *%%fs:%P1"					      \ +		   : "=a" (__res)					      \ +		   : "i" (offsetof (struct pthread, start_routine)),	      \ +		     "i" (offsetof (struct pthread, arg))		      \ +		   : "di", "si", "cx", "dx", "r8", "r9", "r10", "r11",	      \ +		     "memory", "cc");					      \ +     __res; }) + + +#endif /* __ASSEMBLER__ */ + +#endif	/* tls.h */ diff --git a/libpthread/nptl/unwind.c b/libpthread/nptl/unwind.c new file mode 100644 index 000000000..56a423815 --- /dev/null +++ b/libpthread/nptl/unwind.c @@ -0,0 +1,176 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com> +   and Richard Henderson <rth@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <setjmp.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "pthreadP.h" +#include "jmpbuf-unwind.h" + +#ifdef HAVE_FORCED_UNWIND + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other, adj) \ +  ((uintptr_t) frame - adj >= (uintptr_t) other - adj) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other, adj) \ +  ((uintptr_t) frame - adj <= (uintptr_t) other - adj) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + +static _Unwind_Reason_Code +unwind_stop (int version, _Unwind_Action actions, +	     _Unwind_Exception_Class exc_class, +	     struct _Unwind_Exception *exc_obj, +	     struct _Unwind_Context *context, void *stop_parameter) +{ +  struct pthread_unwind_buf *buf = stop_parameter; +  struct pthread *self = THREAD_SELF; +  struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup); +  int do_longjump = 0; + +  /* Adjust all pointers used in comparisons, so that top of thread's +     stack is at the top of address space.  Without that, things break +     if stack is allocated above the main stack.  */ +  uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size; + +  /* Do longjmp if we're at "end of stack", aka "end of unwind data". +     We assume there are only C frame without unwind data in between +     here and the jmp_buf target.  Otherwise simply note that the CFA +     of a function is NOT within it's stack frame; it's the SP of the +     previous frame.  */ +  if ((actions & _UA_END_OF_STACK) +      || ! _JMPBUF_CFA_UNWINDS_ADJ (buf->cancel_jmp_buf[0].jmp_buf, context, +				    adj)) +    do_longjump = 1; + +  if (__builtin_expect (curp != NULL, 0)) +    { +      /* Handle the compatibility stuff.  Execute all handlers +	 registered with the old method which would be unwound by this +	 step.  */ +      struct _pthread_cleanup_buffer *oldp = buf->priv.data.cleanup; +      void *cfa = (void *) _Unwind_GetCFA (context); + +      if (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp, adj))) +	{ +	  do +	    { +	      /* Pointer to the next element.  */ +	      struct _pthread_cleanup_buffer *nextp = curp->__prev; + +	      /* Call the handler.  */ +	      curp->__routine (curp->__arg); + +	      /* To the next.  */ +	      curp = nextp; +	    } +	  while (curp != oldp +		 && (do_longjump || FRAME_LEFT (cfa, curp, adj))); + +	  /* Mark the current element as handled.  */ +	  THREAD_SETMEM (self, cleanup, curp); +	} +    } + +  if (do_longjump) +    __libc_unwind_longjmp ((struct __jmp_buf_tag *) buf->cancel_jmp_buf, 1); + +  return _URC_NO_REASON; +} + + +static void +unwind_cleanup (_Unwind_Reason_Code reason, struct _Unwind_Exception *exc) +{ +  /* When we get here a C++ catch block didn't rethrow the object.  We +     cannot handle this case and therefore abort.  */ +# define STR_N_LEN(str) str, strlen (str) +  INTERNAL_SYSCALL_DECL (err); +  INTERNAL_SYSCALL (write, err, 3, STDERR_FILENO, +		    STR_N_LEN ("FATAL: exception not rethrown\n")); +  abort (); +} + +#endif	/* have forced unwind */ + + +void +__cleanup_fct_attribute __attribute ((noreturn)) +__pthread_unwind (__pthread_unwind_buf_t *buf) +{ +  struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; +  struct pthread *self = THREAD_SELF; + +#ifdef HAVE_FORCED_UNWIND +  /* This is not a catchable exception, so don't provide any details about +     the exception type.  We do need to initialize the field though.  */ +  THREAD_SETMEM (self, exc.exception_class, 0); +  THREAD_SETMEM (self, exc.exception_cleanup, unwind_cleanup); + +  _Unwind_ForcedUnwind (&self->exc, unwind_stop, ibuf); +#else +  /* Handle the compatibility stuff first.  Execute all handlers +     registered with the old method.  We don't execute them in order, +     instead, they will run first.  */ +  struct _pthread_cleanup_buffer *oldp = ibuf->priv.data.cleanup; +  struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup); + +  if (curp != oldp) +    { +      do +	{ +	  /* Pointer to the next element.  */ +	  struct _pthread_cleanup_buffer *nextp = curp->__prev; + +	  /* Call the handler.  */ +	  curp->__routine (curp->__arg); + +	  /* To the next.  */ +	  curp = nextp; +	} +      while (curp != oldp); + +      /* Mark the current element as handled.  */ +      THREAD_SETMEM (self, cleanup, curp); +    } + +  /* We simply jump to the registered setjmp buffer.  */ +  __libc_unwind_longjmp ((struct __jmp_buf_tag *) ibuf->cancel_jmp_buf, 1); +#endif +  /* NOTREACHED */ + +  /* We better do not get here.  */ +  abort (); +} +hidden_def (__pthread_unwind) + + +void +__cleanup_fct_attribute __attribute ((noreturn)) +__pthread_unwind_next (__pthread_unwind_buf_t *buf) +{ +  struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + +  __pthread_unwind ((__pthread_unwind_buf_t *) ibuf->priv.data.prev); +} +hidden_def (__pthread_unwind_next) diff --git a/libpthread/nptl/vars.c b/libpthread/nptl/vars.c new file mode 100644 index 000000000..1e1a3cf5b --- /dev/null +++ b/libpthread/nptl/vars.c @@ -0,0 +1,43 @@ +/* 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <pthreadP.h> +#include <stdlib.h> +#include <tls.h> +#include <unistd.h> + +/* Default stack size.  */ +size_t __default_stacksize attribute_hidden +#ifdef SHARED +; +#else +  = PTHREAD_STACK_MIN; +#endif + +/* Flag whether the machine is SMP or not.  */ +int __is_smp attribute_hidden; + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Variable set to a nonzero value if more than one thread runs or ran.  */ +int __pthread_multiple_threads attribute_hidden; +#endif + +/* Table of the key information.  */ +struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX] +  __attribute__ ((nocommon)); +hidden_data_def (__pthread_keys) diff --git a/libpthread/nptl_db/Makefile b/libpthread/nptl_db/Makefile new file mode 100644 index 000000000..5c73ff28f --- /dev/null +++ b/libpthread/nptl_db/Makefile @@ -0,0 +1,60 @@ +# Copyright (C) 2002, 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 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. + +# Makefile for NPTL debug library subdirectory of GNU C Library. + +subdir          := nptl_db + +nptl_db-version = 1.0 + +extra-libs = libthread_db +extra-libs-others := $(extra-libs) + +headers         = thread_db.h + +libthread_db-routines = td_init td_log td_ta_new td_ta_delete \ +			td_ta_get_nthreads td_ta_get_ph \ +			td_ta_map_id2thr td_ta_map_lwp2thr \ +			td_ta_thr_iter td_ta_tsd_iter \ +			td_thr_get_info td_thr_getfpregs td_thr_getgregs \ +			td_thr_getxregs td_thr_getxregsize td_thr_setfpregs \ +			td_thr_setgregs td_thr_setprio td_thr_setsigpending \ +			td_thr_setxregs td_thr_sigsetmask td_thr_tsd \ +			td_thr_validate td_thr_dbsuspend td_thr_dbresume \ +			td_ta_setconcurrency td_ta_enable_stats \ +			td_ta_reset_stats td_ta_get_stats td_ta_event_addr \ +			td_thr_event_enable td_thr_set_event \ +			td_thr_clear_event td_thr_event_getmsg \ +			td_ta_set_event td_ta_event_getmsg \ +			td_ta_clear_event td_symbol_list \ +			td_thr_tlsbase td_thr_tls_get_addr \ +			fetch-value + +libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes)) + +# The ps_* callback functions are not defined. +libthread_db.so-no-z-defs = yes + +distribute = thread_dbP.h shlib-versions proc_service.h db_info.c structs.def +include ../Rules + +# Depend on libc.so so a DT_NEEDED is generated in the shared objects. +# This ensures they will load libc.so for needed symbols if loaded by +# a statically-linked program that hasn't already loaded it. +$(objpfx)libthread_db.so: $(common-objpfx)libc.so \ +			  $(common-objpfx)libc_nonshared.a diff --git a/libpthread/nptl_db/Versions b/libpthread/nptl_db/Versions new file mode 100644 index 000000000..063493c67 --- /dev/null +++ b/libpthread/nptl_db/Versions @@ -0,0 +1,24 @@ +libthread_db { +  GLIBC_2.1.3 { +    # t* +    td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats; +    td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph; +    td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new; +    td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency; +    td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume; +    td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg; +    td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs; +    td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs; +    td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask; +    td_thr_tsd; td_thr_validate; +  } +  GLIBC_2.2.3 { +    td_symbol_list; +  } +  GLIBC_2.3 { +    td_thr_tls_get_addr; +  } +  GLIBC_2.3.3 { +    td_thr_tlsbase; +  } +} diff --git a/libpthread/nptl_db/db_info.c b/libpthread/nptl_db/db_info.c new file mode 100644 index 000000000..5000b99ba --- /dev/null +++ b/libpthread/nptl_db/db_info.c @@ -0,0 +1,103 @@ +/* This file is included by pthread_create.c to define in libpthread +   all the magic symbols required by libthread_db. + +   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 +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" +#include <tls.h> + +typedef struct pthread pthread; +typedef struct pthread_key_struct pthread_key_struct; +typedef struct pthread_key_data pthread_key_data; +typedef struct +{ +  struct pthread_key_data data[PTHREAD_KEY_2NDLEVEL_SIZE]; +} +pthread_key_data_level2; + +typedef struct +{ +  union dtv dtv[UINT32_MAX / 2 / sizeof (union dtv)]; /* No constant bound.  */ +} dtv; + +typedef struct link_map link_map; + + +#define schedparam_sched_priority schedparam.sched_priority + +#define eventbuf_eventmask eventbuf.eventmask +#define eventbuf_eventmask_event_bits eventbuf.eventmask.event_bits + +#define DESC(name, offset, obj) \ +  DB_DEFINE_DESC (name, 8 * sizeof (obj), 1, offset); +#define ARRAY_DESC(name, offset, obj) \ +  DB_DEFINE_DESC (name, \ +		  8 * sizeof (obj)[0], sizeof (obj) / sizeof (obj)[0], \ +		  offset); + +#if TLS_TCB_AT_TP +# define dtvp header.dtv +#elif TLS_DTV_AT_TP +/* Special case hack.  If TLS_TCB_SIZE == 0 (on PowerPC), there is no TCB +   containing the DTV at the TP, but actually the TCB lies behind the TP, +   i.e. at the very end of the area covered by TLS_PRE_TCB_SIZE.  */ +DESC (_thread_db_pthread_dtvp, +      TLS_PRE_TCB_SIZE + offsetof (tcbhead_t, dtv) +      - (TLS_TCB_SIZE == 0 ? sizeof (tcbhead_t) : 0), union dtv) +#endif + + +#define DB_STRUCT(type) \ +  const uint32_t _thread_db_sizeof_##type = sizeof (type); +#define DB_STRUCT_FIELD(type, field) \ +  DESC (_thread_db_##type##_##field, \ +	offsetof (type, field), ((type *) 0)->field) +#define DB_STRUCT_ARRAY_FIELD(type, field) \ +  ARRAY_DESC (_thread_db_##type##_##field, \ +	      offsetof (type, field), ((type *) 0)->field) +#define DB_VARIABLE(name) DESC (_thread_db_##name, 0, name) +#define DB_ARRAY_VARIABLE(name) ARRAY_DESC (_thread_db_##name, 0, name) +#define DB_SYMBOL(name)	/* Nothing.  */ +#define DB_FUNCTION(name) /* Nothing.  */ +#include "structs.def" +#undef DB_STRUCT +#undef DB_STRUCT_FIELD +#undef DB_SYMBOL +#undef DB_FUNCTION +#undef DB_VARIABLE +#undef DESC + + + +#ifdef DB_THREAD_SELF +# ifdef DB_THREAD_SELF_INCLUDE +#  include DB_THREAD_SELF_INCLUDE +# endif + +/* This macro is defined in the machine's tls.h using the three below.  */ +# define CONST_THREAD_AREA(bits, value) \ +  const uint32_t _thread_db_const_thread_area = (value); +# define REGISTER_THREAD_AREA(bits, regofs, scale) \ +  DB_DEFINE_DESC (_thread_db_register##bits##_thread_area, \ +		  bits, (scale), (regofs)); +# define REGISTER(bits, size, regofs, bias) \ +  DB_DEFINE_DESC (_thread_db_register##bits, size, (uint32_t)(bias), (regofs)); + +DB_THREAD_SELF +#endif diff --git a/libpthread/nptl_db/fetch-value.c b/libpthread/nptl_db/fetch-value.c new file mode 100644 index 000000000..0d9bb0eb8 --- /dev/null +++ b/libpthread/nptl_db/fetch-value.c @@ -0,0 +1,284 @@ +/* Helper routines for libthread_db. +   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 +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" +#include <byteswap.h> +#include <assert.h> + +td_err_e +_td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name) +{ +  if (*sizep == 0) +    { +      psaddr_t descptr; +      ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr); +      if (err == PS_NOSYM) +	return TD_NOCAPAB; +      if (err == PS_OK) +	err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep); +      if (err != PS_OK) +	return TD_ERR; +      if (*sizep & 0xff000000U) +	*sizep = bswap_32 (*sizep); +    } +  return TD_OK; +} + +td_err_e +_td_locate_field (td_thragent_t *ta, +		  db_desc_t desc, int descriptor_name, +		  psaddr_t idx, psaddr_t *address) +{ +  uint32_t elemsize; + +  if (DB_DESC_SIZE (desc) == 0) +    { +      /* Read the information about this field from the inferior.  */ +      psaddr_t descptr; +      ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr); +      if (err == PS_NOSYM) +	return TD_NOCAPAB; +      if (err == PS_OK) +	err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC); +      if (err != PS_OK) +	return TD_ERR; +      if (DB_DESC_SIZE (desc) == 0) +	return TD_DBERR; +      if (DB_DESC_SIZE (desc) & 0xff000000U) +	{ +	  /* Byte-swap these words, though we leave the size word +	     in native order as the handy way to distinguish.  */ +	  DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc)); +	  DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc)); +	} +    } + +  if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc)) +    /* This is an internal indicator to callers with nonzero IDX +       that the IDX value is too big.  */ +    return TD_NOAPLIC; + +  elemsize = DB_DESC_SIZE (desc); +  if (elemsize & 0xff000000U) +    elemsize = bswap_32 (elemsize); + +  *address += (int32_t) DB_DESC_OFFSET (desc); +  *address += (elemsize / 8 * (idx - (psaddr_t) 0)); +  return TD_OK; +} + +td_err_e +_td_fetch_value (td_thragent_t *ta, +		 db_desc_t desc, int descriptor_name, +		 psaddr_t idx, psaddr_t address, +		 psaddr_t *result) +{ +  ps_err_e err; +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      value = bswap_32 (value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      value = bswap_64 (value); +      *result = (psaddr_t) 0 + value; +    } +  else +    return TD_DBERR; + +  return err == PS_OK ? TD_OK : TD_ERR; +} + + +td_err_e +_td_store_value (td_thragent_t *ta, +		 uint32_t desc[2], int descriptor_name, psaddr_t idx, +		 psaddr_t address, psaddr_t widened_value) +{ +  ps_err_e err; +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value = widened_value - (psaddr_t) 0; +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      value = bswap_32 (value); +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      value = bswap_64 (value); +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else +    return TD_DBERR; + +  return err == PS_OK ? TD_OK : TD_ERR; +} + +td_err_e +_td_fetch_value_local (td_thragent_t *ta, +		       db_desc_t desc, int descriptor_name, psaddr_t idx, +		       void *address, +		       psaddr_t *result) +{ +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value; +      memcpy (&value, address, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value; +      memcpy (&value, address, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      memcpy (&value, address, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value; +      memcpy (&value, address, sizeof value); +      value = bswap_32 (value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      memcpy (&value, address, sizeof value); +      value = bswap_64 (value); +      *result = (psaddr_t) 0 + value; +    } +  else +    return TD_DBERR; + +  return TD_OK; +} + + +td_err_e +_td_store_value_local (td_thragent_t *ta, +		       uint32_t desc[2], int descriptor_name, psaddr_t idx, +		       void *address, psaddr_t widened_value) +{ +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value = widened_value - (psaddr_t) 0; +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      value = bswap_32 (value); +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      value = bswap_64 (value); +      memcpy (address, &value, sizeof value); +    } +  else +    return TD_DBERR; + +  return TD_OK; +} diff --git a/libpthread/nptl_db/proc_service.h b/libpthread/nptl_db/proc_service.h new file mode 100644 index 000000000..d49e87ab3 --- /dev/null +++ b/libpthread/nptl_db/proc_service.h @@ -0,0 +1,87 @@ +/* Callback interface for libthread_db, functions users must define. +   Copyright (C) 1999,2002,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 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.  */ + +/* The definitions in this file must correspond to those in the debugger.  */ +#include <sys/procfs.h> + +/* Functions in this interface return one of these status codes.  */ +typedef enum +{ +  PS_OK,		/* Generic "call succeeded".  */ +  PS_ERR,		/* Generic error. */ +  PS_BADPID,		/* Bad process handle.  */ +  PS_BADLID,		/* Bad LWP identifier.  */ +  PS_BADADDR,		/* Bad address.  */ +  PS_NOSYM,		/* Could not find given symbol.  */ +  PS_NOFREGS		/* FPU register set not available for given LWP.  */ +} ps_err_e; + + +/* This type is opaque in this interface. +   It's defined by the user of libthread_db.  */ +struct ps_prochandle; + + +/* Read or write process memory at the given address.  */ +extern ps_err_e ps_pdread (struct ps_prochandle *, +			   psaddr_t, void *, size_t); +extern ps_err_e ps_pdwrite (struct ps_prochandle *, +			    psaddr_t, const void *, size_t); +extern ps_err_e ps_ptread (struct ps_prochandle *, +			   psaddr_t, void *, size_t); +extern ps_err_e ps_ptwrite (struct ps_prochandle *, +			    psaddr_t, const void *, size_t); + + +/* Get and set the given LWP's general or FPU register set.  */ +extern ps_err_e ps_lgetregs (struct ps_prochandle *, +			     lwpid_t, prgregset_t); +extern ps_err_e ps_lsetregs (struct ps_prochandle *, +			     lwpid_t, const prgregset_t); +extern ps_err_e ps_lgetfpregs (struct ps_prochandle *, +			       lwpid_t, prfpregset_t *); +extern ps_err_e ps_lsetfpregs (struct ps_prochandle *, +			       lwpid_t, const prfpregset_t *); + +/* Return the PID of the process.  */ +extern pid_t ps_getpid (struct ps_prochandle *); + +/* Fetch the special per-thread address associated with the given LWP. +   This call is only used on a few platforms (most use a normal register). +   The meaning of the `int' parameter is machine-dependent.  */ +extern ps_err_e ps_get_thread_area (const struct ps_prochandle *, +				    lwpid_t, int, psaddr_t *); + + +/* Look up the named symbol in the named DSO in the symbol tables +   associated with the process being debugged, filling in *SYM_ADDR +   with the corresponding run-time address.  */ +extern ps_err_e ps_pglobal_lookup (struct ps_prochandle *, +				   const char *object_name, +				   const char *sym_name, +				   psaddr_t *sym_addr); + + +/* Stop or continue the entire process.  */ +extern ps_err_e ps_pstop (const struct ps_prochandle *); +extern ps_err_e ps_pcontinue (const struct ps_prochandle *); + +/* Stop or continue the given LWP alone.  */ +extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t); +extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t); diff --git a/libpthread/nptl_db/structs.def b/libpthread/nptl_db/structs.def new file mode 100644 index 000000000..b17a628e0 --- /dev/null +++ b/libpthread/nptl_db/structs.def @@ -0,0 +1,86 @@ +/* List of types and symbols in libpthread examined by libthread_db. +   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 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 DB_STRUCT_ARRAY_FIELD +# define DB_STRUCT_ARRAY_FIELD(type, field) DB_STRUCT_FIELD (type, field) +# define DB_ARRAY_VARIABLE(name) DB_VARIABLE (name) +# define STRUCTS_DEF_DEFAULTS 1 +#endif + +DB_STRUCT (pthread) +DB_STRUCT_FIELD (pthread, list) +DB_STRUCT_FIELD (pthread, report_events) +DB_STRUCT_FIELD (pthread, tid) +DB_STRUCT_FIELD (pthread, start_routine) +DB_STRUCT_FIELD (pthread, cancelhandling) +DB_STRUCT_FIELD (pthread, schedpolicy) +DB_STRUCT_FIELD (pthread, schedparam_sched_priority) +DB_STRUCT_FIELD (pthread, specific) +DB_STRUCT_FIELD (pthread, eventbuf) +DB_STRUCT_FIELD (pthread, eventbuf_eventmask) +DB_STRUCT_ARRAY_FIELD (pthread, eventbuf_eventmask_event_bits) +DB_STRUCT_FIELD (pthread, nextevent) + +DB_STRUCT (list_t) +DB_STRUCT_FIELD (list_t, next) +DB_STRUCT_FIELD (list_t, prev) + +DB_STRUCT (td_thr_events_t) +DB_STRUCT_ARRAY_FIELD (td_thr_events_t, event_bits) + +DB_STRUCT (td_eventbuf_t) +DB_STRUCT_FIELD (td_eventbuf_t, eventnum) +DB_STRUCT_FIELD (td_eventbuf_t, eventdata) + +DB_SYMBOL (stack_used) +DB_SYMBOL (__stack_user) +DB_SYMBOL (nptl_version) +DB_FUNCTION (__nptl_create_event) +DB_FUNCTION (__nptl_death_event) +DB_SYMBOL (__nptl_threads_events) +DB_VARIABLE (__nptl_nthreads) +DB_VARIABLE (__nptl_last_event) + +DB_ARRAY_VARIABLE (__pthread_keys) +DB_STRUCT (pthread_key_struct) +DB_STRUCT_FIELD (pthread_key_struct, seq) +DB_STRUCT_FIELD (pthread_key_struct, destr) + +DB_STRUCT (pthread_key_data) +DB_STRUCT_FIELD (pthread_key_data, seq) +DB_STRUCT_FIELD (pthread_key_data, data) +DB_STRUCT (pthread_key_data_level2) +DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data) + +#if USE_TLS +DB_STRUCT_FIELD (link_map, l_tls_modid) +#endif + +#if !defined IS_IN_libpthread || USE_TLS +DB_STRUCT_ARRAY_FIELD (dtv, dtv) +#endif +#if !defined IS_IN_libpthread || TLS_TCB_AT_TP +DB_STRUCT_FIELD (pthread, dtvp) +#endif + +#ifdef STRUCTS_DEF_DEFAULTS +# undef DB_STRUCT_ARRAY_FIELD +# undef DB_ARRAY_VARIABLE +# undef STRUCTS_DEF_DEFAULTS +#endif diff --git a/libpthread/nptl_db/td_init.c b/libpthread/nptl_db/td_init.c new file mode 100644 index 000000000..946ff7244 --- /dev/null +++ b/libpthread/nptl_db/td_init.c @@ -0,0 +1,32 @@ +/* Initialization function of thread debugger support library. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + +int __td_debug; + + +td_err_e +td_init (void) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_init"); +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_log.c b/libpthread/nptl_db/td_log.c new file mode 100644 index 000000000..52212a0e9 --- /dev/null +++ b/libpthread/nptl_db/td_log.c @@ -0,0 +1,32 @@ +/* Noop, left for historical reasons. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_log (void) +{ +  /* This interface is deprecated in the Sun interface.  We provide it +     for compatibility but don't do anything ourself.  We might in +     future do some logging if this seems reasonable.  */ +  LOG ("td_log"); +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_symbol_list.c b/libpthread/nptl_db/td_symbol_list.c new file mode 100644 index 000000000..5d6c94e5b --- /dev/null +++ b/libpthread/nptl_db/td_symbol_list.c @@ -0,0 +1,85 @@ +/* Return list of symbols the library can request. +   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <assert.h> +#include <gnu/lib-names.h> +#include "thread_dbP.h" + + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT "."		/* PPC64 requires . prefix on code symbols.  */ +#else +# define DOT			/* No prefix.  */ +#endif + +static const char *symbol_list_arr[] = +{ +# define DB_STRUCT(type) \ +  [SYM_SIZEOF_##type] = "_thread_db_sizeof_" #type, +# define DB_STRUCT_FIELD(type, field) \ +  [SYM_##type##_FIELD_##field] = "_thread_db_" #type "_" #field, +# define DB_SYMBOL(name) \ +  [SYM_##name] = #name, +# define DB_FUNCTION(name) \ +  [SYM_##name] = DOT #name, +# define DB_VARIABLE(name) \ +  [SYM_##name] = #name, \ +  [SYM_DESC_##name] = "_thread_db_" #name, +# include "structs.def" +# undef DB_STRUCT +# undef DB_FUNCTION +# undef DB_SYMBOL +# undef DB_VARIABLE + +  [SYM_TH_UNIQUE_CONST_THREAD_AREA] = "_thread_db_const_thread_area", +  [SYM_TH_UNIQUE_REGISTER64] = "_thread_db_register64", +  [SYM_TH_UNIQUE_REGISTER32] = "_thread_db_register32", +  [SYM_TH_UNIQUE_REGISTER32_THREAD_AREA] = "_thread_db_register32_thread_area", +  [SYM_TH_UNIQUE_REGISTER64_THREAD_AREA] = "_thread_db_register64_thread_area", + +  [SYM_NUM_MESSAGES] = NULL +}; + + +const char ** +td_symbol_list (void) +{ +  return symbol_list_arr; +} + + +ps_err_e +td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) +{ +  ps_err_e result; +  assert (idx >= 0 && idx < SYM_NUM_MESSAGES); +  result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], +			      sym_addr); + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +  /* For PowerPC, 64-bit uses dot symbols but 32-bit does not. +     We could be a 64-bit libthread_db debugging a 32-bit libpthread.  */ +  if (result == PS_NOSYM && symbol_list_arr[idx][0] == '.') +    result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, &symbol_list_arr[idx][1], +				sym_addr); +#endif + +  return result; +} diff --git a/libpthread/nptl_db/td_ta_clear_event.c b/libpthread/nptl_db/td_ta_clear_event.c new file mode 100644 index 000000000..7a2850c4e --- /dev/null +++ b/libpthread/nptl_db/td_ta_clear_event.c @@ -0,0 +1,79 @@ +/* Globally disable events. +   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_clear_event (ta_arg, event) +     const td_thragent_t *ta_arg; +     td_thr_events_t *event; +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  td_err_e err; +  psaddr_t eventmask = 0; +  void *copy = NULL; + +  LOG ("td_ta_clear_event"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  /* Fetch the old event mask from the inferior and modify it in place.  */ +  err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events); +  if (err == TD_OK) +    err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t); +  if (err == TD_OK) +    { +      uint32_t idx; +      for (idx = 0; idx < TD_EVENTSIZE; ++idx) +	{ +	  psaddr_t word; +	  uint32_t mask; +	  err = DB_GET_FIELD_LOCAL (word, ta, copy, +				    td_thr_events_t, event_bits, idx); +	  if (err != TD_OK) +	    break; +	  mask = (uintptr_t) word; +	  mask &= ~event->event_bits[idx]; +	  word = (psaddr_t) (uintptr_t) mask; +	  err = DB_PUT_FIELD_LOCAL (ta, copy, +				    td_thr_events_t, event_bits, idx, word); +	  if (err != TD_OK) +	    break; +	} +      if (err == TD_NOAPLIC) +	{ +	  err = TD_OK; +	  while (idx < TD_EVENTSIZE) +	    if (event->event_bits[idx++] != 0) +	      { +		err = TD_NOEVENT; +		break; +	      } +	} +      if (err == TD_OK) +	/* Now write it back to the inferior.  */ +	err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy); +    } + +  return err; +} diff --git a/libpthread/nptl_db/td_ta_delete.c b/libpthread/nptl_db/td_ta_delete.c new file mode 100644 index 000000000..57b90e57f --- /dev/null +++ b/libpthread/nptl_db/td_ta_delete.c @@ -0,0 +1,42 @@ +/* Detach to target process. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stdlib.h> + +#include "thread_dbP.h" + + +td_err_e +td_ta_delete (td_thragent_t *ta) +{ +  LOG ("td_ta_delete"); + +  /* Safety check.  Note that the test will also fail for TA == NULL.  */ +  if (!ta_ok (ta)) +    return TD_BADTA; + +  /* Remove the handle from the list.  */ +  list_del (&ta->list); + +  /* The handle was allocated in `td_ta_new'.  */ +  free (ta); + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_enable_stats.c b/libpthread/nptl_db/td_ta_enable_stats.c new file mode 100644 index 000000000..ec7014ad2 --- /dev/null +++ b/libpthread/nptl_db/td_ta_enable_stats.c @@ -0,0 +1,35 @@ +/* Enable collection of statistics for process. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_enable_stats (const td_thragent_t *ta, int enable) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_ta_enable_stats"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_event_addr.c b/libpthread/nptl_db/td_ta_event_addr.c new file mode 100644 index 000000000..37196e643 --- /dev/null +++ b/libpthread/nptl_db/td_ta_event_addr.c @@ -0,0 +1,61 @@ +/* Get event address. +   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_addr (const td_thragent_t *ta_arg, +		  td_event_e event, td_notify_t *addr) +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  td_err_e err; +  psaddr_t taddr; + +  LOG ("td_ta_event_addr"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  switch (event) +    { +    case TD_CREATE: +      err = DB_GET_SYMBOL (taddr, ta, __nptl_create_event); +      break; + +    case TD_DEATH: +      err = DB_GET_SYMBOL (taddr, ta, __nptl_death_event); +      break; + +    default: +      /* Event cannot be handled.  */ +      return TD_NOEVENT; +    } + +  if (err == TD_OK) +    { +      /* Success, we got the address.  */ +      addr->type = NOTIFY_BPT; +      addr->u.bptaddr = taddr; +    } + +  return err; +} diff --git a/libpthread/nptl_db/td_ta_event_getmsg.c b/libpthread/nptl_db/td_ta_event_getmsg.c new file mode 100644 index 000000000..6e68ff4ff --- /dev/null +++ b/libpthread/nptl_db/td_ta_event_getmsg.c @@ -0,0 +1,105 @@ +/* Retrieve event. +   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stddef.h> +#include <string.h> + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_getmsg (const td_thragent_t *ta_arg, td_event_msg_t *msg) +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  td_err_e err; +  psaddr_t eventbuf, eventnum, eventdata; +  psaddr_t thp, next; +  void *copy; + +  /* XXX I cannot think of another way but using a static variable.  */ +  /* XXX Use at least __thread once it is possible.  */ +  static td_thrhandle_t th; + +  LOG ("td_thr_event_getmsg"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  /* Get the pointer to the thread descriptor with the last event.  */ +  err = DB_GET_VALUE (thp, ta, __nptl_last_event, 0); +  if (err != TD_OK) +    return err; + +  if (thp == 0) +    /* Nothing waiting.  */ +    return TD_NOMSG; + +  /* Copy the event message buffer in from the inferior.  */ +  err = DB_GET_FIELD_ADDRESS (eventbuf, ta, thp, pthread, eventbuf, 0); +  if (err == TD_OK) +    err = DB_GET_STRUCT (copy, ta, eventbuf, td_eventbuf_t); +  if (err != TD_OK) +    return err; + +  /* Read the event details from the target thread.  */ +  err = DB_GET_FIELD_LOCAL (eventnum, ta, copy, td_eventbuf_t, eventnum, 0); +  if (err != TD_OK) +    return err; +  /* If the structure is on the list there better be an event recorded.  */ +  if ((int) (uintptr_t) eventnum == TD_EVENT_NONE) +    return TD_DBERR; + +  /* Fill the user's data structure.  */ +  err = DB_GET_FIELD_LOCAL (eventdata, ta, copy, td_eventbuf_t, eventdata, 0); +  if (err != TD_OK) +    return err; + +  /* Generate the thread descriptor.  */ +  th.th_ta_p = (td_thragent_t *) ta; +  th.th_unique = thp; + +  /* Fill the user's data structure.  */ +  msg->msg.data = (uintptr_t) eventdata; +  msg->event = (uintptr_t) eventnum; +  msg->th_p = &th; + +  /* And clear the event message in the target.  */ +  memset (copy, 0, ta->ta_sizeof_td_eventbuf_t); +  err = DB_PUT_STRUCT (ta, eventbuf, td_eventbuf_t, copy); +  if (err != TD_OK) +    return err; + +  /* Get the pointer to the next descriptor with an event.  */ +  err = DB_GET_FIELD (next, ta, thp, pthread, nextevent, 0); +  if (err != TD_OK) +    return err; + +  /* Store the pointer in the list head variable.  */ +  err = DB_PUT_VALUE (ta, __nptl_last_event, 0, next); +  if (err != TD_OK) +    return err; + +  if (next != 0) +    /* Clear the next pointer in the current descriptor.  */ +    err = DB_PUT_FIELD (ta, thp, pthread, nextevent, 0, 0); + +  return err; +} diff --git a/libpthread/nptl_db/td_ta_get_nthreads.c b/libpthread/nptl_db/td_ta_get_nthreads.c new file mode 100644 index 000000000..ffe78bd57 --- /dev/null +++ b/libpthread/nptl_db/td_ta_get_nthreads.c @@ -0,0 +1,42 @@ +/* Get the number of threads in the process. +   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + +td_err_e +td_ta_get_nthreads (const td_thragent_t *ta_arg, int *np) +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  td_err_e err; +  psaddr_t n; + +  LOG ("td_ta_get_nthreads"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  /* Access the variable in the inferior that tells us.  */ +  err = DB_GET_VALUE (n, ta, __nptl_nthreads, 0); +  if (err == TD_OK) +    *np = (uintptr_t) n; + +  return err; +} diff --git a/libpthread/nptl_db/td_ta_get_ph.c b/libpthread/nptl_db/td_ta_get_ph.c new file mode 100644 index 000000000..04e01fb73 --- /dev/null +++ b/libpthread/nptl_db/td_ta_get_ph.c @@ -0,0 +1,36 @@ +/* Get external process handle. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) +{ +  LOG ("td_ta_get_ph"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  *ph = ta->ph; + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_get_stats.c b/libpthread/nptl_db/td_ta_get_stats.c new file mode 100644 index 000000000..d5d879c3e --- /dev/null +++ b/libpthread/nptl_db/td_ta_get_stats.c @@ -0,0 +1,35 @@ +/* Retrieve statistics for process. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_ta_get_stats"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_map_id2thr.c b/libpthread/nptl_db/td_ta_map_id2thr.c new file mode 100644 index 000000000..189a67171 --- /dev/null +++ b/libpthread/nptl_db/td_ta_map_id2thr.c @@ -0,0 +1,38 @@ +/* Map thread ID to thread handle. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) +{ +  LOG ("td_ta_map_id2thr"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  /* Create the `td_thrhandle_t' object.  */ +  th->th_ta_p = (td_thragent_t *) ta; +  th->th_unique = (psaddr_t) pt; + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_map_lwp2thr.c b/libpthread/nptl_db/td_ta_map_lwp2thr.c new file mode 100644 index 000000000..1e93210b9 --- /dev/null +++ b/libpthread/nptl_db/td_ta_map_lwp2thr.c @@ -0,0 +1,178 @@ +/* Which thread is running on an LWP? +   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 +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" +#include <stdlib.h> +#include <byteswap.h> +#include <sys/procfs.h> + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta_arg, +		   lwpid_t lwpid, td_thrhandle_t *th) +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  ps_err_e err; +  td_err_e terr; +  prgregset_t regs; +  psaddr_t addr; + +  LOG ("td_ta_map_lwp2thr"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  if (ta->ta_howto == ta_howto_unknown) +    { +      /* We need to read in from the inferior the instructions what to do.  */ +      psaddr_t howto; + +      err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto); +      if (err == PS_OK) +	{ +	  err = ps_pdread (ta->ph, howto, +			   &ta->ta_howto_data.const_thread_area, + 			   sizeof ta->ta_howto_data.const_thread_area); +	  if (err != PS_OK) +	    return TD_ERR; +	  ta->ta_howto = ta_howto_const_thread_area; +	  if (ta->ta_howto_data.const_thread_area & 0xff000000U) +	    ta->ta_howto_data.const_thread_area +	      = bswap_32 (ta->ta_howto_data.const_thread_area); +	} +      else +	{ +	  switch (sizeof (regs[0])) +	    { +	    case 8: +	      err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto); +	      if (err == PS_OK) +		ta->ta_howto = ta_howto_reg; +	      else if (err == PS_NOSYM) +		{ +		  err = td_lookup (ta->ph, +				   SYM_TH_UNIQUE_REGISTER64_THREAD_AREA, +				   &howto); +		  if (err == PS_OK) +		    ta->ta_howto = ta_howto_reg_thread_area; +		} +	      break; + +	    case 4: +	      err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto); +	      if (err == PS_OK) +		ta->ta_howto = ta_howto_reg; +	      else if (err == PS_NOSYM) +		{ +		  err = td_lookup (ta->ph, +				   SYM_TH_UNIQUE_REGISTER32_THREAD_AREA, +				   &howto); +		  if (err == PS_OK) +		    ta->ta_howto = ta_howto_reg_thread_area; +		} +	      break; + +	    default: +	      abort (); +	      return TD_DBERR; +	    } + +	  if (err != PS_OK) +	    return TD_DBERR; + +	  /* For either of these methods we read in the same descriptor.  */ +	  err = ps_pdread (ta->ph, howto, +			   ta->ta_howto_data.reg, DB_SIZEOF_DESC); +	  if (err != PS_OK) +	    return TD_ERR; +	  if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0) +	    return TD_DBERR; +	  if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U) +	    { +	      /* Byte-swap these words, though we leave the size word +		 in native order as the handy way to distinguish.  */ +	      DB_DESC_OFFSET (ta->ta_howto_data.reg) +		= bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg)); +	      DB_DESC_NELEM (ta->ta_howto_data.reg) +		= bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg)); +	    } +	} +    } + +  switch (ta->ta_howto) +    { +    case ta_howto_unknown: +      return TD_DBERR; + +    default: +      return TD_DBERR; + +    case ta_howto_reg: +      /* On most machines, we are just looking at a register.  */ +      if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK) +	return TD_ERR; +      terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1, +				    0, regs, &addr); +      if (terr != TD_OK) +	return terr; +      /* In this descriptor the nelem word is overloaded as the bias.  */ +      addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg); +      th->th_unique = addr; +      break; + +    case ta_howto_const_thread_area: +      /* Some hosts don't have this call and this case won't be used.  */ +# pragma weak ps_get_thread_area +      if (&ps_get_thread_area == NULL) +	return TD_NOCAPAB; + +       /* A la x86-64, there is a constant magic index for get_thread_area.  */ +       if (ps_get_thread_area (ta->ph, lwpid, +			       ta->ta_howto_data.const_thread_area, +			       &th->th_unique) != PS_OK) +	 return TD_ERR;	/* XXX Other error value?  */ +       break; + +     case ta_howto_reg_thread_area: +      if (&ps_get_thread_area == NULL) +	return TD_NOCAPAB; + +       /* A la i386, there is a register with an index for get_thread_area.  */ +       if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK) +	 return TD_ERR; +       terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area, -1, +				     0, regs, &addr); +      if (terr != TD_OK) +	return terr; +      /* In this descriptor the nelem word is overloaded as scale factor.  */ +      if (ps_get_thread_area +	  (ta->ph, lwpid, +	   ((addr - (psaddr_t) 0) +	    >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)), +	   &th->th_unique) != PS_OK) +	return TD_ERR;	/* XXX Other error value?  */ +      break; +    } + +  /* Found it.  Now complete the `td_thrhandle_t' object.  */ +  th->th_ta_p = (td_thragent_t *) ta; + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_new.c b/libpthread/nptl_db/td_ta_new.c new file mode 100644 index 000000000..f84049af3 --- /dev/null +++ b/libpthread/nptl_db/td_ta_new.c @@ -0,0 +1,65 @@ +/* Attach to target process. +   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <version.h> + +#include "thread_dbP.h" + + +/* Datatype for the list of known thread agents.  Normally there will +   be exactly one so we don't spend much though on making it fast.  */ +LIST_HEAD (__td_agent_list); + + +td_err_e +td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) +{ +  psaddr_t versaddr; +  char versbuf[sizeof (VERSION)]; + +  LOG ("td_ta_new"); + +  /* Check whether the versions match.  */ +  if (td_lookup (ps, SYM_nptl_version, &versaddr) != PS_OK) +    return TD_NOLIBTHREAD; +  if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK) +    return TD_ERR; + +  if (memcmp (versbuf, VERSION, sizeof VERSION) != 0) +    /* Not the right version.  */ +    return TD_VERSION; + +  /* Fill in the appropriate information.  */ +  *ta = (td_thragent_t *) calloc (1, sizeof (td_thragent_t)); +  if (*ta == NULL) +    return TD_MALLOC; + +  /* Store the proc handle which we will pass to the callback functions +     back into the debugger.  */ +  (*ta)->ph = ps; + +  /* Now add the new agent descriptor to the list.  */ +  list_add (&(*ta)->list, &__td_agent_list); + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_reset_stats.c b/libpthread/nptl_db/td_ta_reset_stats.c new file mode 100644 index 000000000..ea59d2cda --- /dev/null +++ b/libpthread/nptl_db/td_ta_reset_stats.c @@ -0,0 +1,35 @@ +/* Reset statistics. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_reset_stats (const td_thragent_t *ta) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_ta_reset_stats"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_set_event.c b/libpthread/nptl_db/td_ta_set_event.c new file mode 100644 index 000000000..29fc14bfb --- /dev/null +++ b/libpthread/nptl_db/td_ta_set_event.c @@ -0,0 +1,79 @@ +/* Globally enable events. +   Copyright (C) 1999,2001,2002,2003,2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_set_event (ta_arg, event) +     const td_thragent_t *ta_arg; +     td_thr_events_t *event; +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  td_err_e err; +  psaddr_t eventmask = 0; +  void *copy = NULL; + +  LOG ("td_ta_set_event"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  /* Fetch the old event mask from the inferior and modify it in place.  */ +  err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events); +  if (err == TD_OK) +    err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t); +  if (err == TD_OK) +    { +      uint32_t idx; +      for (idx = 0; idx < TD_EVENTSIZE; ++idx) +	{ +	  psaddr_t word; +	  uint32_t mask; +	  err = DB_GET_FIELD_LOCAL (word, ta, copy, +				    td_thr_events_t, event_bits, idx); +	  if (err != TD_OK) +	    break; +	  mask = (uintptr_t) word; +	  mask |= event->event_bits[idx]; +	  word = (psaddr_t) (uintptr_t) mask; +	  err = DB_PUT_FIELD_LOCAL (ta, copy, +				    td_thr_events_t, event_bits, idx, word); +	  if (err != TD_OK) +	    break; +	} +      if (err == TD_NOAPLIC) +	{ +	  err = TD_OK; +	  while (idx < TD_EVENTSIZE) +	    if (event->event_bits[idx++] != 0) +	      { +		err = TD_NOEVENT; +		break; +	      } +	} +      if (err == TD_OK) +	/* Now write it back to the inferior.  */ +	err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy); +    } + +  return err; +} diff --git a/libpthread/nptl_db/td_ta_setconcurrency.c b/libpthread/nptl_db/td_ta_setconcurrency.c new file mode 100644 index 000000000..8552ffbe0 --- /dev/null +++ b/libpthread/nptl_db/td_ta_setconcurrency.c @@ -0,0 +1,35 @@ +/* Set suggested concurrency level for process. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_setconcurrency (const td_thragent_t *ta, int level) +{ +  /* This is something LinuxThreads does not need to support.  */ +  LOG ("td_ta_setconcurrency"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  return TD_NOCAPAB; +} diff --git a/libpthread/nptl_db/td_ta_thr_iter.c b/libpthread/nptl_db/td_ta_thr_iter.c new file mode 100644 index 000000000..66e437665 --- /dev/null +++ b/libpthread/nptl_db/td_ta_thr_iter.c @@ -0,0 +1,148 @@ +/* Iterate over a process's threads. +   Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +static td_err_e +iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback, +		     void *cbdata_p, td_thr_state_e state, int ti_pri, +		     psaddr_t head, int fake_empty) +{ +  td_err_e err; +  psaddr_t next, ofs; +  void *copy; + +  /* Test the state. +     XXX This is incomplete.  Normally this test should be in the loop.  */ +  if (state != TD_THR_ANY_STATE) +    return TD_OK; + +  err = DB_GET_FIELD (next, ta, head, list_t, next, 0); +  if (err != TD_OK) +    return err; + +  if (next == 0 && fake_empty) +    { +      /* __pthread_initialize_minimal has not run. +	 There is just the main thread to return.  */ +      td_thrhandle_t th; +      err = td_ta_map_lwp2thr (ta, ps_getpid (ta->ph), &th); +      if (err == TD_OK) +	err = callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK; +      return err; +    } + +  /* Cache the offset from struct pthread to its list_t member.  */ +  err = DB_GET_FIELD_ADDRESS (ofs, ta, 0, pthread, list, 0); +  if (err != TD_OK) +    return err; + +  if (ta->ta_sizeof_pthread == 0) +    { +      err = _td_check_sizeof (ta, &ta->ta_sizeof_pthread, SYM_SIZEOF_pthread); +      if (err != TD_OK) +	return err; +    } +  copy = __alloca (ta->ta_sizeof_pthread); + +  while (next != head) +    { +      psaddr_t addr, schedpolicy, schedprio; + +      addr = next - (ofs - (psaddr_t) 0); +      if (next == 0 || addr == 0) /* Sanity check.  */ +	return TD_DBERR; + +      /* Copy the whole descriptor in once so we can access the several +	 fields locally.  Excess copying in one go is much better than +	 multiple ps_pdread calls.  */ +      if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK) +	return TD_ERR; + +      err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread, +				schedpolicy, 0); +      if (err != TD_OK) +	break; +      err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread, +				schedparam_sched_priority, 0); +      if (err != TD_OK) +	break; + +      /* Now test whether this thread matches the specified conditions.  */ + +      /* Only if the priority level is as high or higher.  */ +      int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER +		       ? 0 : (uintptr_t) schedprio); +      if (descr_pri >= ti_pri) +	{ +	  /* Yep, it matches.  Call the callback function.  */ +	  td_thrhandle_t th; +	  th.th_ta_p = (td_thragent_t *) ta; +	  th.th_unique = addr; +	  if (callback (&th, cbdata_p) != 0) +	    return TD_DBERR; +	} + +      /* Get the pointer to the next element.  */ +      err = DB_GET_FIELD_LOCAL (next, ta, copy + (ofs - (psaddr_t) 0), list_t, +				next, 0); +      if (err != TD_OK) +	break; +    } + +  return err; +} + + +td_err_e +td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback, +		void *cbdata_p, td_thr_state_e state, int ti_pri, +		sigset_t *ti_sigmask_p, unsigned int ti_user_flags) +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  td_err_e err; +  psaddr_t list = 0; + +  LOG ("td_ta_thr_iter"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  /* The thread library keeps two lists for the running threads.  One +     list contains the thread which are using user-provided stacks +     (this includes the main thread) and the other includes the +     threads for which the thread library allocated the stacks.  We +     have to iterate over both lists separately.  We start with the +     list of threads with user-defined stacks.  */ + +  err = DB_GET_SYMBOL (list, ta, __stack_user); +  if (err == TD_OK) +    err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 1); + +  /* And the threads with stacks allocated by the implementation.  */ +  if (err == TD_OK) +    err = DB_GET_SYMBOL (list, ta, stack_used); +  if (err == TD_OK) +    err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 0); + +  return err; +} diff --git a/libpthread/nptl_db/td_ta_tsd_iter.c b/libpthread/nptl_db/td_ta_tsd_iter.c new file mode 100644 index 000000000..9cfb1e8de --- /dev/null +++ b/libpthread/nptl_db/td_ta_tsd_iter.c @@ -0,0 +1,81 @@ +/* Iterate over a process's thread-specific data. +   Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" +#include <alloca.h> + +td_err_e +td_ta_tsd_iter (const td_thragent_t *ta_arg, td_key_iter_f *callback, +		void *cbdata_p) +{ +  td_thragent_t *const ta = (td_thragent_t *) ta_arg; +  td_err_e err; +  void *keys; +  size_t keys_nb, keys_elemsize; +  psaddr_t addr; +  uint32_t idx; + +  LOG ("td_ta_tsd_iter"); + +  /* Test whether the TA parameter is ok.  */ +  if (! ta_ok (ta)) +    return TD_BADTA; + +  /* This makes sure we have the size information on hand.  */ +  addr = 0; +  err = _td_locate_field (ta, +			  ta->ta_var___pthread_keys, SYM_DESC___pthread_keys, +			  (psaddr_t) 0 + 1, &addr); +  if (err != TD_OK) +    return err; + +  /* Now copy in the entire array of key descriptors.  */ +  keys_elemsize = (addr - (psaddr_t) 0) / 8; +  keys_nb = keys_elemsize * DB_DESC_NELEM (ta->ta_var___pthread_keys); +  keys = __alloca (keys_nb); +  err = DB_GET_SYMBOL (addr, ta, __pthread_keys); +  if (err != TD_OK) +    return err; +  if (ps_pdread (ta->ph, addr, keys, keys_nb) != PS_OK) +    return TD_ERR; + +  /* Now get all descriptors, one after the other.  */ +  for (idx = 0; idx < DB_DESC_NELEM (ta->ta_var___pthread_keys); ++idx) +    { +      psaddr_t seq, destr; +      err = DB_GET_FIELD_LOCAL (seq, ta, keys, pthread_key_struct, seq, 0); +      if (err != TD_OK) +	return err; +      if (((uintptr_t) seq) & 1) +	{ +	  err = DB_GET_FIELD_LOCAL (destr, ta, keys, pthread_key_struct, +				    destr, 0); +	  if (err != TD_OK) +	    return err; +	  /* Return with an error if the callback returns a nonzero value.  */ +	  if (callback ((thread_key_t) idx, destr, cbdata_p) != 0) +	    return TD_DBERR; +	} +      /* Advance to the next element in the copied array.  */ +      keys += keys_elemsize; +    } + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_clear_event.c b/libpthread/nptl_db/td_thr_clear_event.c new file mode 100644 index 000000000..fc999df9c --- /dev/null +++ b/libpthread/nptl_db/td_thr_clear_event.c @@ -0,0 +1,77 @@ +/* Disable specific event for thread. +   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stddef.h> + +#include "thread_dbP.h" + + +td_err_e +td_thr_clear_event (th, event) +     const td_thrhandle_t *th; +     td_thr_events_t *event; +{ +  td_err_e err; +  psaddr_t eventmask; +  void *copy; + +  LOG ("td_thr_clear_event"); + +  /* Fetch the old event mask from the inferior and modify it in place.  */ +  err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p, +			      th->th_unique, pthread, eventbuf_eventmask, 0); +  if (err == TD_OK) +    err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t); +  if (err == TD_OK) +    { +      uint32_t idx; +      for (idx = 0; idx < TD_EVENTSIZE; ++idx) +	{ +	  psaddr_t word; +	  uint32_t mask; +	  err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, +				    td_thr_events_t, event_bits, idx); +	  if (err != TD_OK) +	    break; +	  mask = (uintptr_t) word; +	  mask &= ~event->event_bits[idx]; +	  word = (psaddr_t) (uintptr_t) mask; +	  err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy, +				    td_thr_events_t, event_bits, idx, word); +	  if (err != TD_OK) +	    break; +	} +      if (err == TD_NOAPLIC) +	{ +	  err = TD_OK; +	  while (idx < TD_EVENTSIZE) +	    if (event->event_bits[idx++] != 0) +	      { +		err = TD_NOEVENT; +		break; +	      } +	} +      if (err == TD_OK) +	/* Now write it back to the inferior.  */ +	err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy); +    } + +  return err; +} diff --git a/libpthread/nptl_db/td_thr_dbresume.c b/libpthread/nptl_db/td_thr_dbresume.c new file mode 100644 index 000000000..3fd794377 --- /dev/null +++ b/libpthread/nptl_db/td_thr_dbresume.c @@ -0,0 +1,30 @@ +/* Resume execution of given thread. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbresume (const td_thrhandle_t *th) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_thr_dbresume"); +  return TD_NOCAPAB; +} diff --git a/libpthread/nptl_db/td_thr_dbsuspend.c b/libpthread/nptl_db/td_thr_dbsuspend.c new file mode 100644 index 000000000..6ef82ad34 --- /dev/null +++ b/libpthread/nptl_db/td_thr_dbsuspend.c @@ -0,0 +1,30 @@ +/* Suspend execution of given thread. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbsuspend (const td_thrhandle_t *th) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_thr_dbsuspend"); +  return TD_NOCAPAB; +} diff --git a/libpthread/nptl_db/td_thr_event_enable.c b/libpthread/nptl_db/td_thr_event_enable.c new file mode 100644 index 000000000..a02be5da4 --- /dev/null +++ b/libpthread/nptl_db/td_thr_event_enable.c @@ -0,0 +1,34 @@ +/* Enable event process-wide. +   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_enable (th, onoff) +     const td_thrhandle_t *th; +     int onoff; +{ +  LOG ("td_thr_event_enable"); + +  /* Write the new value into the thread data structure.  */ +  return DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread, report_events, 0, +		       (psaddr_t) 0 + (onoff != 0)); +} diff --git a/libpthread/nptl_db/td_thr_event_getmsg.c b/libpthread/nptl_db/td_thr_event_getmsg.c new file mode 100644 index 000000000..70ea6953e --- /dev/null +++ b/libpthread/nptl_db/td_thr_event_getmsg.c @@ -0,0 +1,119 @@ +/* Retrieve event. +   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" +#include <assert.h> + + +td_err_e +td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) +{ +  td_err_e err; +  psaddr_t eventbuf, eventnum, eventdata; +  psaddr_t thp, prevp; +  void *copy; + +  LOG ("td_thr_event_getmsg"); + +  /* Copy the event message buffer in from the inferior.  */ +  err = DB_GET_FIELD_ADDRESS (eventbuf, th->th_ta_p, th->th_unique, pthread, +			      eventbuf, 0); +  if (err == TD_OK) +    err = DB_GET_STRUCT (copy, th->th_ta_p, eventbuf, td_eventbuf_t); +  if (err != TD_OK) +    return err; + +  /* Check whether an event occurred.  */ +  err = DB_GET_FIELD_LOCAL (eventnum, th->th_ta_p, copy, +			    td_eventbuf_t, eventnum, 0); +  if (err != TD_OK) +    return err; +  if ((int) (uintptr_t) eventnum == TD_EVENT_NONE) +    /* Nothing.  */ +    return TD_NOMSG; + +  /* Fill the user's data structure.  */ +  err = DB_GET_FIELD_LOCAL (eventdata, th->th_ta_p, copy, +			    td_eventbuf_t, eventdata, 0); +  if (err != TD_OK) +    return err; + +  msg->msg.data = (uintptr_t) eventdata; +  msg->event = (uintptr_t) eventnum; +  msg->th_p = th; + +  /* And clear the event message in the target.  */ +  memset (copy, 0, th->th_ta_p->ta_sizeof_td_eventbuf_t); +  err = DB_PUT_STRUCT (th->th_ta_p, eventbuf, td_eventbuf_t, copy); +  if (err != TD_OK) +    return err; + +  /* Get the pointer to the thread descriptor with the last event. +     If it doesn't match TH, then walk down the list until we find it. +     We must splice it out of the list so that there is no dangling +     pointer to it later when it dies.  */ +  err = DB_GET_SYMBOL (prevp, th->th_ta_p, __nptl_last_event); +  if (err != TD_OK) +    return err; +  err = DB_GET_VALUE (thp, th->th_ta_p, __nptl_last_event, 0); +  if (err != TD_OK) +    return err; + +  while (thp != 0) +    { +      psaddr_t next; +      err = DB_GET_FIELD (next, th->th_ta_p, th->th_unique, pthread, +			  nextevent, 0); +      if (err != TD_OK) +	return err; + +      if (next == thp) +	return TD_DBERR; + +      if (thp == th->th_unique) +	{ +	  /* PREVP points at this thread, splice it out.  */ +	  psaddr_t next_nextp; +	  err = DB_GET_FIELD_ADDRESS (next_nextp, th->th_ta_p, next, pthread, +				      nextevent, 0); +	  assert (err == TD_OK); /* We used this field before.  */ +	  if (prevp == next_nextp) +	    return TD_DBERR; + +	  err = _td_store_value (th->th_ta_p, +				 th->th_ta_p->ta_var___nptl_last_event, -1, +				 0, prevp, next); +	  if (err != TD_OK) +	    return err; + +	  /* Now clear this thread's own next pointer so it's not dangling +	     when the thread resumes and then chains on for its next event.  */ +	  return DB_PUT_FIELD (th->th_ta_p, thp, pthread, nextevent, 0, 0); +	} + +      err = DB_GET_FIELD_ADDRESS (prevp, th->th_ta_p, thp, pthread, +				  nextevent, 0); +      assert (err == TD_OK); /* We used this field before.  */ +      thp = next; +    } + +  /* Ack!  This should not happen.  */ +  return TD_DBERR; +} diff --git a/libpthread/nptl_db/td_thr_get_info.c b/libpthread/nptl_db/td_thr_get_info.c new file mode 100644 index 000000000..bb1388804 --- /dev/null +++ b/libpthread/nptl_db/td_thr_get_info.c @@ -0,0 +1,110 @@ +/* Get thread information. +   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stddef.h> +#include <string.h> +#include "thread_dbP.h" + + +td_err_e +td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) +{ +  td_err_e err; +  void *copy; +  psaddr_t tls, schedpolicy, schedprio, cancelhandling, tid, report_events; + +  LOG ("td_thr_get_info"); + +  /* Copy the whole descriptor in once so we can access the several +     fields locally.  Excess copying in one go is much better than +     multiple ps_pdread calls.  */ +  err = DB_GET_STRUCT (copy, th->th_ta_p, th->th_unique, pthread); +  if (err != TD_OK) +    return err; + +  err = DB_GET_FIELD_ADDRESS (tls, th->th_ta_p, th->th_unique, +			      pthread, specific, 0); +  if (err != TD_OK) +    return err; + +  err = DB_GET_FIELD_LOCAL (schedpolicy, th->th_ta_p, copy, pthread, +			    schedpolicy, 0); +  if (err != TD_OK) +    return err; +  err = DB_GET_FIELD_LOCAL (schedprio, th->th_ta_p, copy, pthread, +			    schedparam_sched_priority, 0); +  if (err != TD_OK) +    return err; +  err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0); +  if (err != TD_OK) +    return err; +  err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread, +			    cancelhandling, 0); +  if (err != TD_OK) +    return err; +  err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread, +			    report_events, 0); +  if (err != TD_OK) +    return err; + +  /* Fill in information.  Clear first to provide reproducable +     results for the fields we do not fill in.  */ +  memset (infop, '\0', sizeof (td_thrinfo_t)); + +  infop->ti_tid = (thread_t) th->th_unique; +  infop->ti_tls = (char *) tls; +  infop->ti_pri = ((uintptr_t) schedpolicy == SCHED_OTHER +		   ? 0 : (uintptr_t) schedprio); +  infop->ti_type = TD_THR_USER; + +  if ((((int) (uintptr_t) cancelhandling) & EXITING_BITMASK) == 0) +    /* XXX For now there is no way to get more information.  */ +    infop->ti_state = TD_THR_ACTIVE; +  else if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) +    infop->ti_state = TD_THR_ZOMBIE; +  else +    infop->ti_state = TD_THR_UNKNOWN; + +  /* Initialization which are the same in both cases.  */ +  infop->ti_ta_p = th->th_ta_p; +  infop->ti_lid = tid == 0 ? ps_getpid (th->th_ta_p->ph) : (uintptr_t) tid; +  infop->ti_traceme = report_events != 0; + +  err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread, +			    start_routine, 0); +  if (err == TD_OK) +    { +      uint32_t idx; +      for (idx = 0; idx < TD_EVENTSIZE; ++idx) +	{ +	  psaddr_t word; +	  err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, pthread, +				    eventbuf_eventmask_event_bits, idx); +	  if (err != TD_OK) +	    break; +	  infop->ti_events.event_bits[idx] = (uintptr_t) word; +	} +      if (err == TD_NOAPLIC) +	memset (&infop->ti_events.event_bits[idx], 0, +		(TD_EVENTSIZE - idx) * sizeof infop->ti_events.event_bits[0]); +    } + +  return err; +} diff --git a/libpthread/nptl_db/td_thr_getfpregs.c b/libpthread/nptl_db/td_thr_getfpregs.c new file mode 100644 index 000000000..7760512eb --- /dev/null +++ b/libpthread/nptl_db/td_thr_getfpregs.c @@ -0,0 +1,53 @@ +/* Get a thread's floating-point register set. +   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) +{ +  psaddr_t cancelhandling, tid; +  td_err_e err; + +  LOG ("td_thr_getfpregs"); + +  /* We have to get the state and the PID for this thread.  */ +  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, +		      cancelhandling, 0); +  if (err != TD_OK) +    return err; + +  /* If the thread already terminated we return all zeroes.  */ +  if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) +    memset (regset, '\0', sizeof (*regset)); +  /* Otherwise get the register content through the callback.  */ +  else +    { +      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); +      if (err != TD_OK) +	return err; + +      if (ps_lgetfpregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK) +	return TD_ERR; +    } + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_getgregs.c b/libpthread/nptl_db/td_thr_getgregs.c new file mode 100644 index 000000000..4c2373ef6 --- /dev/null +++ b/libpthread/nptl_db/td_thr_getgregs.c @@ -0,0 +1,53 @@ +/* Get a thread's general register set. +   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset) +{ +  psaddr_t cancelhandling, tid; +  td_err_e err; + +  LOG ("td_thr_getgregs"); + +  /* We have to get the state and the PID for this thread.  */ +  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, +		      cancelhandling, 0); +  if (err != TD_OK) +    return err; + +  /* If the thread already terminated we return all zeroes.  */ +  if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) +    memset (regset, '\0', sizeof (*regset)); +  /* Otherwise get the register content through the callback.  */ +  else +    { +      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); +      if (err != TD_OK) +	return err; + +      if (ps_lgetregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK) +	return TD_ERR; +    } + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_getxregs.c b/libpthread/nptl_db/td_thr_getxregs.c new file mode 100644 index 000000000..3c77ab6be --- /dev/null +++ b/libpthread/nptl_db/td_thr_getxregs.c @@ -0,0 +1,30 @@ +/* Get a thread's extra state register set. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregs (const td_thrhandle_t *th, void *xregs) +{ +  /* XXX This might be platform specific.  */ +  LOG ("td_thr_getxregs"); +  return TD_NOXREGS; +} diff --git a/libpthread/nptl_db/td_thr_getxregsize.c b/libpthread/nptl_db/td_thr_getxregsize.c new file mode 100644 index 000000000..1704e4b0a --- /dev/null +++ b/libpthread/nptl_db/td_thr_getxregsize.c @@ -0,0 +1,30 @@ +/* Get the size of the extra state register set for this architecture. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregsize (const td_thrhandle_t *th, int *sizep) +{ +  /* XXX This might be platform specific.  */ +  LOG ("td_thr_getxregsize"); +  return TD_NOXREGS; +} diff --git a/libpthread/nptl_db/td_thr_set_event.c b/libpthread/nptl_db/td_thr_set_event.c new file mode 100644 index 000000000..2bb0b9d1f --- /dev/null +++ b/libpthread/nptl_db/td_thr_set_event.c @@ -0,0 +1,77 @@ +/* Enable specific event for thread. +   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <stddef.h> + +#include "thread_dbP.h" + + +td_err_e +td_thr_set_event (th, event) +     const td_thrhandle_t *th; +     td_thr_events_t *event; +{ +  td_err_e err; +  psaddr_t eventmask; +  void *copy; + +  LOG ("td_thr_set_event"); + +  /* Fetch the old event mask from the inferior and modify it in place.  */ +  err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p, +			      th->th_unique, pthread, eventbuf_eventmask, 0); +  if (err == TD_OK) +    err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t); +  if (err == TD_OK) +    { +      uint32_t idx; +      for (idx = 0; idx < TD_EVENTSIZE; ++idx) +	{ +	  psaddr_t word; +	  uint32_t mask; +	  err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, +				    td_thr_events_t, event_bits, idx); +	  if (err != TD_OK) +	    break; +	  mask = (uintptr_t) word; +	  mask |= event->event_bits[idx]; +	  word = (psaddr_t) (uintptr_t) mask; +	  err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy, +				    td_thr_events_t, event_bits, idx, word); +	  if (err != TD_OK) +	    break; +	} +      if (err == TD_NOAPLIC) +	{ +	  err = TD_OK; +	  while (idx < TD_EVENTSIZE) +	    if (event->event_bits[idx++] != 0) +	      { +		err = TD_NOEVENT; +		break; +	      } +	} +      if (err == TD_OK) +	/* Now write it back to the inferior.  */ +	err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy); +    } + +  return err; +} diff --git a/libpthread/nptl_db/td_thr_setfpregs.c b/libpthread/nptl_db/td_thr_setfpregs.c new file mode 100644 index 000000000..01bdb5323 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setfpregs.c @@ -0,0 +1,50 @@ +/* Set a thread's floating-point register set. +   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ +  psaddr_t cancelhandling, tid; +  td_err_e err; + +  LOG ("td_thr_setfpregs"); + +  /* We have to get the state and the PID for this thread.  */ +  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, +		      cancelhandling, 0); +  if (err != TD_OK) +    return err; + +  /* Only set the registers if the thread hasn't yet terminated.  */ +  if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) +    { +      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); +      if (err != TD_OK) +	return err; + +      if (ps_lsetfpregs (th->th_ta_p->ph, (uintptr_t) tid, fpregs) != PS_OK) +	return TD_ERR; +    } + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setgregs.c b/libpthread/nptl_db/td_thr_setgregs.c new file mode 100644 index 000000000..2a9ce7e01 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setgregs.c @@ -0,0 +1,50 @@ +/* Set a thread's general register set. +   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ +  psaddr_t cancelhandling, tid; +  td_err_e err; + +  LOG ("td_thr_setgregs"); + +  /* We have to get the state and the PID for this thread.  */ +  err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, +		      cancelhandling, 0); +  if (err != TD_OK) +    return err; + +  /* Only set the registers if the thread hasn't yet terminated.  */ +  if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) +    { +      err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); +      if (err != TD_OK) +	return err; + +      if (ps_lsetregs (th->th_ta_p->ph, tid - (psaddr_t) 0, gregs) != PS_OK) +	return TD_ERR; +    } + +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setprio.c b/libpthread/nptl_db/td_thr_setprio.c new file mode 100644 index 000000000..6032b0ed4 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setprio.c @@ -0,0 +1,30 @@ +/* Set a thread's priority. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setprio (const td_thrhandle_t *th, int prio) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_thr_setprio"); +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setsigpending.c b/libpthread/nptl_db/td_thr_setsigpending.c new file mode 100644 index 000000000..e2c9d7ad2 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setsigpending.c @@ -0,0 +1,31 @@ +/* Raise a signal for a thread. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n, +		      const sigset_t *ss) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_thr_setsigpending"); +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setxregs.c b/libpthread/nptl_db/td_thr_setxregs.c new file mode 100644 index 000000000..f48877c78 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setxregs.c @@ -0,0 +1,30 @@ +/* Set a thread's extra state register set. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setxregs (const td_thrhandle_t *ta, const void *addr) +{ +  /* XXX This might have to be platform specific.  */ +  LOG ("td_thr_setxregs"); +  return TD_NOXREGS; +} diff --git a/libpthread/nptl_db/td_thr_sigsetmask.c b/libpthread/nptl_db/td_thr_sigsetmask.c new file mode 100644 index 000000000..3a68aecd3 --- /dev/null +++ b/libpthread/nptl_db/td_thr_sigsetmask.c @@ -0,0 +1,30 @@ +/* Set a thread's signal mask. +   Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss) +{ +  /* XXX We have to figure out what has to be done.  */ +  LOG ("td_thr_sigsetmask"); +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_tls_get_addr.c b/libpthread/nptl_db/td_thr_tls_get_addr.c new file mode 100644 index 000000000..e7d232272 --- /dev/null +++ b/libpthread/nptl_db/td_thr_tls_get_addr.c @@ -0,0 +1,43 @@ +/* Get address of thread local variable. +   Copyright (C) 2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@cygnus.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <link.h> +#include "thread_dbP.h" + +td_err_e +td_thr_tls_get_addr (const td_thrhandle_t *th, +		     psaddr_t map_address, size_t offset, psaddr_t *address) +{ +  td_err_e err; +  psaddr_t modid; + +  /* Get the TLS module ID from the `struct link_map' in the inferior.  */ +  err = DB_GET_FIELD (modid, th->th_ta_p, map_address, link_map, +		      l_tls_modid, 0); +  if (err == TD_NOCAPAB) +    return TD_NOAPLIC; +  if (err == TD_OK) +    { +      err = td_thr_tlsbase (th, (uintptr_t) modid, address); +      if (err == TD_OK) +	*address += offset; +    } +  return err; +} diff --git a/libpthread/nptl_db/td_thr_tlsbase.c b/libpthread/nptl_db/td_thr_tlsbase.c new file mode 100644 index 000000000..c57009a73 --- /dev/null +++ b/libpthread/nptl_db/td_thr_tlsbase.c @@ -0,0 +1,50 @@ +/* Locate TLS data for a 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 Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + +td_err_e +td_thr_tlsbase (const td_thrhandle_t *th, +		unsigned long int modid, +		psaddr_t *base) +{ +  td_err_e err; +  psaddr_t dtv, dtvptr; + +  if (modid < 1) +    return TD_NOTLS; + +  /* Get the DTV pointer from the thread descriptor.  */ +  err = DB_GET_FIELD (dtv, th->th_ta_p, th->th_unique, pthread, dtvp, 0); +  if (err != TD_OK) +    return err; + +  /* Get the corresponding entry in the DTV.  */ +  err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtv, dtv, dtv, modid); +  if (err != TD_OK) +    return err; + +  /* It could be that the memory for this module is not allocated for +     the given thread.  */ +  if ((uintptr_t) dtvptr & 1) +    return TD_TLSDEFER; + +  *base = dtvptr; +  return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_tsd.c b/libpthread/nptl_db/td_thr_tsd.c new file mode 100644 index 000000000..08f617b7d --- /dev/null +++ b/libpthread/nptl_db/td_thr_tsd.c @@ -0,0 +1,96 @@ +/* Get a thread-specific data pointer for a thread. +   Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) +{ +  td_err_e err; +  psaddr_t tk_seq, level1, level2, seq, value; +  void *copy; +  uint32_t pthread_key_2ndlevel_size, idx1st, idx2nd; + +  LOG ("td_thr_tsd"); + +  /* Get the key entry.  */ +  err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk); +  if (err == TD_NOAPLIC) +    return TD_BADKEY; +  if (err != TD_OK) +    return err; + +  /* Fail if this key is not at all used.  */ +  if (((uintptr_t) tk_seq & 1) == 0) +    return TD_BADKEY; + +  /* This makes sure we have the size information on hand.  */ +  err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, 0, pthread_key_data_level2, +			      data, 1); +  if (err != TD_OK) +    return err; + +  /* Compute the indeces.  */ +  pthread_key_2ndlevel_size +    = DB_DESC_NELEM (th->th_ta_p->ta_field_pthread_key_data_level2_data); +  idx1st = tk / pthread_key_2ndlevel_size; +  idx2nd = tk % pthread_key_2ndlevel_size; + +  /* Now fetch the first level pointer.  */ +  err = DB_GET_FIELD (level1, th->th_ta_p, th->th_unique, pthread, +		      specific, idx1st); +  if (err == TD_NOAPLIC) +    return TD_DBERR; +  if (err != TD_OK) +    return err; + +  /* Check the pointer to the second level array.  */ +  if (level1 == 0) +    return TD_NOTSD; + +  /* Locate the element within the second level array.  */ +  err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, +			      level1, pthread_key_data_level2, data, idx2nd); +  if (err == TD_NOAPLIC) +    return TD_DBERR; +  if (err != TD_OK) +    return err; + +  /* Now copy in that whole structure.  */ +  err = DB_GET_STRUCT (copy, th->th_ta_p, level2, pthread_key_data); +  if (err != TD_OK) +    return err; + +  /* Check whether the data is valid.  */ +  err = DB_GET_FIELD_LOCAL (seq, th->th_ta_p, copy, pthread_key_data, seq, 0); +  if (err != TD_OK) +    return err; +  if (seq != tk_seq) +    return TD_NOTSD; + +  /* Finally, fetch the value.  */ +  err = DB_GET_FIELD_LOCAL (value, th->th_ta_p, copy, pthread_key_data, +			    data, 0); +  if (err == TD_OK) +    *data = value; + +  return err; +} diff --git a/libpthread/nptl_db/td_thr_validate.c b/libpthread/nptl_db/td_thr_validate.c new file mode 100644 index 000000000..3d560a621 --- /dev/null +++ b/libpthread/nptl_db/td_thr_validate.c @@ -0,0 +1,91 @@ +/* Validate a thread handle. +   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" +#include <stdbool.h> + +static td_err_e +check_thread_list (const td_thrhandle_t *th, psaddr_t head, bool *uninit) +{ +  td_err_e err; +  psaddr_t next, ofs; + +  err = DB_GET_FIELD (next, th->th_ta_p, head, list_t, next, 0); +  if (err == TD_OK) +    { +      if (next == 0) +	{ +	  *uninit = true; +	  return TD_NOTHR; +	} +      err = DB_GET_FIELD_ADDRESS (ofs, th->th_ta_p, 0, pthread, list, 0); +    } + +  while (err == TD_OK) +    { +      if (next == head) +	return TD_NOTHR; + +      if (next - (ofs - (psaddr_t) 0) == th->th_unique) +	return TD_OK; + +      err = DB_GET_FIELD (next, th->th_ta_p, next, list_t, next, 0); +    } + +  return err; +} + + +td_err_e +td_thr_validate (const td_thrhandle_t *th) +{ +  td_err_e err; +  psaddr_t list; + +  LOG ("td_thr_validate"); + +  /* First check the list with threads using user allocated stacks.  */ +  bool uninit = false; +  err = DB_GET_SYMBOL (list, th->th_ta_p, __stack_user); +  if (err == TD_OK) +    err = check_thread_list (th, list, &uninit); + +  /* If our thread is not on this list search the list with stack +     using implementation allocated stacks.  */ +  if (err == TD_NOTHR) +    { +      err = DB_GET_SYMBOL (list, th->th_ta_p, stack_used); +      if (err == TD_OK) +	err = check_thread_list (th, list, &uninit); + +      if (err == TD_NOTHR && uninit) +	{ +	  /* __pthread_initialize_minimal has not run yet. +	     But the main thread still has a valid ID.  */ +	  td_thrhandle_t main_th; +	  err = td_ta_map_lwp2thr (th->th_ta_p, +				   ps_getpid (th->th_ta_p->ph), &main_th); +	  if (err == TD_OK && th->th_unique != main_th.th_unique) +	    err = TD_NOTHR; +	} +    } + +  return err; +} diff --git a/libpthread/nptl_db/thread_db.h b/libpthread/nptl_db/thread_db.h new file mode 100644 index 000000000..433b54fd5 --- /dev/null +++ b/libpthread/nptl_db/thread_db.h @@ -0,0 +1,459 @@ +/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread +   Copyright (C) 1999,2001,2002,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 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 _THREAD_DB_H +#define _THREAD_DB_H	1 + +/* This is the debugger interface for the NPTL library.  It is +   modelled closely after the interface with same names in Solaris +   with the goal to share the same code in the debugger.  */ +#include <pthread.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/procfs.h> + + +/* Error codes of the library.  */ +typedef enum +{ +  TD_OK,	  /* No error.  */ +  TD_ERR,	  /* No further specified error.  */ +  TD_NOTHR,	  /* No matching thread found.  */ +  TD_NOSV,	  /* No matching synchronization handle found.  */ +  TD_NOLWP,	  /* No matching light-weighted process found.  */ +  TD_BADPH,	  /* Invalid process handle.  */ +  TD_BADTH,	  /* Invalid thread handle.  */ +  TD_BADSH,	  /* Invalid synchronization handle.  */ +  TD_BADTA,	  /* Invalid thread agent.  */ +  TD_BADKEY,	  /* Invalid key.  */ +  TD_NOMSG,	  /* No event available.  */ +  TD_NOFPREGS,	  /* No floating-point register content available.  */ +  TD_NOLIBTHREAD, /* Application not linked with thread library.  */ +  TD_NOEVENT,	  /* Requested event is not supported.  */ +  TD_NOCAPAB,	  /* Capability not available.  */ +  TD_DBERR,	  /* Internal debug library error.  */ +  TD_NOAPLIC,	  /* Operation is not applicable.  */ +  TD_NOTSD,	  /* No thread-specific data available.  */ +  TD_MALLOC,	  /* Out of memory.  */ +  TD_PARTIALREG,  /* Not entire register set was read or written.  */ +  TD_NOXREGS,	  /* X register set not available for given thread.  */ +  TD_TLSDEFER,	  /* Thread has not yet allocated TLS for given module.  */ +  TD_NOTALLOC = TD_TLSDEFER, +  TD_VERSION,	  /* Version if libpthread and libthread_db do not match.  */ +  TD_NOTLS	  /* There is no TLS segment in the given module.  */ +} td_err_e; + + +/* Possible thread states.  TD_THR_ANY_STATE is a pseudo-state used to +   select threads regardless of state in td_ta_thr_iter().  */ +typedef enum +{ +  TD_THR_ANY_STATE, +  TD_THR_UNKNOWN, +  TD_THR_STOPPED, +  TD_THR_RUN, +  TD_THR_ACTIVE, +  TD_THR_ZOMBIE, +  TD_THR_SLEEP, +  TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +/* Thread type: user or system.  TD_THR_ANY_TYPE is a pseudo-type used +   to select threads regardless of type in td_ta_thr_iter().  */ +typedef enum +{ +  TD_THR_ANY_TYPE, +  TD_THR_USER, +  TD_THR_SYSTEM +} td_thr_type_e; + + +/* Types of the debugging library.  */ + +/* Handle for a process.  This type is opaque.  */ +typedef struct td_thragent td_thragent_t; + +/* The actual thread handle type.  This is also opaque.  */ +typedef struct td_thrhandle +{ +  td_thragent_t *th_ta_p; +  psaddr_t th_unique; +} td_thrhandle_t; + + +/* Forward declaration of a type defined by and for the dynamic linker.  */ +struct link_map; + + +/* Flags for `td_ta_thr_iter'.  */ +#define TD_THR_ANY_USER_FLAGS	0xffffffff +#define TD_THR_LOWEST_PRIORITY	-20 +#define TD_SIGNO_MASK		NULL + + +#define TD_EVENTSIZE	2 +#define BT_UISHIFT	5 /* log base 2 of BT_NBIPUI, to extract word index */ +#define BT_NBIPUI	(1 << BT_UISHIFT)       /* n bits per uint */ +#define BT_UIMASK	(BT_NBIPUI - 1)         /* to extract bit index */ + +/* Bitmask of enabled events. */ +typedef struct td_thr_events +{ +  uint32_t event_bits[TD_EVENTSIZE]; +} td_thr_events_t; + +/* Event set manipulation macros. */ +#define __td_eventmask(n) \ +  (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) +#define __td_eventword(n) \ +  ((UINT32_C ((n) - 1)) >> BT_UISHIFT) + +#define td_event_emptyset(setp) \ +  do {									      \ +    int __i;								      \ +    for (__i = TD_EVENTSIZE; __i > 0; --__i)				      \ +      (setp)->event_bits[__i - 1] = 0;					      \ +  } while (0) + +#define td_event_fillset(setp) \ +  do {									      \ +    int __i;								      \ +    for (__i = TD_EVENTSIZE; __i > 0; --__i)				      \ +      (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff);		      \ +  } while (0) + +#define td_event_addset(setp, n) \ +  (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) +#define td_event_delset(setp, n) \ +  (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) +#define td_eventismember(setp, n) \ +  (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) +#if TD_EVENTSIZE == 2 +# define td_eventisempty(setp) \ +  (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) +#else +# error "td_eventisempty must be changed to match TD_EVENTSIZE" +#endif + +/* Events reportable by the thread implementation.  */ +typedef enum +{ +  TD_ALL_EVENTS,		 /* Pseudo-event number.  */ +  TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context.  */ +  TD_READY,			 /* Is executable now. */ +  TD_SLEEP,			 /* Blocked in a synchronization obj.  */ +  TD_SWITCHTO,			 /* Now assigned to a process.  */ +  TD_SWITCHFROM,		 /* Not anymore assigned to a process.  */ +  TD_LOCK_TRY,			 /* Trying to get an unavailable lock.  */ +  TD_CATCHSIG,			 /* Signal posted to the thread.  */ +  TD_IDLE,			 /* Process getting idle.  */ +  TD_CREATE,			 /* New thread created.  */ +  TD_DEATH,			 /* Thread terminated.  */ +  TD_PREEMPT,			 /* Preempted.  */ +  TD_PRI_INHERIT,		 /* Inherited elevated priority.  */ +  TD_REAP,			 /* Reaped.  */ +  TD_CONCURRENCY,		 /* Number of processes changing.  */ +  TD_TIMEOUT,			 /* Conditional variable wait timed out.  */ +  TD_MIN_EVENT_NUM = TD_READY, +  TD_MAX_EVENT_NUM = TD_TIMEOUT, +  TD_EVENTS_ENABLE = 31		/* Event reporting enabled.  */ +} td_event_e; + +/* Values representing the different ways events are reported.  */ +typedef enum +{ +  NOTIFY_BPT,			/* User must insert breakpoint at u.bptaddr. */ +  NOTIFY_AUTOBPT,		/* Breakpoint at u.bptaddr is automatically +				   inserted.  */ +  NOTIFY_SYSCALL		/* System call u.syscallno will be invoked.  */ +} td_notify_e; + +/* Description how event type is reported.  */ +typedef struct td_notify +{ +  td_notify_e type;		/* Way the event is reported.  */ +  union +  { +    psaddr_t bptaddr;		/* Address of breakpoint.  */ +    int syscallno;		/* Number of system call used.  */ +  } u; +} td_notify_t; + +/* Structure used to report event.  */ +typedef struct td_event_msg +{ +  td_event_e event;		/* Event type being reported.  */ +  const td_thrhandle_t *th_p;	/* Thread reporting the event.  */ +  union +  { +# if 0 +    td_synchandle_t *sh;	/* Handle of synchronization object.  */ +#endif +    uintptr_t data;		/* Event specific data.  */ +  } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure.  */ +typedef struct +{ +  td_thr_events_t eventmask;	/* Mask of enabled events.  */ +  td_event_e eventnum;		/* Number of last event.  */ +  void *eventdata;		/* Data associated with event.  */ +} td_eventbuf_t; + + +/* Gathered statistics about the process.  */ +typedef struct td_ta_stats +{ +  int nthreads;       		/* Total number of threads in use.  */ +  int r_concurrency;		/* Concurrency level requested by user.  */ +  int nrunnable_num;		/* Average runnable threads, numerator.  */ +  int nrunnable_den;		/* Average runnable threads, denominator.  */ +  int a_concurrency_num;	/* Achieved concurrency level, numerator.  */ +  int a_concurrency_den;	/* Achieved concurrency level, denominator.  */ +  int nlwps_num;		/* Average number of processes in use, +				   numerator.  */ +  int nlwps_den;		/* Average number of processes in use, +				   denominator.  */ +  int nidle_num;		/* Average number of idling processes, +				   numerator.  */ +  int nidle_den;		/* Average number of idling processes, +				   denominator.  */ +} td_ta_stats_t; + + +/* Since Sun's library is based on Solaris threads we have to define a few +   types to map them to POSIX threads.  */ +typedef pthread_t thread_t; +typedef pthread_key_t thread_key_t; + + +/* Callback for iteration over threads.  */ +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); + +/* Callback for iteration over thread local data.  */ +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); + + + +/* Forward declaration.  This has to be defined by the user.  */ +struct ps_prochandle; + + +/* Information about the thread.  */ +typedef struct td_thrinfo +{ +  td_thragent_t *ti_ta_p;		/* Process handle.  */ +  unsigned int ti_user_flags;		/* Unused.  */ +  thread_t ti_tid;			/* Thread ID returned by +					   pthread_create().  */ +  char *ti_tls;				/* Pointer to thread-local data.  */ +  psaddr_t ti_startfunc;		/* Start function passed to +					   pthread_create().  */ +  psaddr_t ti_stkbase;			/* Base of thread's stack.  */ +  long int ti_stksize;			/* Size of thread's stack.  */ +  psaddr_t ti_ro_area;			/* Unused.  */ +  int ti_ro_size;			/* Unused.  */ +  td_thr_state_e ti_state;		/* Thread state.  */ +  unsigned char ti_db_suspended;	/* Nonzero if suspended by debugger. */ +  td_thr_type_e ti_type;		/* Type of the thread (system vs +					   user thread).  */ +  intptr_t ti_pc;			/* Unused.  */ +  intptr_t ti_sp;			/* Unused.  */ +  short int ti_flags;			/* Unused.  */ +  int ti_pri;				/* Thread priority.  */ +  lwpid_t ti_lid;			/* Kernel PID for this thread.  */ +  sigset_t ti_sigmask;			/* Signal mask.  */ +  unsigned char ti_traceme;		/* Nonzero if event reporting +					   enabled.  */ +  unsigned char ti_preemptflag;		/* Unused.  */ +  unsigned char ti_pirecflag;		/* Unused.  */ +  sigset_t ti_pending;			/* Set of pending signals.  */ +  td_thr_events_t ti_events;		/* Set of enabled events.  */ +} td_thrinfo_t; + + + +/* Prototypes for exported library functions.  */ + +/* Initialize the thread debug support library.  */ +extern td_err_e td_init (void); + +/* Historical relict.  Should not be used anymore.  */ +extern td_err_e td_log (void); + +/* Return list of symbols the library can request.  */ +extern const char **td_symbol_list (void); + +/* Generate new thread debug library handle for process PS.  */ +extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); + +/* Free resources allocated for TA.  */ +extern td_err_e td_ta_delete (td_thragent_t *__ta); + +/* Get number of currently running threads in process associated with TA.  */ +extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); + +/* Return process handle passed in `td_ta_new' for process associated with +   TA.  */ +extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, +			      struct ps_prochandle **__ph); + +/* Map thread library handle PT to thread debug library handle for process +   associated with TA and store result in *TH.  */ +extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, +				  td_thrhandle_t *__th); + +/* Map process ID LWPID to thread debug library handle for process +   associated with TA and store result in *TH.  */ +extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, +				   td_thrhandle_t *__th); + + +/* Call for each thread in a process associated with TA the callback function +   CALLBACK.  */ +extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, +				td_thr_iter_f *__callback, void *__cbdata_p, +				td_thr_state_e __state, int __ti_pri, +				sigset_t *__ti_sigmask_p, +				unsigned int __ti_user_flags); + +/* Call for each defined thread local data entry the callback function KI.  */ +extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, +				void *__p); + + +/* Get event address for EVENT.  */ +extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, +				  td_event_e __event, td_notify_t *__ptr); + +/* Enable EVENT in global mask.  */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, +				 td_thr_events_t *__event); + +/* Disable EVENT in global mask.  */ +extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, +				   td_thr_events_t *__event); + +/* Return information about last event.  */ +extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, +				    td_event_msg_t *__msg); + + +/* Set suggested concurrency level for process associated with TA.  */ +extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); + + +/* Enable collecting statistics for process associated with TA.  */ +extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); + +/* Reset statistics.  */ +extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); + +/* Retrieve statistics from process associated with TA.  */ +extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, +				 td_ta_stats_t *__statsp); + + +/* Validate that TH is a thread handle.  */ +extern td_err_e td_thr_validate (const td_thrhandle_t *__th); + +/* Return information about thread TH.  */ +extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, +				 td_thrinfo_t *__infop); + +/* Retrieve floating-point register contents of process running thread TH.  */ +extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, +				  prfpregset_t *__regset); + +/* Retrieve general register contents of process running thread TH.  */ +extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, +				 prgregset_t __gregs); + +/* Retrieve extended register contents of process running thread TH.  */ +extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); + +/* Get size of extended register set of process running thread TH.  */ +extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); + +/* Set floating-point register contents of process running thread TH.  */ +extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, +				  const prfpregset_t *__fpregs); + +/* Set general register contents of process running thread TH.  */ +extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, +				 prgregset_t __gregs); + +/* Set extended register contents of process running thread TH.  */ +extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, +				 const void *__addr); + + +/* Get address of the given module's TLS storage area for the given thread.  */ +extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, +				unsigned long int __modid, +				psaddr_t *__base); + +/* Get address of thread local variable.  */ +extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, +				     psaddr_t __map_address, size_t __offset, +				     psaddr_t *__address); + + +/* Enable reporting for EVENT for thread TH.  */ +extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); + +/* Enable EVENT for thread TH.  */ +extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, +				  td_thr_events_t *__event); + +/* Disable EVENT for thread TH.  */ +extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, +				    td_thr_events_t *__event); + +/* Get event message for thread TH.  */ +extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, +				     td_event_msg_t *__msg); + + +/* Set priority of thread TH.  */ +extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); + + +/* Set pending signals for thread TH.  */ +extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, +				      unsigned char __n, const sigset_t *__ss); + +/* Set signal mask for thread TH.  */ +extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, +				   const sigset_t *__ss); + + +/* Return thread local data associated with key TK in thread TH.  */ +extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, +			    const thread_key_t __tk, void **__data); + + +/* Suspend execution of thread TH.  */ +extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); + +/* Resume execution of thread TH.  */ +extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); + +#endif	/* thread_db.h */ diff --git a/libpthread/nptl_db/thread_dbP.h b/libpthread/nptl_db/thread_dbP.h new file mode 100644 index 000000000..c53d1ed94 --- /dev/null +++ b/libpthread/nptl_db/thread_dbP.h @@ -0,0 +1,254 @@ +/* Private header for thread debug library +   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 +   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 _THREAD_DBP_H +#define _THREAD_DBP_H	1 + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include "proc_service.h" +#include "thread_db.h" +#include "../nptl/pthreadP.h"  	/* This is for *_BITMASK only.  */ + +/* Indeces for the symbol names.  */ +enum +  { +# define DB_STRUCT(type)		SYM_SIZEOF_##type, +# define DB_STRUCT_FIELD(type, field)	SYM_##type##_FIELD_##field, +# define DB_SYMBOL(name)		SYM_##name, +# define DB_FUNCTION(name)		SYM_##name, +# define DB_VARIABLE(name)		SYM_##name, SYM_DESC_##name, +# include "structs.def" +# undef DB_STRUCT +# undef DB_STRUCT_FIELD +# undef DB_SYMBOL +# undef DB_FUNCTION +# undef DB_VARIABLE + +    SYM_TH_UNIQUE_CONST_THREAD_AREA, +    SYM_TH_UNIQUE_REGISTER64, +    SYM_TH_UNIQUE_REGISTER32, +    SYM_TH_UNIQUE_REGISTER64_THREAD_AREA, +    SYM_TH_UNIQUE_REGISTER32_THREAD_AREA, + +    SYM_NUM_MESSAGES +  }; + + +/* Comment out the following for less verbose output.  */ +#ifndef NDEBUG +# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n")) +extern int __td_debug attribute_hidden; +#else +# define LOG(c) +#endif + + +#define DB_DESC_SIZE(desc)	((desc)[0]) +#define DB_DESC_NELEM(desc)	((desc)[1]) +#define DB_DESC_OFFSET(desc)	((desc)[2]) +#define DB_SIZEOF_DESC		(3 * sizeof (uint32_t)) +#define DB_DEFINE_DESC(name, size, nelem, offset) \ +  const uint32_t name[3] = { (size), (nelem), (offset) } +typedef uint32_t db_desc_t[3]; + + +/* Handle for a process.  This type is opaque.  */ +struct td_thragent +{ +  /* Chain on the list of all agent structures.  */ +  list_t list; + +  /* Delivered by the debugger and we have to pass it back in the +     proc callbacks.  */ +  struct ps_prochandle *ph; + +  /* Cached values read from the inferior.  */ +# define DB_STRUCT(type) \ +  uint32_t ta_sizeof_##type; +# define DB_STRUCT_FIELD(type, field) \ +  db_desc_t ta_field_##type##_##field; +# define DB_SYMBOL(name) \ +  psaddr_t ta_addr_##name; +# define DB_FUNCTION(name) \ +  psaddr_t ta_addr_##name; +# define DB_VARIABLE(name) \ +  psaddr_t ta_addr_##name; \ +  db_desc_t ta_var_##name; +# include "structs.def" +# undef DB_STRUCT +# undef DB_STRUCT_FIELD +# undef DB_FUNCTION +# undef DB_SYMBOL +# undef DB_VARIABLE + +  /* The method of locating a thread's th_unique value.  */ +  enum +    { +      ta_howto_unknown, +      ta_howto_reg, +      ta_howto_reg_thread_area, +      ta_howto_const_thread_area +    } ta_howto; +  union +  { +    uint32_t const_thread_area;	/* Constant argument to ps_get_thread_area.  */ +    /* These are as if the descriptor of the field in prregset_t, +       but DB_DESC_NELEM is overloaded as follows: */ +    db_desc_t reg;		/* Signed bias applied to register value.  */ +    db_desc_t reg_thread_area;	/* Bits to scale down register value.  */ +  } ta_howto_data; +}; + + +/* List of all known descriptors.  */ +extern list_t __td_agent_list attribute_hidden; + + +/* Function used to test for correct thread agent pointer.  */ +static inline bool +ta_ok (const td_thragent_t *ta) +{ +  list_t *runp; + +  list_for_each (runp, &__td_agent_list) +    if (list_entry (runp, td_thragent_t, list) == ta) +      return true; + +  return false; +} + + +/* Internal wrapper around ps_pglobal_lookup.  */ +extern ps_err_e td_lookup (struct ps_prochandle *ps, +			   int idx, psaddr_t *sym_addr) attribute_hidden; + + + + +/* Store in psaddr_t VAR the address of inferior's symbol NAME.  */ +#define DB_GET_SYMBOL(var, ta, name)					      \ +  (((ta)->ta_addr_##name == 0						      \ +    && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK)      \ +   ? TD_ERR : ((var) = (ta)->ta_addr_##name, TD_OK)) + +/* Store in psaddr_t VAR the value of ((TYPE) PTR)->FIELD[IDX] in the inferior. +   A target field smaller than psaddr_t is zero-extended.  */ +#define DB_GET_FIELD(var, ta, ptr, type, field, idx) \ +  _td_fetch_value ((ta), (ta)->ta_field_##type##_##field, \ +		   SYM_##type##_FIELD_##field, \ +		   (psaddr_t) 0 + (idx), (ptr), &(var)) + +#define DB_GET_FIELD_ADDRESS(var, ta, ptr, type, field, idx) \ +  ((var) = (ptr), _td_locate_field ((ta), (ta)->ta_field_##type##_##field, \ +				    SYM_##type##_FIELD_##field, \ +				    (psaddr_t) 0 + (idx), &(var))) + +extern td_err_e _td_locate_field (td_thragent_t *ta, +				  db_desc_t desc, int descriptor_name, +				  psaddr_t idx, +				  psaddr_t *address) attribute_hidden; + + +/* Like DB_GET_FIELD, but PTR is a local pointer to a structure that +   has already been copied in from the inferior.  */ +#define DB_GET_FIELD_LOCAL(var, ta, ptr, type, field, idx) \ +  _td_fetch_value_local ((ta), (ta)->ta_field_##type##_##field, \ +		         SYM_##type##_FIELD_##field, \ +			 (psaddr_t) 0 + (idx), (ptr), &(var)) + +/* Store in psaddr_t VAR the value of variable NAME[IDX] in the inferior. +   A target value smaller than psaddr_t is zero-extended.  */ +#define DB_GET_VALUE(var, ta, name, idx)				      \ +  (((ta)->ta_addr_##name == 0						      \ +    && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK)      \ +   ? TD_ERR								      \ +   : _td_fetch_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, 	      \ +		      (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, &(var))) + +/* Helper functions for those.  */ +extern td_err_e _td_fetch_value (td_thragent_t *ta, +				 db_desc_t field, int descriptor_name, +				 psaddr_t idx, psaddr_t address, +				 psaddr_t *result) attribute_hidden; +extern td_err_e _td_fetch_value_local (td_thragent_t *ta, +				       db_desc_t field, +				       int descriptor_name, +				       psaddr_t idx, void *address, +				       psaddr_t *result) attribute_hidden; + +/* Store psaddr_t VALUE in ((TYPE) PTR)->FIELD[IDX] in the inferior. +   A target field smaller than psaddr_t is zero-extended.  */ +#define DB_PUT_FIELD(ta, ptr, type, field, idx, value) \ +  _td_store_value ((ta), (ta)->ta_field_##type##_##field, \ +		   SYM_##type##_FIELD_##field, \ +		   (psaddr_t) 0 + (idx), (ptr), (value)) + +#define DB_PUT_FIELD_LOCAL(ta, ptr, type, field, idx, value) \ +  _td_store_value_local ((ta), (ta)->ta_field_##type##_##field, \ +			 SYM_##type##_FIELD_##field, \ +			 (psaddr_t) 0 + (idx), (ptr), (value)) + +/* Store psaddr_t VALUE in variable NAME[IDX] in the inferior. +   A target field smaller than psaddr_t is zero-extended.  */ +#define DB_PUT_VALUE(ta, name, idx, value)				      \ +  (((ta)->ta_addr_##name == 0						      \ +    && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK)      \ +   ? TD_ERR								      \ +   : _td_store_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, 	      \ +		      (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, (value))) + +/* Helper functions for those.  */ +extern td_err_e _td_store_value (td_thragent_t *ta, +				 db_desc_t field, int descriptor_name, +				 psaddr_t idx, psaddr_t address, +				 psaddr_t value) attribute_hidden; +extern td_err_e _td_store_value_local (td_thragent_t *ta, +				       db_desc_t field, int descriptor_name, +				       psaddr_t idx, void *address, +				       psaddr_t value) attribute_hidden; + +#define DB_GET_STRUCT(var, ta, ptr, type)				      \ +  ({ td_err_e _err = TD_OK;						      \ +     if ((ta)->ta_sizeof_##type == 0)					      \ +       _err = _td_check_sizeof ((ta), &(ta)->ta_sizeof_##type,		      \ +				      SYM_SIZEOF_##type);		      \ +     if (_err == TD_OK)							      \ +       _err = ps_pdread ((ta)->ph, (ptr),				      \ +			 (var) = __alloca ((ta)->ta_sizeof_##type),	      \ +			 (ta)->ta_sizeof_##type)			      \ +	 == PS_OK ? TD_OK : TD_ERR;					      \ +     else								      \ +       (var) = NULL; 							      \ +     _err;								      \ +  }) +#define DB_PUT_STRUCT(ta, ptr, type, copy)				      \ +  ({ assert ((ta)->ta_sizeof_##type != 0);				      \ +     ps_pdwrite ((ta)->ph, (ptr), (copy), (ta)->ta_sizeof_##type)	      \ +       == PS_OK ? TD_OK : TD_ERR;					      \ +  }) + +extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, +				  int sizep_name) attribute_hidden; + +#endif /* thread_dbP.h */  | 
