Understanding Win16Mutex
ID: Q125867
|
The information in this article applies to:
-
Microsoft Win32 Application Programming Interface (API), included with:
SUMMARY
Windows 95 offers preemptive multithreaded scheduling for Win32 processes,
yet also provides the familiar non-preemptive task switching found in
Windows 3.x for Win16 applications. Some of the Win32 system DLLs, such as
USER32.DLL and GDI32.DLL, thunk to their 16-bit counterparts for
compatibility and size. Unlike Windows 3.x, which did not preemptively
schedule processes, Windows 95 must be able to handle the possibility that
it might be reentered by two or more processes each calling the same API
functions. Windows 95 must do so in a way that uses little memory and is
compatible with all existing 16-bit applications and DLLs.
Win16Mutex is a global semaphore that is used to protect the 16-bit Windows
95 components from being reentered by preventing Win32 threads from
thunking to 16-bit components while other 16-bit code is running.
Win16Mutex is internal to Windows 95 and is not accessible from
applications or DLLs. This article explains how Win16Mutex works and offers
design tips for minimizing the effects Win16Mutex may have on Win32
applications.
MORE INFORMATION
Because Windows 3.x is a non-preemptive system, Windows 3.x did not need to
be designed to prevent the system from being reentered. Only one task
(application instance) at a time can call system services (API functions)
because other tasks cannot run until the active task voluntarily yields
control of the CPU. Since only one task can execute at a time, it is not
possible to have two different tasks calling the same API function, and
thus Windows does not need to protect itself from reentrancy.
Windows 95 differs from Windows 3.x because Windows 95 provides support for
both Win32 and Win16 applications. In Windows 95, every instance of every
Win16 application is a process with exactly one thread, and every Win32
process has at least one thread. Win32 threads are preemptively scheduled
and may even preempt Win16 processes. Because many Win32 API functions are
thunked to 16-bit Windows API functions, there is now a possibility for the
16-bit Windows components to be reentered. Since the 16-bit Windows
components are largely the same as in Windows 3.x, they need to be
protected from being reentered.
The Win16Mutex provides this protection by allowing only one thread (not
process) at a time to access the 16-bit APIs. Whenever Win16Mutex is owned
by a thread, any other thread that tries to claim Win16Mutex will block
until Win16Mutex is released. Now the question remains: "When does
Win16Mutex get claimed and released?"
Whenever a Win16 process is running, it owns Win16Mutex. That is, when a
Win16 process first gets a message via GetMessage or PeekMessage, the Win16
process claims Win16Mutex. The Win16 process releases Win16Mutex whenever
the process yields, such as when the process calls GetMessage or
PeekMessage and doesn't return. The only way a Win16 process can keep
Win16Mutex indefinitely is to never yield; since the message-processing
mechanism provides the scheduler in 16-bit Windows, the only way to never
yield is to stop processing messages (which makes the application
unresponsive to user input).
The only time a thread in a Win32 process claims Win16Mutex is when the
thread makes a call to an API function which thunks to one of the 16-bit
Windows components or when the thread thunks directly to a Win16 DLL.
Immediately after the call returns, the process releases Win16Mutex. Not
all API functions thunk to 16-bit components; most 32-bit USER and GDI
functions thunk to 16-bit USER and GDI, but none of the 32-bit KERNEL
functions thunk to 16-bit KRNL386. One exception is when a Win32 process
spawns a Win16 process, KERNEL32 thunks to KRNL386 to call the Win16
loader.
Putting 16-bit and 32-bit behaviors together, you can see that when a Win16
process is running, and a thread of a Win32 process preempts the Win16
process and calls a function which thunks to a 16-bit component, the Win32
thread is put to sleep until the Win16 process yields, which releases
Win16Mutex. Likewise, when one Win32 process's thread claims Win16Mutex and
then loses its timeslice, and another thread from either the same or a
different process tries to claim Win16Mutex, the second thread blocks until
Win16Mutex is released.
Win16Mutex is internal to Windows 95 and may not be manipulated or even
checked by applications and DLLs. Win16Mutex is implemented mainly in the
thunk layer so that every Win32 API which thunks to a Win16 component will
automatically claim Win16Mutex before entering 16-bit code. Additionally,
thunks created by the thunk compiler to allow Win32 applications and DLLs
to call 16-bit DLLs claim Win16Mutex automatically, so programmers do not
have to do so explicitly.
One way to lessen the impact that Win16 applications have on the
responsiveness of Win32 applications is to create multiple threads where
the primary thread (the initial thread of the process) controls the entire
user interface for the process and each additional thread performs some
useful task, such as reading or writing to a data file, but does not make
user interface or graphics calls. This way, if the Win32 process's primary
thread blocks waiting for a Win16 process to yield, its other threads are
still performing useful work.
Additional query words:
4.00
Keywords : kbKernBase kbThread kbWinOS95 kbGrpKernBase
Version : 4.00
Platform : WINDOWS
Issue type :