xref: /freebsd/tools/test/stress2/misc/umtx_suspend.sh (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1#!/bin/sh
2
3# Test scenario from
4# Bug 192918 - [patch] A thread will spin if a signal interrupts umtxq_sleep_pi.
5# by eric@vangyzen.net
6
7. ../default.cfg
8
9here=`pwd`
10cd /tmp
11sed '1,/^EOF/d' < $here/$0 > umtx_suspend.c
12mycc -o umtx_suspend -Wall -Wextra -O0 -g umtx_suspend.c \
13    -lpthread || exit 1
14rm -f umtx_suspend.c
15
16/tmp/umtx_suspend
17
18rm -f /tmp/umtx_suspend
19exit 0
20EOF
21// cc -lpthread -o umtx_suspend umtx_suspend.c
22//
23// failure: a thread spins around "umtxpi" the kernel, ignoring signals
24// success: the process exits
25
26#include <sys/cdefs.h>
27
28#include <err.h>
29#include <pthread.h>
30#include <pthread_np.h>
31#include <stdio.h>
32#include <unistd.h>
33
34pthread_mutex_t the_mutex;
35
36void *
37spinning_thread_func(void *arg __unused)
38{
39    int error;
40
41    error = pthread_mutex_lock(&the_mutex);
42    if (error)
43        errc(1, error, "%s: pthread_mutex_lock", __func__);
44
45    return (NULL);
46}
47
48int
49main(int argc __unused, char *argv[] __unused)
50{
51    int error;
52    pthread_t spinning_thread;
53    pthread_mutexattr_t the_mutex_attr;
54
55    error = pthread_mutexattr_init(&the_mutex_attr);
56    if (error)
57        errc(1, error, "pthread_mutexattr_init");
58
59    error = pthread_mutexattr_setprotocol(&the_mutex_attr, PTHREAD_PRIO_INHERIT);
60    if (error)
61        errc(1, error, "pthread_mutexattr_setprotocol");
62
63    error = pthread_mutex_init(&the_mutex, &the_mutex_attr);
64    if (error)
65        errc(1, error, "pthread_mutex_init");
66
67    error = pthread_mutex_lock(&the_mutex);
68    if (error)
69        errc(1, error, "pthread_mutex_lock");
70
71    error = pthread_create(&spinning_thread, NULL, spinning_thread_func, NULL);
72    if (error)
73        errc(1, error, "pthread_create");
74
75    // Wait for the spinning_thread to call pthread_mutex_lock(3)
76    // and enter the kernel.
77    (void) sleep(1);
78
79    error = pthread_suspend_np(spinning_thread);
80    if (error)
81        errc(1, error, "pthread_suspend_np");
82
83    // The spinning_thread should be spinning in the kernel.
84    // This thread should be blocked in pthread_suspend_np(3).
85    fputs("This test failed to reproduce the bug.\n", stderr);
86
87    return (0);
88}
89