aboutsummaryrefslogtreecommitdiff
path: root/testcases/open_posix_testsuite/functional/semaphores/sem_sleepingbarber.c
blob: 915ccb8ec7c2d59aac8c6492ba0fa2222698a9d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 * Copyright (c) 2002, Intel Corporation. All rights reserved.
 * Created by:  crystal.xiong REMOVE-THIS AT intel DOT com
 * This file is licensed under the GPL license.  For the full content
 * of this license, see the COPYING file at the top level of this
 * source tree.
 *
 * Test the well-known sleeping barber problem.
 */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>

#include "posixtest.h"
#define CHAIR_NUM	5
#define CUS_NUM		10
#define LOOP_NUM	30

sem_t customer;
sem_t barber;
sem_t lock;
sem_t print;

int waiting = 0;

#ifdef __GNUC__
#define my_printf(x...) do { \
	sem_wait(&print); \
	printf(x); \
	sem_post(&print); \
} while (0)
#else
#define my_printf printf
#endif

void mdelay(unsigned msecs)
{
	struct timespec req;
	req.tv_sec = msecs / 1000;
	req.tv_nsec = (msecs % 1000) * 1000000;
	nanosleep(&req, NULL);
}

void *barbers(void *unused LTP_ATTRIBUTE_UNUSED)
{
	int i;
	for (i = 0; i < LOOP_NUM; i++) {
		if (-1 == sem_wait(&lock)) {
			perror("sem_wait(&lock) didn't return success");
			pthread_exit((void *)1);
		}
		if (waiting == 0) {
			my_printf
			    ("There are no more customers waiting, barber will sleep.\n");
		}
		if (-1 == sem_post(&lock)) {
			perror("sem_post(&lock) didn't return success");
			pthread_exit((void *)1);
		}
		if (-1 == sem_wait(&customer)) {
			perror("sem_wait(&customer) didn't return success");
			pthread_exit((void *)1);
		}
		if (-1 == sem_wait(&lock)) {
			perror("sem_wait(&lock) didn't return success");
			pthread_exit((void *)1);
		}
		if (waiting >= 1)
			waiting--;
		my_printf
		    ("A customer sits in the barber's chair and get a hair cut.  %d customers left waiting.\n",
		     waiting);
		if (-1 == sem_post(&lock)) {
			perror("sem_post(&lock) didn't return success");
			pthread_exit((void *)1);
		}
		if (-1 == sem_post(&barber)) {
			perror("sem_post(&barber) didn't return success");
			pthread_exit((void *)1);
		}

	}
	return NULL;
}

void *customers(void *ID)
{
	int CusID;
	CusID = *(int *)ID;

	if (CusID == 8)
		mdelay(10);

	my_printf("customer %d enters the room.\n", CusID);
	if (-1 == sem_wait(&lock)) {
		perror("sem_wait(&lock) didn't return success");
		pthread_exit((void *)1);
	}
	if (waiting < CHAIR_NUM) {
		waiting = waiting + 1;
		if (-1 == sem_post(&customer)) {
			perror("sem_post(&customer) didn't return success");
			pthread_exit((void *)1);
		}
		my_printf
		    ("Customer %d sits down, now %d customers are waiting.\n",
		     CusID, waiting);
		if (-1 == sem_post(&lock)) {
			perror("sem_post(&lock) didn't return success");
			pthread_exit((void *)1);
		}
		if (-1 == sem_wait(&barber)) {
			perror("sem_wait(&barber) didn't return success");
			pthread_exit((void *)1);
		}
		my_printf("Customer %d leaves with nice hair.\n", CusID);
	} else {
		my_printf
		    ("No chairs available, customer %d leaves without a haircut.\n",
		     CusID);
		if (-1 == sem_post(&lock)) {
			perror("sem_post(&lock) didn't return success");
			pthread_exit((void *)1);
		}
	}
	return NULL;
}

int main(void)
{
	pthread_t bar, cus[CUS_NUM];
	int shared = 0;
	int barber_value = 0;
	int customer_value = 0;
	int lock_value = 1;
	int i, ID[CUS_NUM];

	if (-1 == sem_init(&print, shared, 1)) {
		perror("sem_init(&print) didn't return success");
		return PTS_UNRESOLVED;
	}
#ifndef  _POSIX_SEMAPHORES
	my_printf("_POSIX_SEMAPHORES is not defined\n");
	return PTS_UNRESOLVED;
#endif
	if (-1 == sem_init(&customer, shared, customer_value)) {
		perror("sem_init(&customer) didn't return success");
		return PTS_UNRESOLVED;
	}
	if (-1 == sem_init(&barber, shared, barber_value)) {
		perror("sem_init(&barber) didn't return success");
		return PTS_UNRESOLVED;
	}
	if (-1 == sem_init(&lock, shared, lock_value)) {
		perror("sem_init(&lock) didn't return success");
		return PTS_UNRESOLVED;
	}
	for (i = 0; i < CUS_NUM; i++) {
		ID[i] = i;
		pthread_create(&cus[i], NULL, customers, (void *)&ID[i]);
	}
	pthread_create(&bar, NULL, barbers, NULL);
	for (i = 0; i < CUS_NUM; i++)
		pthread_join(cus[i], NULL);

	return PTS_PASS;
}