36325fd4e65befcfb3c19126b5b63d89a649803b
[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()
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         LWP_CreateProcess(read_process, STACK_SIZE, 0, (void *)&readerid[i],
225                           "Reader", &readers[i]);
226     printf("done]\n");
227
228     printf("\t[Creating Writer...\n");
229     LWP_CreateProcess(write_process, STACK_SIZE, 1, 0, "Writer", &writer);
230     printf("done]\n");
231
232     /* Now loop until everyone's done */
233     while (asleep != nreaders + 1)
234         LWP_DispatchProcess();
235     /* Destroy the readers */
236     for (i = nreaders - 1; i >= 0; i--)
237         LWP_DestroyProcess(readers[i]);
238     printf("\n*Exiting*\n");
239 }