Skip to content

Commit adb6fbc

Browse files
committed
Some rewording done.
1 parent fc2b29c commit adb6fbc

File tree

1 file changed

+51
-53
lines changed

1 file changed

+51
-53
lines changed

threads.tex

Lines changed: 51 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -739,13 +739,13 @@
739739
\begin{itemize}
740740
\item Process synchronization is described on pages
741741
\pageref{SYNCHRONIZATION} to \pageref{SYNCHRONIZATIONEND}.
742-
\item Using mutexes and conditional variables it is possible to construct any
742+
\item By using mutexes and conditional variables it is possible to construct any
743743
other synchronization model.
744744
\item The exact behavior of synchronization primitives is largely determined by
745-
the scheduler, that decides which of the threads waiting for unlock will be
746-
waked up after the unlock happens. This leads to classical problems such as
747-
\emph{thundering horde} (lots of threads waiting for unlock)
748-
or \emph{priority inversion} (thread holding a lock has lower priority than
745+
the scheduler. It decides which of the threads waiting for releasing a lock
746+
will be woken up after the lock is actually released. This leads to classical
747+
problems such as a \emph{thundering horde} (lots of threads waiting for unlock)
748+
or a \emph{priority inversion} (thread holding a lock has lower priority than
749749
the thread waiting for the lock).
750750
\end{itemize}
751751

@@ -794,41 +794,38 @@
794794
when acquiring it, it is necessary to test return value of
795795
\texttt{p\-thread\_mutex\_lock}, and also have the lock checking set, see below.
796796
\item Mutexes are meant to be held for short time only. They are used for
797-
critical section (see the definition on page \pageref{CRITICALSECTION}),
798-
implementation, similarly to lock-files or semaphores (used like locks).
799-
\item Lock checking is governed by mutex type. By default the mutex type is set to
800-
\texttt{PTHREAD\_MUTEX\_DEF\-AULT}. This type does not define the result of
801-
locking a locked mutex, unlocking a mutex locked by different thread or
802-
unlocking an unlocked mutex. Concrete Unix implementations will map this define
803-
to \texttt{PTHREAD\_MUTEX\_NORMAL} or \texttt{PTHREAD\_\-MUT\-EX\_ERRORCHECK}.
804-
Thus, depending on correct implementation, that locking already locked mutex
805-
will result in deadlock (\texttt{NORMAL}) or not (\texttt{ERRORCHECK}).
806-
In the second case, return value will contain information about the error.
807-
If not tested, the program will wrongly assume that the mutex is locked.
808-
For the \texttt{NORMAL} type the result of the remaining two situations is not
809-
defined, for \texttt{ERRORCHECK} an error will be returned. ``Not defined``
810-
means that the thread unlocking a mutex locked by different thread can succeed.
811-
Or not -- everything depends on the implementation at hand. It also means that
812-
the result of such operations is of no interest because these should be avoided.
813-
More info can be found in the POSIX standard or the
814-
\texttt{pth\-read\_mutex\-attr\_set\-ty\-pe} man page.
815-
Checking return values of mutex functions can make the code slightly less
816-
readable however it can be wrapped in a macro. Alternatively, the checks can be
817-
used during development only.
818-
Solaris and Linux use \texttt{NORMAL} type by default, FreeBSD uses
819-
\texttt{ERRORCHECK}.
820-
\label{NOTMYLOCK}
797+
critical section (see the definition on page \pageref{CRITICALSECTION})
798+
implementation, similarly to lock-files or semaphores (if used like locks).
799+
\item Lock checking is governed by a mutex type. By default the mutex type is
800+
set to \texttt{PTHREAD\_MUTEX\_DEF\-AULT}. This type by itself does not define
801+
the result of (a) locking a locked mutex, (b) unlocking a mutex locked by a
802+
different thread, or (c) unlocking an unlocked mutex. Unix/Linux systems will
803+
map that macro to \texttt{PTHREAD\_MUTEX\_NORMAL} or
804+
\texttt{PTHREAD\_\-MUT\-EX\_ERRORCHECK} (ignoring the recursive type, see
805+
below). Thus, depending on a specific system, locking an already locked mutex
806+
will result in a deadlock (\texttt{NORMAL}) or not (\texttt{ERRORCHECK}). In
807+
the latter case, a return value will contain information about the error and if
808+
not tested, the program will wrongly assume the mutex is locked. For the
809+
\texttt{NORMAL} mutex type the result of (b) and (c) is not
810+
defined, for \texttt{ERRORCHECK} an error will be returned.
811+
In general you should avoid any undefined behavior unless specifically
812+
documented by the system at hand. More information can be found in the POSIX
813+
standard or the \texttt{pth\-read\_mutex\-attr\_set\-ty\-pe} man page. Checking
814+
return values of mutex functions can make the code slightly less readable
815+
however it can be wrapped in a macro. Alternatively, the checks can be used
816+
during development only. Solaris and Linux use \texttt{NORMAL} type by default,
817+
FreeBSD uses \texttt{ERRORCHECK}. \label{NOTMYLOCK}
821818
Example: \example{mutexes/not-my-lock.c}.
822-
\item Another type is \texttt{PTHREAD\_MUTEX\_RECURSIVE} that holds count of
819+
\item Another type is \texttt{PTHREAD\_MUTEX\_RECURSIVE} that holds a count of
823820
lock actions done by given thread. The remaining threads will be granted access
824821
only if the count reaches 0. This mutex cannot be shared between processes.
825-
\item What are recursive mutexes good for ? Let's assume there are two
822+
\item What are recursive mutexes good for? Let's assume there are two
826823
libraries, \texttt{A} and \texttt{B}. There is a library
827-
function \texttt{A:foo()}, that will acquire a mutex and calls \texttt{B:bar()}
828-
that can in turn call \texttt{A:bar()}, which will try to acquire the same
829-
mutex. Without recursive locks a deadlock will ensue. With recursive mutexes
824+
function \texttt{A:foo()} acquires a mutex and calls \texttt{B:bar()},
825+
and in turn calls \texttt{A:bar()} which tries to acquire the same
826+
mutex. Without recursive locks a deadlock will ensue. With recursive mutexes
830827
that's fine if these two calls are done by the same thread (another thread will
831-
get blocked). That is, assuming \texttt{A:foo()} and \texttt{A:bar()} are aware
828+
get blocked). That is, assuming \texttt{A:foo()} and \texttt{A:bar()} are aware
832829
that the same thread can be already in the critical section.
833830
\item \label{MUTEXTAB} The behavior according to mutex types:\\
834831
\\
@@ -849,15 +846,15 @@
849846
allocated mutex. If a mutex is dynamically allocated, it is always necessary to
850847
use \texttt{pthread\_mutex\_init}, even if the default attributes are desired or
851848
not.
852-
\item Dynamic mutexes are needed e.g. when a data structure which contains a
853-
mutex protecting it, is dynamically allocated.
854-
In such case before calling \texttt{free} with the data structure, it is first
855-
necessary to properly destroy the mutex (that can also have some memory
856-
allocated). Destroying locked mutex is not defined by the standard.
849+
\item Dynamic mutexes are needed e.g. when a data structure containing a mutex
850+
protecting it is dynamically allocated. In such a case, before calling
851+
\texttt{free} with the data structure, it is first necessary to properly destroy
852+
the mutex (that can also have some memory allocated). Destroying a locked mutex
853+
is not defined by the standard.
857854
\item Copying mutexes is also not defined by the standard -- the result of such
858-
operation depends on implementation. It is possible to copy pointer to mutex
859-
and work with that.
860-
\item Mutex destroy means its deinitialization.
855+
an operation depends on the implementation. It is possible to copy a pointer to
856+
a mutex and work with that.
857+
\item A mutex destroy means its deinitialization.
861858
\end{itemize}
862859

