Windows: record history of read lock threads
[openafs.git] / src / WINNT / client_osi / osibasel.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_OSIBASEL_H
13 #define OPENAFS_WINNT_CLIENT_OSI_OSIBASEL_H 1
14
15 /* flags for osi_mutex_t and osi_rwlock_t flags fields.  Some bits
16  * are used only in one structure or another.
17  */
18 #define OSI_LOCKFLAG_EXCL               1       /* exclusive locked (rwlock only) */
19
20 /* a mutex (pure exclusive lock).  This structure has two forms.  In the
21  * base type (type == 0), the d field is interpreted as an atomic counter,
22  * and all the other fields are used.  In the other types, type specifies
23  * which operations to use (via the global osi_lockOps), and d.privateDatap
24  * points to the real data used by the mutex.
25  *
26  * For the base type, flags tells us if the lock is held, and if anyone else
27  * is waiting for the lock.  The field d.atomicCount is used to implement a spin
28  * lock using an atomic increment operation.
29  */
30 typedef struct osi_mutex {
31     char type;                  /* for all types; type 0 uses atomic count */
32     char flags;                 /* flags for base type */
33     unsigned short atomicIndex; /* index of lock for low-level sync */
34     DWORD tid;                  /* tid of thread that owns the lock */
35     unsigned short waiters;     /* waiters */
36     unsigned short pad;
37     union {
38         void *privateDatap;     /* data pointer for non-zero types */
39         osi_turnstile_t turn;   /* turnstile */
40     } d;
41     unsigned short level;       /* locking hierarchy level */
42 } osi_mutex_t;
43
44 /* a read/write lock.  This structure has two forms.  In the
45  * base type (type == 0), the d field is interpreted as an atomic counter,
46  * and all the other fields are used.  In the other types, type specifies
47  * which operations to use (via the global osi_lockOps), and d.privateDatap
48  * points to the real data used by the mutex.
49  *
50  * For the base type, flags tells us if the lock is held, and if anyone else
51  * is waiting for the lock.  The field d.atomicCount is used to implement a spin
52  * lock using an atomic increment operation.
53  *
54  * This type of lock has N readers or one writer.
55  */
56
57 #define OSI_RWLOCK_THREADS 32
58
59 typedef struct osi_rwlock {
60     char type;                  /* for all types; type 0 uses atomic count */
61     char flags;                 /* flags for base type */
62     unsigned short atomicIndex; /* index into hash table for low-level sync */
63     DWORD tid[OSI_RWLOCK_THREADS];                      /* writer's tid */
64     unsigned short waiters;     /* waiters */
65     unsigned short readers;     /* readers */
66     union {
67         void *privateDatap;     /* data pointer for non-zero types */
68         osi_turnstile_t turn;   /* turnstile */
69     } d;
70     unsigned short level;       /* locking hierarchy level */
71 } osi_rwlock_t;
72
73
74 /*
75  * a lock reference is a queue object that maintains a reference to a
76  * mutex or read/write lock object.  Its intended purpose is for
77  * maintaining lists of lock objects on a per thread basis.
78  */
79 typedef struct osi_lock_ref {
80     osi_queue_t q;
81     char type;
82     union {
83         osi_rwlock_t *rw;
84         osi_mutex_t  *mx;
85     };
86 } osi_lock_ref_t;
87
88 #define OSI_LOCK_MUTEX  1
89 #define OSI_LOCK_RW     2
90
91 extern void lock_ObtainRead (struct osi_rwlock *);
92
93 extern void lock_ObtainWrite (struct osi_rwlock *);
94
95 extern void lock_ReleaseRead (struct osi_rwlock *);
96
97 extern void lock_ReleaseWrite (struct osi_rwlock *);
98
99 extern void lock_ObtainMutex (struct osi_mutex *);
100
101 extern void lock_ReleaseMutex (struct osi_mutex *);
102
103 extern int lock_TryRead (struct osi_rwlock *);
104
105 extern int lock_TryWrite (struct osi_rwlock *);
106
107 extern int lock_TryMutex (struct osi_mutex *);
108
109 extern void osi_SleepR (LONG_PTR, struct osi_rwlock *);
110
111 extern void osi_SleepW (LONG_PTR, struct osi_rwlock *);
112
113 extern void osi_SleepM (LONG_PTR, struct osi_mutex *);
114
115 extern void osi_Sleep (LONG_PTR);
116
117 extern void osi_Wakeup (LONG_PTR);
118
119 extern void lock_FinalizeRWLock(struct osi_rwlock *);
120
121 extern void lock_FinalizeMutex(struct osi_mutex *);
122
123 extern CRITICAL_SECTION osi_baseAtomicCS[];
124
125 /* and define the functions that create basic locks and mutexes */
126
127 extern void lock_InitializeRWLock(struct osi_rwlock *, char *, unsigned short level);
128
129 extern void lock_InitializeMutex(struct osi_mutex *, char *, unsigned short level);
130
131 extern void osi_Init (void);
132
133 extern void lock_ConvertWToR(struct osi_rwlock *);
134
135 extern void lock_ConvertRToW(struct osi_rwlock *);
136
137 /* and stat functions */
138
139 extern int lock_GetRWLockState(struct osi_rwlock *);
140
141 extern int lock_GetMutexState(struct osi_mutex *);
142
143 /* and init stuff */
144
145 extern void osi_BaseInit(void);
146
147 extern void osi_SetLockOrderValidation(int);
148
149 /* and friendly macros */
150
151 #define lock_AssertNone(x) osi_assertx(lock_GetRWLockState(x) == 0, "(OSI_RWLOCK_READHELD | OSI_RWLOCK_WRITEHELD)")
152
153 #define lock_AssertRead(x) osi_assertx(lock_GetRWLockState(x) & OSI_RWLOCK_READHELD, "!OSI_RWLOCK_READHELD")
154
155 #define lock_AssertWrite(x) osi_assertx((lock_GetRWLockState(x) & OSI_RWLOCK_WRITEHELD) && ((x)->tid[0] == thrd_Current()), "!OSI_RWLOCK_WRITEHELD")
156
157 #define lock_AssertAny(x) osi_assertx(lock_GetRWLockState(x) != 0, "!(OSI_RWLOCK_READHELD | OSI_RWLOCK_WRITEHELD)")
158
159 #define lock_AssertMutex(x) osi_assertx((lock_GetMutexState(x) & OSI_MUTEX_HELD) && ((x)->tid == thrd_Current()), "!OSI_MUTEX_HELD")
160
161 #endif /* OPENAFS_WINNT_CLIENT_OSI_OSIBASEL_H */