Vous êtes sur la page 1sur 14

POSIX THREADS VERSUS

WIN32 THREADS
A Case Study on the Similarities and Differences between
POSIX threads in UNIX and WIN32 threads in Windows.
CONOR KELLEHER
JACK BEEGAN
OISN KYNE

13395381
13397866
13398651

Contents
Who Wrote What? .................................................................................................................................. 2
Introduction ............................................................................................................................................ 3
Win32 Threads in Windows .................................................................................................................... 4
History ................................................................................................................................................. 4
Threads ............................................................................................................................................... 4
Thread Creation .................................................................................................................................. 4
Thread Interaction .............................................................................................................................. 5
Thread Destruction ............................................................................................................................. 5
POSIX Threads in UNIX ............................................................................................................................ 6
History ................................................................................................................................................. 6
Threads ............................................................................................................................................... 6
Thread Creation .................................................................................................................................. 6
Thread Interaction .............................................................................................................................. 7
Thread Termination ............................................................................................................................ 7
Win32 Threads and POSIX Threads Comparison .................................................................................... 9
Overview ............................................................................................................................................. 9
Modern Usage and Popularity ............................................................................................................ 9
Thread Creation .................................................................................................................................. 9
Thread Interaction ............................................................................................................................ 10
Thread Termination .......................................................................................................................... 10
Conclusions ........................................................................................................................................... 11
References ............................................................................................................................................ 12

1|Page

Who Wrote What?

2|Page

Research
o Initial topic exploration
o POSIX threads
History
Implementation
o WIN32 threads
History
Implementation
Document
o Introduction
o Thread Overview - Windows
History
Threads
Thread Creation
Thread Interaction
Thread Termination
o Thread Overview - POSIX
History
Threads
Thread Creation
Thread Interaction
Thread Termination
o Thread Comparisons
Overview
Popularity & Modern Use
Thread Creation
Thread Interaction
Thread Termination
o Discussion & Conclusions
o References
Proof Reading & Editing

Conor Kelleher
Jack Beegan

Oisn Kyne

Conor Kelleher
Oisn Kyne

Jack Beegan

Conor Kelleher

Jack Beegan

Various

Introduction
In this study we will be examining the differences between the Windows API for thread handling and
the Unix POSIX Threads. The body of the study is divided into three sections; one explaining the
history, use and implementation of threading systems in the Windows OS family, one looking into
the same areas in POSIX threads in a UNIX environment and, lastly, a section giving a side-by-side
comparison of the two. The ease of use for the developer and the subsequent popularity in modern
computing, the efficiency of the operations and the security involved (deadlock avoidance) are all
things that are going to be considered in this comparison. After the two thread APIs have been
subject to an in-depth analysis, we will conclude the study (touching on points brought up in the
comparison section) by giving a brief statement of our current view on the two and giving our
opinion as to which is the better implementation.

3|Page

Win32 Threads in Windows


History
The Windows operating systems have always maintained an API for developers to use to build
applications on the Windows platforms. Until recently, this API was called the Win32 API, but
recently, Windows have moved to change this name to the Windows API, to more accurately
reflect its roots in 16-bit Windows and its support on 64-bit Windows. (API Index, MSDN). The
Windows API has been in development since the beginning of the Windows operating systems;
almost every new operating system version has implemented its own specific changes to the API but
these are only reflected in a name change for the major architectural changes. At the point of
writing this case study, The Windows API refers to the Win32 API, as opposed to any of the other
versions or implementations of the API.
The Windows API is defined in most of its official documentation in C or C++ programming
languages, but at this point, there have been many different wrapper classes and extensions for
other languages to make the Windows API more object-oriented and more accessible to
programmers who prefer other languages.

Threads
The Microsoft Developer Network, the central hub for all documentation and resource material for
Windows developers, defines a thread as such:
A thread is the entity within a process that can be scheduled for execution. All threads of a process
share its virtual address space and system resources. Each process is started with a single thread, but
can create additional threads from any of its threads. (Multiple Threads, MSDN)
Windows threading systems are described as a high level way of operating with threads, they
simplify many of the processes which results in higher level code, which is generally easier to
interpret. The Intel Developer Zone has an article written by Clay Breshears (2006) which
complements the Windows Threads API due to its simplicity of use and elegance of design. This
simplicity is self-evident in the MSDN documentation on threads, the entire repository on thread
functions consists of 37 separate functions, many of which, stem from the same concepts. It is
absolutely undeniable that the thread API is as concise as possible.
The creation, interaction and destruction of threads are arguably some of the most important and
divergent aspects of thread APIs between different operating systems, in this section, we will look at
the implementation of these three tasks in the Windows operating systems, for further comparison
to be made later in this case study.

