                              Wine Documentation                               
Prev                                                                       Next
-------------------------------------------------------------------------------

Chapter 7. Overview

Brief overview of Wine's architecture...

7.1. Basic Overview

Written by Ove Kven <ovek@winehq.com>

With the fundamental architecture of Wine stabilizing, and people starting to
think that we might soon be ready to actually release this thing, it may be
time to take a look at how Wine actually works and operates.

7.1.1. Wine Overview

Wine is often used as a recursive acronym, standing for "Wine Is Not an
Emulator". Sometimes it is also known to be used for "Windows Emulator". In a
way, both meanings are correct, only seen from different perspectives. The
first meaning says that Wine is not a virtual machine, it does not emulate a
CPU, and you are not supposed to install neither Windows nor any Windows device
drivers on top of it; rather, Wine is an implementation of the Windows API, and
can be used as a library to port Windows applications to Unix. The second
meaning, obviously, is that to Windows binaries (.exe files), Wine does look
like Windows, and emulates its behaviour and quirks rather closely.

Note Note                                                                      
     The "Emulator" perspective should not be thought of as if Wine is a       
     typical inefficient emulation layer that means Wine can't be anything but 
     slow - the faithfulness to the badly designed Windows API may of course   
     impose a minor overhead in some cases, but this is both balanced out by   
     the higher efficiency of the Unix platforms Wine runs on, and that other  
     possible abstraction libraries (like Motif, GTK+, CORBA, etc) has a       
     runtime overhead typically comparable to Wine's.                          

7.1.2. Win16 and Win32

Win16 and Win32 applications have different requirements; for example, Win16
apps expect cooperative multitasking among themselves, and to exist in the same
address space, while Win32 apps expect the complete opposite, i.e. preemptive
multitasking, and separate address spaces.

Wine now deals with this issue by launching a separate Wine process for each
Win32 process, but not for Win16 tasks. Win16 tasks are now run as different
intersynchronized threads in the same Wine process; this Wine process is
commonly known as a WOW process, referring to a similar mechanism used by
Windows NT. Synchronization between the Win16 tasks running in the WOW process
is normally done through the Win16 mutex - whenever one of them is running, it
holds the Win16 mutex, keeping the others from running. When the task wishes to
let the other tasks run, the thread releases the Win16 mutex, and one of the
waiting threads will then acquire it and let its task run.

7.1.3. The Wine server

The Wine server is among the most confusing concepts in Wine. What is its
function in Wine? Well, to be brief, it provides Inter-Process Communication
(IPC), synchronization, and process/thread management. When the wineserver
launches, it creates a Unix socket for the current host in your home
directory's .wine subdirectory (or wherever the WINEPREFIX environment variable
points) - all Wine processes launched later connects to the wineserver using
this socket. (If a wineserver was not already running, the first Wine process
will start up the wineserver in auto-terminate mode (i.e. the wineserver will
then terminate itself once the last Wine process has terminated).)

Every thread in each Wine process has its own request buffer, which is shared
with the wineserver. When a thread needs to synchronize or communicate with any
other thread or process, it fills out its request buffer, then writes a command
code through the socket. The wineserver handles the command as appropriate,
while the client thread waits for a reply. In some cases, like with the various
WaitFor synchronization primitives, the server handles it by marking the client
thread as waiting and does not send it a reply before the wait condition has
been satisfied.

The wineserver itself is a single and separate process and does not have its
own threading - instead, it is built on top of a large poll() loop that alerts
the wineserver whenever anything happens, such as a client having sent a
command, or a wait condition having been satisfied. There is thus no danger of
race conditions inside the wineserver itself - it is often called upon to do
operations that look completely atomic to its clients.

Because the wineserver needs to manage processes, threads, shared handles,
synchronization, and any related issues, all the clients' Win32 objects are
also managed by the wineserver, and the clients must send requests to the
wineserver whenever they need to know any Win32 object handle's associated Unix
file descriptor (in which case the wineserver duplicates the file descriptor,
transmits it to the client, and leaves it to the client to close the duplicate
when the client has finished with it).

7.1.4. The Service Thread

