This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
Hi!
This patch makes IA-64 port work again, with the exception of expected
math failures and tst-cancel5 make check passes.
linuxthreads/sysdeps/ia64/tls.h is really just a small part, I had no time
to make full TLS working ATM on IA-64.
I've removed SPARC bits from the patch set, because I hit a linker bug
and thus will have to redo part of those changes.
2002-12-21 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/ia64/sysdep.h (INLINE_SYSCALL,
INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERROR):
Define. Patch by Richard Henderson and Jes Sorensen.
(PSEUDO): Remove unnecessary ;;.
* elf/rtld.c (dl_main): Initialize TLS even if no PT_TLS segments
are found unless TLS_INIT_TP_EXPENSIVE. Use NONTLS_INIT_TP.
* sysdeps/generic/libc-tls.c (__libc_setup_tls): Use NONTLS_INIT_TP
if not initializing thread pointer.
[!USE_TLS && NONTLS_INIT_TP] (__pthread_initialize_minimal): New.
* sysdeps/generic/libc-start.c (__pthread_initialize_minimal): Don't
make it weak also if NONTLS_INIT_TP.
* sysdeps/unix/common/pause.c: Handle cancellation.
linuxthreads/
* libc_pthread_init.c: Include stdlib.h.
* sysdeps/i386/tls.h (tcbhead_t): Add multiple_threads member.
(TLS_INIT_TP_EXPENSIVE): Define.
* sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call,
__libc_maybe_call2): In _LIBC check SHARED define.
* sysdeps/ia64/tls.h: New file.
* sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: New file.
* sysdeps/unix/sysv/linux/ia64/Makefile: New file.
* sysdeps/x86_64/tls.h (TLS_INIT_TP_EXPENSIVE): Define.
* Makefile (tests): Add tst-cancel[1-6].
(tests-reverse): Add tst-cancel5.
Link libc.so before libpthread.so for tests-reverse.
* tst-cancel1.c: New file.
* tst-cancel2.c: New file.
* tst-cancel3.c: New file.
* tst-cancel4.c: New file.
* tst-cancel5.c: New file.
* tst-cancel6.c: New file.
nptl/
* 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.
--- libc/elf/rtld.c.jj 2002-12-20 13:34:41.000000000 +0100
+++ libc/elf/rtld.c 2002-12-20 16:02:39.000000000 +0100
@@ -1157,7 +1157,7 @@ of this helper program; chances are you
an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
used. Trying to do it lazily is too hairy to try when there could be
multiple threads (from a non-TLS-using libpthread). */
- if (GL(dl_tls_max_dtv_idx) > 0)
+ if (GL(dl_tls_max_dtv_idx) > 0 || !TLS_INIT_TP_EXPENSIVE)
{
struct link_map *l;
size_t nelem;
@@ -1565,8 +1565,12 @@ cannot allocate TLS data structures for
we need it in the memory handling later. */
GL(dl_initial_searchlist) = *GL(dl_main_searchlist);
+#ifndef NONTLS_INIT_TP
+# define NONTLS_INIT_TP do { } while (0)
+#endif
+
#ifdef USE_TLS
- if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD)
+ if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD || !TLS_INIT_TP_EXPENSIVE)
{
/* Now that we have completed relocation, the initializer data
for the TLS blocks has its final values and we can copy them
@@ -1579,7 +1583,9 @@ cannot allocate TLS data structures for
if (__builtin_expect (lossage != NULL, 0))
_dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
}
+ else
#endif
+ NONTLS_INIT_TP;
{
/* Initialize _r_debug. */
--- libc/linuxthreads/libc_pthread_init.c.jj 2002-12-18 02:15:55.000000000 +0100
+++ libc/linuxthreads/libc_pthread_init.c 2002-12-20 17:23:42.000000000 +0100
@@ -17,9 +17,10 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <locale.h>
+#include <stdlib.h>
#include <string.h>
#include <tls.h>
-#include <locale.h>
#include "internals.h"
#include <sysdep-cancel.h>
--- libc/linuxthreads/sysdeps/i386/tls.h.jj 2002-12-10 15:08:36.000000000 +0100
+++ libc/linuxthreads/sysdeps/i386/tls.h 2002-12-20 16:00:18.000000000 +0100
@@ -39,6 +39,7 @@ typedef struct
thread descriptor used by libpthread. */
dtv_t *dtv;
void *self; /* Pointer to the thread descriptor. */
+ int multiple_threads;
} tcbhead_t;
#endif
@@ -192,6 +193,10 @@ TLS_DO_MODIFY_LDT_KERNEL_CHECK(
TLS_SETUP_GS_SEGMENT (_descr, secondcall); \
})
+/* Indicate that dynamic linker shouldn't try to initialize TLS even
+ when no PT_TLS segments are found in the program and libraries
+ it is linked against. */
+# define TLS_INIT_TP_EXPENSIVE 1
/* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \
--- libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h.jj 2002-12-20 13:35:37.000000000 +0100
+++ libc/linuxthreads/sysdeps/pthread/bits/libc-lock.h 2002-12-20 17:33:13.000000000 +0100
@@ -97,7 +97,7 @@ typedef pthread_key_t __libc_key_t;
#if defined _LIBC && defined IS_IN_libpthread
# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS
#else
-# ifdef __PIC__
+# if defined __PIC__ || (defined _LIBC && defined SHARED)
# define __libc_maybe_call(FUNC, ARGS, ELSE) \
(__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
_fn != NULL ? (*_fn) ARGS : ELSE; }))
@@ -106,7 +106,7 @@ typedef pthread_key_t __libc_key_t;
(FUNC != NULL ? FUNC ARGS : ELSE)
# endif
#endif
-#if defined _LIBC && !defined NOT_IN_libc && defined __PIC__
+#if defined _LIBC && !defined NOT_IN_libc && defined SHARED
# define __libc_maybe_call2(FUNC, ARGS, ELSE) \
({__libc_pthread_functions.ptr_##FUNC != NULL \
? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; })
--- libc/linuxthreads/sysdeps/ia64/tls.h.jj 2002-12-20 14:01:54.000000000 +0100
+++ libc/linuxthreads/sysdeps/ia64/tls.h 2002-12-20 20:39:50.000000000 +0100
@@ -0,0 +1,64 @@
+/* Definitions for thread-local data handling. linuxthreads/IA-64 version.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ This file is part of the 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
+
+#ifndef __ASSEMBLER__
+
+# include <pt-machine.h>
+# include <stddef.h>
+
+/* Type for the dtv. */
+typedef union dtv
+{
+ size_t counter;
+ void *pointer;
+} dtv_t;
+
+
+/* FIXME: Only temporary. When TLS is supported on IA-64,
+ pthread_descr struct needs to be immediately below r13 and
+ at r13 a struct { dtv_t *dtv; void *private; }. */
+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;
+#endif /* __ASSEMBLER__ */
+
+#undef USE_TLS
+
+#if USE_TLS
+
+#else
+
+#define NONTLS_INIT_TP \
+ do { \
+ static const tcbhead_t nontls_init_tp \
+ = { .multiple_threads = NULL }; \
+ __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \
+ } while (0)
+
+#endif /* USE_TLS */
+
+#endif /* tls.h */
--- libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h.jj 2002-12-20 14:00:36.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h 2002-12-20 22:18:54.000000000 +0100
@@ -0,0 +1,107 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <sysdep.h>
+#include <tls.h>
+#ifndef ASSEMBLER
+# include <linuxthreads/internals.h>
+#endif
+
+#define MULTIPLE_THREADS_OFFSET 24
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+.text; \
+ENTRY (name) \
+ adds r14 = MULTIPLE_THREADS_OFFSET, r13;; \
+ ld4 r14 = [r14]; \
+ mov r15 = SYS_ify(syscall_name);; \
+ cmp4.ne p6, p7 = 0, r14; \
+(p6) br.cond.spnt .Lpseudo_cancel;; \
+ break __BREAK_SYSCALL;; \
+ cmp.eq p6,p0=-1,r10; \
+(p6) br.cond.spnt.few __syscall_error; \
+ ret;; \
+.Lpseudo_cancel: \
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(args); \
+ alloc loc0 = ar.pfs, args, 5, args, 0; \
+ mov loc1 = rp;; \
+ CENABLE;; \
+ mov loc2 = r8; \
+ COPY_ARGS_##args \
+ mov r15 = SYS_ify(syscall_name); \
+ break __BREAK_SYSCALL;; \
+ mov loc3 = r8; \
+ mov loc4 = r10; \
+ mov out0 = loc2; \
+ CDISABLE;; \
+ cmp.eq p6,p0=-1,loc4; \
+(p6) br.cond.spnt.few __syscall_error_##args; \
+ mov r8 = loc3; \
+ mov rp = loc1; \
+ mov ar.pfs = loc0; \
+.section .gnu.linkonce.t.__syscall_error_##args, "ax"; \
+.global __syscall_error_##args; \
+.hidden __syscall_error_##args; \
+__syscall_error_##args: \
+ mov loc4 = r1;; \
+ br.call.sptk.many b0 = __errno_location;; \
+ st4 [r8] = loc3; \
+ mov r1 = loc4; \
+ mov rp = loc1; \
+ mov r8 = -1; \
+ mov ar.pfs = loc0; \
+ ret; \
+.previous; \
+.Lpseudo_end:
+
+# ifdef IS_IN_libpthread
+# define CENABLE br.call.sptk.many b0 = __pthread_enable_asynccancel
+# define CDISABLE br.call.sptk.many b0 = __pthread_disable_asynccancel
+# else
+# define CENABLE br.call.sptk.many b0 = __libc_enable_asynccancel
+# define CDISABLE br.call.sptk.many b0 = __libc_disable_asynccancel
+# endif
+
+#define COPY_ARGS_0 /* Nothing */
+#define COPY_ARGS_1 COPY_ARGS_0 mov out0 = in0;
+#define COPY_ARGS_2 COPY_ARGS_1 mov out1 = in1;
+#define COPY_ARGS_3 COPY_ARGS_2 mov out2 = in2;
+#define COPY_ARGS_4 COPY_ARGS_3 mov out3 = in3;
+#define COPY_ARGS_5 COPY_ARGS_4 mov out4 = in4;
+#define COPY_ARGS_6 COPY_ARGS_5 mov out5 = in5;
+#define COPY_ARGS_7 COPY_ARGS_6 mov out6 = in6;
+
+# ifndef ASSEMBLER
+# define SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ p_header.data.multiple_threads) == 0, 1)
+# else
+# define SINGLE_THREAD_P \
+ adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14 ;;
+# endif
+
+#elif !defined ASSEMBLER
+
+/* This code should never be used but we define it anyhow. */
+# define SINGLE_THREAD_P (1)
+
+#endif
--- libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile.jj 2002-12-20 19:07:20.000000000 +0100
+++ libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile 2002-12-20 19:07:14.000000000 +0100
@@ -0,0 +1,3 @@
+ifeq ($(subdir),linuxthreads)
+libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
+endif
--- libc/linuxthreads/sysdeps/x86_64/tls.h.jj 2002-12-10 15:08:39.000000000 +0100
+++ libc/linuxthreads/sysdeps/x86_64/tls.h 2002-12-20 16:00:54.000000000 +0100
@@ -109,6 +109,11 @@ typedef struct
_result ? "cannot set %fs base address for thread-local storage" : 0; \
})
+/* Indicate that dynamic linker shouldn't try to initialize TLS even
+ when no PT_TLS segments are found in the program and libraries
+ it is linked against. */
+# define TLS_INIT_TP_EXPENSIVE 1
+
/* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \
({ struct _pthread_descr_struct *__descr; \
--- libc/linuxthreads/Makefile.jj 2002-12-20 13:35:29.000000000 +0100
+++ libc/linuxthreads/Makefile 2002-12-20 22:02:23.000000000 +0100
@@ -72,8 +72,12 @@ endif
librt-tests = ex10 ex11
tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 $(librt-tests) ex12 ex13 joinrace \
tststack $(tests-nodelete-$(have-z-nodelete)) ecmutex ex14 ex15 ex16 \
- ex17 ex18 tst-cancel tst-context bug-sleep
+ ex17 ex18 tst-cancel tst-context bug-sleep \
+ tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
+ tst-cancel6
test-srcs = tst-signal
+# These tests are linked with libc before libpthread
+tests-reverse += tst-cancel5
ifeq ($(build-static),yes)
tests += tststatic tst-static-locale
@@ -147,8 +151,12 @@ $(objpfx)libpthread.so: $(libc-link.so)
# Make sure we link with the thread library.
ifeq ($(build-shared),yes)
$(addprefix $(objpfx), \
- $(filter-out $(tests-static) unload, \
+ $(filter-out $(tests-static) $(tests-reverse) unload, \
$(tests) $(test-srcs))): $(objpfx)libpthread.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
$(addprefix $(objpfx),$(librt-tests)): $(common-objpfx)rt/librt.so
$(objpfx)unload: $(common-objpfx)dlfcn/libdl.so
$(objpfx)unload.out: $(objpfx)libpthread.so
--- libc/linuxthreads/tst-cancel1.c.jj 2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel1.c 2002-11-26 23:49:41.000000000 +0100
@@ -0,0 +1,150 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+static int cntr;
+
+
+static void
+cleanup (void *arg)
+{
+ if (arg != (void *) 42l)
+ cntr = 42;
+ else
+ cntr = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+ int err;
+
+ pthread_cleanup_push (cleanup, (void *) 42l);
+
+ err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+ if (err != 0)
+ {
+ printf ("setcanceltype failed: %s\n", strerror (err));
+ exit (1);
+ }
+
+ err = pthread_mutex_unlock (&m2);
+ if (err != 0)
+ {
+ printf ("child: mutex_unlock failed: %s\n", strerror (err));
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&m1);
+ if (err != 0)
+ {
+ printf ("child: 1st mutex_lock failed: %s\n", strerror (err));
+ exit (1);
+ }
+
+ /* We should never come here. */
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int err;
+ pthread_t th;
+ int result = 0;
+ void *retval;
+
+ /* Get the mutexes. */
+ err = pthread_mutex_lock (&m1);
+ if (err != 0)
+ {
+ printf ("parent: 1st mutex_lock failed: %s\n", strerror (err));
+ return 1;
+ }
+ err = pthread_mutex_lock (&m2);
+ if (err != 0)
+ {
+ printf ("parent: 2nd mutex_lock failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ {
+ printf ("create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_mutex_lock (&m2);
+ if (err != 0)
+ {
+ printf ("parent: 3rd mutex_lock failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_cancel (th);
+ if (err != 0)
+ {
+ printf ("cancel failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_join (th, &retval);
+ if (err != 0)
+ {
+ printf ("join failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ if (retval != PTHREAD_CANCELED)
+ {
+ printf ("wrong return value: %p\n", retval);
+ result = 1;
+ }
+
+ if (cntr == 42)
+ {
+ puts ("cleanup handler called with wrong argument");
+ result = 1;
+ }
+ else if (cntr != 1)
+ {
+ puts ("cleanup handling not called");
+ result = 1;
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel2.c.jj 2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel2.c 2002-11-26 23:49:53.000000000 +0100
@@ -0,0 +1,100 @@
+/* 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 <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+ /* The buffer size must be larger than the pipe size so that the
+ write blocks. */
+ char buf[100000];
+
+ if (write (fd[1], buf, sizeof (buf)) == sizeof (buf))
+ {
+ puts ("write succeeded");
+ return (void *) 1l;
+ }
+
+ return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ void *r;
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGPIPE, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the write in the child to return. */
+ close (fd[0]);
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel3.c.jj 2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel3.c 2002-11-26 23:49:53.000000000 +0100
@@ -0,0 +1,98 @@
+/* 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 <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+ char buf[100];
+
+ if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
+ {
+ puts ("read succeeded");
+ return (void *) 1l;
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ void *r;
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGPIPE, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the read in the child to return. */
+ close (fd[0]);
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("result is wrong");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel4.c.jj 2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel4.c 2002-12-20 21:58:50.000000000 +0100
@@ -0,0 +1,461 @@
+/* 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. */
+
+/* NOTE: this tests functionality beyond POSIX. POSIX does not allow
+ exit to be called more than once. */
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+
+/* The following interfaces are defined to be cancellation points but
+ tests are not yet implemented:
+
+ accept() aio_suspend() clock_nanosleep()
+ close() connect() creat()
+ fcntl() fsync() getmsg()
+ getpmsg() lockf() mq_receive()
+ mq_send() mq_timedreceive() mq_timedsend()
+ msgrcv() msgsnd() msync()
+ open() pause()
+ pread() pthread_cond_timedwait()
+ pthread_cond_wait() pthread_join() pthread_testcancel()
+ putmsg() putpmsg() pwrite()
+ recv()
+ recvfrom() recvmsg()
+ sem_timedwait() sem_wait() send()
+ sendmsg() sendto() sigpause()
+ sigsuspend() sigtimedwait() sigwait()
+ sigwaitinfo() system()
+ tcdrain()
+
+ Since STREAMS are not supported in the standard Linux kernel there
+ is no need to test the STREAMS related functions.
+*/
+
+/* Pipe descriptors. */
+static int fds[2];
+
+/* Often used barrier for two threads. */
+static pthread_barrier_t b2;
+
+
+static void *
+tf_read (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ char buf[100];
+ ssize_t s = read (fds[0], buf, sizeof (buf));
+
+ printf ("%s: read returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_readv (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ char buf[100];
+ struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+ ssize_t s = readv (fds[0], iov, 1);
+
+ printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_write (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ char buf[100000];
+ memset (buf, '\0', sizeof (buf));
+ ssize_t s = write (fds[1], buf, sizeof (buf));
+
+ printf ("%s: write returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_writev (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ char buf[100000];
+ memset (buf, '\0', sizeof (buf));
+ struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+ ssize_t s = writev (fds[1], iov, 1);
+
+ printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_sleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sleep (10000000);
+
+ printf ("%s: sleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_usleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ usleep ((useconds_t) ULONG_MAX);
+
+ printf ("%s: usleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_nanosleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ struct timespec ts = { .tv_sec = 10000000, .tv_nsec = 0 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ printf ("%s: nanosleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_select (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ fd_set rfs;
+ FD_ZERO (&rfs);
+ FD_SET (fds[0], &rfs);
+
+ int s = select (fds[0] + 1, &rfs, NULL, NULL, NULL);
+
+ printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_pselect (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ fd_set rfs;
+ FD_ZERO (&rfs);
+ FD_SET (fds[0], &rfs);
+
+ int s = pselect (fds[0] + 1, &rfs, NULL, NULL, NULL, NULL);
+
+ printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_poll (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ struct pollfd rfs[1] = { [0] = { .fd = fds[0], .events = POLLIN } };
+
+ int s = poll (rfs, 1, -1);
+
+ printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_wait (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ sleep (10);
+ exit (0);
+ }
+
+ int s = wait (NULL);
+
+ printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_waitpid (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ sleep (10);
+ exit (0);
+ }
+
+ int s = waitpid (-1, NULL, 0);
+
+ printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_waitid (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ sleep (10);
+ exit (0);
+ }
+
+ siginfo_t si;
+ int s = waitid (P_PID, pid, &si, 0);
+
+ printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static struct
+{
+ void *(*tf) (void *);
+ int nb;
+} tests[] =
+{
+ { tf_read, 2 },
+ { tf_readv, 2 },
+ { tf_select, 2 },
+ { tf_pselect, 2 },
+ { tf_poll, 2 },
+ { tf_write, 2 },
+ { tf_writev, 2},
+ { tf_sleep, 2 },
+ { tf_usleep, 2 },
+ { tf_nanosleep, 2 },
+ { tf_wait, 2 },
+ { tf_waitid, 2 },
+ { tf_waitpid, 2 },
+};
+#define ntest_tf (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+ if (pipe (fds) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ int cnt;
+ for (cnt = 0; cnt < ntest_tf; ++cnt)
+ {
+ if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+ {
+ puts ("b2 init failed");
+ exit (1);
+ }
+
+ /* read(2) test. */
+ pthread_t th;
+ if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
+ {
+ printf ("create for round %d test failed\n", cnt);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ if (pthread_cancel (th) != 0)
+ {
+ printf ("cancel in round %d failed\n", cnt);
+ exit (1);
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("join in round %d failed\n", cnt);
+ exit (1);
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ printf ("thread in round %d not canceled\n", cnt);
+ exit (1);
+ }
+ printf ("test %d successful\n", cnt);
+
+ if (pthread_barrier_destroy (&b2) != 0)
+ {
+ puts ("barrier_destroy failed");
+ exit (1);
+ }
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/linuxthreads/tst-cancel5.c.jj 2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel5.c 2002-12-14 20:28:32.000000000 +0100
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
--- libc/linuxthreads/tst-cancel6.c.jj 2002-12-20 22:03:13.000000000 +0100
+++ libc/linuxthreads/tst-cancel6.c 2002-12-17 23:47:54.000000000 +0100
@@ -0,0 +1,79 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ char buf[100];
+ fgets (buf, sizeof (buf), arg);
+ /* This call should never return. */
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ FILE *fp = fdopen (fd[0], "r");
+ if (fp == NULL)
+ {
+ puts ("fdopen failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, fp) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("pthread_cancel failed");
+ return 1;
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ return r != PTHREAD_CANCELED;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/sysdeps/generic/libc-tls.c.jj 2002-12-10 15:08:54.000000000 +0100
+++ libc/sysdeps/generic/libc-tls.c 2002-12-20 20:37:00.000000000 +0100
@@ -135,8 +135,13 @@ __libc_setup_tls (size_t tcbsize, size_t
}
if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE)
- /* We do not need a TLS block and no thread descriptor. */
- return;
+ {
+ /* We do not need a TLS block and no thread descriptor. */
+#ifdef NONTLS_INIT_TP
+ NONTLS_INIT_TP;
+#endif
+ return;
+ }
/* We have to set up the TCB block which also (possibly) contains
@@ -249,4 +254,16 @@ __pthread_initialize_minimal (void)
{
__libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
}
+
+#elif defined NONTLS_INIT_TP
+
+/* This is the minimal initialization function used when libpthread is
+ not used. */
+void
+__attribute__ ((weak))
+__pthread_initialize_minimal (void)
+{
+ NONTLS_INIT_TP;
+}
+
#endif
--- libc/sysdeps/generic/libc-start.c.jj 2002-12-10 15:08:54.000000000 +0100
+++ libc/sysdeps/generic/libc-start.c 2002-12-20 22:00:08.000000000 +0100
@@ -32,7 +32,7 @@ extern void *__libc_stack_end;
#ifndef SHARED
# include <dl-osinfo.h>
extern void __pthread_initialize_minimal (void)
-# if !(USE_TLS - 0)
+# if !(USE_TLS - 0) && !defined NONTLS_INIT_TP
__attribute__ ((weak))
# endif
;
@@ -97,7 +97,7 @@ BP_SYM (__libc_start_main) (int (*main)
we need to setup errno. If there is no thread library and we
handle TLS the function is defined in the libc to initialized the
TLS handling. */
-# if !(USE_TLS - 0)
+# if !(USE_TLS - 0) && !defined NONTLS_INIT_TP
if (__pthread_initialize_minimal)
# endif
__pthread_initialize_minimal ();
--- libc/sysdeps/unix/common/pause.c.jj 2001-08-23 18:50:34.000000000 +0200
+++ libc/sysdeps/unix/common/pause.c 2002-12-20 21:33:08.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1996, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -18,7 +18,7 @@
#include <signal.h>
#include <unistd.h>
-
+#include <sysdep-cancel.h>
/* Suspend the process until a signal arrives.
This always returns -1 and sets errno to EINTR. */
@@ -26,6 +26,12 @@
int
__libc_pause (void)
{
- return __sigpause (__sigblock (0), 0);
+ if (SINGLE_THREAD_P)
+ return __sigpause (__sigblock (0), 0);
+
+ int oldtype = LIBC_CANCEL_ASYNC ();
+ int result = __sigpause (__sigblock (0), 0);
+ LIBC_CANCEL_RESET (oldtype);
+ return result;
}
weak_alias (__libc_pause, pause)
--- libc/sysdeps/unix/sysv/linux/ia64/sysdep.h.jj 2002-12-10 15:09:30.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/ia64/sysdep.h 2002-12-20 14:00:36.000000000 +0100
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
Based on code originally written by David Mosberger-Tang
@@ -83,7 +83,7 @@
#define PSEUDO(name, syscall_name, args) \
ENTRY(name) \
DO_CALL (SYS_ify(syscall_name)); \
- cmp.eq p6,p0=-1,r10;; \
+ cmp.eq p6,p0=-1,r10; \
(p6) br.cond.spnt.few __syscall_error;
#define DO_CALL(num) \
@@ -102,11 +102,98 @@
#else /* not __ASSEMBLER__ */
-/* Define a macro which expands into the inline wrapper code for a system
- call. */
-#if 0
+/* On IA-64 we have stacked registers for passing arguments. The
+ "out" registers end up being the called function's "in"
+ registers.
+
+ Also, since we have plenty of registers we have two return values
+ from a syscall. r10 is set to -1 on error, whilst r8 contains the
+ (non-negative) errno on error or the return value on success.
+ */
#undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...) __##name (args)
-#endif
+#define INLINE_SYSCALL(name, nr, args...) \
+ ({ \
+ register long _r8 asm ("r8"); \
+ register long _r10 asm ("r10"); \
+ register long _r15 asm ("r15") = __NR_##name; \
+ long _retval; \
+ LOAD_ARGS_##nr (args); \
+ __asm __volatile ("break %3;;\n\t" \
+ : "=r" (_r8), "=r" (_r10), "=r" (_r15) \
+ : "i" (__BREAK_SYSCALL), "2" (_r15) \
+ ASM_ARGS_##nr \
+ : "memory" ASM_CLOBBERS_##nr); \
+ _retval = _r8; \
+ if (_r10 == -1) \
+ { \
+ __set_errno (_retval); \
+ _retval = -1; \
+ } \
+ _retval; })
+
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, nr, args...) \
+ ({ \
+ register long _r8 asm ("r8"); \
+ register long _r10 asm ("r10"); \
+ register long _r15 asm ("r15") = __NR_##name; \
+ long _retval; \
+ LOAD_ARGS_##nr (args); \
+ __asm __volatile ("break %3;;\n\t" \
+ : "=r" (_r8), "=r" (_r10), "=r" (_r15) \
+ : "i" (__BREAK_SYSCALL), "2" (_r15) \
+ ASM_ARGS_##nr \
+ : "memory" ASM_CLOBBERS_##nr); \
+ _retval = _r8; \
+ if (_r10 == -1) \
+ _retval = -_retval; \
+ _retval; })
+
+#undef INTERNAL_SYSCALL_ERROR_P
+#define INTERNAL_SYSCALL_ERROR_P(val) ((unsigned long) (val) >= -4095UL)
+
+#undef INTERNAL_SYSCALL_ERRNO
+#define INTERNAL_SYSCALL_ERRNO(val) (-(val))
+
+#define LOAD_ARGS_0() do { } while (0)
+#define LOAD_ARGS_1(out0) \
+ register long _out0 asm ("out0") = (long) (out0); \
+ LOAD_ARGS_0 ()
+#define LOAD_ARGS_2(out0, out1) \
+ register long _out1 asm ("out1") = (long) (out1); \
+ LOAD_ARGS_1 (out0)
+#define LOAD_ARGS_3(out0, out1, out2) \
+ register long _out2 asm ("out2") = (long) (out2); \
+ LOAD_ARGS_2 (out0, out1)
+#define LOAD_ARGS_4(out0, out1, out2, out3) \
+ register long _out3 asm ("out3") = (long) (out3); \
+ LOAD_ARGS_3 (out0, out1, out2)
+#define LOAD_ARGS_5(out0, out1, out2, out3, out4) \
+ register long _out4 asm ("out4") = (long) (out4); \
+ LOAD_ARGS_4 (out0, out1, out2, out3)
+
+#define ASM_ARGS_0
+#define ASM_ARGS_1 ASM_ARGS_0, "r" (_out0)
+#define ASM_ARGS_2 ASM_ARGS_1, "r" (_out1)
+#define ASM_ARGS_3 ASM_ARGS_2, "r" (_out2)
+#define ASM_ARGS_4 ASM_ARGS_3, "r" (_out3)
+#define ASM_ARGS_5 ASM_ARGS_4, "r" (_out4)
+
+#define ASM_CLOBBERS_0 ASM_CLOBBERS_1, "out0"
+#define ASM_CLOBBERS_1 ASM_CLOBBERS_2, "out1"
+#define ASM_CLOBBERS_2 ASM_CLOBBERS_3, "out2"
+#define ASM_CLOBBERS_3 ASM_CLOBBERS_4, "out3"
+#define ASM_CLOBBERS_4 ASM_CLOBBERS_5, "out4"
+#define ASM_CLOBBERS_5 , "out5", "out6", "out7", \
+ /* Non-stacked integer registers, minus r8, r10, r15. */ \
+ "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \
+ "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \
+ "r28", "r29", "r30", "r31", \
+ /* Predicate registers. */ \
+ "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \
+ /* Non-rotating fp registers. */ \
+ "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ /* Branch registers. */ \
+ "b6", "b7"
#endif /* not __ASSEMBLER__ */
--- libc/nptl/Makefile.jj 2002-12-20 12:17:13.000000000 +0100
+++ libc/nptl/Makefile 2002-12-20 21:58:19.000000000 +0100
@@ -214,8 +214,10 @@ $(addprefix $(objpfx), \
$(tests) $(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)): \
- $(common-objpfx)libc.so $(objpfx)libpthread.so \
+ $(objpfx)../libc.so $(objpfx)libpthread.so \
$(objpfx)libpthread_nonshared.a
$(addprefix $(objpfx),$(tests-static)): $(objpfx)libpthread.a
else
--- libc/nptl/tst-cancel4.c.jj 2002-11-26 23:50:02.000000000 +0100
+++ libc/nptl/tst-cancel4.c 2002-12-20 21:58:50.000000000 +0100
@@ -113,7 +113,7 @@ tf_write (void *arg)
exit (1);
}
- char buf[10000];
+ char buf[100000];
memset (buf, '\0', sizeof (buf));
ssize_t s = write (fds[1], buf, sizeof (buf));
@@ -133,7 +133,7 @@ tf_writev (void *arg)
exit (1);
}
- char buf[10000];
+ char buf[100000];
memset (buf, '\0', sizeof (buf));
struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
ssize_t s = writev (fds[1], iov, 1);
@@ -172,7 +172,7 @@ tf_usleep (void *arg)
exit (1);
}
- usleep (ULONG_MAX);
+ usleep ((useconds_t) ULONG_MAX);
printf ("%s: usleep returns\n", __FUNCTION__);
Jakub
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |