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. */
12 #ifndef OPENAFS_WINNT_CLIENT_OSI_OSISLEEP_H
13 #define OPENAFS_WINNT_CLIENT_OSI_OSISLEEP_H 1
20 #define OSI_SLEEPINFO_SIGNALLED 1 /* this sleep structure has been signalled */
21 #define OSI_SLEEPINFO_INHASH 2 /* this guy is in the hash table */
22 #define OSI_SLEEPINFO_DELETED 4 /* remove this guy when refcount hits 0 */
25 #define OSI_SLEEPINFO_W4READ 1 /* waiting for a read lock */
26 #define OSI_SLEEPINFO_W4WRITE 2 /* waiting for a write lock */
27 typedef struct osi_sleepInfo {
29 LONG_PTR value; /* sleep value when in a sleep queue, patch addr for turnstiles */
30 size_t tid; /* thread ID of sleeper */
31 EVENT_HANDLE sema; /* semaphore for this entry */
32 unsigned short states; /* states bits */
33 unsigned short idx; /* sleep hash table we're in, if in hash */
34 unsigned short waitFor; /* what are we waiting for; used for bulk wakeups */
35 unsigned long refCount; /* reference count from FDs */
38 /* first guy is the most recently added process */
39 typedef struct osi_turnstile {
40 osi_sleepInfo_t *firstp;
41 osi_sleepInfo_t *lastp;
44 typedef struct osi_sleepFD{
45 osi_fd_t fd; /* FD header */
46 osi_sleepInfo_t *sip; /* ptr to the dude */
47 int idx; /* hash index */
50 /* struct for single-shot initialization support */
51 typedef struct osi_once {
52 long atomic; /* used for atomicity */
53 int done; /* tells if initialization is done */
56 /* size of mutex hash table; should be a prime number; used for mutex and lock hashing */
57 #define OSI_MUTEXHASHSIZE 251 /* prime number */
59 #define osi_MUTEXHASH(x) ((unsigned short) (((LONG_PTR) x) % (intptr_t) OSI_MUTEXHASHSIZE))
61 /* size of sleep value hash table. Must be power of 2 */
62 #define OSI_SLEEPHASHSIZE 128
65 #define osi_SLEEPHASH(x) (((x)>>2)&(OSI_SLEEPHASHSIZE-1))
67 /* export this so that RPC function can call osi_NextSleepCookie while
68 * holding this lock, so that locks don't get released while we're copying
71 extern Crit_Sec osi_sleepCookieCS;
73 /* spin lock version of atomic sleep, used internally only */
74 extern void osi_SleepSpin(LONG_PTR value, Crit_Sec *counterp);
76 /* spin lock version of wakeup, used internally only */
77 extern void osi_WakeupSpin(LONG_PTR value);
79 /* exported function to sleep on a value */
80 extern void osi_Sleep (LONG_PTR);
82 extern void osi_FreeSleepInfo(osi_sleepInfo_t *);
84 /* function to atomically initialize and return a "once only"
85 * structure. Returns true if you're the first caller, otherwise
88 extern int osi_Once(osi_once_t *);
90 /* function like the above, but doesn't set the once-only flag.
91 * Can be used as optimization to tell if osi_Once has been
92 * called. If it returns true, by the time you really call
93 * osi_Once, someone else may have called it, but if it
94 * return false, you're guaranteed it will stay false, and that
95 * osi_Once would return false, too.
97 extern int osi_TestOnce(osi_once_t *);
99 /* called once for each call to osi_Once that returns true; permits other
100 * calls to osi_Once to proceed (and return false).
102 extern void osi_EndOnce(osi_once_t *);
105 /* exported function to wakeup those sleeping on a value */
106 extern void osi_Wakeup (LONG_PTR);
108 extern void osi_Init (void);
110 /* create a ptr to a cookie */
111 osi_sleepFD_t *osi_CreateSleepCookie(void);
113 /* release a ptr to a sleep cookie */
114 void osi_FreeSleepCookie(osi_sleepFD_t *);
116 /* advance a sleep cookie to the next ptr */
117 int osi_NextSleepCookie(osi_sleepFD_t *);
119 /* functions for the sleep FD implementation */
120 extern long osi_SleepFDCreate(osi_fdType_t *, osi_fd_t **);
121 extern long osi_SleepFDGetInfo(osi_fd_t *, osi_remGetInfoParms_t *);
122 extern long osi_SleepFDClose(osi_fd_t *);
124 /* functions for getting hash sizes */
125 extern int osi_IsPrime(unsigned long);
126 extern unsigned long osi_PrimeLessThan(unsigned long);
129 unsigned long osi_GetBootTime(void);
131 #define osi_assert(x) \
133 if (!(x)) osi_panic(NULL, __FILE__, __LINE__); \
136 #define osi_assertx(x,s) \
138 if (!(x)) osi_panic((s), __FILE__, __LINE__); \
142 void osi_InitPanic(void *anotifFunc);
143 void osi_panic(char *, char *, long);
145 time_t osi_Time(void);
147 extern void osi_TWait(osi_turnstile_t *turnp, int waitFor, void *patchp,
150 extern void osi_TSignal(osi_turnstile_t *turnp);
152 extern void osi_TBroadcast(osi_turnstile_t *turnp);
154 extern void osi_TSignalForMLs(osi_turnstile_t *turnp, int stillHaveReaders, Crit_Sec *csp);
156 #define osi_TInit(t) ((t)->firstp = (t)->lastp = 0)
158 #define osi_TEmpty(t) ((t)->firstp == NULL)
160 #endif /* OPENAFS_WINNT_CLIENT_OSI_OSISLEEP_H */