Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / lwp / rw.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /*
11 (Multiple) readers & writers test of LWP stuff.
12
13 Created: 11/1/83, J. Rosenberg
14
15 */
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20 #include <roken.h>
21
22 #include "lwp.h"
23 #include "lock.h"
24
25 #define DEFAULT_READERS 5
26
27 #define STACK_SIZE (16*1024)
28
29 /* The shared queue */
30 typedef struct QUEUE {
31 struct QUEUE *prev, *next;
32 char *data;
33 struct Lock lock;
34 } queue;
35
36 queue *
37 init(void)
38 {
39 queue *q;
40
41 q = malloc(sizeof(queue));
42 q->prev = q->next = q;
43 return (q);
44 }
45
46 char
47 empty(queue *q)
48 {
49 return (q->prev == q && q->next == q);
50 }
51
52 void
53 insert(queue * q, char *s)
54 {
55 queue *new;
56
57 new = malloc(sizeof(queue));
58 new->data = s;
59 new->prev = q->prev;
60 q->prev->next = new;
61 q->prev = new;
62 new->next = q;
63 }
64
65 char *
66 Remove(queue *q)
67 {
68 queue *old;
69 char *s;
70
71 if (empty(q)) {
72 printf("Remove from empty queue");
73 exit(0);
74 }
75
76 old = q->next;
77 q->next = old->next;
78 q->next->prev = q;
79 s = old->data;
80 free(old);
81 return (s);
82 }
83
84 queue *q;
85
86 int asleep; /* Number of processes sleeping -- used for
87 * clean termination */
88
89 static void *
90 read_process(void *arg)
91 {
92 int *id = (int *) arg;
93 printf("\t[Reader %d]\n", *id);
94 LWP_DispatchProcess(); /* Just relinquish control for now */
95
96 for (;;) {
97 int i;
98
99 /* Wait until there is something in the queue */
100 asleep++;
101 ObtainReadLock(&q->lock);
102 while (empty(q)) {
103 ReleaseReadLock(&q->lock);
104 LWP_WaitProcess(q);
105 ObtainReadLock(&q->lock);
106 }
107 asleep--;
108 for (i = 0; i < 10000; i++);
109 printf("[%d: %s]\n", *id, Remove(q));
110 ReleaseReadLock(&q->lock);
111 LWP_DispatchProcess();
112 }
113 return 0;
114 }
115
116 static void *
117 write_process(void *dummy)
118 {
119 static char *messages[] = {
120 "Mary had a little lamb,",
121 "Its fleece was white as snow,",
122 "And everywhere that Mary went,",
123 "The lamb was sure to go",
124 "Mary had a little lamb,",
125 "Its fleece was white as snow,",
126 "And everywhere that Mary went,",
127 "The lamb was sure to go",
128 "Mary had a little lamb,",
129 "Its fleece was white as snow,",
130 "And everywhere that Mary went,",
131 "The lamb was sure to go",
132 "Mary had a little lamb,",
133 "Its fleece was white as snow,",
134 "And everywhere that Mary went,",
135 "The lamb was sure to go",
136 "Mary had a little lamb,",
137 "Its fleece was white as snow,",
138 "And everywhere that Mary went,",
139 "The lamb was sure to go",
140 "Mary had a little lamb,",
141 "Its fleece was white as snow,",
142 "And everywhere that Mary went,",
143 "The lamb was sure to go",
144 "Mary had a little lamb,",
145 "Its fleece was white as snow,",
146 "And everywhere that Mary went,",
147 "The lamb was sure to go",
148 "Mary had a little lamb,",
149 "Its fleece was white as snow,",
150 "And everywhere that Mary went,",
151 "The lamb was sure to go",
152 "Mary had a little lamb,",
153 "Its fleece was white as snow,",
154 "And everywhere that Mary went,",
155 "The lamb was sure to go",
156 "Mary had a little lamb,",
157 "Its fleece was white as snow,",
158 "And everywhere that Mary went,",
159 "The lamb was sure to go",
160 0
161 };
162 char **mesg;
163
164 printf("\t[Writer]\n");
165
166 /* Now loop & write data */
167 for (mesg = messages; *mesg != 0; mesg++) {
168 ObtainWriteLock(&q->lock);
169 insert(q, *mesg);
170 ReleaseWriteLock(&q->lock);
171 LWP_SignalProcess(q);
172 }
173
174 asleep++;
175 return 0;
176 }
177
178 /*
179 Arguments:
180 0: Unix junk, ignore
181 1: Number of readers to create (default is DEFAULT_READERS)
182 2: # msecs for interrupt (to satisfy Larry)
183 3: Present if lwp_debug to be set
184 */
185
186 #include "AFS_component_version_number.c"
187
188 int
189 main(int argc, char **argv)
190 {
191 int nreaders, i;
192 PROCESS pid;
193 PROCESS *readers;
194 int *readerid;
195 PROCESS writer;
196
197 printf("\n*Readers & Writers*\n\n");
198 setbuf(stdout, 0);
199
200 /* Determine # readers */
201 if (argc == 1)
202 nreaders = DEFAULT_READERS;
203 else
204 sscanf(*++argv, "%d", &nreaders);
205 printf("[There will be %d readers]\n", nreaders);
206
207 if (argc == 4)
208 lwp_debug = 1;
209 LWP_InitializeProcessSupport(0, &pid);
210 printf("[Support initialized]\n");
211
212 /* Initialize queue */
213 q = init();
214
215 /* Initialize lock */
216 Lock_Init(&q->lock);
217
218 asleep = 0;
219 /* Now create readers */
220 printf("[Creating Readers...\n");
221 readers = (PROCESS *) calloc(nreaders, sizeof(PROCESS));
222 readerid = calloc(nreaders, sizeof(i));
223 for (i = 0; i < nreaders; i++) {
224 readerid[i] = i;
225 LWP_CreateProcess(read_process, STACK_SIZE, 0, (void *)&readerid[i],
226 "Reader", &readers[i]);
227 }
228 printf("done]\n");
229
230 printf("\t[Creating Writer...\n");
231 LWP_CreateProcess(write_process, STACK_SIZE, 1, 0, "Writer", &writer);
232 printf("done]\n");
233
234 /* Now loop until everyone's done */
235 while (asleep != nreaders + 1)
236 LWP_DispatchProcess();
237 /* Destroy the readers */
238 for (i = nreaders - 1; i >= 0; i--)
239 LWP_DestroyProcess(readers[i]);
240 LWP_DestroyProcess(writer);
241
242 LWP_TerminateProcessSupport();
243
244 printf("\n*Exiting*\n");
245
246 exit(0);
247 }