Thread Creation
Thread creation with the Windows API is a reasonably simple procedure; the API documentation
describes the action in C.
CreateThread(Security Attributes, Stack Size, Thread Function name, Arguments to be passed
to thread function, creation flags, &threadIdentifier);

4|Page

The security attributes declare whether or not a child process can inherit this thread, by default, this
is set to NULL and is not possible. The stack size is the size of the stack to be allocated to the thread
in bytes, (the system rounds this to the nearest page). The thread function name is interesting as you
pass a pointer to the address of the first line of a function to be executed in this thread; this is
followed by an array of arguments to be passed to said function. Any specific creation flags to be
used are passed then, such as creating an already suspended process. Finally, the address of a
variable to store the ID of the new thread is passed such that you can then access this thread with
that identifier, if this variable remains null after calling createthread, the creation failed and you
should react accordingly to this failure.

Thread Interaction
Windows provides many separate ways for threads to interact but the first and foremost thing to
keep in mind is that threads operate on shared memory in a single process, such that an API for
thread interaction isnt necessarily required. It is good practice to protect shared data with
semaphores or mutexes to prevent concurrent access and corruption of data due to competing
threads accessing the same data simultaneously.
Some of the available methods of multi thread management include:

Console input buffers


Events
Mutexes
Semaphores
Processes
Threads
Timers

I wont discuss the operation of these methods for interaction between threads in this case
study as the title is the similarities and differences between POSIX and WIN32 threads, whereas
these arent unique to one or the other, they merely have different implementations.

Thread Destruction
Thread destruction in a Windows environment is a reasonably simple process. The function to exit a
thread is ExitThread(status). This function is called when a thread that was created for a specific
function hits a return statement, or when it is called explicitly. ExitThread deallocates the threads
stack and any pending I/O is cancelled before the thread terminates. The status is the exit code for
the thread; by convention, a normal termination is a status code of 0. When a thread is terminated it
becomes signalled, indicating to any other threads waiting for its termination can now unblock.
If this thread is the last thread in a process, ExitProcess is also called and the process is ended too.
Interestingly, terminating a thread does not remove it from the system completely until all handles
to the thread are closed too.

5|Page

POSIX Threads in UNIX


History
The POSIX (Portable Operating System Interface) standard was created in 1988 as a convention to be
used across compliant operating systems so as to maintain programming compatibility across
systems, and allowing portable code to be written by developers. It is formally denoted as IEEE 1003
but is commonly referred to as POSIX. Since its inception, it has undergone numerous revisions as
standards for new technologies were added, leading to the current version, 1003.1, 2013 edition.
The standards for POSIX threads were originally outlined in the 1995 revision. They are defined in
the form of a C library called Pthreads within the POSIX API, and contain more than 60 functions.
(Tanenbaum & Herbert, 2014). Due to the widespread adoption of POSIX compliance or near
compliance across many common operating systems, POSIX threads, are available on most UNIX and
Linux distros, including but not limited to Mac OS X, Android, Solaris, BSD derivatives and Ubuntu.

Threads
The POSIX Base Specification (IEEE Computer Society and The Open Group, 2013) provides formal
definitions of all components of the OS interface. Within this, threads are defined as:
A single flow of control within a process {consisting of} thread ID, scheduling priority and
policy, errno value, thread-specific key/value bindings, and the required system resources to
support a flow of control
By breaking a process into multiple flows of control, multiple tasks can be accomplished at the same
time, while also preventing the whole process stopping when part of a process is blocked. POSIX
threads, or Pthreads, also provide a much faster and lightweight solution to parallelism than process
forks, costing the programmer between a tenth and a hundredth of the execution time in
comparison, as per performance tests ran at research laboratories in California (Barney, Blaise Lawrence Livermore National Laboratory, 2014).

