-
Notifications
You must be signed in to change notification settings - Fork 1
/
read_write.c
154 lines (125 loc) · 3.49 KB
/
read_write.c
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
/*************************************************************
*
Author: Denny Abraham Cheriyan, Adrin Peter Fernandes
Readers/Writers problem using custom semaphores.
Code taken from the Readers/Writers problem using lpthreads
which was written by Partha Dasgupta
rwc - readers waiting count
wwc - writer waiting count
rc - reader count
wc - writer count
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sem.h"
Semaphore_t r_sem, w_sem, mutex;
int rwc = 0, wwc = 0, rc = 0, wc = 0, global_ID=0;
//When there are no waiting writers or current writers -
//Reader entry - One reader will acquire the lock, and then -
// If there are no waiting readers ( happens when waiting writers or current writers ) it will release the lock
// else it will release one waiting reader which will release another waiting reader(cascading effect),
// and the last waiting reader will release the lock
void reader_entry(int ID)
{
printf("[reader: #%d]\ttrying to read\n", ID);
P(&mutex);
if (wwc > 0 || wc > 0) {
printf("[reader: #%d]\tblocking for writer\n", ID);
rwc++; // increment waiting reader count.
V(&mutex); // let other processes use the mutex.
P(&r_sem); // sleep on r_sem
rwc--; // program now has mutex and r_sem, go
// into CS.
}
rc++;
if (rwc > 0)
V(&r_sem);
else
V(&mutex); // let other processes use the mutex.
}
//Reader exit - Acquire lock. Then -
// if its the last reader and someone is waiting to write release write lock
// else release lock
void reader_exit(int ID)
{
P(&mutex);
rc--; // i'm no longer a reader
if (rc == 0 && wwc > 0) {
// if was the last reader, and there are waiting writers, open
// the w_sem door for them.
V(&w_sem);
} else
V(&mutex);
}
//if there is no active reader or writer
// Acquire lock -> increment counter -> release lock
// else make writer wait release mutex and acquire write mutex. (Release mutex which the reader exit forgot to)
void writer_entry(int ID)
{
printf("\t\t\t\t[writer: #%d]\ttrying to write\n", ID);
P(&mutex);
if (rc > 0 || wc > 0) {
printf("\t\t\t\t[writer: #%d] blocking for others\n", ID);
wwc++; // increment waiting writers
V(&mutex); // let go of the mutex, since i'll be
// blocked
P(&w_sem); // wait in my line, when i wake up i DON'T
// need a P(mutex since i've been given it
// by the waking process.
wwc--; // i'm no longer waiting
}
wc++; // increment writers
V(&mutex); // let go of the mutex
}
void writer_exit(int ID)
{
P(&mutex);
wc--;
if (rwc > 0) { // first, i let all the readers go.
V(&r_sem);
} else if (wwc > 0) { // then i let another writer go
V(&w_sem);
} else { // lastly, i give up the mutex
V(&mutex);
}
}
void reader(void)
{
int ID;
P(&mutex); ID = global_ID++; V(&mutex);
while(1){
reader_entry(ID);
printf
("[reader #%d]\t****READING****\n", ID);
sleep(1);
reader_exit(ID);
};
}
void writer(void)
{
int ID;
P(&mutex); ID = global_ID++; V(&mutex);
while(1){
writer_entry(ID);
printf
("\t\t\t\t[writer: #%d]\t&&&WRITING!&&&\n", ID);
sleep(1);
writer_exit(ID);
};
}
//-------------------------------------------------------
int main()
{
mutex = CreateSem(1);
r_sem = CreateSem(0);
w_sem = CreateSem(0);
start_thread(reader);
start_thread(reader);
start_thread(reader);
start_thread(reader);
start_thread(writer);
start_thread(writer);
run();
while (1) sleep(1);
}