reindent-20030715
[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 RCSID
21     ("$Header$");
22
23 #ifdef AFS_NT40_ENV
24 #include <malloc.h>
25 #include <stdlib.h>
26 #else
27 #include <sys/time.h>
28 extern char *calloc();
29 #endif
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #include "lwp.h"
34 #include "lock.h"
35 #include "preempt.h"
36 #include <afs/assert.h>
37
38 #define DEFAULT_READERS 5
39
40 #define STACK_SIZE      (16*1024)
41
42 /* The shared queue */
43 typedef struct QUEUE {
44     struct QUEUE *prev, *next;
45     char *data;
46     struct Lock lock;
47 } queue;
48
49 queue *
50 init()
51 {
52     queue *q;
53
54     q = (queue *) malloc(sizeof(queue));
55     q->prev = q->next = q;
56     return (q);
57 }
58
59 char
60 empty(q)
61      queue *q;
62 {
63     return (q->prev == q && q->next == q);
64 }
65
66 void
67 insert(queue * q, char *s)
68 {
69     queue *new;
70
71     new = (queue *) malloc(sizeof(queue));
72     new->data = s;
73     new->prev = q->prev;
74     q->prev->next = new;
75     q->prev = new;
76     new->next = q;
77 }
78
79 char *
80 Remove(q)
81      queue *q;
82 {
83     queue *old;
84     char *s;
85
86     if (empty(q)) {
87         printf("Remove from empty queue");
88         assert(0);
89     }
90
91     old = q->next;
92     q->next = old->next;
93     q->next->prev = q;
94     s = old->data;
95     free(old);
96     return (s);
97 }
98 \f
99 queue *q;
100
101 int asleep;                     /* Number of processes sleeping -- used for
102                                  * clean termination */
103
104 static int
105 read_process(id)
106      int *id;
107 {
108     printf("\t[Reader %d]\n", *id);
109     LWP_DispatchProcess();      /* Just relinquish control for now */
110
111     PRE_PreemptMe();
112     for (;;) {
113         register int i;
114
115         /* Wait until there is something in the queue */
116         asleep++;
117         ObtainReadLock(&q->lock);
118         while (empty(q)) {
119             ReleaseReadLock(&q->lock);
120             LWP_WaitProcess(q);
121             ObtainReadLock(&q->lock);
122         }
123         asleep--;
124         for (i = 0; i < 10000; i++);
125         PRE_BeginCritical();
126         printf("[%d: %s]\n", *id, Remove(q));
127         PRE_EndCritical();
128         ReleaseReadLock(&q->lock);
129         LWP_DispatchProcess();
130     }
131     return 0;
132 }
133
134 static int
135 write_process()
136 {
137     static char *messages[] = {
138         "Mary had a little lamb,",
139         "Its fleece was white as snow,",
140         "And everywhere that Mary went,",
141         "The lamb was sure to go",
142         "Mary had a little lamb,",
143         "Its fleece was white as snow,",
144         "And everywhere that Mary went,",
145         "The lamb was sure to go",
146         "Mary had a little lamb,",
147         "Its fleece was white as snow,",
148         "And everywhere that Mary went,",
149         "The lamb was sure to go",
150         "Mary had a little lamb,",
151         "Its fleece was white as snow,",
152         "And everywhere that Mary went,",
153         "The lamb was sure to go",
154         "Mary had a little lamb,",
155         "Its fleece was white as snow,",
156         "And everywhere that Mary went,",
157         "The lamb was sure to go",
158         "Mary had a little lamb,",
159         "Its fleece was white as snow,",
160         "And everywhere that Mary went,",
161         "The lamb was sure to go",
162         "Mary had a little lamb,",
163         "Its fleece was white as snow,",
164         "And everywhere that Mary went,",
165         "The lamb was sure to go",
166         "Mary had a little lamb,",
167         "Its fleece was white as snow,",
168         "And everywhere that Mary went,",
169         "The lamb was sure to go",
170         "Mary had a little lamb,",
171         "Its fleece was white as snow,",
172         "And everywhere that Mary went,",
173         "The lamb was sure to go",
174         "Mary had a little lamb,",
175         "Its fleece was white as snow,",
176         "And everywhere that Mary went,",
177         "The lamb was sure to go",
178         0
179     };
180     char **mesg;
181
182     printf("\t[Writer]\n");
183     PRE_PreemptMe();
184
185     /* Now loop & write data */
186     for (mesg = messages; *mesg != 0; mesg++) {
187         ObtainWriteLock(&q->lock);
188         insert(q, *mesg);
189         ReleaseWriteLock(&q->lock);
190         LWP_SignalProcess(q);
191     }
192
193     asleep++;
194     return 0;
195 }
196
197 /*
198         Arguments:
199                 0:      Unix junk, ignore
200                 1:      Number of readers to create (default is DEFAULT_READERS)
201                 2:      # msecs for interrupt (to satisfy Larry)
202                 3:      Present if lwp_debug to be set
203 */
204
205 #include "AFS_component_version_number.c"
206
207 main(argc, argv)
208      int argc;
209      char **argv;
210 {
211     int nreaders, i;
212     PROCESS pid;
213     afs_int32 interval;         /* To satisfy Brad */
214     PROCESS *readers;
215     int *readerid;
216     PROCESS writer;
217     struct timeval tv;
218
219     printf("\n*Readers & Writers*\n\n");
220     setbuf(stdout, 0);
221
222     /* Determine # readers */
223     if (argc == 1)
224         nreaders = DEFAULT_READERS;
225     else
226         sscanf(*++argv, "%d", &nreaders);
227     printf("[There will be %d readers]\n", nreaders);
228
229     interval = (argc >= 3 ? atoi(*++argv) * 1000 : 50000);
230
231     if (argc == 4)
232         lwp_debug = 1;
233     LWP_InitializeProcessSupport(0, &pid);
234     printf("[Support initialized]\n");
235     tv.tv_sec = 0;
236     tv.tv_usec = interval;
237     PRE_InitPreempt(&tv);
238
239     /* Initialize queue */
240     q = init();
241
242     /* Initialize lock */
243     Lock_Init(&q->lock);
244
245     asleep = 0;
246     /* Now create readers */
247     printf("[Creating Readers...\n");
248     readers = (PROCESS *) calloc(nreaders, sizeof(PROCESS));
249     readerid = (int *)calloc(nreaders, sizeof(i));
250     for (i = 0; i < nreaders; i++)
251         LWP_CreateProcess(read_process, STACK_SIZE, 0, (void *)&readerid[i],
252                           "Reader", &readers[i]);
253     printf("done]\n");
254
255     printf("\t[Creating Writer...\n");
256     LWP_CreateProcess(write_process, STACK_SIZE, 1, 0, "Writer", &writer);
257     printf("done]\n");
258
259     /* Now loop until everyone's done */
260     while (asleep != nreaders + 1)
261         LWP_DispatchProcess();
262     /* Destroy the readers */
263     for (i = nreaders - 1; i >= 0; i--)
264         LWP_DestroyProcess(readers[i]);
265     printf("\n*Exiting*\n");
266 }