mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-01 10:06:57 +03:00
htl: Enable more tests
* htl/Makefile: Remove rules adding libpthread.so and libpthread.a to link lines. * nptl/Makefile: Move rules adding libpthread.so and libpthread.a to link lines to... * sysdeps/pthread/Makefile: ... here. * nptl/eintr.c, tst-align.c tst-align3.c tst-atfork1.c tst-backtrace1.c tst-bad-schedattr.c tst-cancel-self-canceltype.c tst-cancel-self-cleanup.c tst-cancel-self-testcancel.c tst-cancel1.c tst-cancel10.c tst-cancel12.c tst-cancel14.c tst-cancel15.c tst-cancel18.c tst-cancel19.c tst-cancel2.c tst-cancel22.c tst-cancel23.c tst-cancel26.c tst-cancel27.c tst-cancel28.c tst-cancel3.c tst-cancel8.c tst-cancelx1.c tst-cancelx10.c tst-cancelx12.c tst-cancelx14.c tst-cancelx15.c tst-cancelx18.c tst-cancelx2.c tst-cancelx3.c tst-cancelx8.c tst-cleanup0.c tst-cleanup0.expect tst-cleanup1.c tst-cleanup2.c tst-cleanup3.c tst-cleanupx0.c tst-cleanupx0.expect tst-cleanupx1.c tst-cleanupx2.c tst-cleanupx3.c tst-clock1.c tst-create-detached.c tst-detach1.c tst-eintr2.c tst-eintr3.c tst-eintr4.c tst-eintr5.c tst-exec1.c tst-exec2.c tst-exec3.c tst-exit1.c tst-exit2.c tst-exit3.c tst-flock1.c tst-fork1.c tst-fork2.c tst-fork3.c tst-fork4.c tst-getpid3.c tst-kill1.c tst-kill2.c tst-kill3.c tst-kill4.c tst-kill5.c tst-kill6.c tst-locale1.c tst-locale2.c tst-memstream.c tst-popen1.c tst-raise1.c tst-sem5.c tst-setuid3.c tst-signal4.c tst-signal5.c tst-signal6.c tst-signal8.c tst-stack1.c tst-stdio1.c tst-stdio2.c tst-sysconf.c tst-tls1.c tst-tls2.c tst-tsd1.c tst-tsd2.c tst-tsd5.c tst-tsd6.c tst-umask1.c tst-unload.c tst-unwind-thread.c tst-vfork1.c tst-vfork1x.c tst-vfork2.c tst-vfork2x.c: Move tests to... * sysdeps/pthread: ... here. Rename tst-popen1.c -> tst-pt-popen1.c tst-align.c -> tst-pt-align.c tst-align3.c -> tst-pt-align3.c tst-sysconf.c -> tst-pt-sysconf.c tst-tls1.c -> tst-pt-tls1.c tst-tls2.c -> tst-pt-tls2.c tst-vfork1.c -> tst-pt-vfork1.c tst-vfork2.c -> tst-pt-vfork2.c to avoid conflicting with libio/tst-popen1.c, elf/tst-align.c, posix/tst-sysconf.c, elf/tst-tls1.c, elf/tst-tls2.c, posix/tst-vfork1.c, posix/tst-vfork2.c. * nptl/Makefile: Move corresponding tests references and special rules to... * sysdeps/pthread/Makefile: ... here. * sysdeps/pthread/tst-stack1.c (do_test): Do not clamp stack size to PTHREAD_STACK_MIN if not defined. Tested on linux-x86_64 and hurd-i386
This commit is contained in:
@ -42,23 +42,48 @@ libpthread-routines += thrd_create thrd_detach thrd_exit thrd_join \
|
||||
tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
|
||||
tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
|
||||
tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
|
||||
\
|
||||
tst-abstime \
|
||||
tst-pt-align tst-pt-align3 \
|
||||
tst-attr1 \
|
||||
tst-backtrace1 \
|
||||
tst-bad-schedattr \
|
||||
tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
|
||||
tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
|
||||
tst-basic7 \
|
||||
tst-cancel-self-canceltype tst-cancel-self-testcancel \
|
||||
tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel8 tst-cancel10 \
|
||||
tst-cancel12 tst-cancel14 tst-cancel15 tst-cancel18 tst-cancel19 \
|
||||
tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \
|
||||
tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
|
||||
tst-clock1 \
|
||||
tst-cond-except \
|
||||
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-cond23 tst-cond24 tst-cond25 tst-cond27 \
|
||||
tst-cond-except \
|
||||
tst-create-detached \
|
||||
tst-detach1 \
|
||||
tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
|
||||
tst-exec1 tst-exec2 tst-exec3 \
|
||||
tst-exit1 tst-exit2 tst-exit3 \
|
||||
tst-flock1 \
|
||||
tst-fork1 tst-fork2 tst-fork3 tst-fork4 \
|
||||
tst-atfork1 \
|
||||
tst-getpid3 \
|
||||
tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
|
||||
tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \
|
||||
tst-join14 \
|
||||
tst-key1 tst-key2 tst-key3 tst-key4 \
|
||||
tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
|
||||
tst-locale1 tst-locale2 \
|
||||
tst-memstream \
|
||||
tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \
|
||||
tst-mutex5 tst-mutex6 tst-mutex7 tst-mutex7robust tst-mutex9 \
|
||||
tst-mutex10 tst-mutex11 tst-pthread-mutexattr \
|
||||
tst-once1 tst-once2 tst-once3 tst-once4 \
|
||||
tst-pt-popen1 \
|
||||
tst-raise1 \
|
||||
tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
|
||||
tst-robust6 tst-robust7 tst-robust9 tst-robust10 \
|
||||
tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock12 \
|
||||
@ -66,8 +91,79 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
|
||||
tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
|
||||
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
|
||||
tst-sem8 tst-sem9 tst-sem10 tst-sem14 tst-sem15 tst-sem16 \
|
||||
tst-setuid3 \
|
||||
tst-signal4 tst-signal5 tst-signal6 tst-signal8 \
|
||||
tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
|
||||
tst-abstime
|
||||
tst-stack1 \
|
||||
tst-stdio1 tst-stdio2 \
|
||||
tst-pt-sysconf \
|
||||
tst-pt-tls1 tst-pt-tls2 \
|
||||
tst-tsd1 tst-tsd2 tst-tsd5 tst-tsd6 \
|
||||
tst-umask1 \
|
||||
tst-unload \
|
||||
tst-unwind-thread \
|
||||
tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
|
||||
|
||||
|
||||
# Files which must not be linked with libpthread.
|
||||
tests-nolibpthread = tst-unload
|
||||
|
||||
# GCC-4.9 compiles 'sprintf(NULL, ...)' into UD2 on x86_64 without -fno-builtin
|
||||
CFLAGS-tst-cleanup2.c += -fno-builtin
|
||||
CFLAGS-tst-cleanupx2.c += -fno-builtin
|
||||
|
||||
tests += tst-cancelx2 tst-cancelx3 tst-cancelx8 tst-cancelx10 \
|
||||
tst-cancelx12 tst-cancelx14 tst-cancelx15 tst-cancelx18 \
|
||||
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
|
||||
|
||||
tests-static += tst-locale1 tst-locale2
|
||||
|
||||
tests += tst-cond11-static
|
||||
|
||||
|
||||
# These tests are linked with libc before libpthread
|
||||
tests-reverse += tst-cancel23 tst-vfork1x tst-vfork2x
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
ifeq ($(build-shared),yes)
|
||||
tests-special += $(objpfx)tst-cleanup0-cmp.out
|
||||
endif
|
||||
endif
|
||||
|
||||
# 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-cancelx8.c += -fexceptions
|
||||
CFLAGS-tst-cancelx10.c += -fexceptions
|
||||
CFLAGS-tst-cancelx12.c += -fexceptions
|
||||
CFLAGS-tst-cancelx14.c += -fexceptions
|
||||
CFLAGS-tst-cancelx15.c += -fexceptions
|
||||
CFLAGS-tst-cancelx18.c += -fexceptions
|
||||
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-pt-align.c += $(stack-align-test-flags)
|
||||
CFLAGS-tst-pt-align3.c += $(stack-align-test-flags)
|
||||
|
||||
tst-umask1-ARGS = $(objpfx)tst-umask1.temp
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
$(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0
|
||||
$(make-test-out) > $@ 2>&1; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-cleanup0-cmp.out: $(..)sysdeps/pthread/tst-cleanup0.expect $(objpfx)tst-cleanup0.out
|
||||
cmp $^ > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-cancel28: $(common-objpfx)rt/librt.so
|
||||
else
|
||||
$(objpfx)tst-cancel28: $(common-objpfx)rt/librt.a
|
||||
endif
|
||||
|
||||
|
||||
|
||||
tests-internal += tst-robust8
|
||||
|
||||
@ -88,4 +184,24 @@ $(objpfx)tst-join7.out: $(objpfx)tst-join7mod.so
|
||||
$(objpfx)tst-join7mod.so: $(shared-thread-library)
|
||||
LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
|
||||
|
||||
CFLAGS-tst-unwind-thread.c += -funwind-tables
|
||||
|
||||
# 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) $(tests-internal) $(xtests) $(test-srcs) $(tests-container))): \
|
||||
$(objpfx)libpthread.so
|
||||
$(objpfx)tst-unload: $(libdl)
|
||||
# $(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)../libc.so: $(common-objpfx)libc.so ;
|
||||
$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
|
||||
else
|
||||
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
|
||||
endif
|
||||
|
||||
endif
|
||||
|
86
sysdeps/pthread/eintr.c
Normal file
86
sysdeps/pthread/eintr.c
Normal file
@ -0,0 +1,86 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <support/xthread.h>
|
||||
#include <support/xsignal.h>
|
||||
#include <support/xthread.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);
|
||||
xpthread_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. */
|
||||
xpthread_create (NULL, eintr_source, thp);
|
||||
}
|
120
sysdeps/pthread/tst-atfork1.c
Normal file
120
sysdeps/pthread/tst-atfork1.c
Normal file
@ -0,0 +1,120 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
static int val;
|
||||
|
||||
|
||||
static void
|
||||
prepare1 (void)
|
||||
{
|
||||
val *= 2;
|
||||
}
|
||||
|
||||
static void
|
||||
prepare2 (void)
|
||||
{
|
||||
++val;
|
||||
}
|
||||
|
||||
static void
|
||||
parent1 (void)
|
||||
{
|
||||
val += 4;
|
||||
}
|
||||
|
||||
static void
|
||||
parent2 (void)
|
||||
{
|
||||
val *= 4;
|
||||
}
|
||||
|
||||
static void
|
||||
child1 (void)
|
||||
{
|
||||
val += 8;
|
||||
}
|
||||
|
||||
static void
|
||||
child2 (void)
|
||||
{
|
||||
val *= 8;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pid_t pid;
|
||||
int status = 0;
|
||||
|
||||
if (pthread_atfork (prepare1, parent1, child1) != 0)
|
||||
{
|
||||
puts ("1st atfork failed");
|
||||
exit (1);
|
||||
}
|
||||
if (pthread_atfork (prepare2, parent2, child2) != 0)
|
||||
{
|
||||
puts ("2nd atfork failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pid = fork ();
|
||||
if (pid == -1)
|
||||
{
|
||||
puts ("fork failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
/* Parent. */
|
||||
if (val != 24)
|
||||
{
|
||||
printf ("expected val=%d, got %d\n", 24, val);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
|
||||
{
|
||||
puts ("waitpid failed");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Child. */
|
||||
if (val != 80)
|
||||
{
|
||||
printf ("expected val=%d, got %d\n", 80, val);
|
||||
exit (2);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
85
sysdeps/pthread/tst-backtrace1.c
Normal file
85
sysdeps/pthread/tst-backtrace1.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* Copyright (C) 2004-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define BT_SIZE 64
|
||||
void *bt_array[BT_SIZE];
|
||||
int bt_cnt;
|
||||
|
||||
int
|
||||
do_bt (void)
|
||||
{
|
||||
bt_cnt = backtrace (bt_array, BT_SIZE);
|
||||
return 56;
|
||||
}
|
||||
|
||||
int
|
||||
call_do_bt (void)
|
||||
{
|
||||
return do_bt () + 1;
|
||||
}
|
||||
|
||||
void *
|
||||
tf (void *arg)
|
||||
{
|
||||
if (call_do_bt () != 57)
|
||||
return (void *) 1L;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL))
|
||||
{
|
||||
puts ("create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *res;
|
||||
if (pthread_join (th, &res))
|
||||
{
|
||||
puts ("join failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (res != NULL)
|
||||
{
|
||||
puts ("thread failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char **text = backtrace_symbols (bt_array, bt_cnt);
|
||||
if (text == NULL)
|
||||
{
|
||||
puts ("backtrace_symbols failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < bt_cnt; ++i)
|
||||
puts (text[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
97
sysdeps/pthread/tst-bad-schedattr.c
Normal file
97
sysdeps/pthread/tst-bad-schedattr.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* Test that pthread_create diagnoses invalid scheduling parameters.
|
||||
Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void *
|
||||
thread_function (void *arg)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#if !defined SCHED_FIFO || !defined SCHED_OTHER
|
||||
puts ("SCHED_FIFO or SCHED_OTHER not available at compile time");
|
||||
return 0; /* 77 */
|
||||
#else
|
||||
|
||||
int err;
|
||||
|
||||
#define TRY(func, arglist) \
|
||||
if ((err = func arglist) != 0) \
|
||||
{ \
|
||||
printf ("%s: %s\n", #func, strerror (err)); \
|
||||
return 2; \
|
||||
}
|
||||
|
||||
int fifo_max = sched_get_priority_max (SCHED_FIFO);
|
||||
if (fifo_max == -1)
|
||||
{
|
||||
assert (errno == ENOTSUP || errno == ENOSYS);
|
||||
puts ("SCHED_FIFO not supported, cannot test");
|
||||
return 0; /* 77 */
|
||||
}
|
||||
|
||||
int other_max = sched_get_priority_max (SCHED_OTHER);
|
||||
if (other_max == -1)
|
||||
{
|
||||
assert (errno == ENOTSUP || errno == ENOSYS);
|
||||
puts ("SCHED_OTHER not supported, cannot test");
|
||||
return 0; /* 77 */
|
||||
}
|
||||
|
||||
assert (fifo_max > other_max);
|
||||
|
||||
pthread_attr_t attr;
|
||||
TRY (pthread_attr_init, (&attr));
|
||||
TRY (pthread_attr_setinheritsched, (&attr, PTHREAD_EXPLICIT_SCHED));
|
||||
TRY (pthread_attr_setschedpolicy, (&attr, SCHED_FIFO));
|
||||
|
||||
/* This value is chosen so as to be valid for SCHED_FIFO but invalid for
|
||||
SCHED_OTHER. */
|
||||
struct sched_param param = { .sched_priority = other_max + 1 };
|
||||
TRY (pthread_attr_setschedparam, (&attr, ¶m));
|
||||
|
||||
TRY (pthread_attr_setschedpolicy, (&attr, SCHED_OTHER));
|
||||
|
||||
/* Now ATTR has a sched_param that is invalid for its policy. */
|
||||
pthread_t th;
|
||||
err = pthread_create (&th, &attr, &thread_function, NULL);
|
||||
if (err != EINVAL)
|
||||
{
|
||||
printf ("pthread_create returned %d (%s), expected %d (EINVAL: %s)\n",
|
||||
err, strerror (err), EINVAL, strerror (EINVAL));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
53
sysdeps/pthread/tst-cancel-self-canceltype.c
Normal file
53
sysdeps/pthread/tst-cancel-self-canceltype.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* Copyright (C) 2012-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "tst-cancel-self-cleanup.c"
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int ret = 0, should_fail = 0;
|
||||
|
||||
pthread_cleanup_push (cleanup, &should_fail);
|
||||
|
||||
if ((ret = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) != 0)
|
||||
{
|
||||
printf ("setcanceltype failed: %s\n", strerror (ret));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if ((ret = pthread_cancel (pthread_self ())) != 0)
|
||||
{
|
||||
printf ("cancel failed: %s\n", strerror (ret));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Wait to be canceled. Don't give any cancellation points to play with. */
|
||||
while (1);
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
23
sysdeps/pthread/tst-cancel-self-cleanup.c
Normal file
23
sysdeps/pthread/tst-cancel-self-cleanup.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* Copyright (C) 2012-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
static void
|
||||
cleanup (void *cleanup_should_fail)
|
||||
{
|
||||
printf ("Main thread got cancelled and is being cleaned up now\n");
|
||||
exit (*(int *)cleanup_should_fail);
|
||||
}
|
48
sysdeps/pthread/tst-cancel-self-testcancel.c
Normal file
48
sysdeps/pthread/tst-cancel-self-testcancel.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2012-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "tst-cancel-self-cleanup.c"
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int ret = 0, should_fail = 0;
|
||||
|
||||
pthread_cleanup_push (cleanup, &should_fail);
|
||||
if ((ret = pthread_cancel (pthread_self ())) != 0)
|
||||
{
|
||||
printf ("cancel failed: %s\n", strerror (ret));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_testcancel ();
|
||||
|
||||
printf ("Could not cancel self.\n");
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
162
sysdeps/pthread/tst-cancel1.c
Normal file
162
sysdeps/pthread/tst-cancel1.c
Normal file
@ -0,0 +1,162 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.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)
|
||||
{
|
||||
/* Ignore all signals. This must not have any effect on delivering
|
||||
the cancellation signal. */
|
||||
sigset_t ss;
|
||||
|
||||
sigfillset (&ss);
|
||||
|
||||
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("pthread_sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_cleanup_push (cleanup, (void *) 42l);
|
||||
|
||||
int err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("setcanceltype failed: %s\n", strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
/* The following code is not standard compliant: the mutex functions
|
||||
must not be called with asynchronous cancellation enabled. */
|
||||
|
||||
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"
|
125
sysdeps/pthread/tst-cancel10.c
Normal file
125
sysdeps/pthread/tst-cancel10.c
Normal file
@ -0,0 +1,125 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void
|
||||
cleanup (void *arg)
|
||||
{
|
||||
/* Just for fun. */
|
||||
if (pthread_cancel (pthread_self ()) != 0)
|
||||
{
|
||||
puts ("cleanup: cancel failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
printf ("cleanup for %ld\n", (long int) arg);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
long int n = (long int) arg;
|
||||
|
||||
pthread_cleanup_push (cleanup, arg);
|
||||
|
||||
if (pthread_setcanceltype ((n & 1) == 0
|
||||
? PTHREAD_CANCEL_DEFERRED
|
||||
: PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)
|
||||
{
|
||||
puts ("setcanceltype failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_cancel (pthread_self ()) != 0)
|
||||
{
|
||||
puts ("cancel failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_testcancel ();
|
||||
|
||||
/* We should never come here. */
|
||||
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_attr_t at;
|
||||
|
||||
if (pthread_attr_init (&at) != 0)
|
||||
{
|
||||
puts ("attr_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
|
||||
{
|
||||
puts ("attr_setstacksize failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define N 20
|
||||
int i;
|
||||
pthread_t th[N];
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy (&at) != 0)
|
||||
{
|
||||
puts ("attr_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
void *r;
|
||||
if (pthread_join (th[i], &r) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (r != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("thread not canceled");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
123
sysdeps/pthread/tst-cancel12.c
Normal file
123
sysdeps/pthread/tst-cancel12.c
Normal file
@ -0,0 +1,123 @@
|
||||
/* Test sem_wait cancellation for uncontended case.
|
||||
Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static pthread_barrier_t bar;
|
||||
static sem_t sem;
|
||||
|
||||
|
||||
static void
|
||||
cleanup (void *arg)
|
||||
{
|
||||
static int ncall;
|
||||
|
||||
if (++ncall != 1)
|
||||
{
|
||||
puts ("second call to cleanup");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_cleanup_push (cleanup, NULL);
|
||||
|
||||
int e = pthread_barrier_wait (&bar);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("error: tf: 1st barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* This call should be cancelable. */
|
||||
sem_wait (&sem);
|
||||
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_barrier_init (&bar, NULL, 2) != 0)
|
||||
{
|
||||
puts ("error: barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* A value higher than 0 will check for uncontended pthread cancellation,
|
||||
where the sem_wait operation will return immediatelly. */
|
||||
if (sem_init (&sem, 0, 1) != 0)
|
||||
{
|
||||
puts ("error: sem_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("error: create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("error: pthread_cancel failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&bar);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("error: 1st barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
if (pthread_join (th, &r) != 0)
|
||||
{
|
||||
puts ("error: pthread_join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (r != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("error: thread not canceled");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
133
sysdeps/pthread/tst-cancel14.c
Normal file
133
sysdeps/pthread/tst-cancel14.c
Normal file
@ -0,0 +1,133 @@
|
||||
/* Test sem_timedwait cancellation for uncontended case.
|
||||
Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
static pthread_barrier_t bar;
|
||||
static sem_t sem;
|
||||
|
||||
|
||||
static void
|
||||
cleanup (void *arg)
|
||||
{
|
||||
static int ncall;
|
||||
|
||||
if (++ncall != 1)
|
||||
{
|
||||
puts ("second call to cleanup");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_cleanup_push (cleanup, NULL);
|
||||
|
||||
int e = pthread_barrier_wait (&bar);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("error: tf: 1st barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
(void) gettimeofday (&tv, NULL);
|
||||
|
||||
struct timespec ts;
|
||||
TIMEVAL_TO_TIMESPEC (&tv, &ts);
|
||||
|
||||
/* Timeout in 5 seconds. */
|
||||
ts.tv_sec += 5;
|
||||
|
||||
/* This call should block and be cancelable. */
|
||||
sem_timedwait (&sem, &ts);
|
||||
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_barrier_init (&bar, NULL, 2) != 0)
|
||||
{
|
||||
puts ("error: barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (sem_init (&sem, 0, 1) != 0)
|
||||
{
|
||||
puts ("error: sem_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("error: create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Check whether cancellation is honored even before sem_timedwait does
|
||||
anything. */
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("error: 1st cancel failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&bar);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("1st barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
if (pthread_join (th, &r) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (r != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("thread not canceled");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
138
sysdeps/pthread/tst-cancel15.c
Normal file
138
sysdeps/pthread/tst-cancel15.c
Normal file
@ -0,0 +1,138 @@
|
||||
/* Test sem_timedwait cancellation for contended case.
|
||||
Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
static pthread_barrier_t bar;
|
||||
static sem_t sem;
|
||||
|
||||
|
||||
static void
|
||||
cleanup (void *arg)
|
||||
{
|
||||
static int ncall;
|
||||
|
||||
if (++ncall != 1)
|
||||
{
|
||||
puts ("second call to cleanup");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
int e;
|
||||
|
||||
pthread_cleanup_push (cleanup, NULL);
|
||||
|
||||
e = pthread_barrier_wait (&bar);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("error: tf: 1st barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
(void) gettimeofday (&tv, NULL);
|
||||
|
||||
struct timespec ts;
|
||||
TIMEVAL_TO_TIMESPEC (&tv, &ts);
|
||||
|
||||
/* Timeout in 5 seconds. */
|
||||
ts.tv_sec += 5;
|
||||
|
||||
/* This call should block and be cancelable. */
|
||||
errno = 0;
|
||||
e = sem_timedwait (&sem, &ts);
|
||||
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_barrier_init (&bar, NULL, 2) != 0)
|
||||
{
|
||||
puts ("error: barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (sem_init (&sem, 0, 0) != 0)
|
||||
{
|
||||
puts ("error: sem_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("error: create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&bar);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("error: 1st barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Give the child a chance to go to sleep in sem_wait. */
|
||||
sleep (1);
|
||||
|
||||
/* Check whether cancellation is honored when waiting in sem_timedwait. */
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("error: 1st cancel failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
if (pthread_join (th, &r) != 0)
|
||||
{
|
||||
puts ("error: join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (r != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("error: thread not canceled");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
173
sysdeps/pthread/tst-cancel18.c
Normal file
173
sysdeps/pthread/tst-cancel18.c
Normal file
@ -0,0 +1,173 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static pthread_barrier_t b;
|
||||
|
||||
|
||||
/* Cleanup handling test. */
|
||||
static int cl_called;
|
||||
|
||||
static void
|
||||
cl (void *arg)
|
||||
{
|
||||
++cl_called;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
int r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_cleanup_push (cl, NULL);
|
||||
|
||||
struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
|
||||
TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts));
|
||||
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
puts ("clock_nanosleep returned");
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("1st create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
|
||||
while (nanosleep (&ts, &ts) != 0)
|
||||
continue;
|
||||
|
||||
puts ("going to cancel in-time");
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("1st cancel failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *status;
|
||||
if (pthread_join (th, &status) != 0)
|
||||
{
|
||||
puts ("1st join failed");
|
||||
return 1;
|
||||
}
|
||||
if (status != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("1st thread not canceled");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cl_called == 0)
|
||||
{
|
||||
puts ("cleanup handler not called");
|
||||
return 1;
|
||||
}
|
||||
if (cl_called > 1)
|
||||
{
|
||||
puts ("cleanup handler called more than once");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts ("in-time cancellation succeeded");
|
||||
|
||||
|
||||
cl_called = 0;
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("2nd create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts ("going to cancel early");
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("2nd cancel failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_join (th, &status) != 0)
|
||||
{
|
||||
puts ("2nd join failed");
|
||||
return 1;
|
||||
}
|
||||
if (status != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("2nd thread not canceled");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cl_called == 0)
|
||||
{
|
||||
printf ("cleanup handler not called\n");
|
||||
return 1;
|
||||
}
|
||||
if (cl_called > 1)
|
||||
{
|
||||
printf ("cleanup handler called more than once\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts ("early cancellation succeeded");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
285
sysdeps/pthread/tst-cancel19.c
Normal file
285
sysdeps/pthread/tst-cancel19.c
Normal file
@ -0,0 +1,285 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
handler (int sig)
|
||||
{
|
||||
}
|
||||
|
||||
static void __attribute__ ((noinline))
|
||||
clobber_lots_of_regs (void)
|
||||
{
|
||||
#define X1(n) long r##n = 10##n; __asm __volatile ("" : "+r" (r##n));
|
||||
#define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4)
|
||||
#define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4)
|
||||
X3(0) X3(1) X3(2) X3(3) X3(4)
|
||||
#undef X1
|
||||
#define X1(n) __asm __volatile ("" : : "r" (r##n));
|
||||
X3(0) X3(1) X3(2) X3(3) X3(4)
|
||||
#undef X1
|
||||
#undef X2
|
||||
#undef X3
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
int old, rc;
|
||||
int ret = 0;
|
||||
int fd[2];
|
||||
|
||||
rc = pipe (fd);
|
||||
if (rc < 0)
|
||||
error (EXIT_FAILURE, errno, "couldn't create pipe");
|
||||
|
||||
rc = pthread_create (&th, NULL, tf, NULL);
|
||||
if (rc)
|
||||
error (EXIT_FAILURE, rc, "couldn't create thread");
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "1st pthread_setcanceltype failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
{
|
||||
error (0, 0, "1st pthread_setcanceltype returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
close (fd[0]);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after close failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_DEFERRED)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after close returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
close (fd[1]);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after 2nd close failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sigaction (SIGALRM, &sa, NULL);
|
||||
|
||||
struct itimerval it;
|
||||
it.it_value.tv_sec = 1;
|
||||
it.it_value.tv_usec = 0;
|
||||
it.it_interval = it.it_value;
|
||||
setitimer (ITIMER_REAL, &it, NULL);
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
pause ();
|
||||
|
||||
memset (&it, 0, sizeof (it));
|
||||
setitimer (ITIMER_REAL, &it, NULL);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after pause failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_DEFERRED)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after pause returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
it.it_value.tv_sec = 1;
|
||||
it.it_value.tv_usec = 0;
|
||||
it.it_interval = it.it_value;
|
||||
setitimer (ITIMER_REAL, &it, NULL);
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
pause ();
|
||||
|
||||
memset (&it, 0, sizeof (it));
|
||||
setitimer (ITIMER_REAL, &it, NULL);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after 2nd pause failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
char fname[] = "/tmp/tst-cancel19-dir-XXXXXX\0foo/bar";
|
||||
char *enddir = strchr (fname, '\0');
|
||||
if (mkdtemp (fname) == NULL)
|
||||
{
|
||||
error (0, errno, "mkdtemp failed");
|
||||
ret = 1;
|
||||
}
|
||||
*enddir = '/';
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
creat (fname, 0400);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after creat failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_DEFERRED)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after creat returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
creat (fname, 0400);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after 2nd creat failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
open (fname, O_CREAT, 0400);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after open failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_DEFERRED)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after open returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
open (fname, O_CREAT, 0400);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after 2nd open failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
*enddir = '\0';
|
||||
rmdir (fname);
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
select (-1, NULL, NULL, NULL, NULL);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after select failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_DEFERRED)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after select returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
clobber_lots_of_regs ();
|
||||
select (-1, NULL, NULL, NULL, NULL);
|
||||
|
||||
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
if (rc)
|
||||
{
|
||||
error (0, rc, "pthread_setcanceltype after 2nd select failed");
|
||||
ret = 1;
|
||||
}
|
||||
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
{
|
||||
error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d",
|
||||
old);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
pthread_join (th, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
95
sysdeps/pthread/tst-cancel2.c
Normal file
95
sysdeps/pthread/tst-cancel2.c
Normal file
@ -0,0 +1,95 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#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];
|
||||
|
||||
while (write (fd[1], buf, sizeof (buf)) > 0);
|
||||
|
||||
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"
|
119
sysdeps/pthread/tst-cancel22.c
Normal file
119
sysdeps/pthread/tst-cancel22.c
Normal file
@ -0,0 +1,119 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
pthread_barrier_t b;
|
||||
int seen;
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
int old;
|
||||
int r = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
|
||||
if (r != 0)
|
||||
{
|
||||
puts ("setcancelstate failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
|
||||
TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
|
||||
}
|
||||
|
||||
seen = 1;
|
||||
pthread_setcancelstate (old, NULL);
|
||||
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
|
||||
TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("thread creation failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("cancel failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *status;
|
||||
if (pthread_join (th, &status) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
return 1;
|
||||
}
|
||||
if (status != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("thread not canceled");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrier_destroy (&b) != 0)
|
||||
{
|
||||
puts ("barrier_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (seen != 1)
|
||||
{
|
||||
puts ("thread cancelled when PTHREAD_CANCEL_DISABLED");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
1
sysdeps/pthread/tst-cancel23.c
Normal file
1
sysdeps/pthread/tst-cancel23.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel22.c"
|
68
sysdeps/pthread/tst-cancel26.c
Normal file
68
sysdeps/pthread/tst-cancel26.c
Normal file
@ -0,0 +1,68 @@
|
||||
/* Check for failure paths handling for cancellation points.
|
||||
Copyright (C) 2015-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Check that the cancel syscall points handles both the errno and return code
|
||||
correctly for invalid arguments. */
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
#ifdef SET_CANCEL_DISABLE
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
#endif
|
||||
|
||||
/* This is a cancellation point, but we should not be cancelled. */
|
||||
int r = write (-1, 0, 0);
|
||||
|
||||
if (r != -1 || errno != EBADF)
|
||||
{
|
||||
printf ("error: write returned %d, errno %d\n", r, errno);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("error: pthread_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_join (th, NULL) != 0)
|
||||
{
|
||||
puts ("error: pthread_join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
23
sysdeps/pthread/tst-cancel27.c
Normal file
23
sysdeps/pthread/tst-cancel27.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* Check for failure paths handling for cancellation points.
|
||||
Copyright (C) 2015-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Similar to tst-cancel26.c but with pthread cancel state set to
|
||||
PTHREAD_CANCEL_DISABLE. */
|
||||
|
||||
#define SET_CANCEL_DISABLE 1
|
||||
#include "tst-cancel26.c"
|
79
sysdeps/pthread/tst-cancel28.c
Normal file
79
sysdeps/pthread/tst-cancel28.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* Check if the thread created by POSIX timer using SIGEV_THREAD is
|
||||
cancellable.
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
static pthread_barrier_t barrier;
|
||||
static pthread_t timer_thread;
|
||||
|
||||
static void
|
||||
cl (void *arg)
|
||||
{
|
||||
xpthread_barrier_wait (&barrier);
|
||||
}
|
||||
|
||||
static void
|
||||
thread_handler (union sigval sv)
|
||||
{
|
||||
timer_thread = pthread_self ();
|
||||
|
||||
xpthread_barrier_wait (&barrier);
|
||||
|
||||
pthread_cleanup_push (cl, NULL);
|
||||
while (1)
|
||||
clock_nanosleep (CLOCK_REALTIME, 0, &(struct timespec) { 1, 0 }, NULL);
|
||||
pthread_cleanup_pop (0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
struct sigevent sev = { 0 };
|
||||
sev.sigev_notify = SIGEV_THREAD;
|
||||
sev.sigev_notify_function = &thread_handler;
|
||||
|
||||
timer_t timerid;
|
||||
TEST_COMPARE (timer_create (CLOCK_REALTIME, &sev, &timerid), 0);
|
||||
|
||||
xpthread_barrier_init (&barrier, NULL, 2);
|
||||
|
||||
struct itimerspec trigger = { 0 };
|
||||
trigger.it_value.tv_nsec = 1000000;
|
||||
TEST_COMPARE (timer_settime (timerid, 0, &trigger, NULL), 0);
|
||||
|
||||
xpthread_barrier_wait (&barrier);
|
||||
|
||||
xpthread_cancel (timer_thread);
|
||||
|
||||
xpthread_barrier_init (&barrier, NULL, 2);
|
||||
xpthread_barrier_wait (&barrier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A stall in cancellation is a regression. */
|
||||
#include <support/test-driver.c>
|
97
sysdeps/pthread/tst-cancel3.c
Normal file
97
sysdeps/pthread/tst-cancel3.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#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"
|
142
sysdeps/pthread/tst-cancel8.c
Normal file
142
sysdeps/pthread/tst-cancel8.c
Normal file
@ -0,0 +1,142 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static pthread_barrier_t bar;
|
||||
|
||||
static int global;
|
||||
|
||||
|
||||
static void
|
||||
cleanup (void *arg)
|
||||
{
|
||||
global = 1;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
/* Enable cancellation, but defer it. */
|
||||
if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
|
||||
{
|
||||
puts ("setcancelstate failed");
|
||||
exit (1);
|
||||
}
|
||||
if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
|
||||
{
|
||||
puts ("setcanceltype failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Add cleanup handler. */
|
||||
pthread_cleanup_push (cleanup, NULL);
|
||||
|
||||
/* Synchronize with the main thread. */
|
||||
int r = pthread_barrier_wait (&bar);
|
||||
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("tf: first barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* And again. Once this is done the main thread should have canceled
|
||||
this thread. */
|
||||
r = pthread_barrier_wait (&bar);
|
||||
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("tf: second barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Remove the cleanup handler without executing it. */
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
/* Now react on the cancellation. */
|
||||
pthread_testcancel ();
|
||||
|
||||
/* This call should never return. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (pthread_barrier_init (&bar, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("pthread_create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int r = pthread_barrier_wait (&bar);
|
||||
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("first barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("pthread_cancel failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = pthread_barrier_wait (&bar);
|
||||
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("second barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *result;
|
||||
if (pthread_join (th, &result) != 0)
|
||||
{
|
||||
puts ("pthread_join failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (result != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("thread was not canceled");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (global != 0)
|
||||
{
|
||||
puts ("cancellation handler has been called");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
1
sysdeps/pthread/tst-cancelx1.c
Normal file
1
sysdeps/pthread/tst-cancelx1.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel1.c"
|
1
sysdeps/pthread/tst-cancelx10.c
Normal file
1
sysdeps/pthread/tst-cancelx10.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel10.c"
|
1
sysdeps/pthread/tst-cancelx12.c
Normal file
1
sysdeps/pthread/tst-cancelx12.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel12.c"
|
1
sysdeps/pthread/tst-cancelx14.c
Normal file
1
sysdeps/pthread/tst-cancelx14.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel14.c"
|
1
sysdeps/pthread/tst-cancelx15.c
Normal file
1
sysdeps/pthread/tst-cancelx15.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel15.c"
|
1
sysdeps/pthread/tst-cancelx18.c
Normal file
1
sysdeps/pthread/tst-cancelx18.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel18.c"
|
1
sysdeps/pthread/tst-cancelx2.c
Normal file
1
sysdeps/pthread/tst-cancelx2.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel2.c"
|
1
sysdeps/pthread/tst-cancelx3.c
Normal file
1
sysdeps/pthread/tst-cancelx3.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel3.c"
|
1
sysdeps/pthread/tst-cancelx8.c
Normal file
1
sysdeps/pthread/tst-cancelx8.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cancel8.c"
|
74
sysdeps/pthread/tst-cleanup0.c
Normal file
74
sysdeps/pthread/tst-cleanup0.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static int global;
|
||||
|
||||
|
||||
static void
|
||||
ch (void *arg)
|
||||
{
|
||||
int val = (long int) arg;
|
||||
|
||||
printf ("ch (%d)\n", val);
|
||||
|
||||
global *= val;
|
||||
global += val;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
endfct (void)
|
||||
{
|
||||
/* We force exit right here. */
|
||||
_exit (global);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
atexit (endfct);
|
||||
|
||||
pthread_cancel (pthread_self ());
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 1l);
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 2l);
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 3l);
|
||||
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECTED_STATUS 9
|
||||
#include <support/test-driver.c>
|
3
sysdeps/pthread/tst-cleanup0.expect
Normal file
3
sysdeps/pthread/tst-cleanup0.expect
Normal file
@ -0,0 +1,3 @@
|
||||
ch (3)
|
||||
ch (2)
|
||||
ch (1)
|
100
sysdeps/pthread/tst-cleanup1.c
Normal file
100
sysdeps/pthread/tst-cleanup1.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static int global;
|
||||
|
||||
|
||||
static void
|
||||
ch (void *arg)
|
||||
{
|
||||
int val = (long int) arg;
|
||||
|
||||
printf ("ch (%d)\n", val);
|
||||
|
||||
global *= val;
|
||||
global += val;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
pthread_cancel (pthread_self ());
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 1l);
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 2l);
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 3l);
|
||||
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
write_message ("create failed\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
int e;
|
||||
if ((e = pthread_join (th, &r)) != 0)
|
||||
{
|
||||
printf ("join failed: %d\n", e);
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
if (r != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("thread not canceled");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (global != 9)
|
||||
{
|
||||
printf ("global = %d, expected 9\n", global);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
63
sysdeps/pthread/tst-cleanup2.c
Normal file
63
sysdeps/pthread/tst-cleanup2.c
Normal file
@ -0,0 +1,63 @@
|
||||
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Bao Duong <bduong@progress.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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
static sigjmp_buf jmpbuf;
|
||||
|
||||
static void
|
||||
sig_handler (int signo)
|
||||
{
|
||||
siglongjmp (jmpbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
char *p = NULL;
|
||||
/* gcc can overwrite the success written value by scheduling instructions
|
||||
around sprintf. It is allowed to do this since according to C99 the first
|
||||
argument of sprintf is a character array and NULL is not a valid character
|
||||
array. Mark the return value as volatile so that it gets reloaded on
|
||||
return. */
|
||||
volatile int ret = 0;
|
||||
|
||||
if (signal (SIGSEGV, &sig_handler) == SIG_ERR)
|
||||
{
|
||||
perror ("installing SIGSEGV handler");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts ("Attempting to sprintf to null ptr");
|
||||
if (setjmp (jmpbuf))
|
||||
{
|
||||
puts ("Exiting main...");
|
||||
return ret;
|
||||
}
|
||||
|
||||
sprintf (p, "This should segv\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
98
sysdeps/pthread/tst-cleanup3.c
Normal file
98
sysdeps/pthread/tst-cleanup3.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static int global;
|
||||
|
||||
|
||||
static void
|
||||
ch (void *arg)
|
||||
{
|
||||
int val = (long int) arg;
|
||||
|
||||
printf ("ch (%d)\n", val);
|
||||
|
||||
global *= val;
|
||||
global += val;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
pthread_cleanup_push (ch, (void *) 1l);
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 2l);
|
||||
|
||||
pthread_cleanup_push (ch, (void *) 3l);
|
||||
|
||||
pthread_exit ((void *) 1l);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
pthread_cleanup_pop (1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
write_message ("create failed\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
int e;
|
||||
if ((e = pthread_join (th, &r)) != 0)
|
||||
{
|
||||
printf ("join failed: %d\n", e);
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
if (r != (void *) 1l)
|
||||
{
|
||||
puts ("thread not canceled");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (global != 9)
|
||||
{
|
||||
printf ("global = %d, expected 9\n", global);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1
sysdeps/pthread/tst-cleanupx0.c
Normal file
1
sysdeps/pthread/tst-cleanupx0.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup0.c"
|
3
sysdeps/pthread/tst-cleanupx0.expect
Normal file
3
sysdeps/pthread/tst-cleanupx0.expect
Normal file
@ -0,0 +1,3 @@
|
||||
ch (3)
|
||||
ch (2)
|
||||
ch (1)
|
1
sysdeps/pthread/tst-cleanupx1.c
Normal file
1
sysdeps/pthread/tst-cleanupx1.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup1.c"
|
1
sysdeps/pthread/tst-cleanupx2.c
Normal file
1
sysdeps/pthread/tst-cleanupx2.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup2.c"
|
1
sysdeps/pthread/tst-cleanupx3.c
Normal file
1
sysdeps/pthread/tst-cleanupx3.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup3.c"
|
50
sysdeps/pthread/tst-clock1.c
Normal file
50
sysdeps/pthread/tst-clock1.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
|
||||
clockid_t cl;
|
||||
/* This is really only a linking-test here. */
|
||||
int e = pthread_getcpuclockid (pthread_self (), &cl);
|
||||
if (e != 0)
|
||||
{
|
||||
# if _POSIX_THREAD_CPUTIME == 0
|
||||
if (sysconf (_SC_THREAD_CPUTIME) >= 0)
|
||||
# endif
|
||||
{
|
||||
puts ("cpuclock advertized, but cannot get ID");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -1,162 +0,0 @@
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static pthread_barrier_t b;
|
||||
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
static void
|
||||
cl (void *arg)
|
||||
{
|
||||
pthread_mutex_unlock (&m);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
printf ("%s: mutex_lock failed\n", __func__);
|
||||
exit (1);
|
||||
}
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
printf ("%s: barrier_wait failed\n", __func__);
|
||||
exit (1);
|
||||
}
|
||||
pthread_cleanup_push (cl, NULL);
|
||||
/* We have to loop here because the cancellation might come after
|
||||
the cond_wait call left the cancelable area and is then waiting
|
||||
on the mutex. In this case the beginning of the second cond_wait
|
||||
call will cause the cancellation to happen. */
|
||||
do
|
||||
if (pthread_cond_wait (&c, &m) != 0)
|
||||
{
|
||||
printf ("%s: cond_wait failed\n", __func__);
|
||||
exit (1);
|
||||
}
|
||||
while (arg == NULL);
|
||||
pthread_cleanup_pop (0);
|
||||
if (pthread_mutex_unlock (&m) != 0)
|
||||
{
|
||||
printf ("%s: mutex_unlock failed\n", __func__);
|
||||
exit (1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("1st create failed");
|
||||
return 1;
|
||||
}
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("1st barrier_wait failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("1st mutex_lock failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_cond_signal (&c) != 0)
|
||||
{
|
||||
puts ("1st cond_signal failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("cancel failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_mutex_unlock (&m) != 0)
|
||||
{
|
||||
puts ("1st mutex_unlock failed");
|
||||
return 1;
|
||||
}
|
||||
void *res;
|
||||
if (pthread_join (th, &res) != 0)
|
||||
{
|
||||
puts ("1st join failed");
|
||||
return 1;
|
||||
}
|
||||
if (res != PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("first thread not canceled");
|
||||
status = 1;
|
||||
}
|
||||
|
||||
printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
|
||||
c.__data.__wseq, c.__data.__g1_start,
|
||||
c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
|
||||
c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
|
||||
c.__data.__g1_orig_size, c.__data.__wrefs);
|
||||
|
||||
if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
|
||||
{
|
||||
puts ("2nd create failed");
|
||||
return 1;
|
||||
}
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("2nd barrier_wait failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("2nd mutex_lock failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_cond_signal (&c) != 0)
|
||||
{
|
||||
puts ("2nd cond_signal failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_mutex_unlock (&m) != 0)
|
||||
{
|
||||
puts ("2nd mutex_unlock failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_join (th, &res) != 0)
|
||||
{
|
||||
puts ("2nd join failed");
|
||||
return 1;
|
||||
}
|
||||
if (res != NULL)
|
||||
{
|
||||
puts ("2nd thread canceled");
|
||||
status = 1;
|
||||
}
|
||||
|
||||
printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
|
||||
c.__data.__wseq, c.__data.__g1_start,
|
||||
c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
|
||||
c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
|
||||
c.__data.__g1_orig_size, c.__data.__wrefs);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -1,77 +0,0 @@
|
||||
/* Test unsupported/bad clocks passed to pthread_cond_clockwait.
|
||||
|
||||
Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <support/check.h>
|
||||
#include <support/timespec.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#define NOT_A_VALID_CLOCK 123456
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
xpthread_mutex_lock (&mut);
|
||||
|
||||
const struct timespec ts = make_timespec (0, 0);
|
||||
|
||||
/* These clocks are meaningless to sem_clockwait. */
|
||||
#if defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
CLOCK_PROCESS_CPUTIME_ID, &ts), EINVAL);
|
||||
#endif
|
||||
#if defined(CLOCK_THREAD_CPUTIME_ID)
|
||||
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
CLOCK_THREAD_CPUTIME_ID, &ts), EINVAL);
|
||||
#endif
|
||||
|
||||
/* These clocks might be meaningful, but are currently unsupported
|
||||
by pthread_cond_clockwait. */
|
||||
#if defined(CLOCK_REALTIME_COARSE)
|
||||
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
CLOCK_REALTIME_COARSE, &ts), EINVAL);
|
||||
#endif
|
||||
#if defined(CLOCK_MONOTONIC_RAW)
|
||||
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
CLOCK_MONOTONIC_RAW, &ts), EINVAL);
|
||||
#endif
|
||||
#if defined(CLOCK_MONOTONIC_COARSE)
|
||||
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
CLOCK_MONOTONIC_COARSE, &ts), EINVAL);
|
||||
#endif
|
||||
#if defined(CLOCK_BOOTTIME)
|
||||
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
CLOCK_BOOTTIME, &ts), EINVAL);
|
||||
#endif
|
||||
|
||||
/* This is a completely invalid clock. */
|
||||
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
|
||||
NOT_A_VALID_CLOCK, &ts), EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
138
sysdeps/pthread/tst-create-detached.c
Normal file
138
sysdeps/pthread/tst-create-detached.c
Normal file
@ -0,0 +1,138 @@
|
||||
/* Bug 20116: Test rapid creation of detached threads.
|
||||
Copyright (C) 2017-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* The goal of the test is to trigger a failure if the parent touches
|
||||
any part of the thread descriptor after the detached thread has
|
||||
exited. We test this by creating many detached threads with large
|
||||
stacks. The stacks quickly fill the the stack cache and subsequent
|
||||
threads will start to cause the thread stacks to be immediately
|
||||
unmapped to satisfy the stack cache max. With the stacks being
|
||||
unmapped the parent's read of any part of the thread descriptor will
|
||||
trigger a segfault. That segfault is what we are trying to cause,
|
||||
since any segfault is a defect in the implementation. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/resource.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
/* Number of threads to create. */
|
||||
enum { threads_to_create = 100000 };
|
||||
|
||||
/* Number of threads which should spawn other threads. */
|
||||
enum { creator_threads = 2 };
|
||||
|
||||
/* Counter of threads created so far. This is incremented by all the
|
||||
running creator threads. */
|
||||
static unsigned threads_created;
|
||||
|
||||
/* Thread callback which does nothing, so that the thread exits
|
||||
immediatedly. */
|
||||
static void *
|
||||
do_nothing (void *arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attribute indicating that the thread should be created in a detached
|
||||
fashion. */
|
||||
static pthread_attr_t detached;
|
||||
|
||||
/* Barrier to synchronize initialization. */
|
||||
static pthread_barrier_t barrier;
|
||||
|
||||
static void *
|
||||
creator_thread (void *arg)
|
||||
{
|
||||
int ret;
|
||||
xpthread_barrier_wait (&barrier);
|
||||
|
||||
while (true)
|
||||
{
|
||||
pthread_t thr;
|
||||
/* Thread creation will fail if the kernel does not free old
|
||||
threads quickly enough, so we do not report errors. */
|
||||
ret = pthread_create (&thr, &detached, do_nothing, NULL);
|
||||
if (ret == 0 && __atomic_add_fetch (&threads_created, 1, __ATOMIC_SEQ_CST)
|
||||
>= threads_to_create)
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Limit the size of the process, so that memory allocation will
|
||||
fail without impacting the entire system. */
|
||||
{
|
||||
struct rlimit limit;
|
||||
if (getrlimit (RLIMIT_AS, &limit) != 0)
|
||||
{
|
||||
printf ("FAIL: getrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
/* This limit, 800MB, is just a heuristic. Any value can be
|
||||
picked. */
|
||||
long target = 800 * 1024 * 1024;
|
||||
if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
|
||||
{
|
||||
limit.rlim_cur = target;
|
||||
if (setrlimit (RLIMIT_AS, &limit) != 0)
|
||||
{
|
||||
printf ("FAIL: setrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xpthread_attr_init (&detached);
|
||||
|
||||
xpthread_attr_setdetachstate (&detached, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
/* A large thread stack seems beneficial for reproducing a race
|
||||
condition in detached thread creation. The goal is to reach the
|
||||
limit of the runtime thread stack cache such that the detached
|
||||
thread's stack is unmapped after exit and causes a segfault when
|
||||
the parent reads the thread descriptor data stored on the the
|
||||
unmapped stack. */
|
||||
xpthread_attr_setstacksize (&detached, 16 * 1024 * 1024);
|
||||
|
||||
xpthread_barrier_init (&barrier, NULL, creator_threads);
|
||||
|
||||
pthread_t threads[creator_threads];
|
||||
|
||||
for (int i = 0; i < creator_threads; ++i)
|
||||
threads[i] = xpthread_create (NULL, creator_thread, NULL);
|
||||
|
||||
for (int i = 0; i < creator_threads; ++i)
|
||||
xpthread_join (threads[i]);
|
||||
|
||||
xpthread_attr_destroy (&detached);
|
||||
|
||||
xpthread_barrier_destroy (&barrier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TIMEOUT 100
|
||||
#include <support/test-driver.c>
|
55
sysdeps/pthread/tst-detach1.c
Normal file
55
sysdeps/pthread/tst-detach1.c
Normal file
@ -0,0 +1,55 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Give the child a chance to finish. */
|
||||
sleep (1);
|
||||
|
||||
if (pthread_detach (th) != 0)
|
||||
{
|
||||
puts ("detach failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
88
sysdeps/pthread/tst-eintr2.c
Normal file
88
sysdeps/pthread/tst-eintr2.c
Normal file
@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <support/check.h>
|
||||
#include <support/timespec.h>
|
||||
#include <support/xtime.h>
|
||||
|
||||
#include "eintr.c"
|
||||
|
||||
|
||||
static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
static void *
|
||||
tf1 (void *arg)
|
||||
{
|
||||
struct timespec ts = timespec_add (xclock_now (CLOCK_REALTIME),
|
||||
make_timespec (10000, 0));
|
||||
|
||||
/* This call must never return. */
|
||||
int e = pthread_mutex_timedlock (&m1, &ts);
|
||||
char buf[100];
|
||||
printf ("tf1: mutex_timedlock returned: %s\n",
|
||||
strerror_r (e, buf, sizeof (buf)));
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf2 (void *arg)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
TEST_COMPARE (pthread_mutex_lock (&m2), 0);
|
||||
TEST_COMPARE (pthread_mutex_unlock (&m2), 0);
|
||||
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
|
||||
nanosleep (&ts, NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
TEST_COMPARE (pthread_mutex_lock (&m1), 0);
|
||||
|
||||
setup_eintr (SIGUSR1, NULL);
|
||||
|
||||
char buf[100];
|
||||
xpthread_create (NULL, tf1, NULL);
|
||||
xpthread_create (NULL, tf2, NULL);
|
||||
|
||||
delayed_exit (3);
|
||||
/* This call must never return. */
|
||||
int e = pthread_mutex_lock (&m1);
|
||||
printf ("main: mutex_lock returned: %s\n",
|
||||
strerror_r (e, buf, sizeof (buf)));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
60
sysdeps/pthread/tst-eintr3.c
Normal file
60
sysdeps/pthread/tst-eintr3.c
Normal file
@ -0,0 +1,60 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
#include "eintr.c"
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
xpthread_mutex_lock (&m);
|
||||
/* This call must not return. */
|
||||
xpthread_mutex_lock (&m);
|
||||
|
||||
puts ("tf: mutex_lock returned");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t self = pthread_self ();
|
||||
|
||||
setup_eintr (SIGUSR1, &self);
|
||||
|
||||
pthread_t th = xpthread_create (NULL, tf, NULL);
|
||||
|
||||
delayed_exit (1);
|
||||
/* This call must never return. */
|
||||
xpthread_join (th);
|
||||
puts ("error: pthread_join returned");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
48
sysdeps/pthread/tst-eintr4.c
Normal file
48
sysdeps/pthread/tst-eintr4.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
#include "eintr.c"
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t self = pthread_self ();
|
||||
|
||||
setup_eintr (SIGUSR1, &self);
|
||||
|
||||
pthread_barrier_t b;
|
||||
xpthread_barrier_init (&b, NULL, 2);
|
||||
|
||||
delayed_exit (1);
|
||||
/* This call must never return. */
|
||||
xpthread_barrier_wait (&b);
|
||||
puts ("error: pthread_barrier_wait returned");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
63
sysdeps/pthread/tst-eintr5.c
Normal file
63
sysdeps/pthread/tst-eintr5.c
Normal file
@ -0,0 +1,63 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <support/check.h>
|
||||
#include <support/timespec.h>
|
||||
#include <support/xthread.h>
|
||||
#include <support/xtime.h>
|
||||
|
||||
#include "eintr.c"
|
||||
|
||||
|
||||
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
struct timespec ts = timespec_add (xclock_now (CLOCK_REALTIME),
|
||||
make_timespec (10000, 0));
|
||||
|
||||
/* This call must never return. */
|
||||
TEST_COMPARE (pthread_cond_timedwait (&c, &m, &ts), 0);
|
||||
FAIL_EXIT1 ("pthread_cond_timedwait returned unexpectedly\n");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
setup_eintr (SIGUSR1, NULL);
|
||||
|
||||
xpthread_create (NULL, tf, NULL);
|
||||
|
||||
delayed_exit (3);
|
||||
/* This call must never return. */
|
||||
xpthread_cond_wait (&c, &m);
|
||||
FAIL_RET ("error: pthread_cond_wait returned");
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
156
sysdeps/pthread/tst-exec1.c
Normal file
156
sysdeps/pthread/tst-exec1.c
Normal file
@ -0,0 +1,156 @@
|
||||
/* Simple exec test, only a thread in the parent.
|
||||
Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <support/xsignal.h>
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_t th = (pthread_t) arg;
|
||||
|
||||
if (pthread_join (th, NULL) == 0)
|
||||
{
|
||||
puts ("thread in parent joined!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("join in thread in parent returned!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int fd[2];
|
||||
if (pipe (fd) != 0)
|
||||
{
|
||||
puts ("pipe failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Not interested in knowing when the pipe is closed. */
|
||||
xsignal (SIGPIPE, SIG_IGN);
|
||||
|
||||
posix_spawn_file_actions_t a;
|
||||
if (posix_spawn_file_actions_init (&a) != 0)
|
||||
{
|
||||
puts ("spawn_file_actions_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (posix_spawn_file_actions_adddup2 (&a, fd[1], STDOUT_FILENO) != 0)
|
||||
{
|
||||
puts ("spawn_file_actions_adddup2 failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (posix_spawn_file_actions_addclose (&a, fd[0]) != 0)
|
||||
{
|
||||
puts ("spawn_file_actions_addclose");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pid_t pid;
|
||||
char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
|
||||
NULL };
|
||||
if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
|
||||
{
|
||||
puts ("spawn failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd[1]);
|
||||
|
||||
char buf[200];
|
||||
ssize_t n;
|
||||
bool seen_pid = false;
|
||||
while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
|
||||
{
|
||||
/* We only expect to read the PID. */
|
||||
char *endp;
|
||||
long int rpid = strtol (buf, &endp, 10);
|
||||
|
||||
if (*endp != '\n')
|
||||
{
|
||||
printf ("didn't parse whole line: \"%s\"\n", buf);
|
||||
exit (1);
|
||||
}
|
||||
if (endp == buf)
|
||||
{
|
||||
puts ("read empty line");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (rpid != pid)
|
||||
{
|
||||
printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (seen_pid)
|
||||
{
|
||||
puts ("found more than one PID line");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
seen_pid = true;
|
||||
}
|
||||
|
||||
close (fd[0]);
|
||||
|
||||
int status;
|
||||
int err = waitpid (pid, &status, 0);
|
||||
if (err != pid)
|
||||
{
|
||||
puts ("waitpid failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!seen_pid)
|
||||
{
|
||||
puts ("didn't get PID");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("read correct PID");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
151
sysdeps/pthread/tst-exec2.c
Normal file
151
sysdeps/pthread/tst-exec2.c
Normal file
@ -0,0 +1,151 @@
|
||||
/* Thread with running thread calls exec.
|
||||
Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <support/xsignal.h>
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_t th = (pthread_t) arg;
|
||||
|
||||
if (pthread_join (th, NULL) == 0)
|
||||
{
|
||||
puts ("thread in parent joined!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("join in thread in parent returned!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int fd[2];
|
||||
if (pipe (fd) != 0)
|
||||
{
|
||||
puts ("pipe failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Not interested in knowing when the pipe is closed. */
|
||||
xsignal (SIGPIPE, SIG_IGN);
|
||||
|
||||
pid_t pid = fork ();
|
||||
if (pid == -1)
|
||||
{
|
||||
puts ("fork failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
/* Use the fd for stdout. This is kind of ugly because it
|
||||
substitutes the fd of stdout but we know what we are doing
|
||||
here... */
|
||||
if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
|
||||
{
|
||||
puts ("dup2 failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd[0]);
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
|
||||
|
||||
puts ("execl failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd[1]);
|
||||
|
||||
char buf[200];
|
||||
ssize_t n;
|
||||
bool seen_pid = false;
|
||||
while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
|
||||
{
|
||||
/* We only expect to read the PID. */
|
||||
char *endp;
|
||||
long int rpid = strtol (buf, &endp, 10);
|
||||
|
||||
if (*endp != '\n')
|
||||
{
|
||||
printf ("didn't parse whole line: \"%s\"\n", buf);
|
||||
exit (1);
|
||||
}
|
||||
if (endp == buf)
|
||||
{
|
||||
puts ("read empty line");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (rpid != pid)
|
||||
{
|
||||
printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (seen_pid)
|
||||
{
|
||||
puts ("found more than one PID line");
|
||||
exit (1);
|
||||
}
|
||||
seen_pid = true;
|
||||
}
|
||||
|
||||
close (fd[0]);
|
||||
|
||||
int status;
|
||||
int err = waitpid (pid, &status, 0);
|
||||
if (err != pid)
|
||||
{
|
||||
puts ("waitpid failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!seen_pid)
|
||||
{
|
||||
puts ("didn't get PID");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
149
sysdeps/pthread/tst-exec3.c
Normal file
149
sysdeps/pthread/tst-exec3.c
Normal file
@ -0,0 +1,149 @@
|
||||
/* Thread calls exec.
|
||||
Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <support/xsignal.h>
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
|
||||
|
||||
puts ("execl failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int fd[2];
|
||||
if (pipe (fd) != 0)
|
||||
{
|
||||
puts ("pipe failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Not interested in knowing when the pipe is closed. */
|
||||
xsignal (SIGPIPE, SIG_IGN);
|
||||
|
||||
pid_t pid = fork ();
|
||||
if (pid == -1)
|
||||
{
|
||||
puts ("fork failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
/* Use the fd for stdout. This is kind of ugly because it
|
||||
substitutes the fd of stdout but we know what we are doing
|
||||
here... */
|
||||
if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
|
||||
{
|
||||
puts ("dup2 failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd[0]);
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_join (th, NULL) == 0)
|
||||
{
|
||||
puts ("join succeeded!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("join returned!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd[1]);
|
||||
|
||||
char buf[200];
|
||||
ssize_t n;
|
||||
bool seen_pid = false;
|
||||
while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
|
||||
{
|
||||
/* We only expect to read the PID. */
|
||||
char *endp;
|
||||
long int rpid = strtol (buf, &endp, 10);
|
||||
|
||||
if (*endp != '\n')
|
||||
{
|
||||
printf ("didn't parse whole line: \"%s\"\n", buf);
|
||||
exit (1);
|
||||
}
|
||||
if (endp == buf)
|
||||
{
|
||||
puts ("read empty line");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (rpid != pid)
|
||||
{
|
||||
printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (seen_pid)
|
||||
{
|
||||
puts ("found more than one PID line");
|
||||
exit (1);
|
||||
}
|
||||
seen_pid = true;
|
||||
}
|
||||
|
||||
close (fd[0]);
|
||||
|
||||
int status;
|
||||
int err = waitpid (pid, &status, 0);
|
||||
if (err != pid)
|
||||
{
|
||||
puts ("waitpid failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!seen_pid)
|
||||
{
|
||||
puts ("didn't get PID");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
78
sysdeps/pthread/tst-exit1.c
Normal file
78
sysdeps/pthread/tst-exit1.c
Normal file
@ -0,0 +1,78 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* NOTE: this tests functionality beyond POSIX. POSIX does not allow
|
||||
exit to be called more than once. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static pthread_barrier_t b;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
int r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Do nothing. */
|
||||
if (pthread_join (th, NULL) == 0)
|
||||
{
|
||||
puts ("join succeeded!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("join returned!?");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
42
sysdeps/pthread/tst-exit2.c
Normal file
42
sysdeps/pthread/tst-exit2.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
while (1)
|
||||
sleep (100);
|
||||
|
||||
/* NOTREACHED */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
int e = pthread_create (&th, NULL, tf, NULL);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("create failed: %s\n", strerror (e));
|
||||
return 1;
|
||||
}
|
||||
|
||||
delayed_exit (1);
|
||||
|
||||
/* Terminate only this thread. */
|
||||
pthread_exit (NULL);
|
||||
|
||||
/* NOTREACHED */
|
||||
return 1;
|
||||
}
|
83
sysdeps/pthread/tst-exit3.c
Normal file
83
sysdeps/pthread/tst-exit3.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static pthread_barrier_t b;
|
||||
|
||||
|
||||
static void *
|
||||
tf2 (void *arg)
|
||||
{
|
||||
while (1)
|
||||
sleep (100);
|
||||
|
||||
/* NOTREACHED */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
e = pthread_create (&th, NULL, tf2, NULL);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("create failed: %s\n", strerror (e));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Terminate only this thread. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_create (&th, NULL, tf, NULL);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("create failed: %s\n", strerror (e));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
delayed_exit (3);
|
||||
|
||||
/* Terminate only this thread. */
|
||||
pthread_exit (NULL);
|
||||
|
||||
/* NOTREACHED */
|
||||
return 1;
|
||||
}
|
92
sysdeps/pthread/tst-flock1.c
Normal file
92
sysdeps/pthread/tst-flock1.c
Normal file
@ -0,0 +1,92 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
|
||||
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static int fd;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
if (flock (fd, LOCK_SH | LOCK_NB) != 0)
|
||||
{
|
||||
puts ("second flock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
char tmp[] = "/tmp/tst-flock1-XXXXXX";
|
||||
|
||||
fd = mkstemp (tmp);
|
||||
if (fd == -1)
|
||||
{
|
||||
puts ("mkstemp failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
unlink (tmp);
|
||||
|
||||
write (fd, "foobar xyzzy", 12);
|
||||
|
||||
if (flock (fd, LOCK_EX | LOCK_NB) != 0)
|
||||
{
|
||||
puts ("first flock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_mutex_lock (&lock);
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("pthread_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_mutex_lock (&lock);
|
||||
|
||||
void *result;
|
||||
if (pthread_join (th, &result) != 0)
|
||||
{
|
||||
puts ("pthread_join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
return result != NULL;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
121
sysdeps/pthread/tst-fork1.c
Normal file
121
sysdeps/pthread/tst-fork1.c
Normal file
@ -0,0 +1,121 @@
|
||||
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Roland McGrath <roland@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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static void *
|
||||
thread_function (void * arg)
|
||||
{
|
||||
int i = (intptr_t) arg;
|
||||
int status;
|
||||
pid_t pid;
|
||||
pid_t pid2;
|
||||
|
||||
pid = fork ();
|
||||
switch (pid)
|
||||
{
|
||||
case 0:
|
||||
printf ("%ld for %d\n", (long int) getpid (), i);
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 * i };
|
||||
nanosleep (&ts, NULL);
|
||||
_exit (i);
|
||||
break;
|
||||
case -1:
|
||||
printf ("fork: %m\n");
|
||||
return (void *) 1l;
|
||||
break;
|
||||
}
|
||||
|
||||
pid2 = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
|
||||
if (pid2 != pid)
|
||||
{
|
||||
printf ("waitpid returned %ld, expected %ld\n",
|
||||
(long int) pid2, (long int) pid);
|
||||
return (void *) 1l;
|
||||
}
|
||||
|
||||
printf ("%ld with %d, expected %d\n",
|
||||
(long int) pid, WEXITSTATUS (status), i);
|
||||
|
||||
return WEXITSTATUS (status) == i ? NULL : (void *) 1l;
|
||||
}
|
||||
|
||||
#define N 5
|
||||
static const int t[N] = { 7, 6, 5, 4, 3 };
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th[N];
|
||||
int i;
|
||||
int result = 0;
|
||||
pthread_attr_t at;
|
||||
|
||||
if (pthread_attr_init (&at) != 0)
|
||||
{
|
||||
puts ("attr_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
|
||||
{
|
||||
puts ("attr_setstacksize failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_create (&th[i], NULL, thread_function,
|
||||
(void *) (intptr_t) t[i]) != 0)
|
||||
{
|
||||
printf ("creation of thread %d failed\n", i);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy (&at) != 0)
|
||||
{
|
||||
puts ("attr_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
void *v;
|
||||
if (pthread_join (th[i], &v) != 0)
|
||||
{
|
||||
printf ("join of thread %d failed\n", i);
|
||||
result = 1;
|
||||
}
|
||||
else if (v != NULL)
|
||||
{
|
||||
printf ("join %d successful, but child failed\n", i);
|
||||
result = 1;
|
||||
}
|
||||
else
|
||||
printf ("join %d successful\n", i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
89
sysdeps/pthread/tst-fork2.c
Normal file
89
sysdeps/pthread/tst-fork2.c
Normal file
@ -0,0 +1,89 @@
|
||||
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Roland McGrath <roland@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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
static pid_t initial_pid;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
if (getppid () != initial_pid)
|
||||
{
|
||||
printf ("getppid in thread returned %ld, expected %ld\n",
|
||||
(long int) getppid (), (long int) initial_pid);
|
||||
return (void *) -1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
initial_pid = getpid ();
|
||||
|
||||
pid_t child = fork ();
|
||||
if (child == 0)
|
||||
{
|
||||
if (getppid () != initial_pid)
|
||||
{
|
||||
printf ("first getppid returned %ld, expected %ld\n",
|
||||
(long int) getppid (), (long int) initial_pid);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("pthread_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *result;
|
||||
if (pthread_join (th, &result) != 0)
|
||||
{
|
||||
puts ("pthread_join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
exit (result == NULL ? 0 : 1);
|
||||
}
|
||||
else if (child == -1)
|
||||
{
|
||||
puts ("initial fork failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int status;
|
||||
if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
|
||||
{
|
||||
printf ("waitpid failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
108
sysdeps/pthread/tst-fork3.c
Normal file
108
sysdeps/pthread/tst-fork3.c
Normal file
@ -0,0 +1,108 @@
|
||||
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Roland McGrath <roland@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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
static pid_t initial_pid;
|
||||
|
||||
|
||||
static void *
|
||||
tf2 (void *arg)
|
||||
{
|
||||
if (getppid () != initial_pid)
|
||||
{
|
||||
printf ("getppid in thread returned %ld, expected %ld\n",
|
||||
(long int) getppid (), (long int) initial_pid);
|
||||
return (void *) -1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf1 (void *arg)
|
||||
{
|
||||
pid_t child = fork ();
|
||||
if (child == 0)
|
||||
{
|
||||
if (getppid () != initial_pid)
|
||||
{
|
||||
printf ("first getppid returned %ld, expected %ld\n",
|
||||
(long int) getppid (), (long int) initial_pid);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th2;
|
||||
if (pthread_create (&th2, NULL, tf2, NULL) != 0)
|
||||
{
|
||||
puts ("child: pthread_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *result;
|
||||
if (pthread_join (th2, &result) != 0)
|
||||
{
|
||||
puts ("pthread_join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
exit (result == NULL ? 0 : 1);
|
||||
}
|
||||
else if (child == -1)
|
||||
{
|
||||
puts ("initial fork failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int status;
|
||||
if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
|
||||
{
|
||||
printf ("waitpid failed: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
exit (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
initial_pid = getpid ();
|
||||
|
||||
pthread_t th1;
|
||||
if (pthread_create (&th1, NULL, tf1, NULL) != 0)
|
||||
{
|
||||
puts ("parent: pthread_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* This call should never return. */
|
||||
pthread_join (th1, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
64
sysdeps/pthread/tst-fork4.c
Normal file
64
sysdeps/pthread/tst-fork4.c
Normal file
@ -0,0 +1,64 @@
|
||||
/* Test of fork updating child universe's pthread structures.
|
||||
Copyright (C) 2003-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t me = pthread_self ();
|
||||
|
||||
pid_t pid = fork ();
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
printf ("fork: %m\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
int err = pthread_kill (me, SIGTERM);
|
||||
printf ("pthread_kill returned: %s\n", strerror (err));
|
||||
return 3;
|
||||
}
|
||||
|
||||
int status;
|
||||
errno = 0;
|
||||
if (wait (&status) != pid)
|
||||
printf ("wait failed: %m\n");
|
||||
else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGTERM)
|
||||
{
|
||||
printf ("child correctly died with SIGTERM\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
printf ("child died with bad status %#x\n", status);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
114
sysdeps/pthread/tst-getpid3.c
Normal file
114
sysdeps/pthread/tst-getpid3.c
Normal file
@ -0,0 +1,114 @@
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
static pid_t pid;
|
||||
|
||||
static void *
|
||||
pid_thread (void *arg)
|
||||
{
|
||||
if (pid != getpid ())
|
||||
{
|
||||
printf ("pid wrong in thread: should be %d, is %d\n",
|
||||
(int) pid, (int) getpid ());
|
||||
return (void *) 1L;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pid = getpid ();
|
||||
|
||||
pthread_t thr;
|
||||
int ret = pthread_create (&thr, NULL, pid_thread, NULL);
|
||||
if (ret)
|
||||
{
|
||||
printf ("pthread_create failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *thr_ret;
|
||||
ret = pthread_join (thr, &thr_ret);
|
||||
if (ret)
|
||||
{
|
||||
printf ("pthread_create failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
else if (thr_ret)
|
||||
{
|
||||
printf ("thread getpid failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t child = fork ();
|
||||
if (child == -1)
|
||||
{
|
||||
printf ("fork failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
else if (child == 0)
|
||||
{
|
||||
if (pid == getpid ())
|
||||
{
|
||||
puts ("pid did not change after fork");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pid = getpid ();
|
||||
ret = pthread_create (&thr, NULL, pid_thread, NULL);
|
||||
if (ret)
|
||||
{
|
||||
printf ("pthread_create failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = pthread_join (thr, &thr_ret);
|
||||
if (ret)
|
||||
{
|
||||
printf ("pthread_create failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
else if (thr_ret)
|
||||
{
|
||||
printf ("thread getpid failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int status;
|
||||
if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
|
||||
{
|
||||
puts ("waitpid failed");
|
||||
kill (child, SIGKILL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!WIFEXITED (status))
|
||||
{
|
||||
if (WIFSIGNALED (status))
|
||||
printf ("died from signal %s\n", strsignal (WTERMSIG (status)));
|
||||
else
|
||||
puts ("did not terminate correctly");
|
||||
return 1;
|
||||
}
|
||||
if (WEXITSTATUS (status) != 0)
|
||||
{
|
||||
printf ("exit code %d\n", WEXITSTATUS (status));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
99
sysdeps/pthread/tst-kill1.c
Normal file
99
sysdeps/pthread/tst-kill1.c
Normal file
@ -0,0 +1,99 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_barrier_t b;
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("child: mutex_lock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("child: barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* This call should never return. */
|
||||
pthread_cond_wait (&c, &m);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("mutex_lock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Send the thread a signal which it doesn't catch and which will
|
||||
cause the process to terminate. */
|
||||
if (pthread_kill (th, SIGUSR1) != 0)
|
||||
{
|
||||
puts ("kill failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* This call should never return. */
|
||||
pthread_join (th, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECTED_SIGNAL SIGUSR1
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
137
sysdeps/pthread/tst-kill2.c
Normal file
137
sysdeps/pthread/tst-kill2.c
Normal file
@ -0,0 +1,137 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_barrier_t b;
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
/* Block SIGUSR1. */
|
||||
sigset_t ss;
|
||||
|
||||
sigemptyset (&ss);
|
||||
sigaddset (&ss, SIGUSR1);
|
||||
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("child: sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("child: mutex_lock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("child: barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Compute timeout. */
|
||||
struct timeval tv;
|
||||
(void) gettimeofday (&tv, NULL);
|
||||
struct timespec ts;
|
||||
TIMEVAL_TO_TIMESPEC (&tv, &ts);
|
||||
/* Timeout: 1sec. */
|
||||
ts.tv_sec += 1;
|
||||
|
||||
/* This call should never return. */
|
||||
if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
|
||||
{
|
||||
puts ("cond_timedwait didn't time out");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("mutex_lock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Send the thread a signal which it has blocked. */
|
||||
if (pthread_kill (th, SIGUSR1) != 0)
|
||||
{
|
||||
puts ("kill failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock (&m) != 0)
|
||||
{
|
||||
puts ("mutex_unlock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
if (pthread_join (th, &r) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
if (r != NULL)
|
||||
{
|
||||
puts ("return value wrong");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
158
sysdeps/pthread/tst-kill3.c
Normal file
158
sysdeps/pthread/tst-kill3.c
Normal file
@ -0,0 +1,158 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
|
||||
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_barrier_t b;
|
||||
|
||||
|
||||
static void
|
||||
handler (int sig)
|
||||
{
|
||||
write_message ("handler called\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
/* Block SIGUSR1. */
|
||||
sigset_t ss;
|
||||
|
||||
sigemptyset (&ss);
|
||||
sigaddset (&ss, SIGUSR1);
|
||||
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("child: sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("child: mutex_lock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("child: barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Compute timeout. */
|
||||
struct timeval tv;
|
||||
(void) gettimeofday (&tv, NULL);
|
||||
struct timespec ts;
|
||||
TIMEVAL_TO_TIMESPEC (&tv, &ts);
|
||||
/* Timeout: 1sec. */
|
||||
ts.tv_sec += 1;
|
||||
|
||||
/* This call should never return. */
|
||||
if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
|
||||
{
|
||||
puts ("cond_timedwait didn't time out");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
struct sigaction sa;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_handler = handler;
|
||||
if (sigaction (SIGUSR1, &sa, NULL) != 0)
|
||||
{
|
||||
puts ("sigaction failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("mutex_lock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Send the thread a signal which it has blocked. */
|
||||
if (pthread_kill (th, SIGUSR1) != 0)
|
||||
{
|
||||
puts ("kill failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock (&m) != 0)
|
||||
{
|
||||
puts ("mutex_unlock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
if (pthread_join (th, &r) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
if (r != NULL)
|
||||
{
|
||||
puts ("return value wrong");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
90
sysdeps/pthread/tst-kill4.c
Normal file
90
sysdeps/pthread/tst-kill4.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_attr_t at;
|
||||
if (pthread_attr_init (&at) != 0)
|
||||
{
|
||||
puts ("attr_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Limit thread stack size, because if it is too large, pthread_join
|
||||
will free it immediately rather than put it into stack cache. */
|
||||
if (pthread_attr_setstacksize (&at, 2 * 1024 * 1024) != 0)
|
||||
{
|
||||
puts ("setstacksize failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, &at, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_attr_destroy (&at);
|
||||
|
||||
if (pthread_join (th, NULL) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* The following only works because we assume here something about
|
||||
the implementation. Namely, that the memory allocated for the
|
||||
thread descriptor is not going away, that the TID field is
|
||||
cleared and therefore the signal is sent to process 0, and that
|
||||
we can savely assume there is no other process with this ID at
|
||||
that time. */
|
||||
int e = pthread_kill (th, 0);
|
||||
if (e == 0)
|
||||
{
|
||||
puts ("pthread_kill succeeded");
|
||||
exit (1);
|
||||
}
|
||||
if (e != ESRCH)
|
||||
{
|
||||
puts ("pthread_kill didn't return ESRCH");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
49
sysdeps/pthread/tst-kill5.c
Normal file
49
sysdeps/pthread/tst-kill5.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
/* XXX This test might require architecture and system specific changes.
|
||||
There is no guarantee that this signal number is invalid. */
|
||||
int e = pthread_kill (pthread_self (), INT_MAX);
|
||||
if (e == 0)
|
||||
{
|
||||
puts ("kill didn't failed");
|
||||
exit (1);
|
||||
}
|
||||
if (e != EINVAL)
|
||||
{
|
||||
puts ("error not EINVAL");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
162
sysdeps/pthread/tst-kill6.c
Normal file
162
sysdeps/pthread/tst-kill6.c
Normal file
@ -0,0 +1,162 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static pthread_t receiver;
|
||||
static sem_t sem;
|
||||
static pthread_barrier_t b;
|
||||
|
||||
static void
|
||||
handler (int sig)
|
||||
{
|
||||
if (sig != SIGUSR1)
|
||||
{
|
||||
write_message ("wrong signal\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
if (pthread_self () != receiver)
|
||||
{
|
||||
write_message ("not the intended receiver\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
if (sem_post (&sem) != 0)
|
||||
{
|
||||
write_message ("sem_post failed\n");
|
||||
_exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("child: barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_handler = handler;
|
||||
if (sigaction (SIGUSR1, &sa, NULL) != 0)
|
||||
{
|
||||
puts ("sigaction failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#define N 20
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, N + 1) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_attr_t a;
|
||||
|
||||
if (pthread_attr_init (&a) != 0)
|
||||
{
|
||||
puts ("attr_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
|
||||
{
|
||||
puts ("attr_setstacksize failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th[N];
|
||||
int i;
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_create (&th[i], &a, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy (&a) != 0)
|
||||
{
|
||||
puts ("attr_destroy failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (sem_init (&sem, 0, 0) != 0)
|
||||
{
|
||||
puts ("sem_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (i = 0; i < N * 10; ++i)
|
||||
{
|
||||
receiver = th[i % N];
|
||||
|
||||
if (pthread_kill (receiver, SIGUSR1) != 0)
|
||||
{
|
||||
puts ("kill failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
|
||||
{
|
||||
puts ("sem_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_join (th[i], NULL) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
22
sysdeps/pthread/tst-locale1.c
Normal file
22
sysdeps/pthread/tst-locale1.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* Test that the thread-local locale works right in the main thread
|
||||
when statically linked. */
|
||||
|
||||
#include "../locale/tst-C-locale.c"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* This is never called, just here to get pthreads linked in. */
|
||||
int
|
||||
useless (void)
|
||||
{
|
||||
pthread_t th;
|
||||
pthread_create (&th, 0, (void *(*) (void *)) useless, 0);
|
||||
int result = 0;
|
||||
#ifdef SIGRTMIN
|
||||
/* This is to check __libc_current_sigrt* can be used in statically
|
||||
linked apps. */
|
||||
result = SIGRTMIN;
|
||||
#endif
|
||||
return result;
|
||||
}
|
15
sysdeps/pthread/tst-locale2.c
Normal file
15
sysdeps/pthread/tst-locale2.c
Normal file
@ -0,0 +1,15 @@
|
||||
/* Test that the thread-local locale works right in the main thread
|
||||
when statically linked. */
|
||||
|
||||
#include "../argp/tst-argp1.c"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* This is never called, just here to get pthreads linked in. */
|
||||
void *
|
||||
useless (void *a)
|
||||
{
|
||||
pthread_t th;
|
||||
pthread_create (&th, 0, useless, a);
|
||||
return NULL;
|
||||
}
|
101
sysdeps/pthread/tst-memstream.c
Normal file
101
sysdeps/pthread/tst-memstream.c
Normal file
@ -0,0 +1,101 @@
|
||||
/* Test for open_memstream locking.
|
||||
Copyright (C) 2017-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This test checks if concurrent writes to a FILE created with
|
||||
open_memstream are correctly interleaved without loss or corruption
|
||||
of data. Large number of concurrent fputc operations are used
|
||||
and in the end the bytes written to the memstream buffer are
|
||||
counted to see if they all got recorded.
|
||||
|
||||
This is a regression test to see if the single threaded stdio
|
||||
optimization broke multi-threaded open_memstream usage. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
enum
|
||||
{
|
||||
thread_count = 2,
|
||||
byte_count = 1000000,
|
||||
};
|
||||
|
||||
struct closure
|
||||
{
|
||||
FILE *fp;
|
||||
char b;
|
||||
};
|
||||
|
||||
static void *
|
||||
thread_func (void *closure)
|
||||
{
|
||||
struct closure *args = closure;
|
||||
|
||||
for (int i = 0; i < byte_count; ++i)
|
||||
fputc (args->b, args->fp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
size_t buffer_length = 0;
|
||||
FILE *fp = open_memstream (&buffer, &buffer_length);
|
||||
if (fp == NULL)
|
||||
FAIL_RET ("open_memstream: %m");
|
||||
|
||||
pthread_t threads[thread_count];
|
||||
struct closure args[thread_count];
|
||||
|
||||
for (int i = 0; i < thread_count; ++i)
|
||||
{
|
||||
args[i].fp = fp;
|
||||
args[i].b = 'A' + i;
|
||||
threads[i] = xpthread_create (NULL, thread_func, args + i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < thread_count; ++i)
|
||||
xpthread_join (threads[i]);
|
||||
|
||||
fclose (fp);
|
||||
|
||||
if (buffer_length != thread_count * byte_count)
|
||||
FAIL_RET ("unexpected number of written bytes: %zu (should be %d)",
|
||||
buffer_length, thread_count * byte_count);
|
||||
|
||||
/* Verify that each thread written its unique character byte_count times. */
|
||||
size_t counts[thread_count] = { 0, };
|
||||
for (size_t i = 0; i < buffer_length; ++i)
|
||||
{
|
||||
if (buffer[i] < 'A' || buffer[i] >= 'A' + thread_count)
|
||||
FAIL_RET ("written byte at %zu out of range: %d", i, buffer[i] & 0xFF);
|
||||
++counts[buffer[i] - 'A'];
|
||||
}
|
||||
for (int i = 0; i < thread_count; ++i)
|
||||
if (counts[i] != byte_count)
|
||||
FAIL_RET ("incorrect write count for thread %d: %zu (should be %d)", i,
|
||||
counts[i], byte_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TIMEOUT 100
|
||||
#include <support/test-driver.c>
|
70
sysdeps/pthread/tst-pt-align.c
Normal file
70
sysdeps/pthread/tst-pt-align.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <tst-stack-align.h>
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
puts ("in thread");
|
||||
|
||||
if (TEST_STACK_ALIGN ())
|
||||
ok = false;
|
||||
|
||||
return ok ? NULL : (void *) -1l;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
puts ("in main");
|
||||
|
||||
if (TEST_STACK_ALIGN ())
|
||||
ok = false;
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *res;
|
||||
if (pthread_join (th, &res) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (res != NULL)
|
||||
ok = false;
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
56
sysdeps/pthread/tst-pt-align3.c
Normal file
56
sysdeps/pthread/tst-pt-align3.c
Normal file
@ -0,0 +1,56 @@
|
||||
/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <tst-stack-align.h>
|
||||
|
||||
static bool ok = true;
|
||||
static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void
|
||||
once_test (void)
|
||||
{
|
||||
puts ("in once_test");
|
||||
|
||||
if (TEST_STACK_ALIGN ())
|
||||
ok = false;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
puts ("in main");
|
||||
|
||||
if (TEST_STACK_ALIGN ())
|
||||
ok = false;
|
||||
|
||||
if (pthread_once (&once, once_test))
|
||||
{
|
||||
puts ("pthread once failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
59
sysdeps/pthread/tst-pt-popen1.c
Normal file
59
sysdeps/pthread/tst-pt-popen1.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void *
|
||||
dummy (void *x)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char buf[sizeof "something\n"];
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
FILE *f;
|
||||
pthread_t p;
|
||||
int err;
|
||||
|
||||
f = popen ("echo something", "r");
|
||||
if (f == NULL)
|
||||
error (EXIT_FAILURE, errno, "popen failed");
|
||||
if (fgets (buf, sizeof (buf), f) == NULL)
|
||||
error (EXIT_FAILURE, 0, "fgets failed");
|
||||
if (strcmp (buf, "something\n"))
|
||||
error (EXIT_FAILURE, 0, "read wrong data");
|
||||
if (pclose (f))
|
||||
error (EXIT_FAILURE, errno, "pclose returned non-zero");
|
||||
if ((err = pthread_create (&p, NULL, dummy, NULL)))
|
||||
error (EXIT_FAILURE, err, "pthread_create failed");
|
||||
if ((err = pthread_join (p, NULL)))
|
||||
error (EXIT_FAILURE, err, "pthread_join failed");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
47
sysdeps/pthread/tst-pt-sysconf.c
Normal file
47
sysdeps/pthread/tst-pt-sysconf.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
puts ("We expect no limits");
|
||||
/* We have no fixed limit on the number of threads. Make sure the
|
||||
headers tell the right story. */
|
||||
#ifdef PTHREAD_THREADS_MAX
|
||||
printf ("Header report maximum number of threads = %lu\n",
|
||||
(unsigned long int) PTHREAD_THREADS_MAX);
|
||||
return 1;
|
||||
#else
|
||||
long int r = sysconf (_SC_THREAD_THREADS_MAX);
|
||||
if (r != -1)
|
||||
{
|
||||
printf ("sysconf(_SC_THREAD_THREADS_MAX) return %ld\n", r);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
119
sysdeps/pthread/tst-pt-tls1.c
Normal file
119
sysdeps/pthread/tst-pt-tls1.c
Normal file
@ -0,0 +1,119 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <support/support.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
struct test_s
|
||||
{
|
||||
__attribute__ ((aligned(0x20))) int a;
|
||||
__attribute__ ((aligned(0x200))) int b;
|
||||
};
|
||||
|
||||
#define INIT_A 1
|
||||
#define INIT_B 42
|
||||
/* Deliberately not static. */
|
||||
__thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) =
|
||||
{
|
||||
.a = INIT_A,
|
||||
.b = INIT_B
|
||||
};
|
||||
|
||||
/* Use noinline in combination with not static to ensure that the
|
||||
alignment check is really done. Otherwise it was optimized out! */
|
||||
__attribute__ ((noinline)) void
|
||||
check_alignment (const char *thr_name, const char *ptr_name,
|
||||
int *ptr, int alignment)
|
||||
{
|
||||
uintptr_t offset_aligment = ((uintptr_t) ptr) & (alignment - 1);
|
||||
if (offset_aligment)
|
||||
{
|
||||
FAIL_EXIT1 ("%s (%p) is not 0x%x-byte aligned in %s thread\n",
|
||||
ptr_name, ptr, alignment, thr_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_s (const char *thr_name)
|
||||
{
|
||||
if (s.a != INIT_A || s.b != INIT_B)
|
||||
FAIL_EXIT1 ("initial value of s in %s thread wrong\n", thr_name);
|
||||
|
||||
check_alignment (thr_name, "s.a", &s.a, 0x20);
|
||||
check_alignment (thr_name, "s.b", &s.b, 0x200);
|
||||
}
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
check_s ("child");
|
||||
|
||||
++s.a;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
check_s ("main");
|
||||
|
||||
pthread_attr_t a;
|
||||
|
||||
xpthread_attr_init (&a);
|
||||
|
||||
#define STACK_SIZE (1 * 1024 * 1024)
|
||||
xpthread_attr_setstacksize (&a, STACK_SIZE);
|
||||
|
||||
#define N 10
|
||||
int i;
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
#define M 10
|
||||
pthread_t th[M];
|
||||
int j;
|
||||
for (j = 0; j < M; ++j, ++s.a)
|
||||
th[j] = xpthread_create (&a, tf, NULL);
|
||||
|
||||
for (j = 0; j < M; ++j)
|
||||
xpthread_join (th[j]);
|
||||
}
|
||||
|
||||
/* Also check the alignment of the tls variables if a misaligned stack is
|
||||
specified. */
|
||||
pthread_t th;
|
||||
void *thr_stack = NULL;
|
||||
thr_stack = xposix_memalign (0x200, STACK_SIZE + 1);
|
||||
xpthread_attr_setstack (&a, thr_stack + 1, STACK_SIZE);
|
||||
th = xpthread_create (&a, tf, NULL);
|
||||
xpthread_join (th);
|
||||
free (thr_stack);
|
||||
|
||||
xpthread_attr_destroy (&a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
206
sysdeps/pthread/tst-pt-tls2.c
Normal file
206
sysdeps/pthread/tst-pt-tls2.c
Normal file
@ -0,0 +1,206 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define N 10
|
||||
static pthread_t th[N];
|
||||
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
#define CB(n) \
|
||||
static void \
|
||||
cb##n (void) \
|
||||
{ \
|
||||
if (th[n] != pthread_self ()) \
|
||||
{ \
|
||||
write_message ("wrong callback\n"); \
|
||||
_exit (1); \
|
||||
} \
|
||||
}
|
||||
CB (0)
|
||||
CB (1)
|
||||
CB (2)
|
||||
CB (3)
|
||||
CB (4)
|
||||
CB (5)
|
||||
CB (6)
|
||||
CB (7)
|
||||
CB (8)
|
||||
CB (9)
|
||||
static void (*cbs[]) (void) =
|
||||
{
|
||||
cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
|
||||
};
|
||||
|
||||
|
||||
static __thread void (*fp) (void) __attribute__ ((tls_model ("local-exec")));
|
||||
|
||||
|
||||
static sem_t s;
|
||||
|
||||
|
||||
#define THE_SIG SIGUSR1
|
||||
static void
|
||||
handler (int sig)
|
||||
{
|
||||
if (sig != THE_SIG)
|
||||
{
|
||||
write_message ("wrong signal\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
fp ();
|
||||
|
||||
if (sem_post (&s) != 0)
|
||||
{
|
||||
write_message ("sem_post failed\n");
|
||||
_exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static pthread_barrier_t b;
|
||||
|
||||
#define TOTAL_SIGS 1000
|
||||
static int nsigs;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
fp = arg;
|
||||
|
||||
pthread_barrier_wait (&b);
|
||||
|
||||
pthread_barrier_wait (&b);
|
||||
|
||||
if (nsigs != TOTAL_SIGS)
|
||||
{
|
||||
puts ("barrier_wait prematurely returns");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
if (pthread_barrier_init (&b, NULL, N + 1) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (sem_init (&s, 0, 0) != 0)
|
||||
{
|
||||
puts ("sem_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handler;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction (THE_SIG, &sa, NULL) != 0)
|
||||
{
|
||||
puts ("sigaction failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_attr_t a;
|
||||
|
||||
if (pthread_attr_init (&a) != 0)
|
||||
{
|
||||
puts ("attr_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
|
||||
{
|
||||
puts ("attr_setstacksize failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
|
||||
{
|
||||
puts ("pthread_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy (&a) != 0)
|
||||
{
|
||||
puts ("attr_destroy failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_barrier_wait (&b);
|
||||
|
||||
sigset_t ss;
|
||||
sigemptyset (&ss);
|
||||
sigaddset (&ss, THE_SIG);
|
||||
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("pthread_sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Start sending signals. */
|
||||
for (i = 0; i < TOTAL_SIGS; ++i)
|
||||
{
|
||||
if (kill (getpid (), THE_SIG) != 0)
|
||||
{
|
||||
puts ("kill failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
|
||||
{
|
||||
puts ("sem_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
++nsigs;
|
||||
}
|
||||
|
||||
pthread_barrier_wait (&b);
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_join (th[i], NULL) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1
sysdeps/pthread/tst-pt-vfork1.c
Normal file
1
sysdeps/pthread/tst-pt-vfork1.c
Normal file
@ -0,0 +1 @@
|
||||
#include <posix/tst-vfork1.c>
|
1
sysdeps/pthread/tst-pt-vfork2.c
Normal file
1
sysdeps/pthread/tst-pt-vfork2.c
Normal file
@ -0,0 +1 @@
|
||||
#include <posix/tst-vfork2.c>
|
61
sysdeps/pthread/tst-raise1.c
Normal file
61
sysdeps/pthread/tst-raise1.c
Normal file
@ -0,0 +1,61 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
volatile int count;
|
||||
|
||||
void
|
||||
sh (int sig)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = sh;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction (SIGUSR1, &sa, NULL) < 0)
|
||||
{
|
||||
printf ("sigaction failed: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
if (raise (SIGUSR1) < 0)
|
||||
{
|
||||
printf ("first raise failed: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
if (raise (SIGUSR1) < 0)
|
||||
{
|
||||
printf ("second raise failed: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
if (count != 2)
|
||||
{
|
||||
printf ("signal handler not called 2 times\n");
|
||||
exit (1);
|
||||
}
|
||||
exit (0);
|
||||
}
|
118
sysdeps/pthread/tst-setuid3.c
Normal file
118
sysdeps/pthread/tst-setuid3.c
Normal file
@ -0,0 +1,118 @@
|
||||
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* The test must run under a non-privileged user ID. */
|
||||
static const uid_t test_uid = 1;
|
||||
|
||||
static pthread_barrier_t barrier1;
|
||||
static pthread_barrier_t barrier2;
|
||||
|
||||
#define FAIL(fmt, ...) \
|
||||
do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
|
||||
|
||||
#define FAIL_ERR(fmt, ...) \
|
||||
do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0)
|
||||
|
||||
/* True if x is not a successful return code from pthread_barrier_wait. */
|
||||
static inline bool
|
||||
is_invalid_barrier_ret (int x)
|
||||
{
|
||||
return x != 0 && x != PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
|
||||
static void *
|
||||
thread_func (void *ctx __attribute__ ((unused)))
|
||||
{
|
||||
int ret = pthread_barrier_wait (&barrier1);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
|
||||
ret = pthread_barrier_wait (&barrier2);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
setuid_failure (int phase)
|
||||
{
|
||||
int ret = setuid (0);
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
FAIL ("setuid succeeded unexpectedly in phase %d", phase);
|
||||
case -1:
|
||||
if (errno != EPERM)
|
||||
FAIL_ERR ("setuid phase %d", phase);
|
||||
break;
|
||||
default:
|
||||
FAIL ("invalid setuid return value in phase %d: %d", phase, ret);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (getuid () == 0)
|
||||
if (setuid (test_uid) != 0)
|
||||
FAIL_ERR ("setuid (%u)", (unsigned) test_uid);
|
||||
if (setuid (getuid ()))
|
||||
FAIL_ERR ("setuid (%s)", "getuid ()");
|
||||
setuid_failure (1);
|
||||
|
||||
int ret = pthread_barrier_init (&barrier1, NULL, 2);
|
||||
if (ret != 0)
|
||||
FAIL ("pthread_barrier_init (barrier1): %d", ret);
|
||||
ret = pthread_barrier_init (&barrier2, NULL, 2);
|
||||
if (ret != 0)
|
||||
FAIL ("pthread_barrier_init (barrier2): %d", ret);
|
||||
|
||||
pthread_t thread;
|
||||
ret = pthread_create (&thread, NULL, thread_func, NULL);
|
||||
if (ret != 0)
|
||||
FAIL ("pthread_create: %d", ret);
|
||||
|
||||
/* Ensure that the thread is running properly. */
|
||||
ret = pthread_barrier_wait (&barrier1);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
FAIL ("pthread_barrier_wait (barrier1): %d", ret);
|
||||
|
||||
setuid_failure (2);
|
||||
|
||||
/* Check success case. */
|
||||
if (setuid (getuid ()) != 0)
|
||||
FAIL_ERR ("setuid (%s)", "getuid ()");
|
||||
|
||||
/* Shutdown. */
|
||||
ret = pthread_barrier_wait (&barrier2);
|
||||
if (is_invalid_barrier_ret (ret))
|
||||
FAIL ("pthread_barrier_wait (barrier2): %d", ret);
|
||||
|
||||
ret = pthread_join (thread, NULL);
|
||||
if (ret != 0)
|
||||
FAIL ("pthread_join: %d", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
59
sysdeps/pthread/tst-signal4.c
Normal file
59
sysdeps/pthread/tst-signal4.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
sigset_t ss;
|
||||
|
||||
sigemptyset (&ss);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 10000; ++i)
|
||||
{
|
||||
long int r = random ();
|
||||
|
||||
if (r != SIG_BLOCK && r != SIG_SETMASK && r != SIG_UNBLOCK)
|
||||
{
|
||||
int e = pthread_sigmask (r, &ss, NULL);
|
||||
|
||||
if (e == 0)
|
||||
{
|
||||
printf ("pthread_sigmask succeeded for how = %ld\n", r);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (e != EINVAL)
|
||||
{
|
||||
puts ("pthread_sigmask didn't return EINVAL");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
110
sysdeps/pthread/tst-signal5.c
Normal file
110
sysdeps/pthread/tst-signal5.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
static sigset_t ss;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
sigset_t ss2;
|
||||
if (pthread_sigmask (SIG_SETMASK, NULL, &ss2) != 0)
|
||||
{
|
||||
puts ("child: sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 1; i < 32; ++i)
|
||||
if (sigismember (&ss, i) && ! sigismember (&ss2, i))
|
||||
{
|
||||
printf ("signal %d set in parent mask, but not in child\n", i);
|
||||
exit (1);
|
||||
}
|
||||
else if (! sigismember (&ss, i) && sigismember (&ss2, i))
|
||||
{
|
||||
printf ("signal %d set in child mask, but not in parent\n", i);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
sigemptyset (&ss);
|
||||
sigaddset (&ss, SIGUSR1);
|
||||
if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("1st sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("1st create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *r;
|
||||
if (pthread_join (th, &r) != 0)
|
||||
{
|
||||
puts ("1st join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
sigemptyset (&ss);
|
||||
sigaddset (&ss, SIGUSR2);
|
||||
sigaddset (&ss, SIGFPE);
|
||||
if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("2nd sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("2nd create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_join (th, &r) != 0)
|
||||
{
|
||||
puts ("2nd join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
197
sysdeps/pthread/tst-signal6.c
Normal file
197
sysdeps/pthread/tst-signal6.c
Normal file
@ -0,0 +1,197 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#ifdef SIGRTMIN
|
||||
|
||||
# define N 2
|
||||
static pthread_barrier_t bar;
|
||||
static struct
|
||||
{
|
||||
void *p;
|
||||
pthread_t s;
|
||||
} ti[N];
|
||||
static int sig1;
|
||||
|
||||
|
||||
static void
|
||||
handler (int sig)
|
||||
{
|
||||
pthread_t self = pthread_self ();
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
if (ti[i].s == self)
|
||||
{
|
||||
if ((uintptr_t) ti[i].p <= (uintptr_t) &self
|
||||
&& (uintptr_t) ti[i].p + 2 * MINSIGSTKSZ > (uintptr_t) &self)
|
||||
{
|
||||
puts ("alt stack not used");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
printf ("thread %zu used alt stack for signal %d\n", i, sig);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
puts ("handler: thread not found");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
size_t nr = (uintptr_t) arg;
|
||||
if (nr >= N)
|
||||
{
|
||||
puts ("wrong nr parameter");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
sigset_t ss;
|
||||
sigemptyset (&ss);
|
||||
size_t i;
|
||||
for (i = 0; i < N; ++i)
|
||||
if (i != nr)
|
||||
if (sigaddset (&ss, sig1 + i) != 0)
|
||||
{
|
||||
puts ("tf: sigaddset failed");
|
||||
exit (1);
|
||||
}
|
||||
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("tf: sigmask failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *p = malloc (2 * MINSIGSTKSZ);
|
||||
if (p == NULL)
|
||||
{
|
||||
puts ("tf: malloc failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
stack_t s;
|
||||
s.ss_sp = p;
|
||||
s.ss_size = 2 * MINSIGSTKSZ;
|
||||
s.ss_flags = 0;
|
||||
if (sigaltstack (&s, NULL) != 0)
|
||||
{
|
||||
puts ("tf: sigaltstack failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ti[nr].p = p;
|
||||
ti[nr].s = pthread_self ();
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
sig1 = SIGRTMIN;
|
||||
if (sig1 + N > SIGRTMAX)
|
||||
{
|
||||
puts ("too few RT signals");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handler;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
|
||||
if (sigaction (sig1, &sa, NULL) != 0
|
||||
|| sigaction (sig1 + 1, &sa, NULL) != 0
|
||||
|| sigaction (sig1 + 2, &sa, NULL) != 0)
|
||||
{
|
||||
puts ("sigaction failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_barrier_init (&bar, NULL, 1 + N) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th[N];
|
||||
size_t i;
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_create (&th[i], NULL, tf, (void *) (long int) i) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Block the three signals. */
|
||||
sigset_t ss;
|
||||
sigemptyset (&ss);
|
||||
for (i = 0; i <= N; ++i)
|
||||
sigaddset (&ss, sig1 + i);
|
||||
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
|
||||
{
|
||||
puts ("main: sigmask failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
/* Send some signals. */
|
||||
pid_t me = getpid ();
|
||||
kill (me, sig1 + N);
|
||||
for (i = 0; i < N; ++i)
|
||||
kill (me, sig1 + i);
|
||||
kill (me, sig1 + N);
|
||||
|
||||
/* Give the signals a chance to be worked on. */
|
||||
sleep (1);
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
if (pthread_join (th[i], NULL) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
# define TEST_FUNCTION do_test ()
|
||||
|
||||
#else
|
||||
# define TEST_FUNCTION 0
|
||||
#endif
|
||||
#include "../test-skeleton.c"
|
62
sysdeps/pthread/tst-signal8.c
Normal file
62
sysdeps/pthread/tst-signal8.c
Normal file
@ -0,0 +1,62 @@
|
||||
/* Tests for sigisemptyset and pthread_sigmask.
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
This file is part of the 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
{
|
||||
sigset_t set;
|
||||
sigemptyset (&set);
|
||||
TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0);
|
||||
TEST_COMPARE (sigisemptyset (&set), 1);
|
||||
}
|
||||
|
||||
{
|
||||
sigset_t set;
|
||||
sigfillset (&set);
|
||||
TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0);
|
||||
TEST_COMPARE (sigisemptyset (&set), 1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Ensure current SIG_BLOCK mask empty. */
|
||||
{
|
||||
sigset_t set;
|
||||
sigemptyset (&set);
|
||||
TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0);
|
||||
}
|
||||
|
||||
{
|
||||
pthread_t thr = xpthread_create (NULL, tf, NULL);
|
||||
xpthread_join (thr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
148
sysdeps/pthread/tst-stack1.c
Normal file
148
sysdeps/pthread/tst-stack1.c
Normal file
@ -0,0 +1,148 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static void *stack;
|
||||
static size_t size;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
puts ("child start");
|
||||
|
||||
pthread_attr_t attr;
|
||||
if (pthread_getattr_np (pthread_self (), &attr) != 0)
|
||||
{
|
||||
puts ("getattr_np failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
size_t test_size;
|
||||
void *test_stack;
|
||||
if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
|
||||
{
|
||||
puts ("attr_getstack failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (test_size != size)
|
||||
{
|
||||
printf ("child: reported size differs: is %zu, expected %zu\n",
|
||||
test_size, size);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
if (test_stack != stack)
|
||||
{
|
||||
printf ("child: reported stack address differs: is %p, expected %p\n",
|
||||
test_stack, stack);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
puts ("child OK");
|
||||
|
||||
return result ? (void *) 1l : NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
size = 4 * getpagesize ();
|
||||
#ifdef PTHREAD_STACK_MIN
|
||||
size = MAX (size, PTHREAD_STACK_MIN);
|
||||
#endif
|
||||
if (posix_memalign (&stack, getpagesize (), size) != 0)
|
||||
{
|
||||
puts ("out of memory while allocating the stack memory");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_attr_t attr;
|
||||
if (pthread_attr_init (&attr) != 0)
|
||||
{
|
||||
puts ("attr_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("attr_setstack");
|
||||
if (pthread_attr_setstack (&attr, stack, size) != 0)
|
||||
{
|
||||
puts ("attr_setstack failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
size_t test_size;
|
||||
void *test_stack;
|
||||
puts ("attr_getstack");
|
||||
if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
|
||||
{
|
||||
puts ("attr_getstack failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (test_size != size)
|
||||
{
|
||||
printf ("reported size differs: is %zu, expected %zu\n",
|
||||
test_size, size);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
if (test_stack != stack)
|
||||
{
|
||||
printf ("reported stack address differs: is %p, expected %p\n",
|
||||
test_stack, stack);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
puts ("create");
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, &attr, tf, NULL) != 0)
|
||||
{
|
||||
puts ("failed to create thread");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *status;
|
||||
if (pthread_join (th, &status) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
result |= status != NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
56
sysdeps/pthread/tst-stdio1.c
Normal file
56
sysdeps/pthread/tst-stdio1.c
Normal file
@ -0,0 +1,56 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static void *tf (void *a)
|
||||
{
|
||||
flockfile (stdout);
|
||||
/* This call should never return. */
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
flockfile (stdout);
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
write_message ("create failed\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
delayed_exit (1);
|
||||
xpthread_join (th);
|
||||
|
||||
puts ("join returned");
|
||||
|
||||
return 1;
|
||||
}
|
82
sysdeps/pthread/tst-stdio2.c
Normal file
82
sysdeps/pthread/tst-stdio2.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
static void *tf (void *a)
|
||||
{
|
||||
puts ("start tf");
|
||||
|
||||
/* Multiple locking, implicitly or explicitly, must be possible. */
|
||||
flockfile (stdout);
|
||||
|
||||
puts ("after first flockfile");
|
||||
|
||||
flockfile (stdout);
|
||||
|
||||
puts ("foo");
|
||||
|
||||
funlockfile (stdout);
|
||||
|
||||
puts ("after first funlockfile");
|
||||
|
||||
funlockfile (stdout);
|
||||
|
||||
puts ("all done");
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
write_message ("create failed\n");
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
void *result;
|
||||
if (pthread_join (th, &result) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
else if (result != NULL)
|
||||
{
|
||||
printf ("wrong return value: %p, expected %p\n", result, NULL);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("join returned succsefully");
|
||||
|
||||
return 0;
|
||||
}
|
117
sysdeps/pthread/tst-tsd1.c
Normal file
117
sysdeps/pthread/tst-tsd1.c
Normal file
@ -0,0 +1,117 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_key_t key1;
|
||||
pthread_key_t key2;
|
||||
void *value;
|
||||
int result = 0;
|
||||
int err;
|
||||
|
||||
err = pthread_key_create (&key1, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("1st key_create failed: %s\n", strerror (err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initial value must be NULL. */
|
||||
value = pthread_getspecific (key1);
|
||||
if (value != NULL)
|
||||
{
|
||||
puts ("1st getspecific != NULL");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
err = pthread_setspecific (key1, (void *) -2l);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("1st setspecific failed: %s\n", strerror (err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
value = pthread_getspecific (key1);
|
||||
if (value == NULL)
|
||||
{
|
||||
puts ("2nd getspecific == NULL\n");
|
||||
result = 1;
|
||||
}
|
||||
else if (value != (void *) -2l)
|
||||
{
|
||||
puts ("2nd getspecific != -2l\n");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
err = pthread_setspecific (key1, (void *) -3l);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("2nd setspecific failed: %s\n", strerror (err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
value = pthread_getspecific (key1);
|
||||
if (value == NULL)
|
||||
{
|
||||
puts ("3rd getspecific == NULL\n");
|
||||
result = 1;
|
||||
}
|
||||
else if (value != (void *) -3l)
|
||||
{
|
||||
puts ("3rd getspecific != -2l\n");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
err = pthread_key_delete (key1);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("key_delete failed: %s\n", strerror (err));
|
||||
result = 1;
|
||||
}
|
||||
|
||||
|
||||
err = pthread_key_create (&key2, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("2nd key_create failed: %s\n", strerror (err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key1 != key2)
|
||||
puts ("key1 != key2; no more tests performed");
|
||||
else
|
||||
{
|
||||
value = pthread_getspecific (key2);
|
||||
if (value != NULL)
|
||||
{
|
||||
puts ("4th getspecific != NULL");
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
96
sysdeps/pthread/tst-tsd2.c
Normal file
96
sysdeps/pthread/tst-tsd2.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* Copyright (C) 2002-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static int result;
|
||||
|
||||
|
||||
static void
|
||||
destr (void *arg)
|
||||
{
|
||||
if (arg != (void *) -2l)
|
||||
result = 2;
|
||||
else
|
||||
result = 0;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_key_t key = (pthread_key_t) (long int) arg;
|
||||
int err;
|
||||
|
||||
err = pthread_setspecific (key, (void *) -2l);
|
||||
if (err != 0)
|
||||
result = 3;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_key_t key;
|
||||
pthread_t th;
|
||||
int err;
|
||||
|
||||
err = pthread_key_create (&key, destr);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("key_create failed: %s\n", strerror (err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = 1;
|
||||
|
||||
err = pthread_create (&th, NULL, tf, (void *) (long int) key);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("create failed: %s\n", strerror (err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Wait for the thread to terminate. */
|
||||
err = pthread_join (th, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
printf ("join failed: %s\n", strerror (err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (result == 1)
|
||||
puts ("destructor not called");
|
||||
else if (result == 2)
|
||||
puts ("destructor got passed a wrong value");
|
||||
else if (result == 3)
|
||||
puts ("setspecific in child failed");
|
||||
else if (result != 0)
|
||||
puts ("result != 0");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
80
sysdeps/pthread/tst-tsd5.c
Normal file
80
sysdeps/pthread/tst-tsd5.c
Normal file
@ -0,0 +1,80 @@
|
||||
/* Copyright (C) 2004-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
static void
|
||||
cl (void *p)
|
||||
{
|
||||
pthread_mutex_unlock (&m);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("2nd mutex_lock failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_key_t k;
|
||||
if (pthread_key_create (&k, cl) != 0)
|
||||
{
|
||||
puts ("key_create failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_setspecific (k, (void *) 1) != 0)
|
||||
{
|
||||
puts ("setspecific failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_lock (&m) != 0)
|
||||
{
|
||||
puts ("1st mutex_lock failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
89
sysdeps/pthread/tst-tsd6.c
Normal file
89
sysdeps/pthread/tst-tsd6.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define NKEYS 100
|
||||
static pthread_key_t keys[NKEYS];
|
||||
static pthread_barrier_t b;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
void *res = NULL;
|
||||
for (int i = 0; i < NKEYS; ++i)
|
||||
{
|
||||
void *p = pthread_getspecific (keys[i]);
|
||||
pthread_setspecific (keys[i], (void *) 7);
|
||||
if (p != NULL)
|
||||
res = p;
|
||||
}
|
||||
if (arg != NULL)
|
||||
{
|
||||
pthread_barrier_wait (arg);
|
||||
pthread_barrier_wait (arg);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_barrier_init (&b, NULL, 2);
|
||||
|
||||
for (int i = 0; i < NKEYS; ++i)
|
||||
if (pthread_key_create (&keys[i], NULL) != 0)
|
||||
{
|
||||
puts ("cannot create keys");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, &b) != 0)
|
||||
{
|
||||
puts ("cannot create thread in parent");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_barrier_wait (&b);
|
||||
|
||||
pid_t pid = fork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
if (pthread_create (&th, NULL, tf, NULL) != 0)
|
||||
{
|
||||
puts ("cannot create thread in child");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *res;
|
||||
pthread_join (th, &res);
|
||||
|
||||
exit (res != NULL);
|
||||
}
|
||||
else if (pid == -1)
|
||||
{
|
||||
puts ("cannot create child process");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int s;
|
||||
if (TEMP_FAILURE_RETRY (waitpid (pid, &s, 0)) != pid)
|
||||
{
|
||||
puts ("failing to wait for child process");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_barrier_wait (&b);
|
||||
pthread_join (th, NULL);
|
||||
|
||||
return !WIFEXITED (s) ? 2 : WEXITSTATUS (s);
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
136
sysdeps/pthread/tst-umask1.c
Normal file
136
sysdeps/pthread/tst-umask1.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* Copyright (C) 2003-2020 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, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
int (*fp) (const char *, mode_t);
|
||||
const char *name;
|
||||
bool is_fd;
|
||||
} fcts[] =
|
||||
{
|
||||
{ creat, "creat", true },
|
||||
{ mkdir, "mkdir", false },
|
||||
{ mkfifo, "mkfifo", false },
|
||||
};
|
||||
#define nfcts (sizeof (fcts) / sizeof (fcts[0]))
|
||||
|
||||
|
||||
static int
|
||||
work (const char *fname, int mask)
|
||||
{
|
||||
int result = 0;
|
||||
size_t i;
|
||||
for (i = 0; i < nfcts; ++i)
|
||||
{
|
||||
remove (fname);
|
||||
int fd = fcts[i].fp (fname, 0777);
|
||||
if (fd == -1)
|
||||
{
|
||||
printf ("cannot %s %s: %m\n", fcts[i].name, fname);
|
||||
exit (1);
|
||||
}
|
||||
if (fcts[i].is_fd)
|
||||
close (fd);
|
||||
struct stat64 st;
|
||||
if (stat64 (fname, &st) == -1)
|
||||
{
|
||||
printf ("cannot stat %s after %s: %m\n", fname, fcts[i].name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if ((st.st_mode & mask) != 0)
|
||||
{
|
||||
printf ("mask not successful after %s: %x still set\n",
|
||||
fcts[i].name, (unsigned int) (st.st_mode & mask));
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static pthread_barrier_t bar;
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
int result = work (arg, 022);
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
return (work (arg, 0) | result) ? (void *) -1l : NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (const char *fname)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
umask (0);
|
||||
result |= work (fname, 0);
|
||||
|
||||
pthread_barrier_init (&bar, NULL, 2);
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, (void *) fname) != 0)
|
||||
{
|
||||
puts ("cannot create thread");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
umask (022);
|
||||
result |= work (fname, 022);
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
umask (0);
|
||||
|
||||
pthread_barrier_wait (&bar);
|
||||
|
||||
void *res;
|
||||
if (pthread_join (th, &res) != 0)
|
||||
{
|
||||
puts ("join failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
remove (fname);
|
||||
|
||||
return result || res != NULL;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test (argc < 2 ? "/tmp/tst-umask.tmp" : argv[1])
|
||||
#include "../test-skeleton.c"
|
47
sysdeps/pthread/tst-unload.c
Normal file
47
sysdeps/pthread/tst-unload.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Tests for non-unloading of libpthread.
|
||||
Copyright (C) 2000-2020 Free Software Foundation, Inc.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General 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, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gnu/lib-names.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *p = dlopen (LIBPTHREAD_SO, RTLD_LAZY);
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
puts ("failed to load " LIBPTHREAD_SO);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dlclose (p) != 0)
|
||||
{
|
||||
puts ("dlclose (" LIBPTHREAD_SO ") failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts ("seems to work");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
2
sysdeps/pthread/tst-unwind-thread.c
Normal file
2
sysdeps/pthread/tst-unwind-thread.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define USE_PTHREADS 1
|
||||
#include "../elf/tst-unwind-main.c"
|
1
sysdeps/pthread/tst-vfork1x.c
Normal file
1
sysdeps/pthread/tst-vfork1x.c
Normal file
@ -0,0 +1 @@
|
||||
#include <posix/tst-vfork1.c>
|
1
sysdeps/pthread/tst-vfork2x.c
Normal file
1
sysdeps/pthread/tst-vfork2x.c
Normal file
@ -0,0 +1 @@
|
||||
#include <posix/tst-vfork2.c>
|
Reference in New Issue
Block a user