1// readerWriter.c
2
3#include "betalk.h"
4#include "readerWriter.h"
5
6
7void btLock(sem_id semaphore, int32 *atomic)
8{
9	int32 previous = atomic_add(atomic, 1);
10	if (previous >= 1)
11		while (acquire_sem(semaphore) == B_INTERRUPTED);
12}
13
14void btUnlock(sem_id semaphore, int32 *atomic)
15{
16	int32 previous = atomic_add(atomic, -1);
17	if (previous > 1)
18		release_sem(semaphore);
19}
20
21bool initManagedData(bt_managed_data *data)
22{
23	data->readCount = 0;
24	data->writeCount = 0;
25
26	data->readCountVar = 0;
27	data->writeCountVar = 0;
28	data->readerQueueVar = 0;
29	data->readerVar = 0;
30	data->writerVar = 0;
31
32	if ((data->readCountSem = create_sem(1, "Read Counter")) < 0)
33		return false;
34
35	if ((data->writeCountSem = create_sem(1, "Write Counter")) < 0)
36	{
37		delete_sem(data->readCountSem);
38		return false;
39	}
40
41	if ((data->readerQueue = create_sem(1, "Read Queue")) < 0)
42	{
43		delete_sem(data->writeCountSem);
44		delete_sem(data->readCountSem);
45		return false;
46	}
47
48	if ((data->reader = create_sem(1, "Single Reader")) < 0)
49	{
50		delete_sem(data->readerQueue);
51		delete_sem(data->writeCountSem);
52		delete_sem(data->readCountSem);
53		return false;
54	}
55
56	if ((data->writer = create_sem(1, "Writer")) < 0)
57	{
58		delete_sem(data->reader);
59		delete_sem(data->readerQueue);
60		delete_sem(data->writeCountSem);
61		delete_sem(data->readCountSem);
62		return false;
63	}
64
65	set_sem_owner(data->readCountSem, B_SYSTEM_TEAM);
66	set_sem_owner(data->writeCountSem, B_SYSTEM_TEAM);
67	set_sem_owner(data->readerQueue, B_SYSTEM_TEAM);
68	set_sem_owner(data->reader, B_SYSTEM_TEAM);
69	set_sem_owner(data->writer, B_SYSTEM_TEAM);
70
71	return true;
72}
73
74void closeManagedData(bt_managed_data *data)
75{
76	data->readCount = data->writeCount = 0;
77
78	delete_sem(data->writer);
79	delete_sem(data->reader);
80	delete_sem(data->readerQueue);
81	delete_sem(data->writeCountSem);
82	delete_sem(data->readCountSem);
83}
84
85void beginReading(bt_managed_data *data)
86{
87	btLock(data->readerQueue, &data->readerQueueVar);
88	btLock(data->reader, &data->readerVar);
89	btLock(data->readCountSem, &data->readCountVar);
90
91	data->readCount++;
92	if (data->readCount == 1)
93		btLock(data->writer, &data->writerVar);
94
95	btUnlock(data->readCountSem, &data->readCountVar);
96	btUnlock(data->reader, &data->readerVar);
97	btUnlock(data->readerQueue, &data->readerQueueVar);
98}
99
100void endReading(bt_managed_data *data)
101{
102	btLock(data->readCountSem, &data->readCountVar);
103
104	data->readCount--;
105	if (data->readCount == 0)
106		btUnlock(data->writer, &data->writerVar);
107
108	btUnlock(data->readCountSem, &data->readCountVar);
109}
110
111void beginWriting(bt_managed_data *data)
112{
113	btLock(data->writeCountSem, &data->writeCountVar);
114
115	data->writeCount++;
116	if (data->writeCount == 1)
117		btLock(data->reader, &data->readerVar);
118
119	btUnlock(data->writeCountSem, &data->writeCountVar);
120	btLock(data->writer, &data->writerVar);
121}
122
123void endWriting(bt_managed_data *data)
124{
125	btUnlock(data->writer, &data->writerVar);
126	btLock(data->writeCountSem, &data->writeCountVar);
127
128	data->writeCount--;
129	if (data->writeCount == 0)
130		btUnlock(data->reader, &data->readerVar);
131
132	btUnlock(data->writeCountSem, &data->writeCountVar);
133}
134