1/* unnamed semaphore sanity check */
2#include <pthread.h>
3#include <semaphore.h>
4#include <time.h>
5#include <string.h>
6#include <errno.h>
7#include "test.h"
8
9#define T(f) if(f) t_error(#f" failed: %s\n", strerror(errno))
10#define T2(r,f) if((r=(f))) t_error(#f" failed: %s\n", strerror(r))
11
12static void *start(void *arg)
13{
14	struct timespec ts;
15	sem_t *s = arg;
16	T(clock_gettime(CLOCK_REALTIME, &ts));
17	ts.tv_sec += 1;
18	T(sem_post(s));
19	T(sem_timedwait(s+1, &ts));
20	return 0;
21}
22
23static void many_waiters()
24{
25	pthread_t t[3];
26	sem_t s[2];
27	int r;
28	void *p;
29
30	T(sem_init(s, 0, 0));
31	T(sem_init(s+1, 0, 0));
32	T2(r,pthread_create(t, 0, start, s));
33	T2(r,pthread_create(t+1, 0, start, s));
34	T2(r,pthread_create(t+2, 0, start, s));
35	T(sem_wait(s));
36	T(sem_wait(s));
37	T(sem_wait(s));
38	T(sem_getvalue(s, &r));
39	if (r)
40		t_error("sem value should be 0, got %d\n", r);
41	T(sem_post(s+1));
42	T(sem_post(s+1));
43	T(sem_post(s+1));
44	T2(r,pthread_join(t[0],&p));
45	T2(r,pthread_join(t[1],&p));
46	T2(r,pthread_join(t[2],&p));
47	T(sem_getvalue(s+1, &r));
48	if (r)
49		t_error("sem value should be 0, got %d\n", r);
50	T(sem_destroy(s));
51	T(sem_destroy(s+1));
52}
53
54static void single_thread()
55{
56	struct timespec ts;
57	sem_t s;
58	int r;
59
60	T(sem_init(&s, 0, 1));
61	T(sem_wait(&s));
62	T(sem_getvalue(&s, &r));
63	if (r)
64		t_error("sem value should be 0, got %d\n", r);
65	if (sem_trywait(&s) != -1 || errno != EAGAIN)
66		t_error("sem_trywait should fail with EAGAIN, got %s\n", strerror(errno));
67	errno = 0;
68	T(clock_gettime(CLOCK_REALTIME, &ts));
69	if (sem_timedwait(&s, &ts)!=-1 || errno != ETIMEDOUT)
70		t_error("sem_timedwait should fail with ETIMEDOUT, got %s\n", strerror(errno));
71	T(sem_destroy(&s));
72}
73
74int main(void)
75{
76	single_thread();
77	many_waiters();
78	return t_status;
79}
80