Wednesday, February 18, 2009

Ownership and signaled state of synchronization objects

Synchronization objects are indispensable in multithreaded programming. Except critical sections, which are user mode objects, others, such as events, mutexes, semaphores, ERESOURCEs, threads, or processes are all kernel mode objects. I include threads and processes as synchronization objects since in many cases they can be used in xxWaitForSingleObject, and I include ERESOURCEs since they provide similar functionality as critical sections conceptually.

Due to different functionality and role of each type of synchronization object in a multithreaded program, when it comes to debugging, the focus would differ based on the synchronization object investigated. For instance, besides which threads waiting on it, for a critical section, mutex, or ERESOURCE, we would like to know which thread owns it; for an event, thread, or process, we would like to know whether the object is signaled.

Since a critical section is a user mode object, a user mode command, such as !cs or !ntsdexts.locks can be used to find out which thread owns the critical section.

A mutex or ERESOURCE is a kernel mode object, we can use live kernel mode debugging or kernel/complete memory dump to find out its ownership.

0: kd> dt _KMUTANT
nt!_KMUTANT
+0x000 Header : _DISPATCHER_HEADER
+0x010 MutantListEntry : _LIST_ENTRY
+0x018 OwnerThread : Ptr32 _KTHREAD
+0x01c Abandoned : UChar
+0x01d ApcDisable : UChar

lkd> dt _ERESOURCE
nt!_ERESOURCE
+0x000 SystemResourcesList : _LIST_ENTRY
+0x008 OwnerTable : Ptr32 _OWNER_ENTRY
+0x00c ActiveCount : Int2B
+0x00e Flag : Uint2B
+0x010 SharedWaiters : Ptr32 _KSEMAPHORE
+0x014 ExclusiveWaiters : Ptr32 _KEVENT
+0x018 OwnerThreads : [2] _OWNER_ENTRY
+0x028 ContentionCount : Uint4B
+0x02c NumberOfSharedWaiters : Uint2B
+0x02e NumberOfExclusiveWaiters : Uint2B
+0x030 Address : Ptr32 Void
+0x030 CreatorBackTraceIndex : Uint4B
+0x034 SpinLock : Uint4B

lkd> dt _OWNER_ENTRY
nt!_OWNER_ENTRY
+0x000 OwnerThread : Uint4B
+0x004 OwnerCount : Int4B
+0x004 TableSize : Uint4B


Per MSDN documentation, a kernel ERESOURCE pointer is passed as the first paramter into nt!ExAcquireResourceSharedLite and nt!ExAcquireResourceExclusiveLite.

Since an event, thread, or process is a kernel mode object, we can use live kernel mode debugging or kernel/complete memory dump to find out whether it is signaled or not.

0: kd> dt -r1 _KEVENT
nt!_KEVENT
+0x000 Header : _DISPATCHER_HEADER
+0x000 Type : UChar
+0x001 Absolute : UChar
+0x002 Size : UChar
+0x003 Inserted : UChar
+0x004 SignalState : Int4B
+0x008 WaitListHead : _LIST_ENTRY

0: kd> dt -r1 _KTHREAD
nt!_KTHREAD
+0x000 Header : _DISPATCHER_HEADER
+0x000 Type : UChar
+0x001 Absolute : UChar
+0x002 Size : UChar
+0x003 Inserted : UChar
+0x004 SignalState : Int4B
+0x008 WaitListHead : _LIST_ENTRY
...

0: kd> dt -r1 _KPROCESS
nt!_KPROCESS
+0x000 Header : _DISPATCHER_HEADER
+0x000 Type : UChar
+0x001 Absolute : UChar
+0x002 Size : UChar
+0x003 Inserted : UChar
+0x004 SignalState : Int4B
+0x008 WaitListHead : _LIST_ENTRY
...


Signaled Object from Memory Dump Analysis Vol 2 by Dmitry Vostokov provides an in-depth look at the signaled object from kernel mode debugging perspective.
 

0 comments:

Post a Comment