7. The mutex kernel object is used to ensure that a thread exclusively accesses a resource.
■ Composition:
① Count
② Thread ID: indicates the thread in the system that currently occupies the mutex
③ Recursive count: indicates the number of times this thread occupies the mutex.
■ Differences with key code segments:
● Mutex is in kernel mode, while key code segments are in user mode. This also means that key code segments are faster than mutex.
● Threads in different processes can access the same mutex.
■ Mutex rules:
● If the thread ID is 0 (invalid thread ID), the mutex is not occupied by any thread lock and is in trigger state.
● If the thread ID is not 0, one thread occupies the mutex and is not triggered.
● Unlike all other kernel objects, the OS performs special processing on mutex volumes to violate common rules.
■ Operations on mutex
● Create
Handle createmutex (
Psecutry_attributes PSA,
Bool binitialowner, // The initial state of mutex (true indicates that it is not triggered). The thread ID // and recursive count are set to the current thread ID and 1 respectively.
Pctstr pszname );
Handle createmutexex (
Psecutry_attributes PSA,
Pctstr pszname,
DWORD dwflags, // equivalent to binitialowner (0 indicates/false, create_mutex_initial_owner is equivalent to true
DWORD dwdesiredaccess );
● Obtain the mutex handle
Handle openmutex (
DWORD dwdesiredaccess,
Bool binherithandle,
Pctstr pszname );
● Release mutex so that processing can be triggered.
Bool releasemutex (handle hmutex );
Function Method: reduce the recursive count of an object by one. if the thread successfully waits for more than one mutex object, the thread must call releasemutex for the same number of times to set the recursive count to 0, and the thread ID is also set to 0. in this way, the object is set.
Differences between mutex and other kernel objects:
When a thread is added to wait for an untriggered mutex object, the thread enters the waiting state, however, if the system checks that the thread ID to obtain the mutex is the same as the thread ID recorded in the mutex object, the system also keeps the thread in A schedulable State even if the mutex has not been triggered..
■ The root cause of the difference between mutex and other kernel objects is "ownership": that is, other kernel objects do not remember which thread they are waiting for success. this allows him to get the thread even if it is not triggered.
In this case, if the thread that occupies the mutex is terminated before the mutex is released, the mutex will be "abandoned ".
Because the system records all mutex and thread kernel objects, it has the ability to re-trigger the abandoned mutex. in this way, other threads waiting for mutex can obtain mutex resources. however, there is a small difference: the waiting function returns wait_abandoned instead of the normal wait_object_0.
■ Differences between mutex and key segments:
Features |
Mutex |
Key Section |
Cross-process availability |
Slow |
Fast |
Statement |
Handle hctx |
Critical_section CS |
Initialization |
Hmtex = createmutex (null, false, null) |
Initializecriticalsection (& CS) |
Clear |
Closehandle (HGP) |
Deletecriticalsection (& CS) |
Unlimited waiting |
Waitforsignalobject (HGP, infinite) |
Entercriticalsection (& CS) |
0 wait |
Waitforsignalobject (HGP, infinite) |
Tryentercriticalsection (& CS) |
Any wait time |
Waitforsingleobject (HGP, dwmilliseconds) |
Not Supported |
Release |
Releasemutex (HMT) |
Leavecriticalsection (& CS) |
Can I wait for other kernel objects at the same time? |
Yes (using waitformultipleobject or similar functions) |
No |
Thread synchronization object speed query table:
Object |
When is not triggered |
When is triggered |
Side effects of waiting for success |
Process |
The process is still running. |
Process Termination (exitprocess or terminateprocess) |
No |
Thread |
When the thread is still running |
When the thread is terminated (exit (terminate) thread |
No |
Job |
When the job has not timed out |
Job timeout |
No |
File |
When an I/O request is to be processed |
When the I/O request is complete |
No |
Console input |
No input |
Input |
No |
File Change Notification |
No change notification for the file |
When the file system detects a change |
Reset notification |
Auto reset event |
Resetevent, pulseevent, or wait for success |
When setevent/pulseevent is called |
Reset event |
Manual reset event |
Resetevent, pulseevent |
When setevent/pulseevent is called |
No |
Automatic Reset to wait for the timer |
Cancelwaitabletimer |
Time (setwaitabletimer) |
Reset Counter |
Manual reset to wait for the timer |
Cancelwaitabletimer |
Time (setwaitabletimer) |
No |
Semaphores |
Waiting for success |
Count greater than 0 (releasesemaphore) |
Subtract one from the counter |
Mutex |
Waiting for success |
Releasemutex) |
Give ownership to the thread |
Key Section (User Mode) |
Wait (try) entercriticalsection) |
Leavecriticalsection) |
Give ownership to the thread |
Srwlock (User Mode) |
Wait for Success (acquiresrwlock (exclusive )) |
Releasesrwlock (exclusive )) |
Give ownership to the thread |
Condition variable (User Mode) |
Waiting for Success (sleepconditionvariable *) |
Wake-up (wake (all) conditionvariable) |
No |
The interlocked series functions (user mode) never make the threads become unschedulable. They only modify a value and return immediately.
8. asynchronous device I/O: allows a thread to start reading or writing operations without waiting for the read operation or waiting for the Operation to complete. the kernel object that can be synchronized when the device object is used. That is, we can call waitforsignalobject and pass in the file handle, socket, and communication port. When the system executes asynchronous I/O, the device is in the trigger state. Once the operation is completed, the system changes to the trigger state. In this way, the thread will know that the operation has been completed and the thread can continue to execute.
Function: DWORD waitforinputidle (
Handle hprocess,
DWORD dwmillseconds );
First, stop the current process and wait for the process marked by hprocess until no input to be processed is found in the thread in the first window of the application (that is, the process marked by hprocess.
The thread can also call msgwaitformultipleobjects or msgwaitformultipleobjsex, so that the thread waits for the message to be processed by itself.
DWORD msgwaitformultipleobjects (
DWORD dwcount,
Phandle phobjects,
Bool bwaitall,
DWORD dwmilliseconds,
DWORD dwwakemask );
DWORD msgwaitformultipleobjectsex (
DWORD dwcount,
Phandle phobjects,
DWORD dwmilliseconds,
DWORD dwwakemask, // indicates the type of message.
DWORD dwflags );
These functions are similar to waitformultipleobjects. The difference is that not only does the calling thread become schedulable when the kernel object is triggered, in addition, window messages need to be sent to a window created by the call thread, and they also become schedulable.
You should not use waitformultipleobjects to create a window thread or execute a job thread related to the user interface, but msgwaitformultipleobjectsex, because the former will prevent the thread from responding to operations on the user interface.
9. when the debugger starts execution, it attaches itself to the program to be debugged. then the debugger is idle, waiting for the operating system to notify it of time related to the program to be debugged. the debugger waits for these times through the waitfordebugevent function class:
Bool waitfordebugevent (
Pdebug_event PVDF,
DWORD dwmillsecond );
When the debugger calls this function, the debugger thread will be suspended. The system notifies the debugger of debugging by sending the waitfordebugevent response method. the structure pointed to by the parameter 'pge' contains information related to the debugging event that just occurred.
10. The signalobjectandwait function triggers the kernel object through an atomic operation and waits for another kernel object:
DWORD signalobjectandwait (
Handle hobjecttosignal, // indicates a mutex, semaphore, or event.
Handle hobjecttowaiton, // indicates mutex, semaphore, event, timer, process, thread, // job, console input, and change notification.
DWORD dwmilliseconds, // How long should it take to wait for the object to trigger at most?
Bool balertable); // whether the asynchronous process call added to the queue can be processed when the thread is waiting
Hobjecttosignal: Any other type object will cause the function to return wait_failed. when getlasterror is used, error_invalid_handle is returned. this function checks the object type and performs the operations that are equivalent to releasemutex, releasesemaphore (minus one by count), or setevent.
Returned values: wait_object_0, wait_object_timeout, wait_failed, wait_abandoned, or wait_io_completion.
Function advantages: short time consumption.
10. Vista provides a new set of wait chain traversal (WCT) APIs. These functions allow us to list all the locks and detect internal or even deadlocks between processes.
Possible locks |
Description |
Key Section |
Windows records which thread is occupying which key segment |
Mutex |
Windows users record which thread is occupying which mutex, even if abandoned |
Processes and threads |
Window records which thread is waiting for Process Termination or thread termination |
Sendmessage call |
It is important to know that the thread is waiting for sendmessage to return. |
COM Initialization and calling |
Windows records the call to cocreateinstance and the call to the COM Object method. |
Advanced local process call |
In Windows Vista, as a new undisclosed kernel inter-process communication mechanism, alpc has replaced local process calls. |
One thing left is that running XP cannot be debugged. It's a tragedy. Let's see it tomorrow.