Thread Creation
Threads in POSIX are created using the pthread_create() function call. This function, defined within
the base specifications, is specifically designed to reflect the behavior of a process fork call, adapted
to accept arguments. (Tanenbaum & Herbert, 2014) It returns the thread identifier, TID, just as fork
would return the process identifier, PID. The format of this function call is:
pthread_create(tid,

attr,

start_fn,

arg);

(Lewis

&

Berg,

1995)

The 4 arguments of this function are outlined below.

tid
This is a pointer to the address where the ID of the newly created thread will be stored. It is
of type pthread_t and must be declared within your program. (Butenhof, 1997)

attr
This is a pointer to the thread attribute, a variable of type pthread_attr_t. This contains the
details of the desired attributes of the thread. If set to null, the thread will be created with

6|Page

the default attributes which are process scope, nondetachable state, a default stack and
stack size, and a priority of zero. (Sun Microsystems, Inc., 2005)
The attributes that can be set within this variable are (Barney, Blaise - Lawrence Livermore
National Laboratory, 2014):

Thread state (Detached or joinable)


Scheduling inheritance, policy, parameters and contention scope
Stack size, address and overflow size

start_fn
This is the function that the thread will run. It must be of type void *, and take a single
argument, also of type void *.

arg
This is the argument of type void * which will be passed as a parameter to start_fn within
the execution of the thread.
The call returns immediately with the thread ID value and the calling thread continues executing its
instructions. The new thread is created in a ready state and, depending upon the scheduling
outlined in the thread attributes, it will begin running the function that was passed to it during its
creation independently from calling thread. (Butenhof, 1997)

Thread Interaction
To allow for synchronization of tasks across threads, pthreads implement three standard thread
synchronization variables; namely mutexes, semaphores, and condition variables. (Lewis & Berg,
1995)
These objects allow threads to share code, variables and resources while protecting them from
unintentionally altering program behavior due to concurrent attempts to access and alter data.
Mutex, semaphores and condition variables (also known as event semaphores) all have equivalents
in the Win32 threads library and do not differ significantly in behavior, making in-depth study here
redundant.

Thread Termination
Pthread termination occurs in four possible cases; termination of the parent process, cancellation by
another thread, an explicit exit call, or the return of a threads start functions.
If the initial thread of a program ( the thread running main() ) ends without waiting on its subthreads to finish, all sub-threads will disappear per the standard UNIX process behavior in what is
referred to as thread evaporation by David Butenhof. (Butenhof, 1997) This is preventable by
implementing a pthread_join() before the end of the main which requires the pthreads to run to
termination to complete.
Thread cancellation occurs when a thread tells another to exit by calling pthread_cancel() on the
identifier of the thread. This will immediately call pthread_exit() on the subject of the call, provided
7|Page

that its cancelability state is set to enabled, and its cancelability type is set as asynchronous (Lewis &
Berg, 1995). If the cancelability type is deferred, pthread_exit() will only be called when the thread
reaches one of the allowed cancellation points. Functions that constitute valid cancellation points
are listed in the POSIX API (IEEE Computer Society and The Open Group, 2013).
When pthread_exit() is executed, the thread enters a terminated state. In this state, it will continue
to hold most of the system and resources it used when being executed, including its stack, register
state and returned value of type void *. It will remain like this until it is either joined with another
thread, or is detached; only then are its resources recycled and its identifier freed. (Butenhof, 1997)
The return of a threads start function implicitly calls pthread_exit() which terminates the thread
much as a direct call would. The only distinction between the two is that the return type of the start
function can be extracted from any subsequent join or detach calls on the thread ID. (Mitchell, et al.,
2001)

8|Page

Win32 Threads and POSIX Threads Comparison


Overview
While Win32 Threads and POSIX Threads have already been discussed individually in this case study,
we will now give a side-by-side comparison of the two forms of threads, specifically in their
implementations of the functions that are common to both and the under the hood differences, as
well as a brief description of how the two are viewed by the programmers using them.

Modern Usage and Popularity


