alpha-cleanup-20020119
[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("$Header$");
21
22 #ifdef AFS_NT40_ENV
23 #include <malloc.h>
24 #include <stdlib.h>
25 #else
26 #include <sys/time.h>
27 extern char *calloc();
28 #endif
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include "lwp.h"
33 #include "lock.h"
34 #include "preempt.h"
35 #include <afs/assert.h>
36
37 #define DEFAULT_READERS 5
38
39 #define STACK_SIZE      (16*1024)
40
41 /* The shared queue */
42 typedef struct QUEUE {
43     struct QUEUE        *prev, *next;
44     char                *data;
45     struct Lock         lock;
46 } queue;
47
48 queue *init()
49 {
50     queue *q;
51
52     q = (queue *) malloc(sizeof(queue));
53     q -> prev = q -> next = q;
54     return(q);
55 }
56
57 char empty(q)
58     queue *q;
59 {
60     return (q->prev == q && q->next == q);
61 }
62
63 void insert(queue *q, char *s)
64 {
65     queue *new;
66
67     new = (queue *) malloc(sizeof(queue));
68     new -> data = s;
69     new -> prev = q -> prev;
70     q -> prev -> next = new;
71     q -> prev = new;
72     new -> next = q;
73 }
74
75 char *Remove(q)
76     queue *q;
77 {
78     queue *old;
79     char *s;
80
81     if (empty(q)) {
82         printf("Remove from empty queue");
83         assert(0);
84     }
85
86     old = q -> next;
87     q -> next = old -> next;
88     q -> next -> prev = q;
89     s = old -> data;
90     free(old);
91     return(s);
92 }
93 \f
94 queue *q;
95
96 int asleep;     /* Number of processes sleeping -- used for
97                    clean termination */
98
99 static int read_process(id)
100     int *id;
101 {
102     printf("\t[Reader %d]\n", *id);
103     LWP_DispatchProcess();              /* Just relinquish control for now */
104
105     PRE_PreemptMe();
106     for (;;) {
107         register 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 int write_process()
129 {
130     static char *messages[] =
131     {
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 main(argc, argv)
202    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) lwp_debug = 1;
225     LWP_InitializeProcessSupport(0, &pid);
226     printf("[Support initialized]\n");
227     tv.tv_sec = 0;
228     tv.tv_usec = interval;
229     PRE_InitPreempt(&tv);
230
231     /* Initialize queue */
232     q = init();
233
234     /* Initialize lock */
235     Lock_Init(&q->lock);
236
237     asleep = 0;
238     /* Now create readers */
239     printf("[Creating Readers...\n");
240     readers = (PROCESS *) calloc(nreaders, sizeof(PROCESS));
241     readerid = (int *)calloc(nreaders, sizeof(i));
242     for (i=0; i<nreaders; i++)
243         LWP_CreateProcess(read_process, STACK_SIZE, 0, (void*)&readerid[i],
244                           "Reader", &readers[i]);
245     printf("done]\n");
246
247     printf("\t[Creating Writer...\n");
248     LWP_CreateProcess(write_process, STACK_SIZE, 1, 0, "Writer", &writer);
249     printf("done]\n");
250
251     /* Now loop until everyone's done */
252     while (asleep != nreaders+1) LWP_DispatchProcess();
253     /* Destroy the readers */
254     for (i=nreaders-1; i>=0; i--) LWP_DestroyProcess(readers[i]);
255     printf("\n*Exiting*\n");
256 }
257