2 * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
4 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
5 * LICENSED MATERIALS - PROPERTY OF IBM
9 /* Copyright (C) 1994 Cazamar Systems, Inc. */
13 /*#include "lock95.h"*/
21 This code implements a partial OSI-over-LWP(and IOMGR) layer for threading
22 and synchronization, for the AFS NT code port to Windows 9x.
25 // It so happens that all code seen so far throws away *thread_id;
26 // unfortunately, callers do not send thread_id==NULL instead of getting
27 // a value and tossing it. :(
28 thread_t thrd_Create(int attributes, int stacksize, ThreadFunc func,
29 void *parm, int flags, int *thread_id, char *name)
33 // Reserve priority 0 for IOMGR; we use pri 1 by default
35 LWP_CreateProcess(func, stacksize, 1, parm, name, &lwp_pid);
37 LWP_CreateProcess(func, stacksize, 1, parm, "thread", &lwp_pid);
39 // In principle, the "right" way to do thread_id is to create a mapping
40 // between thread_id integers and LWP PROCESS names, but we're not using
41 // the IDs for anything anyway, so...
42 // actually, it turns out PROCESS is a pointer, so we fudge with that for now
43 // just to return a nonzero value
44 *thread_id = (int) lwp_pid;
49 thread_t thrd_Current()
52 LWP_CurrentProcess(&pid);
56 int thrd_Close(thread_t thrd)
58 int rc = LWP_DestroyProcess(thrd);
59 if (rc == LWP_SUCCESS)
65 /* The following thread-local-storage and critical-section functions are
68 DWORD thrd_Alloc(void)
70 char **NewRock = NULL;
71 static int NextTag = 0; // Because LWP is not preemptive, we need no mutex
73 NewRock = (char **) malloc (sizeof(LPVOID *));
76 *NewRock = (LPVOID *) malloc(sizeof(LPVOID));
77 if (*NewRock == NULL) {
82 if (LWP_NewRock(++NextTag,NewRock))
88 LPVOID thrd_GetValue(DWORD Index)
91 if (LWP_GetRock((int) Index, &ptr)) {
95 return * ((LPVOID *) ptr);
99 BOOL thrd_SetValue(DWORD Index, LPVOID Value) {
101 if (LWP_GetRock((int) Index, &ptr)) {
105 * ((LPVOID *) ptr) = Value;
110 #define LPCRITICAL_SECTION (struct Lock*)
112 #define thrd_InitCrit (Lock_Init)
113 #define thrd_EnterCrit (ObtainWriteLock)
114 #define thrd_LeaveCrit (ReleaseWriteLock)
116 // LWP has no formal destructor for locks.
117 #define thrd_DeleteCrit(x) ;
122 /* Since LWP is nonpreemptive, arithmetic needs no special handling. */
124 LONG thrd_Increment(LPLONG number)
130 LONG thrd_Decrement(LPLONG number)
136 LONG thrd_Exchange(LPLONG number, LONG value)
138 LONG oldval = *number;
143 // CreateEvent is always called with (NULL,(T/F),(T/F),NULL)
144 // This code will assume it and fail otherwise.
145 // SetLastError() is not implemented, i.e., if thrd_CreateEvent fails,
146 // there is no corresponding GetLastError() to pull out error codes
148 EVENT *thrd_CreateEvent(void *f, BOOL manual, BOOL startsignaled, void *g)
150 // LWP code checks eventnames against NULL as an error condition,
151 // so we start counting from 1 instead of zero.
152 // It turns out that LWP uses event names as unique integer values,
153 // even though these values are cast as char pointers. We will use
154 // integers, since they are never dereferenced by LWP.
155 static unsigned long NextEventName = 1L;
159 if ((f != NULL) || (g != NULL)) {
160 // Panic! This scenario is not implemented.
166 if ((event=(EVENT*)malloc(sizeof(EVENT))) == NULL)
168 // SetLastError out of memory
172 event->state = startsignaled ? manualsignal : manualunsig;
174 event->state = startsignaled ? autosignal : autounsig;
175 event->name = (char *) NextEventName;
177 // Increment NextEventName
183 BOOL thrd_SetEvent(EVENT *event)
187 if (AUTOMATIC(event))
188 event->state = autosignal;
190 event->state = manualsignal;
191 LWP_SignalProcess(event->name);
195 BOOL thrd_ResetEvent(EVENT *event)
199 if (AUTOMATIC(event))
200 event->state = autounsig;
202 event->state = manualunsig;
206 // It appears there is a slight difference in the two wait schemes.
207 // Win32's WaitForSingleObject returns only when the wait is finished;
208 // LWP's WaitProcess may return randomly, and so requires while() wrapping
209 // (a little busywaiting).
210 DWORD thrd_WaitForSingleObject_Event(EVENT *event, DWORD timeoutms)
212 if (timeoutms != INFINITE) {
220 while (!SIGNALED(event))
221 LWP_WaitProcess(event->name);
222 if (AUTOMATIC(event))
223 event->state = autounsig;
224 return WAIT_OBJECT_0;
227 DWORD thrd_WaitForMultipleObjects_Event(DWORD count, EVENT* events[],
228 BOOL waitforall, DWORD timeoutms)
230 if ((timeoutms != INFINITE) || waitforall) {
231 // Panic! This functionality not implemented.
235 if (events == NULL) {
239 // Do the actual wait
241 // Construct the list of LWP events to wait on
242 char *names[count+1];
244 for (i=0;i<count;++i) {
245 if (SIGNALED(events[i])) {
246 // We're done; one of the events is signaled.
247 if (AUTOMATIC(events[i]))
248 events[i]->state = autounsig;
249 return (WAIT_OBJECT_0 + i);
251 names[i] = events[i]->name;
255 // Do the wait for something to signal
257 LWP_MwaitProcess(1,names);
258 // Find who got signalled: MwaitProcess doesn't tell us.
259 for (i=0; i<count; ++i) {
260 if (SIGNALED(events[i])) {
261 if (AUTOMATIC(events[i]))
262 events[i]->state = autounsig;
263 return WAIT_OBJECT_0 + i;
274 int osi_Once(osi_once_t *argp)
278 lock_ObtainMutex(&argp->atomic);
280 if (argp->done == 0) {
285 /* otherwise we've already been initialized, so clear lock and return */
286 lock_ReleaseMutex(&argp->atomic);
290 void osi_EndOnce(osi_once_t *argp)
292 lock_ReleaseMutex(&argp->atomic);
295 int osi_TestOnce(osi_once_t *argp)
300 lock_ObtainMutex(&argp->atomic);
302 localDone = argp->done;
305 lock_ReleaseMutex(&argp->atomic);
307 return (localDone? 0 : 1);
310 void osi_panic(char *s, char *f, long l)
312 fprintf(stderr, "Fatal error: %s at %s:%d\n", s, f, l);
316 /* return true iff x is prime */
317 int osi_IsPrime(unsigned long x)
321 /* even numbers aren't prime */
322 if ((x & 1) == 0 && x != 2) return 0;
324 for(c = 3; c<x; c += 2) {
325 /* see if x is divisible by c */
326 if ((x % c) == 0) return 0; /* yup, it ain't prime */
328 /* see if we've gone far enough; only have to compute until
331 if (c*c > x) return 1;
334 /* probably never get here */
338 /* return first prime number less than or equal to x */
339 unsigned long osi_PrimeLessThan(unsigned long x) {
342 for(c = x; c > 1; c--) {
343 if (osi_IsPrime(c)) return c;