1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  crystal.xiong REMOVE-THIS AT intel DOT com
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7 *
8 * This test use semaphore to implement reader and writer problem. Some readers
9 * and some writers read/write on one blackboard. Only one writer allow to
10 * write on the board at the same time. Reader and Writer can't use the board
11 * the same time. Reader has higher priority than writer, which means only when
12 * no reader reads the board, the writer can write the board.
13 */
14#include <stdio.h>
15#include <unistd.h>
16#include <fcntl.h>
17#include <stdlib.h>
18#include <sys/wait.h>
19#include <sys/mman.h>
20#include <string.h>
21#include <errno.h>
22#include <semaphore.h>
23#include <pthread.h>
24
25#include "posixtest.h"
26
27#define SEM_NAME       "/tmp/semaphore"
28#define READ_NUM	10
29#define WRITE_NUM	15
30
31sem_t r_lock, w_lock;
32int reader_count = 0;
33int data = 0;
34
35int read_fun(int ID)
36{
37	printf("read the board, data=%d \n", data);
38	return 0;
39}
40
41int write_fun(int ID)
42{
43	data = 100 * ID + ID;
44	printf("write the board, data=%d \n", data);
45	return 0;
46}
47
48int *reader(void *ID)
49{
50	int ThID = *(int *)ID;
51	if (-1 == sem_wait(&r_lock)) {
52		perror("sem_wait didn't return success\n");
53		pthread_exit((void *)1);
54	}
55	reader_count++;
56	printf("Enter into Reader thread, reader_count=%d \n", reader_count);
57	if (reader_count == 1) {
58		if (-1 == sem_wait(&w_lock)) {
59			perror("sem_wait didn't return success \n");
60			pthread_exit((void *)1);
61		}
62	}
63	if (-1 == sem_post(&r_lock)) {
64		perror("sem_post didn't return success \n");
65		pthread_exit((void *)1);
66	}
67	sleep(1);
68	read_fun(ThID);
69	if (-1 == sem_wait(&r_lock)) {
70		perror("sem_wait didn't return success \n");
71		pthread_exit((void *)1);
72	}
73	reader_count--;
74	if (reader_count == 0) {
75		if (-1 == sem_post(&w_lock)) {
76			perror("sem_post didn't return success \n");
77			pthread_exit((void *)1);
78		}
79	}
80	if (-1 == sem_post(&r_lock)) {
81		perror("sem_post didn't return success \n");
82		pthread_exit((void *)1);
83	}
84	printf("Reader Thread [%d] exit...reader_count=%d \n", ThID,
85	       reader_count);
86	pthread_exit(NULL);
87}
88
89int *writer(void *ID)
90{
91	int ThID = *(int *)ID;
92/* When ThID is equal to WRITE_NUM/2, sleep 2 second and let reader read the data */
93	if (ThID >= WRITE_NUM / 2)
94		sleep(2);
95	if (-1 == sem_wait(&w_lock)) {
96		perror("sem_wait didn't return success \n");
97		pthread_exit((void *)1);
98	}
99	write_fun(ThID);
100	if (-1 == sem_post(&w_lock)) {
101		perror("sem_post didn't return success \n");
102		pthread_exit((void *)1);
103	}
104	printf("Writer Thread [%d] exit...\n", ThID);
105	pthread_exit(NULL);
106}
107
108int main(int argc, char *argv[])
109{
110	pthread_t rea[READ_NUM], wri[WRITE_NUM];
111	int ReadID[READ_NUM], WriteID[WRITE_NUM];
112	int shared = 1;
113	int r_value = 1;
114	int w_value = 1;
115	int i;
116
117#ifndef  _POSIX_SEMAPHORES
118	printf("_POSIX_SEMAPHORES is not defined \n");
119	return PTS_UNRESOLVED;
120#endif
121	if (-1 == sem_init(&r_lock, shared, r_value)) {
122		perror("sem_init didn't return success \n");
123		return PTS_UNRESOLVED;
124	}
125	if (-1 == sem_init(&w_lock, shared, w_value)) {
126		perror("sem_init didn't return success \n");
127		return PTS_UNRESOLVED;
128	}
129
130	for (i = 0; i < WRITE_NUM; i++) {
131		WriteID[i] = i;
132		pthread_create(&wri[i], NULL, (void *)writer, &WriteID[i]);
133	}
134	for (i = 0; i < READ_NUM; i++) {
135		ReadID[i] = i;
136		pthread_create(&rea[i], NULL, (void *)reader, &ReadID[i]);
137	}
138
139	for (i = 0; i < READ_NUM; i++)
140		pthread_join(rea[i], NULL);
141	for (i = 0; i < WRITE_NUM; i++)
142		pthread_join(wri[i], NULL);
143
144	if (-1 == sem_destroy(&r_lock)) {
145		perror("sem_destroy didn't return success \n");
146		return PTS_UNRESOLVED;
147	}
148	if (-1 == sem_destroy(&w_lock)) {
149		perror("sem_destroy didn't return success \n");
150		return PTS_UNRESOLVED;
151	}
152	return PTS_PASS;
153}
154