.. _POSIXThreads:

.. raw:: html

   <script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "POSIXThreads";ODSA.SETTINGS.MODULE_LONG_NAME = "POSIX Thread Library";ODSA.SETTINGS.MODULE_CHAPTER = "Concurrency with Multithreading"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 12:51:47"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script>


.. |--| unicode:: U+2013   .. en dash
.. |---| unicode:: U+2014  .. em dash, trimming surrounding whitespace
   :trim:


.. This file is part of the OpenCSF eTextbook project. It was
.. auto-generated by scripts from the OpenDSA eTextbook project.
.. See https://OpenCSF.org for more details. OpenCSF is distributed
.. under a Creative Commons Attribution-NonCommercial 4.0 International
.. License (see http://creativecommons.org/licenses/by-nc/4.0/),
.. Copyright (c) 2019-2021 by Michael S. Kirkpatrick. OpenDSA is
.. distributed under an MIT open source license, Copyright (c) 2012-2021
.. by the OpenDSA Project Contributors.

.. avmetadata::
   :author: Michael S. Kirkpatrick
   :requires:
   :satisfies: 
   :topic: 

POSIX Thread Library
====================

In this section, we'll return to the code from `Code Listing 6.1
<ProcVThreads.html#cl6-1>`_ and replace the comments with functions from the
:term:`POSIX thread library (pthreads) <POSIX thread library>`. Pthread implementations
are available for a wide variety of platforms, including Linux, macOS, and
Windows. After considering the basic techniques to get threads started, we'll
look at how to pass arguments to and return data from the thread.

Creating and Joining Threads
----------------------------

Three functions define the core functionality for creating and managing threads.
The ``pthread_create()`` function will create and start a new thread inside a
process. The ``start_routine`` parameter specifies the name of the function to
use as the thread's entry point, just as ``main()`` serves as the main thread's
entry point. The pthread_exit() is used to exit the current thread and
optionally return a value. Finally, the ``pthread_join()`` function is the
thread equivalent of the ``wait()`` function for processes. That is, calling
``pthread_join()`` on a child thread will cause the current (parent) thread to
wait until the child finishes and calls ``pthread_exit()``.

.. topic:: C library functions – <pthread.h>

   .. figure:: Images/CSF-Images-Library.png
      :align: left
      :width: 100%
      :alt: Decorative C library image

   ``int pthread_create (pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);``
     Create a new thread starting with at the ``start_routine`` function.

   ``void pthread_exit (void *value_ptr);``
     Exit from the current thread.

   ``int pthread_join (pthread_t thread, void **value_ptr);``
     Join a specified thread.

The arg argument to the ``pthread_create()`` function gets passed verbatim as
the argument to the ``start_routine()`` function. That is, when the thread is
created, it begins executing as if the programmer had called ``start_routine
(arg);`` in their code. The only thing that is different is that the function
will begin executing in a different thread.

The prototype for the ``pthread_create()`` function can be rather difficult to
read if you are not completely comfortable with :term:`function pointers
<function pointer>`. Specifically, this prototype declares that the third
parameter must be a pointer to a function that adheres to the following type
declaration:

.. codeinclude:: Threads/Start.c

This prototype requirement simplifies the interface specification for thread
creation. The trade-off is that passing parameters becomes more complicated. The
following program illustrates how to create a child thread and wait for it to finish.

.. _cl6-2:

.. codeinclude:: Threads/CodeListing-6-2.c
   :linenos: true

`Code Listing 6.2 <#cl6-2>`_ illustrates a subtle point that is not immediately
obvious to novices: **The ``main()`` function defines a thread.** Specifically,
every program begins with a single thread of execution with ``main()`` as its
entry point. Once the pthread library creates an additional thread, it is
important that ``main()`` should be treated as a thread. In the simplest terms,
this perspective implies that ``main()`` needs to end with ``pthread_exit()``
instead of the standard return statement. Using ``pthread_exit()`` ensures that
all threads are managed and run correctly.

The main thread uses ``pthread_join()`` function to wait for the thread running
``start_thread()`` to call ``pthread_exit()``. The standard thread terminology
uses the term :term:`joining <fork/join pattern>` to mean waiting on a thread to complete. When a
thread exits, any resources associated with it (such as its run-time stack)
remain allocated until the thread is joined. As such, the ``pthread_join()`` and
``pthread_exit()`` combination can be used to return a value from the exiting
thread to its parent. In this example, nothing is returned, so both of these
functions take NULL as an argument.

Creating threads with ``pthread_create()`` happens :term:`asynchronously <asynchronous>`. That
is, ``pthread_create()`` requests the allocation of resources for a new thread
and returns 0 if the request is successful. **The new thread may or may not
begin running by the time ``pthread_create()`` returns.** In fact, the new
thread may have already run to completion by the time ``pthread_create()``
returns! The timing for running both the new and existing threads are determined
by the system (the pthread library and the kernel). From the programmer's
perspective, this choice is nondeterministic.


.. topic:: Bug Warning

   .. figure:: Images/CSF-Images-BugWarning.png
      :align: left
      :width: 90%
      :alt: Decorative bug warning

   There are a couple of common mistakes with pthread function parameters. With
   ``pthread_create()``, the first parameter must point to a ``pthread_t``
   instance. It is common to (incorrectly) declare the variable as a
   ``pthread_t*``. Instead, the variable should be a ``pthread_t`` and the address
   of it should be passed as shown above. Similarly, the first parameter for
   ``pthread_join()`` must be a ``pthread_t`` instance, not a pointer. Next, the
   third parameter to ``pthread_create()`` must be the name of the function and
   must not include (). The parentheses would indicate that the function should be
   called (before creating the thread) and the function's return value specifies
   the address to start at in the new thread. The following code sample
   illustrates these bugs.

   .. codeinclude:: Threads/BugWarning.c
      :linenos: true

Attached and Detached Threads
-----------------------------

In some scenarios, a thread will be created as :term:`detached <detached thread>` instead of
joinable. When a detached thread exits, its resources are immediately reclaimed
for more efficient reuse. However, once a thread is detached, it can never be
joined. This means that no other thread can wait on it to finish. According to
the pthread specification, all threads are supposed to be created as joinable by
default. The ``pthread_attr_setdetachstate()`` function can be used to change
the ``attr`` argument to ``PTHREAD_CREATE_DETACHED`` to override the default.

.. _cl6-3:

.. codeinclude:: Threads/Detach.c
   :linenos: true

Alternatively, the ``pthread_detach()`` function can be used to detach a running thread instance. A thread can detach itself by using its own ``pthread_t`` identifier as an argument to ``pthread_detach()``.

.. _cl6-4:

.. codeinclude:: Threads/Pthread_detach.c

.. topic:: C library functions – <pthread.h>

   .. figure:: Images/CSF-Images-Library.png
      :align: left
      :width: 100%
      :alt: Decorative C library image

   ``int pthread_detach (pthread_t thread);``
     Detaches the specified thread.

   ``pthread_t pthread_self (void);``
     Returns the current thread's pthread_t identifier.

.. avembed:: Exercises/Threads/POSIXThreadSumm.html ka
   :module: POSIXThreads
   :points: 1.0
   :required: True
   :exer_opts: JXOP-debug=true&amp;JOP-lang=en&amp;JXOP-code=java
   :long_name: POSIX thread questions
   :threshold: 3

