1 /* Test program for timedout read/write lock functions.
2 Copyright (C) 2000-2023 Free Software Foundation, Inc.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, see <https://www.gnu.org/licenses/>. */
26 #include <support/check.h>
27 #include <support/timespec.h>
28 #include <support/xthread.h>
36 static const struct timespec timeout
= { 0,1000000 };
37 static const struct timespec delay
= { 0, 1000000 };
40 # define KIND PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
43 /* A bogus clock value that tells the tests to use pthread_rwlock_timedrdlock
44 and pthread_rwlock_timedwrlock rather than pthread_rwlock_clockrdlock and
45 pthread_rwlock_clockwrlock. */
46 #define CLOCK_USE_TIMEDLOCK (-1)
48 static pthread_rwlock_t lock
;
58 writer_thread (void *arg
)
60 struct thread_args
*args
= arg
;
61 const int nr
= args
->nr
;
62 const clockid_t clockid
= args
->clockid
;
63 const clockid_t clockid_for_get
=
64 (clockid
== CLOCK_USE_TIMEDLOCK
) ? CLOCK_REALTIME
: clockid
;
65 const char *fnname
= args
->fnname
;
70 for (n
= 0; n
< WRITETRIES
; ++n
)
75 xclock_gettime (clockid_for_get
, &ts
);
77 ts
= timespec_add (ts
, timeout
);
78 ts
= timespec_add (ts
, timeout
);
80 printf ("writer thread %d tries again\n", nr
);
82 e
= (clockid
== CLOCK_USE_TIMEDLOCK
)
83 ? pthread_rwlock_timedwrlock (&lock
, &ts
)
84 : pthread_rwlock_clockwrlock (&lock
, clockid
, &ts
);
85 if (e
!= 0 && e
!= ETIMEDOUT
)
86 FAIL_EXIT1 ("%swrlock failed", fnname
);
88 while (e
== ETIMEDOUT
);
90 printf ("writer thread %d succeeded\n", nr
);
92 nanosleep (&delay
, NULL
);
94 if (pthread_rwlock_unlock (&lock
) != 0)
95 FAIL_EXIT1 ("unlock for writer failed");
97 printf ("writer thread %d released\n", nr
);
105 reader_thread (void *arg
)
107 struct thread_args
*args
= arg
;
108 const int nr
= args
->nr
;
109 const clockid_t clockid
= args
->clockid
;
110 const clockid_t clockid_for_get
=
111 (clockid
== CLOCK_USE_TIMEDLOCK
) ? CLOCK_REALTIME
: clockid
;
112 const char *fnname
= args
->fnname
;
117 for (n
= 0; n
< READTRIES
; ++n
)
122 xclock_gettime (clockid_for_get
, &ts
);
124 ts
= timespec_add (ts
, timeout
);
126 printf ("reader thread %d tries again\n", nr
);
128 if (clockid
== CLOCK_USE_TIMEDLOCK
)
129 e
= pthread_rwlock_timedrdlock (&lock
, &ts
);
131 e
= pthread_rwlock_clockrdlock (&lock
, clockid
, &ts
);
132 if (e
!= 0 && e
!= ETIMEDOUT
)
133 FAIL_EXIT1 ("%srdlock failed", fnname
);
135 while (e
== ETIMEDOUT
);
137 printf ("reader thread %d succeeded\n", nr
);
139 nanosleep (&delay
, NULL
);
141 if (pthread_rwlock_unlock (&lock
) != 0)
142 FAIL_EXIT1 ("unlock for reader failed");
144 printf ("reader thread %d released\n", nr
);
152 do_test_clock (clockid_t clockid
, const char *fnname
)
154 pthread_t thwr
[NWRITERS
];
155 pthread_t thrd
[NREADERS
];
157 pthread_rwlockattr_t a
;
159 if (pthread_rwlockattr_init (&a
) != 0)
160 FAIL_EXIT1 ("rwlockattr_t failed");
162 if (pthread_rwlockattr_setkind_np (&a
, KIND
) != 0)
163 FAIL_EXIT1 ("rwlockattr_setkind failed");
165 if (pthread_rwlock_init (&lock
, &a
) != 0)
166 FAIL_EXIT1 ("rwlock_init failed");
168 /* Make standard error the same as standard output. */
171 /* Make sure we see all message, even those on stdout. */
172 setvbuf (stdout
, NULL
, _IONBF
, 0);
174 struct thread_args wargs
[NWRITERS
];
175 for (n
= 0; n
< NWRITERS
; ++n
) {
177 wargs
[n
].clockid
= clockid
;
178 wargs
[n
].fnname
= fnname
;
179 thwr
[n
] = xpthread_create (NULL
, writer_thread
, &wargs
[n
]);
182 struct thread_args rargs
[NREADERS
];
183 for (n
= 0; n
< NREADERS
; ++n
) {
185 rargs
[n
].clockid
= clockid
;
186 rargs
[n
].fnname
= fnname
;
187 thrd
[n
] = xpthread_create (NULL
, reader_thread
, &rargs
[n
]);
190 /* Wait for all the threads. */
191 for (n
= 0; n
< NWRITERS
; ++n
)
192 xpthread_join (thwr
[n
]);
193 for (n
= 0; n
< NREADERS
; ++n
)
194 xpthread_join (thrd
[n
]);
202 do_test_clock (CLOCK_USE_TIMEDLOCK
, "timed");
203 do_test_clock (CLOCK_REALTIME
, "clock(realtime)");
204 do_test_clock (CLOCK_MONOTONIC
, "clock(monotonic)");
210 #include <support/test-driver.c>