windows-more-updates-20030315
[openafs.git] / src / WINNT / client_osi / basic.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 /* Copyright (C) 1994 Cazamar Systems, Inc. */
11
12
13 #include <afs/param.h>
14 #include <afs/stds.h>
15
16 #include "windows.h"
17 #include <string.h>
18 #include "main.h"
19 #include "basic.h"
20 #include "osi.h"
21
22 #define OSI_MOD1LOOPS   15000
23 #define OSI_MOD2LOOPS   10000
24
25 /* global variables for the test */
26 osi_mutex_t main_aMutex;        /* mutex controlling access to a */
27 long a;                         /* variable a */
28
29 osi_rwlock_t main_bRWLock;      /* rwlock controlling access to b */
30 long b;                         /* variable b itself */
31
32 osi_rwlock_t main_doneRWLock;   /* lock for done */
33 int done;                       /* count of done dudes */
34
35 osi_log_t *main_logp;           /* global log */
36
37 /* unlocked stat counters */
38 long m1Loops;
39 long m2Loops;
40 long s1Loops;
41 long s2Loops;
42 long s2Events;
43
44 unsigned long main_Mod1(void *parm)
45 {
46         long i;
47         for(i=0; i<OSI_MOD1LOOPS; i++) {
48                 lock_ObtainMutex(&main_aMutex);
49                 osi_Log0(main_logp, "mod1");
50                 lock_ObtainWrite(&main_bRWLock);
51                 a -= 52;
52                 Sleep(0);
53                 b += 52;
54                 osi_assert(a+b == 100);
55                 Sleep(0);
56                 lock_ReleaseWrite(&main_bRWLock);
57                 Sleep(0);
58                 lock_ReleaseMutex(&main_aMutex);
59                 Sleep(0);
60                 m1Loops = i;
61                 osi_Log1(main_logp, "mod1 done, %d", m1Loops);
62         }
63         lock_ObtainWrite(&main_doneRWLock);
64         done++;
65         Sleep(0);
66         lock_ReleaseWrite(&main_doneRWLock);
67         return 0;
68 }
69
70 unsigned long main_Mod2(void *parm)
71 {
72         long i;
73         for(i=0; i<OSI_MOD2LOOPS; i++) {
74                 osi_Log0(main_logp, "mod2");
75                 lock_ObtainMutex(&main_aMutex);
76                 lock_ObtainWrite(&main_bRWLock);
77                 a += 3;
78                 Sleep(0);
79                 b -= 3;
80                 osi_assert(a+b == 100);
81                 Sleep(0);
82                 lock_ReleaseWrite(&main_bRWLock);
83                 Sleep(0);
84                 lock_ReleaseMutex(&main_aMutex);
85                 Sleep(0);
86                 m2Loops = i;
87                 osi_Log4(main_logp, "mod2 done, %d %d %d %d", m2Loops, 2, 3, 4);
88         }
89         lock_ObtainWrite(&main_doneRWLock);
90         done++;
91         Sleep(0);
92         lock_ReleaseWrite(&main_doneRWLock);
93         return 0;
94 }
95
96 unsigned long main_Scan1(unsigned long parm)
97 {
98         while (1) {
99                 osi_Log0(main_logp, "scan1");
100                 /* check to see if we're done */
101                 lock_ObtainRead(&main_doneRWLock);
102                 lock_AssertRead(&main_doneRWLock);
103                 if (done >= 2) break;
104                 lock_ReleaseRead(&main_doneRWLock);
105
106                 /* check state for consistency */
107                 lock_ObtainMutex(&main_aMutex);
108                 lock_AssertMutex(&main_aMutex);
109                 Sleep(0);
110                 lock_ObtainRead(&main_bRWLock);
111                 Sleep(0);
112                 osi_assert(a+b == 100);
113                 lock_ReleaseRead(&main_bRWLock);
114                 Sleep(0);
115                 lock_ReleaseMutex(&main_aMutex);
116
117                 /* get a read lock here to test people getting stuck on RW lock alone */
118                 lock_ObtainRead(&main_bRWLock);
119                 Sleep(0);
120                 lock_ReleaseRead(&main_bRWLock);
121                 
122                 s1Loops++;
123                 
124                 osi_Log2(main_logp, "scan1 done %d %d", s1Loops, 2);
125         }
126         lock_ReleaseRead(&main_doneRWLock);
127         lock_ObtainWrite(&main_doneRWLock);
128         lock_AssertWrite(&main_doneRWLock);
129         done++;
130         lock_ReleaseWrite(&main_doneRWLock);
131         return 0;
132 }
133
134 unsigned long main_Scan2(unsigned long parm)
135 {
136         while (1) {
137                 osi_Log0(main_logp, "scan2");
138                 /* check to see if we're done */
139                 lock_ObtainRead(&main_doneRWLock);
140                 lock_AssertAny(&main_doneRWLock);
141                 if (done >= 2) break;
142                 lock_ReleaseRead(&main_doneRWLock);
143
144                 /* check state for consistency without locks */
145                 if (a+b != 100) s2Events++;
146
147                 /* and record that we went around again */
148                 s2Loops++;
149
150                 /* give others a chance */
151                 Sleep(0);
152                 osi_Log3(main_logp, "scan2 done %d %d %d", s2Loops, 2, 3);
153         }
154         lock_ReleaseRead(&main_doneRWLock);
155         lock_ObtainWrite(&main_doneRWLock);
156         lock_AssertAny(&main_doneRWLock);
157         done++;
158         lock_ReleaseWrite(&main_doneRWLock);
159         return 0;
160 }
161
162 main_BasicTest(HANDLE hWnd)
163 {
164         long mod1ID;
165         long mod2ID;
166         long scan1ID;
167         long scan2ID;
168         HANDLE mod1Handle;
169         HANDLE mod2Handle;
170         HANDLE scan1Handle;
171         HANDLE scan2Handle;
172         long localDone;
173
174         osi_Init();
175         
176         if (main_logp == NULL) {
177                 main_logp = osi_LogCreate("basic", 0);
178                 osi_LogEnable(main_logp);
179                 osi_SetStatLog(main_logp);
180         }
181         
182         /* create three processes, two modifiers and one scanner.  The scanner
183          * checks that the basic invariants are being maintained, while the
184          * modifiers modify the global variables, maintaining certain invariants
185          * by using locks.
186          *
187          * The invariant is that global variables a and b total 100.
188          */
189         a = 100;
190         b = 0;
191         done = 0;
192         
193         lock_InitializeRWLock(&main_doneRWLock, "done lock");
194         lock_InitializeRWLock(&main_bRWLock, "b lock");
195         lock_InitializeMutex(&main_aMutex, "a mutex");
196
197         mod1Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
198                 (LPTHREAD_START_ROUTINE) main_Mod1, 0, 0, &mod1ID);
199         if (mod1Handle == NULL) return -1;
200
201         mod2Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
202                 (LPTHREAD_START_ROUTINE) main_Mod2, 0, 0, &mod2ID);
203         if (mod2Handle == NULL) return -2;
204
205         scan1Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
206                 (LPTHREAD_START_ROUTINE) main_Scan1, 0, 0, &scan1ID);
207         if (scan1Handle== NULL) return -2;
208
209         scan2Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
210                 (LPTHREAD_START_ROUTINE) main_Scan2, 0, 0, &scan2ID);
211         if (scan2Handle== NULL) return -2;
212
213         /* start running check daemon */
214         while (1) {
215                 Sleep(1000);
216                 wsprintf(main_screenText[1], "Mod1 iteration %d", m1Loops);
217                 wsprintf(main_screenText[2], "Mod2 iteration %d", m2Loops);
218                 wsprintf(main_screenText[3], "Scan1 iteration %d", s1Loops);
219                 wsprintf(main_screenText[4], "Scan2 iteration %d, %d opportunites seen",
220                         s2Loops, s2Events);
221                 main_ForceDisplay(hWnd);
222
223                 /* copy out count of # of dudes finished */
224                 lock_ObtainRead(&main_doneRWLock);
225                 localDone = done;
226                 lock_ReleaseRead(&main_doneRWLock);
227
228                 /* right now, we're waiting for 4 threads */
229                 if (localDone == 4) break;
230         }
231         
232         wsprintf(main_screenText[0], "Test done.");
233         main_ForceDisplay(hWnd);
234
235         /* done, release and finalize all locks */
236         lock_FinalizeRWLock(&main_doneRWLock);
237         lock_FinalizeRWLock(&main_bRWLock);
238         lock_FinalizeMutex(&main_aMutex);
239
240         /* finally clean up thread handles */
241         CloseHandle(mod1Handle);
242         CloseHandle(mod2Handle);
243         CloseHandle(scan1Handle);
244         CloseHandle(scan2Handle);
245
246         return 0;
247 }