00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _SUPPORT_DEBUGLOCK_H
00014 #define _SUPPORT_DEBUGLOCK_H
00015
00016 #include <BuildDefines.h>
00017
00018 #ifndef SUPPORTS_LOCK_DEBUG
00019
00020
00021 #if BUILD_TYPE == BUILD_TYPE_DEBUG
00022 #define SUPPORTS_LOCK_DEBUG 1
00023 #else
00024 #define SUPPORTS_LOCK_DEBUG 0
00025 #endif
00026
00027 #endif
00028
00029 #if !SUPPORTS_LOCK_DEBUG
00030
00031 static inline void AssertNoLocks() { }
00032
00033 #else // !SUPPORTS_LOCK_DEBUG
00034
00035 #include <support/SupportDefs.h>
00036 #include <support/StdIO.h>
00037 #include <support/String.h>
00038 #include <support/StringIO.h>
00039
00040 #include <new>
00041
00042 #if _SUPPORTS_NAMESPACE
00043 namespace palmos {
00044 namespace support {
00045 #endif
00046
00047 class SCallStack;
00048
00049 static int32_t LockDebugLevel();
00050 static bool LockDebugStackCrawls();
00051
00052
00053
00054 void AssertNoLocks();
00055
00056 class StaticStringIO : public sptr<BStringIO>
00057 {
00058 public:
00059 inline StaticStringIO() : sptr<BStringIO>(new BStringIO) { }
00060 inline ~StaticStringIO() { }
00061 };
00062
00063 struct block_links;
00064
00065 enum {
00066
00067
00068
00069
00070
00071 LOCK_CAN_DELETE_WHILE_HELD = 0x00000001,
00072
00073
00074 LOCK_ANYONE_CAN_DELETE = 0x00000002,
00075
00076
00077
00078
00079
00080
00081 LOCK_SKIP_DEADLOCK_CHECK = 0x00010000,
00082
00083
00084 LOCK_DO_NOT_REGISTER_HELD = 0x00020000,
00085
00086
00087 LOCK_ANYONE_CAN_UNLOCK = 0x00040000
00088 };
00089
00090 class DebugLockNode
00091 {
00092 public:
00093 DebugLockNode( const char* type,
00094 const void* addr,
00095 const char* name,
00096 uint32_t debug_flags = 0);
00097
00098 virtual void Delete();
00099
00100 int32_t IncRefs() const;
00101 int32_t DecRefs() const;
00102
00103 const char* Type() const;
00104 const void* Addr() const;
00105 const char* Name() const;
00106 uint32_t GlobalFlags() const;
00107
00108 const SCallStack* CreationStack() const;
00109
00110 nsecs_t CreationTime() const;
00111
00112 bool LockGraph() const;
00113 void UnlockGraph() const;
00114 bool AddToGraph();
00115 void RegisterAsHeld();
00116 void UnregisterAsHeld();
00117
00118 void SetMaxContention(int32_t c);
00119 int32_t MaxContention() const;
00120
00121 int32_t BlockCount() const;
00122
00123 void RemoveFromContention();
00124 void RemoveFromBlockCount();
00125
00126 virtual void PrintToStream(const sptr<ITextOutput>& io) const;
00127 virtual void PrintStacksToStream(sptr<ITextOutput>& io) const;
00128 static void PrintContentionToStream(const sptr<ITextOutput>& io);
00129
00130
00131 inline const block_links* Links() const { return m_links; }
00132
00133 protected:
00134 virtual ~DebugLockNode();
00135 virtual void PrintSubclassToStream(const sptr<ITextOutput>& io) const;
00136
00137 private:
00138 mutable int32_t m_refs;
00139
00140
00141 SString const m_type;
00142 const void* const m_addr;
00143 SString const m_name;
00144 uint32_t const m_globalFlags;
00145 SCallStack* const m_createStack;
00146 nsecs_t const m_createTime;
00147
00148
00149 block_links* m_links;
00150
00151
00152 int32_t m_maxContention;
00153 bool m_inContention;
00154 int32_t m_blockCount;
00155 bool m_inBlockCount;
00156 };
00157
00158 inline const sptr<ITextOutput>& operator<<(const sptr<ITextOutput>& io, const DebugLockNode& db)
00159 {
00160 db.PrintToStream(io);
00161 return io;
00162 }
00163
00164 class DebugLock : public DebugLockNode
00165 {
00166 public:
00167 DebugLock( const char* type,
00168 const void* addr,
00169 const char* name,
00170 uint32_t debug_flags = 0);
00171
00172 virtual void Delete();
00173
00174 virtual void PrintStacksToStream(sptr<ITextOutput>& io) const;
00175
00176 status_t Lock( uint32_t flags = B_TIMEOUT,
00177 nsecs_t timeout = B_INFINITE_TIMEOUT,
00178 uint32_t debug_flags = 0);
00179 status_t Unlock();
00180 bool IsLocked() const;
00181
00182 const SCallStack* OwnerStack() const;
00183
00184
00185 void RestoreOwnership();
00186 volatile int32_t* RemoveOwnership();
00187
00188 protected:
00189 virtual ~DebugLock();
00190 virtual void PrintSubclassToStream(const sptr<ITextOutput>& io) const;
00191
00192 private:
00193 status_t do_lock(uint32_t flags, nsecs_t timeout,
00194 uint32_t debug_flags, bool restoreOnly = false);
00195 status_t do_unlock(bool removeOnly = false);
00196
00197
00198 volatile int32_t m_gehnaphore;
00199 sem_id m_sem;
00200 int32_t m_held;
00201 SysHandle m_owner;
00202 int32_t m_ownerFlags;
00203 SCallStack* m_ownerStack;
00204 int32_t m_contention;
00205 bool m_deleted;
00206 };
00207
00208
00209 extern int32_t gLockDebugLevel;
00210 int32_t LockDebugLevelSlow();
00211 static inline int32_t LockDebugLevel() {
00212 if (gLockDebugLevel >= 0) return gLockDebugLevel;
00213 return LockDebugLevelSlow();
00214 }
00215
00216 extern bool gLockDebugStackCrawls;
00217 static inline bool LockDebugStackCrawls() {
00218 if (gLockDebugLevel < 0) LockDebugLevelSlow();
00219 return gLockDebugStackCrawls;
00220 }
00221
00222 #if _SUPPORTS_NAMESPACE
00223 } }
00224 #endif
00225
00226 #endif // !SUPPORTS_LOCK_DEBUG
00227
00228 #endif // _SUPPORT_DEBUGLOCK_H