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