1 /* Make sure pthread_mutex_timedlock doesn't return spurious error codes.
3 Copyright (C) 2020-2023 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
25 #include <support/check.h>
26 #include <support/timespec.h>
27 #include <support/xsignal.h>
28 #include <support/xthread.h>
29 #include <support/xtime.h>
33 #define NANO_PER_SEC 1000000000LL
34 #define TIMEOUT (NANO_PER_SEC / 1000LL)
35 #define NUM_THREADS 50
36 #define RETEST_TIMES 100
38 static pthread_mutex_t mutex
;
40 static clockid_t clockid
;
43 signal_handler (int sig_num
)
45 TEST_COMPARE (sig_num
, SIGUSR1
);
48 /* Call pthread_mutex_timedlock()/pthread_mutex_unlock() repetitively, hoping
49 that one of them returns EAGAIN or EINTR unexpectedly. */
51 worker_timedlock (void *arg
)
53 for (unsigned int run
= 0; run
< runs
; run
++)
55 struct timespec abs_time
= timespec_add (xclock_now (CLOCK_REALTIME
),
56 make_timespec (0, 1000000));
58 int ret
= pthread_mutex_timedlock (&mutex
, &abs_time
);
61 xpthread_mutex_unlock (&mutex
);
63 TEST_VERIFY_EXIT (ret
== 0 || ret
== ETIMEDOUT
);
69 worker_clocklock (void *arg
)
71 for (unsigned int run
= 0; run
< runs
; run
++)
73 struct timespec time
=
74 timespec_add (xclock_now (clockid
), make_timespec (0, 1000000));
76 int ret
= pthread_mutex_clocklock (&mutex
, clockid
, &time
);
79 xpthread_mutex_unlock (&mutex
);
81 TEST_VERIFY_EXIT (ret
== 0 || ret
== ETIMEDOUT
);
87 run_test_set (void *(*worker
) (void *))
89 pthread_t workers
[NUM_THREADS
];
91 /* Check if default pthread_mutex_{timed,clock}lock with valid arguments
92 returns either 0 or ETIMEDOUT. Since there is no easy way to force
93 the error condition, the test creates multiple threads which in turn
94 issues pthread_mutex_timedlock multiple times. */
96 for (int run
= 0; run
< RETEST_TIMES
; run
++)
98 for (int i
= 0; i
< NUM_THREADS
; i
++)
99 workers
[i
] = xpthread_create (NULL
, worker
, NULL
);
100 for (int i
= 0; i
< NUM_THREADS
; i
++)
101 xpthread_join (workers
[i
]);
104 /* The idea is similar to previous tests, but we check if
105 pthread_mutex_{timed,clock}lock does not return EINTR. */
108 for (int i
= 0; i
< RETEST_TIMES
* 1000; i
++)
110 xpthread_mutex_lock (&mutex
);
111 thread
= xpthread_create (NULL
, worker
, NULL
);
112 /* Sleep just a little bit to reach the lock on the worker thread. */
114 pthread_kill (thread
, SIGUSR1
);
115 xpthread_mutex_unlock (&mutex
);
116 xpthread_join (thread
);
126 xsignal (SIGUSR1
, signal_handler
);
128 xpthread_mutex_init (&mutex
, NULL
);
130 run_test_set (worker_timedlock
);
131 clockid
= CLOCK_REALTIME
;
132 run_test_set (worker_clocklock
);
133 clockid
= CLOCK_MONOTONIC
;
134 run_test_set (worker_clocklock
);
138 #include <support/test-driver.c>