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