While the POSIX standard was originally intended simply to provide a way to program with threads
for use in portable applications (which was a growing concern due to the varying implementations
used by different hardware vendors), currently POSIX Threads are seen by many programmers as
preferable to Win32 Threads. It can be shown that this is especially true by the ongoing work on the
Pthreads-win32 project, which aims to allow POSIX Threads to be used by developers on systems
which use Win32 Threads natively (for the sake of cross-platform portability).
However, despite the added benefit of portability, there is still much dispute among developers over
which implementation is better. These varying opinions can be found in various official and unofficial
forums online and one such developer, Clay Breshears exhibited this dispute through his articles in
2003 and 2006 on the Intel Developer Zone website, entitled Why Pthreads are better than Win32
threads, and Why Windows Threads Are Better Than POSIX Threads, respectively. Across these
two articles, Breshears shows how the features unique to each thread implementation can be
favourable to the user in certain situations, such as when he praises Pthreads for their separate data
types, allowing for easier reading and understanding of code written by someone else while,
conversely, he commends the simplicity of the Windows Threads data types, allowing for easier use
by the developer. Clearly, each implementation can be seen as more or less favourable, depending
on the circumstance and also depending on which person is viewing them.

Thread Creation
POSIX and Windows Threads have a very similar way of creating threads. In fact, this is one of the
areas in which it seems the twos functionality can be directly mapped from one to the other. In the
Windows API, the user can call the CreateThread() function and, the POSIX equivalent of this is
Pthread_Create(). The only difference in the use of these two functions is the arguments that must
be passed to them. (CreateThread Function, MSDN), (pthread_create, QNX).

CreateThread()

lpThreadAttributes A pointer to a
SECURITY_ATTRIBUTES structure
dwStackSize The initial size of the stack
lpStartAddress A pointer to the function
to be executed by the thread
lpParameter A pointer to a variable to be
passed to the thread
dwCreationFlags A flag that controls the
creation of the thread
lpThreadId A pointer to a variable that
9 | Preceives
a g e the thread identifier.

Pthread_Create()

thread A unique identifier for the new


thread to be returned
attr - An Attribute object that can be used
to set the attributes of the thread
start_routine The routine to be executed
by the thread
arg A single argument that can be passed
to start_routine

While the exact information being passed to the functions is different, both implementations
generate roughly the same result. In both cases, the functions are given as an argument a pointer to
the function that the thread will have to execute, information about how the thread should be able
to access memory, and a single argument that can be passed to the function.

Thread Interaction
As mentioned earlier in this case study, thread interaction is quite similar between Win32 and POSIX
threads (to the extent that their respective functions can almost be directly mapped from one to the
other) and, while the use of these functions for thread interaction are quite similar, the way they are
executed by the OS can result in some significant performance differences. One such example is in
the use of mutexes. As Larry Osterman explains in his article Why dont critical sections work cross
process? (2005), the windows implementation for mutexes requires the kernel to be accessed every
time you use it, which is not the case in the POSIX threads equivalent of mutexes unless there is
contention to be overcome via the kernel. For this reason, the Pthreads mutex is considered to be a
much more lightweight mutex. In Jeff Preshings article Always use a lightweight mutex (2011), he
compares the average time taken to use a mutex (looped 1,000,000 and divided to find average)
using both the Windows and the POSIX threads mutexes. Using the equivalent functions, he found
that the average time for locking and unlocking of the Windows mutex was 1.48s, whereas the
POISX mutex only took 92ns. This is clearly a much quicker implementation; however there are some
ways in which the use of Pthreads is made even quicker, for example, there is a condition to check
whether the thread creating the mutex is the only thread running, in which case, a mutex is
unnecessary and a trivial codepath is used, resulting in an average time of only 38ns on the same
system as before.

Thread Termination
Thread termination in Win32 and POSIX threads appear to be very similar, but do have some notable
differences. In the case of both, there are many ways for threads to exit. This can happen if the
starting routine for which the thread was created to execute returns normally after performing its
desired action, if the process that created the thread terminates before the thread terminates and,
(among others) if the respective thread-exit function is called on the thread. In Win32 threads, this
function is called ExitThread() and its POSIX counterpart is Pthread_exit(). Both functions are called
in the same way and each take an Exit_Code argument (usually 0). However, as mentioned earlier in
this case study, the ways in which these two are executed vary between the two Thread
implementations. Win32 threads are considered to be asynchronous in the way ExitThread() is
implemented as, here, if the thread is holding some resource or lock or has been allocated memory,
calling this function will not reallocate these resources, memory, etc. and so, deadlock can occur. In
POSIX threads, however, there is another condition in place to circumvent this issue. Here, threads
are assigned a state determining if cancellation should be enabled or disabled. In the case that it is
enabled, cancellation is asynchronous and functions just like Win32 threads, however if cancellation
is disabled, if the system reaches a Pthread_exit() call, it will use what is called deferred
cancellation, wherein the thread may run for an arbitrary time after cancellation , allowing critical
sections to be fully executed and resources to be released (Lewis & Berg, 1995).

