1570af302Sopenharmony_ci/* unnamed semaphore sanity check */
2570af302Sopenharmony_ci#include <pthread.h>
3570af302Sopenharmony_ci#include <semaphore.h>
4570af302Sopenharmony_ci#include <time.h>
5570af302Sopenharmony_ci#include <string.h>
6570af302Sopenharmony_ci#include <errno.h>
7570af302Sopenharmony_ci#include "test.h"
8570af302Sopenharmony_ci
9570af302Sopenharmony_ci#define T(f) if(f) t_error(#f" failed: %s\n", strerror(errno))
10570af302Sopenharmony_ci#define T2(r,f) if((r=(f))) t_error(#f" failed: %s\n", strerror(r))
11570af302Sopenharmony_ci
12570af302Sopenharmony_cistatic void *start(void *arg)
13570af302Sopenharmony_ci{
14570af302Sopenharmony_ci	struct timespec ts;
15570af302Sopenharmony_ci	sem_t *s = arg;
16570af302Sopenharmony_ci	T(clock_gettime(CLOCK_REALTIME, &ts));
17570af302Sopenharmony_ci	ts.tv_sec += 1;
18570af302Sopenharmony_ci	T(sem_post(s));
19570af302Sopenharmony_ci	T(sem_timedwait(s+1, &ts));
20570af302Sopenharmony_ci	return 0;
21570af302Sopenharmony_ci}
22570af302Sopenharmony_ci
23570af302Sopenharmony_cistatic void many_waiters()
24570af302Sopenharmony_ci{
25570af302Sopenharmony_ci	pthread_t t[3];
26570af302Sopenharmony_ci	sem_t s[2];
27570af302Sopenharmony_ci	int r;
28570af302Sopenharmony_ci	void *p;
29570af302Sopenharmony_ci
30570af302Sopenharmony_ci	T(sem_init(s, 0, 0));
31570af302Sopenharmony_ci	T(sem_init(s+1, 0, 0));
32570af302Sopenharmony_ci	T2(r,pthread_create(t, 0, start, s));
33570af302Sopenharmony_ci	T2(r,pthread_create(t+1, 0, start, s));
34570af302Sopenharmony_ci	T2(r,pthread_create(t+2, 0, start, s));
35570af302Sopenharmony_ci	T(sem_wait(s));
36570af302Sopenharmony_ci	T(sem_wait(s));
37570af302Sopenharmony_ci	T(sem_wait(s));
38570af302Sopenharmony_ci	T(sem_getvalue(s, &r));
39570af302Sopenharmony_ci	if (r)
40570af302Sopenharmony_ci		t_error("sem value should be 0, got %d\n", r);
41570af302Sopenharmony_ci	T(sem_post(s+1));
42570af302Sopenharmony_ci	T(sem_post(s+1));
43570af302Sopenharmony_ci	T(sem_post(s+1));
44570af302Sopenharmony_ci	T2(r,pthread_join(t[0],&p));
45570af302Sopenharmony_ci	T2(r,pthread_join(t[1],&p));
46570af302Sopenharmony_ci	T2(r,pthread_join(t[2],&p));
47570af302Sopenharmony_ci	T(sem_getvalue(s+1, &r));
48570af302Sopenharmony_ci	if (r)
49570af302Sopenharmony_ci		t_error("sem value should be 0, got %d\n", r);
50570af302Sopenharmony_ci	T(sem_destroy(s));
51570af302Sopenharmony_ci	T(sem_destroy(s+1));
52570af302Sopenharmony_ci}
53570af302Sopenharmony_ci
54570af302Sopenharmony_cistatic void single_thread()
55570af302Sopenharmony_ci{
56570af302Sopenharmony_ci	struct timespec ts;
57570af302Sopenharmony_ci	sem_t s;
58570af302Sopenharmony_ci	int r;
59570af302Sopenharmony_ci
60570af302Sopenharmony_ci	T(sem_init(&s, 0, 1));
61570af302Sopenharmony_ci	T(sem_wait(&s));
62570af302Sopenharmony_ci	T(sem_getvalue(&s, &r));
63570af302Sopenharmony_ci	if (r)
64570af302Sopenharmony_ci		t_error("sem value should be 0, got %d\n", r);
65570af302Sopenharmony_ci	if (sem_trywait(&s) != -1 || errno != EAGAIN)
66570af302Sopenharmony_ci		t_error("sem_trywait should fail with EAGAIN, got %s\n", strerror(errno));
67570af302Sopenharmony_ci	errno = 0;
68570af302Sopenharmony_ci	T(clock_gettime(CLOCK_REALTIME, &ts));
69570af302Sopenharmony_ci	if (sem_timedwait(&s, &ts)!=-1 || errno != ETIMEDOUT)
70570af302Sopenharmony_ci		t_error("sem_timedwait should fail with ETIMEDOUT, got %s\n", strerror(errno));
71570af302Sopenharmony_ci	T(sem_destroy(&s));
72570af302Sopenharmony_ci}
73570af302Sopenharmony_ci
74570af302Sopenharmony_ciint main(void)
75570af302Sopenharmony_ci{
76570af302Sopenharmony_ci	single_thread();
77570af302Sopenharmony_ci	many_waiters();
78570af302Sopenharmony_ci	return t_status;
79570af302Sopenharmony_ci}
80