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