Windows: record history of read lock threads
[openafs.git] / src / WINNT / client_osi / osibasel.h
index 7467f06..9ef6b90 100644 (file)
@@ -1,7 +1,7 @@
-/* 
+/*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -9,8 +9,8 @@
 
 /* Copyright (C) 1994 Cazamar Systems, Inc. */
 
-#ifndef _OSIBASEL_H_ENV_
-#define _OSIBASEL_H_ENV_ 1
+#ifndef OPENAFS_WINNT_CLIENT_OSI_OSIBASEL_H
+#define OPENAFS_WINNT_CLIENT_OSI_OSIBASEL_H 1
 
 /* flags for osi_mutex_t and osi_rwlock_t flags fields.  Some bits
  * are used only in one structure or another.
  * lock using an atomic increment operation.
  */
 typedef struct osi_mutex {
-       char type;                      /* for all types; type 0 uses atomic count */
-       char flags;                     /* flags for base type */
-       unsigned short atomicIndex;     /* index of lock for low-level sync */
-        thread_t tid;                  /* tid of thread that owns the lock */
-       unsigned short waiters;         /* waiters */
-        unsigned short pad;
-       union {
-               void *privateDatap;     /* data pointer for non-zero types */
-                osi_turnstile_t turn;  /* turnstile */
-       } d;
+    char type;                 /* for all types; type 0 uses atomic count */
+    char flags;                        /* flags for base type */
+    unsigned short atomicIndex;        /* index of lock for low-level sync */
+    DWORD tid;                 /* tid of thread that owns the lock */
+    unsigned short waiters;    /* waiters */
+    unsigned short pad;
+    union {
+        void *privateDatap;    /* data pointer for non-zero types */
+        osi_turnstile_t turn;  /* turnstile */
+    } d;
+    unsigned short level;       /* locking hierarchy level */
 } osi_mutex_t;
 
 /* a read/write lock.  This structure has two forms.  In the
@@ -52,18 +53,41 @@ typedef struct osi_mutex {
  *
  * This type of lock has N readers or one writer.
  */
+
+#define OSI_RWLOCK_THREADS 32
+
 typedef struct osi_rwlock {
-       char type;                      /* for all types; type 0 uses atomic count */
-       char flags;                     /* flags for base type */
-        unsigned short atomicIndex;    /* index into hash table for low-level sync */
-        unsigned short waiters;                /* waiters */
-       unsigned short readers;         /* readers */
-       union {
-               void *privateDatap;     /* data pointer for non-zero types */
-                osi_turnstile_t turn;  /* turnstile */
-       } d;
+    char type;                 /* for all types; type 0 uses atomic count */
+    char flags;                        /* flags for base type */
+    unsigned short atomicIndex;        /* index into hash table for low-level sync */
+    DWORD tid[OSI_RWLOCK_THREADS];                     /* writer's tid */
+    unsigned short waiters;    /* waiters */
+    unsigned short readers;    /* readers */
+    union {
+        void *privateDatap;    /* data pointer for non-zero types */
+        osi_turnstile_t turn;  /* turnstile */
+    } d;
+    unsigned short level;       /* locking hierarchy level */
 } osi_rwlock_t;
 
+
+/*
+ * a lock reference is a queue object that maintains a reference to a
+ * mutex or read/write lock object.  Its intended purpose is for
+ * maintaining lists of lock objects on a per thread basis.
+ */
+typedef struct osi_lock_ref {
+    osi_queue_t q;
+    char type;
+    union {
+        osi_rwlock_t *rw;
+        osi_mutex_t  *mx;
+    };
+} osi_lock_ref_t;
+
+#define OSI_LOCK_MUTEX  1
+#define OSI_LOCK_RW     2
+
 extern void lock_ObtainRead (struct osi_rwlock *);
 
 extern void lock_ObtainWrite (struct osi_rwlock *);
@@ -82,15 +106,15 @@ extern int lock_TryWrite (struct osi_rwlock *);
 
 extern int lock_TryMutex (struct osi_mutex *);
 
-extern void osi_SleepR (long, struct osi_rwlock *);
+extern void osi_SleepR (LONG_PTR, struct osi_rwlock *);
 
-extern void osi_SleepW (long, struct osi_rwlock *);
+extern void osi_SleepW (LONG_PTR, struct osi_rwlock *);
 
-extern void osi_SleepM (long, struct osi_mutex *);
+extern void osi_SleepM (LONG_PTR, struct osi_mutex *);
 
-extern void osi_Sleep (long);
+extern void osi_Sleep (LONG_PTR);
 
-extern void osi_Wakeup (long);
+extern void osi_Wakeup (LONG_PTR);
 
 extern void lock_FinalizeRWLock(struct osi_rwlock *);
 
@@ -100,14 +124,16 @@ extern CRITICAL_SECTION osi_baseAtomicCS[];
 
 /* and define the functions that create basic locks and mutexes */
 
-extern void lock_InitializeRWLock(struct osi_rwlock *, char *);
+extern void lock_InitializeRWLock(struct osi_rwlock *, char *, unsigned short level);
 
-extern void lock_InitializeMutex(struct osi_mutex *, char *);
+extern void lock_InitializeMutex(struct osi_mutex *, char *, unsigned short level);
 
 extern void osi_Init (void);
 
 extern void lock_ConvertWToR(struct osi_rwlock *);
 
+extern void lock_ConvertRToW(struct osi_rwlock *);
+
 /* and stat functions */
 
 extern int lock_GetRWLockState(struct osi_rwlock *);
@@ -118,14 +144,18 @@ extern int lock_GetMutexState(struct osi_mutex *);
 
 extern void osi_BaseInit(void);
 
+extern void osi_SetLockOrderValidation(int);
+
 /* and friendly macros */
 
-#define lock_AssertRead(x) osi_assert(lock_GetRWLockState(x) & OSI_RWLOCK_READHELD)
+#define lock_AssertNone(x) osi_assertx(lock_GetRWLockState(x) == 0, "(OSI_RWLOCK_READHELD | OSI_RWLOCK_WRITEHELD)")
+
+#define lock_AssertRead(x) osi_assertx(lock_GetRWLockState(x) & OSI_RWLOCK_READHELD, "!OSI_RWLOCK_READHELD")
 
-#define lock_AssertWrite(x) osi_assert(lock_GetRWLockState(x) & OSI_RWLOCK_WRITEHELD)
+#define lock_AssertWrite(x) osi_assertx((lock_GetRWLockState(x) & OSI_RWLOCK_WRITEHELD) && ((x)->tid[0] == thrd_Current()), "!OSI_RWLOCK_WRITEHELD")
 
-#define lock_AssertAny(x) osi_assert(lock_GetRWLockState(x) != 0)
+#define lock_AssertAny(x) osi_assertx(lock_GetRWLockState(x) != 0, "!(OSI_RWLOCK_READHELD | OSI_RWLOCK_WRITEHELD)")
 
-#define lock_AssertMutex(x) osi_assert(lock_GetMutexState(x) & OSI_MUTEX_HELD)
+#define lock_AssertMutex(x) osi_assertx((lock_GetMutexState(x) & OSI_MUTEX_HELD) && ((x)->tid == thrd_Current()), "!OSI_MUTEX_HELD")
 
-#endif /*_OSIBASEL_H_ENV_ */
+#endif /* OPENAFS_WINNT_CLIENT_OSI_OSIBASEL_H */