2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /* Copyright (C) 1994 Cazamar Systems, Inc. */
14 /*#include "lock95.h"*/
22 This code implements a partial OSI-over-LWP(and IOMGR) layer for threading
23 and synchronization, for the AFS NT code port to Windows 9x.
26 // It so happens that all code seen so far throws away *thread_id;
27 // unfortunately, callers do not send thread_id==NULL instead of getting
28 // a value and tossing it. :(
29 thread_t thrd_Create(int attributes, int stacksize, ThreadFunc func,
30 void *parm, int flags, int *thread_id, char *name)
34 // Reserve priority 0 for IOMGR; we use pri 1 by default
36 LWP_CreateProcess(func, stacksize, 1, parm, name, &lwp_pid);
38 LWP_CreateProcess(func, stacksize, 1, parm, "thread", &lwp_pid);
40 // In principle, the "right" way to do thread_id is to create a mapping
41 // between thread_id integers and LWP PROCESS names, but we're not using
42 // the IDs for anything anyway, so...
43 // actually, it turns out PROCESS is a pointer, so we fudge with that for now
44 // just to return a nonzero value
45 *thread_id = (int) lwp_pid;
50 thread_t thrd_Current()
53 LWP_CurrentProcess(&pid);
57 int thrd_Close(thread_t thrd)
59 int rc = LWP_DestroyProcess(thrd);
60 if (rc == LWP_SUCCESS)
66 /* The following thread-local-storage and critical-section functions are
69 DWORD thrd_Alloc(void)
71 char **NewRock = NULL;
72 static int NextTag = 0; // Because LWP is not preemptive, we need no mutex
74 NewRock = (char **) malloc (sizeof(LPVOID *));
77 *NewRock = (LPVOID *) malloc(sizeof(LPVOID));
78 if (*NewRock == NULL) {
83 if (LWP_NewRock(++NextTag,NewRock))
89 LPVOID thrd_GetValue(DWORD Index)
92 if (LWP_GetRock((int) Index, &ptr)) {
96 return * ((LPVOID *) ptr);
100 BOOL thrd_SetValue(DWORD Index, LPVOID Value) {
102 if (LWP_GetRock((int) Index, &ptr)) {
106 * ((LPVOID *) ptr) = Value;
111 #define LPCRITICAL_SECTION (struct Lock*)
113 #define thrd_InitCrit (Lock_Init)
114 #define thrd_EnterCrit (ObtainWriteLock)
115 #define thrd_LeaveCrit (ReleaseWriteLock)
117 // LWP has no formal destructor for locks.
118 #define thrd_DeleteCrit(x) ;
123 /* Since LWP is nonpreemptive, arithmetic needs no special handling. */
125 LONG thrd_Increment(LPLONG number)
131 LONG thrd_Decrement(LPLONG number)
137 LONG thrd_Exchange(LPLONG number, LONG value)
139 LONG oldval = *number;
144 // CreateEvent is always called with (NULL,(T/F),(T/F),NULL)
145 // This code will assume it and fail otherwise.
146 // SetLastError() is not implemented, i.e., if thrd_CreateEvent fails,
147 // there is no corresponding GetLastError() to pull out error codes
149 EVENT *thrd_CreateEvent(void *f, BOOL manual, BOOL startsignaled, void *g)
151 // LWP code checks eventnames against NULL as an error condition,
152 // so we start counting from 1 instead of zero.
153 // It turns out that LWP uses event names as unique integer values,
154 // even though these values are cast as char pointers. We will use
155 // integers, since they are never dereferenced by LWP.
156 static unsigned long NextEventName = 1L;
160 if ((f != NULL) || (g != NULL)) {
161 // Panic! This scenario is not implemented.
167 if ((event=(EVENT*)malloc(sizeof(EVENT))) == NULL)
169 // SetLastError out of memory
173 event->state = startsignaled ? manualsignal : manualunsig;
175 event->state = startsignaled ? autosignal : autounsig;
176 event->name = (char *) NextEventName;
178 // Increment NextEventName
184 BOOL thrd_SetEvent(EVENT *event)
188 if (AUTOMATIC(event))
189 event->state = autosignal;
191 event->state = manualsignal;
192 LWP_SignalProcess(event->name);
196 BOOL thrd_ResetEvent(EVENT *event)
200 if (AUTOMATIC(event))
201 event->state = autounsig;
203 event->state = manualunsig;
207 // It appears there is a slight difference in the two wait schemes.
208 // Win32's WaitForSingleObject returns only when the wait is finished;
209 // LWP's WaitProcess may return randomly, and so requires while() wrapping
210 // (a little busywaiting).
211 DWORD thrd_WaitForSingleObject_Event(EVENT *event, DWORD timeoutms)
213 if (timeoutms != INFINITE) {
221 while (!SIGNALED(event))
222 LWP_WaitProcess(event->name);
223 if (AUTOMATIC(event))
224 event->state = autounsig;
225 return WAIT_OBJECT_0;
228 DWORD thrd_WaitForMultipleObjects_Event(DWORD count, EVENT* events[],
229 BOOL waitforall, DWORD timeoutms)
231 if ((timeoutms != INFINITE) || waitforall) {
232 // Panic! This functionality not implemented.
236 if (events == NULL) {
240 // Do the actual wait
242 // Construct the list of LWP events to wait on
243 char *names[count+1];
245 for (i=0;i<count;++i) {
246 if (SIGNALED(events[i])) {
247 // We're done; one of the events is signaled.
248 if (AUTOMATIC(events[i]))
249 events[i]->state = autounsig;
250 return (WAIT_OBJECT_0 + i);
252 names[i] = events[i]->name;
256 // Do the wait for something to signal
258 LWP_MwaitProcess(1,names);
259 // Find who got signalled: MwaitProcess doesn't tell us.
260 for (i=0; i<count; ++i) {
261 if (SIGNALED(events[i])) {
262 if (AUTOMATIC(events[i]))
263 events[i]->state = autounsig;
264 return WAIT_OBJECT_0 + i;
275 int osi_Once(osi_once_t *argp)
279 lock_ObtainMutex(&argp->atomic);
281 if (argp->done == 0) {
286 /* otherwise we've already been initialized, so clear lock and return */
287 lock_ReleaseMutex(&argp->atomic);
291 void osi_EndOnce(osi_once_t *argp)
293 lock_ReleaseMutex(&argp->atomic);
296 int osi_TestOnce(osi_once_t *argp)
301 lock_ObtainMutex(&argp->atomic);
303 localDone = argp->done;
306 lock_ReleaseMutex(&argp->atomic);
308 return (localDone? 0 : 1);
311 void osi_panic(char *s, char *f, long l)
313 fprintf(stderr, "Fatal error: %s at %s:%d\n", s, f, l);
317 /* return true iff x is prime */
318 int osi_IsPrime(unsigned long x)
322 /* even numbers aren't prime */
323 if ((x & 1) == 0 && x != 2) return 0;
325 for(c = 3; c<x; c += 2) {
326 /* see if x is divisible by c */
327 if ((x % c) == 0) return 0; /* yup, it ain't prime */
329 /* see if we've gone far enough; only have to compute until
332 if (c*c > x) return 1;
335 /* probably never get here */
339 /* return first prime number less than or equal to x */
340 unsigned long osi_PrimeLessThan(unsigned long x) {
343 for(c = x; c > 1; c--) {
344 if (osi_IsPrime(c)) return c;