863860
%%%%%
@@ -899,18 +896,19 @@
899896
\begin{itemize}
900897
\item Locking a mutex that is being held by another thread is not correct.
901898
Sometimes a (self)deadlock can ensue, see the previous page. If you need to
902-
unlock a mutex locked by different thread, use binary semaphores instead.
899+
unlock a mutex locked by a different thread, use binary semaphores instead.
903900
\item When creating a program where efficiency is paramount, it is necessary to
904-
think about how many mutexes will be needed and how exactly will be used.
901+
think about how many mutexes will be needed and how exactly they will be used.
905902
Even a library that was not written with threads in mind can be converted to be
906-
thread-safe (see page \pageref{THREADSAFE}) by inserting arbitrary function from
907-
the library a lock will be acquired and released before the function exits.
908-
Such locked can be called ``giant'' mutex, i.e. there will be lock contention
909-
for every consumer of such library in given program. On the other hand, if using
910-
many mutexes to synchronize access to concrete small sections, lots of time can
911-
be spent in the functions implementing the locking. It is therefore desired to
912-
search for a compromise. (Or use an algorithm that does not require locks at
913-
all)
903+
thread-safe (see page \pageref{THREADSAFE}) by acquiring a per-library lock on
904+
any library function entry and releasing the lock before the function exits.
905+
Such a lock may be called a ``giant'' mutex, and it may lead to lock contention
906+
for every consumer of such a library as at any given moment only one thread may
907+
execute the library code. On the other hand, if using a large number of mutexes
908+
to synchronize access to many small sections, significant amount of time might
909+
be spent in the overhead of calling functions implementing the locking. It is
910+
therefore desired to search for a compromise. (Or use an algorithm that does
911+
not require locks at all).
914912
\item \label{MUTEX_RACE} Examples: \example{mutexes/race.c},
915913
\example{mutexes/race-fixed.c}
916914
\item Mutexes can be shared between processes so that their threads will

0 commit comments

Comments
 (0)