Windows: record history of read lock threads
[openafs.git] / src / WINNT / client_osi / osisleep.h
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 #ifndef OPENAFS_WINNT_CLIENT_OSI_OSISLEEP_H
13 #define OPENAFS_WINNT_CLIENT_OSI_OSISLEEP_H 1
14
15 /*#include "osi.h"*/
16 #include "osifd.h"
17 #include "osiqueue.h"
18
19 /* states bits */
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 */
23
24 /* waitinfo bits */
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 {
28     osi_queue_t q;
29     LONG_PTR value;             /* sleep value when in a sleep queue, patch addr for turnstiles */
30     DWORD *tidp;                /* tid history */
31     size_t tid;                 /* thread ID of sleeper */
32     EVENT_HANDLE sema;          /* semaphore for this entry */
33     unsigned short states;      /* states bits */
34     unsigned short idx;         /* sleep hash table we're in, if in hash */
35     unsigned short waitFor;     /* what are we waiting for; used for bulk wakeups */
36     unsigned long refCount;     /* reference count from FDs */
37 } osi_sleepInfo_t;
38
39 /* first guy is the most recently added process */
40 typedef struct osi_turnstile {
41         osi_sleepInfo_t *firstp;
42         osi_sleepInfo_t *lastp;
43 } osi_turnstile_t;
44
45 typedef struct osi_sleepFD{
46         osi_fd_t fd;            /* FD header */
47         osi_sleepInfo_t *sip;   /* ptr to the dude */
48         int idx;                /* hash index */
49 } osi_sleepFD_t;
50
51 /* struct for single-shot initialization support */
52 typedef struct osi_once {
53         long atomic;    /* used for atomicity */
54         int done;       /* tells if initialization is done */
55 } osi_once_t;
56
57 /* size of mutex hash table; should be a prime number; used for mutex and lock hashing */
58 #define OSI_MUTEXHASHSIZE       251     /* prime number */
59
60 #define osi_MUTEXHASH(x) ((unsigned short) (((LONG_PTR) x) % (intptr_t) OSI_MUTEXHASHSIZE))
61
62 /* size of sleep value hash table.  Must be power of 2 */
63 #define OSI_SLEEPHASHSIZE       128
64
65 /* hash function */
66 #define osi_SLEEPHASH(x)        (((x)>>2)&(OSI_SLEEPHASHSIZE-1))
67
68 /* export this so that RPC function can call osi_NextSleepCookie while
69  * holding this lock, so that locks don't get released while we're copying
70  * out this info.
71  */
72 extern Crit_Sec osi_sleepCookieCS;
73
74 /* spin lock version of atomic sleep, used internally only */
75 extern void osi_SleepSpin(LONG_PTR value, Crit_Sec *counterp);
76
77 /* spin lock version of wakeup, used internally only */
78 extern void osi_WakeupSpin(LONG_PTR value);
79
80 /* exported function to sleep on a value */
81 extern void osi_Sleep (LONG_PTR);
82
83 extern void osi_FreeSleepInfo(osi_sleepInfo_t *);
84
85 /* function to atomically initialize and return a "once only"
86  * structure.  Returns true if you're the first caller, otherwise
87  * returns 0.
88  */
89 extern int osi_Once(osi_once_t *);
90
91 /* function like the above, but doesn't set the once-only flag.
92  * Can be used as optimization to tell if osi_Once has been
93  * called.  If it returns true, by the time you really call
94  * osi_Once, someone else may have called it, but if it
95  * return false, you're guaranteed it will stay false, and that
96  * osi_Once would return false, too.
97  */
98 extern int osi_TestOnce(osi_once_t *);
99
100 /* called once for each call to osi_Once that returns true; permits other
101  * calls to osi_Once to proceed (and return false).
102  */
103 extern void osi_EndOnce(osi_once_t *);
104
105
106 /* exported function to wakeup those sleeping on a value */
107 extern void osi_Wakeup (LONG_PTR);
108
109 extern void osi_Init (void);
110
111 /* create a ptr to a cookie */
112 osi_sleepFD_t *osi_CreateSleepCookie(void);
113
114 /* release a ptr to a sleep cookie */
115 void osi_FreeSleepCookie(osi_sleepFD_t *);
116
117 /* advance a sleep cookie to the next ptr */
118 int osi_NextSleepCookie(osi_sleepFD_t *);
119
120 /* functions for the sleep FD implementation */
121 extern long osi_SleepFDCreate(osi_fdType_t *, osi_fd_t **);
122 extern long osi_SleepFDGetInfo(osi_fd_t *, osi_remGetInfoParms_t *);
123 extern long osi_SleepFDClose(osi_fd_t *);
124
125 /* functions for getting hash sizes */
126 extern int osi_IsPrime(unsigned long);
127 extern unsigned long osi_PrimeLessThan(unsigned long);
128
129 /* time functions */
130 unsigned long osi_GetBootTime(void);
131
132 #define osi_assert(x)   \
133     do { \
134         if (!(x)) osi_panic(NULL, __FILE__, __LINE__); \
135     } while(0)
136
137 #define osi_assertx(x,s)        \
138     do { \
139         if (!(x)) osi_panic((s), __FILE__, __LINE__); \
140     } while(0)
141
142 /* panic */
143 void osi_InitPanic(void *anotifFunc);
144 void osi_panic(char *, char *, long);
145
146 time_t osi_Time(void);
147
148 extern void osi_TWait(osi_turnstile_t *turnp, int waitFor,
149                       void *patchp, DWORD *tidp,
150                       Crit_Sec *releasep);
151
152 extern void osi_TSignal(osi_turnstile_t *turnp);
153
154 extern void osi_TBroadcast(osi_turnstile_t *turnp);
155
156 extern void osi_TSignalForMLs(osi_turnstile_t *turnp, int stillHaveReaders, Crit_Sec *csp);
157
158 #define osi_TInit(t)    ((t)->firstp = (t)->lastp = 0)
159
160 #define osi_TEmpty(t)   ((t)->firstp == NULL)
161
162 #endif /* OPENAFS_WINNT_CLIENT_OSI_OSISLEEP_H */