nptl: Add POSIX-proposed pthread_mutex_clocklock
[external/glibc.git] / nptl / tst-mutex5.c
1 /* Copyright (C) 2002-2019 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <errno.h>
20 #include <pthread.h>
21 #include <stdio.h>
22 #include <time.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 #include <stdint.h>
26 #include <config.h>
27 #include <support/check.h>
28 #include <support/timespec.h>
29
30
31 #ifndef TYPE
32 # define TYPE PTHREAD_MUTEX_NORMAL
33 #endif
34
35 /* A bogus clock value that tells run_test to use
36    pthread_mutex_timedlock rather than pthread_mutex_clocklock.  */
37 #define CLOCK_USE_TIMEDLOCK (-1)
38
39 static int
40 do_test_clock (clockid_t clockid, const char *fnname)
41 {
42   pthread_mutex_t m;
43   pthread_mutexattr_t a;
44   const clockid_t clockid_for_get =
45     (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
46
47   TEST_COMPARE (pthread_mutexattr_init (&a), 0);
48   TEST_COMPARE (pthread_mutexattr_settype (&a, TYPE), 0);
49
50 #ifdef ENABLE_PI
51   TEST_COMPARE (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT), 0);
52 #endif
53
54   int err = pthread_mutex_init (&m, &a);
55   if (err != 0)
56     {
57 #ifdef ENABLE_PI
58       if (err == ENOTSUP)
59         FAIL_UNSUPPORTED ("PI mutexes unsupported");
60 #endif
61       FAIL_EXIT1 ("mutex_init failed");
62     }
63
64   TEST_COMPARE (pthread_mutexattr_destroy (&a), 0);
65   TEST_COMPARE (pthread_mutex_lock (&m), 0);
66   if (pthread_mutex_trylock (&m) == 0)
67     FAIL_EXIT1 ("mutex_trylock succeeded");
68
69   /* Wait 2 seconds.  */
70   struct timespec ts_timeout = timespec_add (xclock_now (clockid_for_get),
71                                              make_timespec (2, 0));
72
73   if (clockid == CLOCK_USE_TIMEDLOCK)
74     TEST_COMPARE (pthread_mutex_timedlock (&m, &ts_timeout), ETIMEDOUT);
75   else
76     TEST_COMPARE (pthread_mutex_clocklock (&m, clockid, &ts_timeout),
77                   ETIMEDOUT);
78   TEST_TIMESPEC_BEFORE_NOW (ts_timeout, clockid_for_get);
79
80   /* The following makes the ts value invalid.  */
81   ts_timeout.tv_nsec += 1000000000;
82
83   if (clockid == CLOCK_USE_TIMEDLOCK)
84     TEST_COMPARE (pthread_mutex_timedlock (&m, &ts_timeout), EINVAL);
85   else
86     TEST_COMPARE (pthread_mutex_clocklock (&m, clockid, &ts_timeout), EINVAL);
87   TEST_COMPARE (pthread_mutex_unlock (&m), 0);
88
89   const struct timespec ts_start = xclock_now (CLOCK_REALTIME);
90
91   /* Wait 2 seconds.  */
92   ts_timeout = timespec_add (ts_start, make_timespec (2, 0));
93
94   if (clockid == CLOCK_USE_TIMEDLOCK)
95     TEST_COMPARE (pthread_mutex_timedlock (&m, &ts_timeout), 0);
96   else
97     TEST_COMPARE (pthread_mutex_clocklock (&m, clockid, &ts_timeout), 0);
98
99   const struct timespec ts_end = xclock_now (clockid_for_get);
100
101   /* Check that timedlock didn't delay.  We use a limit of 0.1 secs.  */
102   TEST_TIMESPEC_BEFORE (ts_end,
103                         timespec_add (ts_start, make_timespec (0, 100000000)));
104
105   TEST_COMPARE (pthread_mutex_unlock (&m), 0);
106   TEST_COMPARE (pthread_mutex_destroy (&m), 0);
107
108   return 0;
109 }
110
111 static int do_test (void)
112 {
113   do_test_clock (CLOCK_USE_TIMEDLOCK, "timedlock");
114   do_test_clock (CLOCK_REALTIME, "clocklock(realtime)");
115   do_test_clock (CLOCK_MONOTONIC, "clocklock(monotonic)");
116   return 0;
117 }
118
119 #include <support/test-driver.c>