10 | P a g e

Conclusions
Throughout our in-depth study of threads and the two most common types of them, we felt we
really developed a pretty thorough and comprehensive understanding of them as a concept, the
differences between the two most popular implementations of threads, and the benefits they
provide to the programmer and the end-user.
We focussed on the lifecycle of a thread as the crux of our comparisons, considering both POSIX and
Win32 threads as they proceeded from thread creation to thread termination, and the thread
interactions that occur in the times between.
In this manner, we were afforded a chance to see just how much they differed from one another, or
didnt differ as it so often proved to be, within each stage of their existence; whether it was the need
for different arguments during creation and the different default values used by each, or the
distinguishing speed increase pthreads provide during mutex-related actions, all the way to
distinctive deferred cancellation offered by POSIX threads when desired, making thread cancellation
less of a programming liability and much more usable.
These comparisons all led us to come to a single, shared consensus within the group regards threads
the flexibility to port across operating systems promised by POSIX threads is unrivalled in Win32
threads, making POSIX threads in UNIX and UNIX-like environments a much more desirable
implementation to work with given their programming elegance and overall ease of use.

11 | P a g e

References
Barney, Blaise - Lawrence Livermore National Laboratory, 2014. POSIX Threads Programming.
[Online]
Available at: https://computing.llnl.gov/tutorials/pthreads/
[Accessed 15 April 2015].
Butenhof, D. R., 1997. Programming with POSIX Threads. 1st ed. s.l.:Addison-Wesley.
IEEE Computer Society and The Open Group, 2013. Standard for Information Technology Portable
Operating System Interface (POSIX) Base Specifications, Issue 7, New York: IEEE Standards
Association.
Lewis, B. & Berg, D. J., 1995. PThreads Primer - A Guide to Multithreaded Programming, Mountain
View, California: SunSoft Press; Prentice Hall;.
Mitchell, M., Oldham, J. & Samuel, A., 2001. Advanced Linux Programming. 1st ed. Indianapolis,
Indiana: New Riders Publishing.
Silberschatz, A., Galvin, P. B. & Gagne, G., 2010. Operating System Concepts. 8th ed. s.l.:John Wiley &
Sons, Inc..
Sun Microsystems, Inc., 2005. Solaris Multithreaded Programming Guide, Santa Clara, CA: Sun
Microsystems, Inc..
Tanenbaum, A. S. & Herbert, B., 2014. Modern Operating Systems. 4th ed. Amsterdam: Prentice Hall.
API Index (Windows). 2015. API Index (Windows). [ONLINE] Available at:
https://msdn.microsoft.com/en-us/library/windows/desktop/hh920508(vs.85).aspx. [Accessed 04
April 2015].
Multiple Threads (Windows). 2015. Multiple Threads (Windows). [ONLINE] Available
at: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684254(v=vs.85).aspx. [Accessed
08 April 2015].
Why Windows Threads Are Better Than POSIX Threads Clay Breshears (Intel) Oct. 19, 2006 | Intel
Developer Zone. 2015. [ONLINE] Available at: https://software.intel.com/enus/blogs/2006/10/19/why-windows-threads-are-better-than-posix-threads. [Accessed 08 April
2015].
Why Pthreads are better than Win32 threads. 2015. Why Pthreads are better than Win32 threads.
[ONLINE] Available at: https://software.intel.com/en-us/forums/topic/311081. [Accessed 19 April
2015].
CreateThread function (Windows). 2015. CreateThread function (Windows). [ONLINE] Available
at: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx.
[Accessed 19 April 2015].

12 | P a g e

Pthread_create. 2015. Pthread_create. [ONLINE] Available


at:http://www.qnx.com/developers/docs/6.4.1/neutrino/lib_ref/p/pthread_create.html. [Accessed
19 April 2015].
Always Use a Lightweight Mutex. 2015. Always Use a Lightweight Mutex. [ONLINE] Available
at: http://preshing.com/20111124/always-use-a-lightweight-mutex/. [Accessed 21 April 2015].

13 | P a g e

Vous aimerez peut-être aussi