The Wine server cannot do everything that needs to be done behind the
application's back, considering that it's not threaded (so cannot do anything
that would block or take any significant amount of time), nor does it share the
address space of its client threads. Thus, a special event loop also exists in
each Win32 process' own address space, but handled like one of the process' own
threads. This special thread is called the service thread, and does things that
it wouldn't be appropriate for the wineserver to do. For example, it can call
the application's asynchronous system timer callbacks every time a timer event
is signalled (the wineserver handles the signalling, of course).

One important function of the service thread is to support the X11 driver's
event loop. Whenever an event arrives from the X server, the service thread
wakes up and sees the event, processes it, and posts messages into the
application's message queues as appropriate. But this function is not unique -
any number of Wine core components can install their own handlers into the
service thread as necessary, whenever they need to do something independent of
the application's own event loop. (At the moment, this includes, but is not
limited to, multimedia timers, serial comms, and winsock async selects.)

The implementation of the service thread is in scheduler/services.c.

7.1.5. Relays, Thunks, and DLL descriptors

Loading a Windows binary into memory isn't that hard by itself, the hard part
is all those various DLLs and entry points it imports and expects to be there
and function as expected; this is, obviously, what the entire Wine
implementation is all about. Wine contains a range of DLL implementations. Each
of the implemented (or half-implemented) DLLs (which can be found in the dlls/
directory) need to make themselves known to the Wine core through a DLL
descriptor. These descriptors point to such things as the DLL's resources and
the entry point table.

The DLL descriptor and entry point table is generated by the winebuild tool
(previously just named build), taking DLL specification files with the
extension .spec as input. The output file contains a global constructor that
automatically registers the DLL's descriptor with the Wine core at runtime.

Once an application module wants to import a DLL, Wine will look through its
list of registered DLLs (if it's not registered, it will look for it on disk).
(Failing that, it will look for a real Windows .DLL file to use, and look
through its imports, etc.) To resolve the module's imports, Wine looks through
the entry point table and finds if it's defined there. (If not, it'll emit the
error "No handler for ...", which, if the application called the entry point,
is a fatal error.)

Since Wine is 32-bit code itself, and if the compiler supports Windows' calling
convention, stdcall (gcc does), Wine can resolve imports into Win32 code by
substituting the addresses of the Wine handlers directly without any thunking
layer in between. This eliminates the overhead most people associate with
"emulation", and is what the applications expect anyway.

However, if the user specified --debugmsg +relay, a thunk layer is inserted
between the application imports and the Wine handlers; this layer is known as
"relay" because all it does is print out the arguments/return values (by using
the argument lists in the DLL descriptor's entry point table), then pass the
call on, but it's invaluable for debugging misbehaving calls into Wine code. A
similar mechanism also exists between Windows DLLs - Wine can optionally insert
thunk layers between them, by using --debugmsg +snoop, but since no DLL
descriptor information exists for non-Wine DLLs, this is less reliable and may
lead to crashes.

For Win16 code, there is no way around thunking - Wine needs to relay between
16-bit and 32-bit code. These thunks switch between the app's 16-bit stack and
Wine's 32-bit stack, copies and converts arguments as appropriate, and handles
the Win16 mutex. Suffice to say that the kind of intricate stack content
juggling this results in, is not exactly suitable study material for beginners.

7.1.6. Core and non-core DLLs

Wine must at least completely replace the "Big Three" DLLs (KERNEL/KERNEL32,
GDI/GDI32, and USER/USER32), which all other DLLs are layered on top of. But
since Wine is (for various reasons) leaning towards the NT way of implementing
things, the NTDLL is another core DLL to be implemented in Wine, and many
KERNEL32 and ADVAPI32 features will be implemented through the NTDLL. The
wineserver and the service thread provide the backbone for the implementation
of these core DLLs, and integration with the X11 driver (which provides GDI/
GDI32 and USER/USER32 functionality along with the Windows standard controls).
All non-core DLLs, on the other hand, are expected to only use routines
exported by other DLLs (and none of these backbone services directly), to keep
the code base as tidy as possible. An example of this is COMCTL32 (Common
Controls), which should only use standard GDI32- and USER32-exported routines.

-------------------------------------------------------------------------------
Prev                                  Home                                 Next
Wine Architecture                      Up                       Module Overview
