1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/Semaphores.html
2025-01-28 10:11:14 +01:00

785 lines
No EOL
51 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>7.4. Semaphores &mdash; Computer Systems Fundamentals</title>
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
<style>
.underline { text-decoration: underline; }
</style>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.4.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": {
scale: "80"
}
});
</script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
<link rel="next" title="5. Barriers" href="Barriers.html" />
<link rel="prev" title="3. Locks" href="Locks.html" />
</head><body>
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
<!-- Show a navbar toggler on mobile -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="defaultNavbars">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle jmu-gold rounded" href="Semaphores.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
<a class="dropdown-item" tabindex="-1" href="Semaphores.html#"><b>Chapter 1</b></a>
<a class="dropdown-item" href="IntroConcSysOverview.html">&nbsp;&nbsp;&nbsp;1.1. Introduction to Concurrent Systems</a>
<a class="dropdown-item" href="SysAndModels.html">&nbsp;&nbsp;&nbsp;1.2. Systems and Models</a>
<a class="dropdown-item" href="Themes.html">&nbsp;&nbsp;&nbsp;1.3. Themes and Guiding Principles</a>
<a class="dropdown-item" href="Architectures.html">&nbsp;&nbsp;&nbsp;1.4. System Architectures</a>
<a class="dropdown-item" href="StateModels.html">&nbsp;&nbsp;&nbsp;1.5. State Models in UML</a>
<a class="dropdown-item" href="SequenceModels.html">&nbsp;&nbsp;&nbsp;1.6. Sequence Models in UML</a>
<a class="dropdown-item" href="StateModelImplementation.html">&nbsp;&nbsp;&nbsp;1.7. Extended Example: State Model Implementation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
<a class="dropdown-item" href="ProcessesOverview.html">&nbsp;&nbsp;&nbsp;2.1. Processes and OS Basics</a>
<a class="dropdown-item" href="Multiprogramming.html">&nbsp;&nbsp;&nbsp;2.2. Processes and Multiprogramming</a>
<a class="dropdown-item" href="KernelMechanics.html">&nbsp;&nbsp;&nbsp;2.3. Kernel Mechanics</a>
<a class="dropdown-item" href="Syscall.html">&nbsp;&nbsp;&nbsp;2.4. System Call Interface</a>
<a class="dropdown-item" href="ProcessCycle.html">&nbsp;&nbsp;&nbsp;2.5. Process Life Cycle</a>
<a class="dropdown-item" href="UnixFile.html">&nbsp;&nbsp;&nbsp;2.6. The UNIX File Abstraction</a>
<a class="dropdown-item" href="EventsSignals.html">&nbsp;&nbsp;&nbsp;2.7. Events and Signals</a>
<a class="dropdown-item" href="Extended2Processes.html">&nbsp;&nbsp;&nbsp;2.8. Extended Example: Listing Files with Processes</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
<a class="dropdown-item" href="IPCOverview.html">&nbsp;&nbsp;&nbsp;3.1. Concurrency with IPC</a>
<a class="dropdown-item" href="IPCModels.html">&nbsp;&nbsp;&nbsp;3.2. IPC Models</a>
<a class="dropdown-item" href="Pipes.html">&nbsp;&nbsp;&nbsp;3.3. Pipes and FIFOs</a>
<a class="dropdown-item" href="MMap.html">&nbsp;&nbsp;&nbsp;3.4. Shared Memory With Memory-mapped Files</a>
<a class="dropdown-item" href="POSIXvSysV.html">&nbsp;&nbsp;&nbsp;3.5. POSIX vs. System V IPC</a>
<a class="dropdown-item" href="MQueues.html">&nbsp;&nbsp;&nbsp;3.6. Message Passing With Message Queues</a>
<a class="dropdown-item" href="ShMem.html">&nbsp;&nbsp;&nbsp;3.7. Shared Memory</a>
<a class="dropdown-item" href="IPCSems.html">&nbsp;&nbsp;&nbsp;3.8. Semaphores</a>
<a class="dropdown-item" href="Extended3Bash.html">&nbsp;&nbsp;&nbsp;3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
<a class="dropdown-item" href="SocketsOverview.html">&nbsp;&nbsp;&nbsp;4.1. Networked Concurrency</a>
<a class="dropdown-item" href="FiveLayer.html">&nbsp;&nbsp;&nbsp;4.2. The TCP/IP Internet Model</a>
<a class="dropdown-item" href="NetApps.html">&nbsp;&nbsp;&nbsp;4.3. Network Applications and Protocols</a>
<a class="dropdown-item" href="Sockets.html">&nbsp;&nbsp;&nbsp;4.4. The Socket Interface</a>
<a class="dropdown-item" href="TCPSockets.html">&nbsp;&nbsp;&nbsp;4.5. TCP Socket Programming: HTTP</a>
<a class="dropdown-item" href="UDPSockets.html">&nbsp;&nbsp;&nbsp;4.6. UDP Socket Programming: DNS</a>
<a class="dropdown-item" href="AppBroadcast.html">&nbsp;&nbsp;&nbsp;4.7. Application-Layer Broadcasting: DHCP</a>
<a class="dropdown-item" href="Extended4CGI.html">&nbsp;&nbsp;&nbsp;4.8. Extended Example: CGI Web Server</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
<a class="dropdown-item" href="InternetOverview.html">&nbsp;&nbsp;&nbsp;5.1. The Internet and Connectivity</a>
<a class="dropdown-item" href="AppLayer.html">&nbsp;&nbsp;&nbsp;5.2. Application Layer: Overlay Networks</a>
<a class="dropdown-item" href="TransLayer.html">&nbsp;&nbsp;&nbsp;5.3. Transport Layer</a>
<a class="dropdown-item" href="NetSec.html">&nbsp;&nbsp;&nbsp;5.4. Network Security Fundamentals</a>
<a class="dropdown-item" href="NetLayer.html">&nbsp;&nbsp;&nbsp;5.5. Network Layer: IP</a>
<a class="dropdown-item" href="LinkLayer.html">&nbsp;&nbsp;&nbsp;5.6. Link Layer</a>
<a class="dropdown-item" href="Wireless.html">&nbsp;&nbsp;&nbsp;5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
<a class="dropdown-item" href="Extended5DNS.html">&nbsp;&nbsp;&nbsp;5.8. Extended Example: DNS client</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
<a class="dropdown-item" href="ThreadsOverview.html">&nbsp;&nbsp;&nbsp;6.1. Concurrency with Multithreading</a>
<a class="dropdown-item" href="ProcVThreads.html">&nbsp;&nbsp;&nbsp;6.2. Processes vs. Threads</a>
<a class="dropdown-item" href="RaceConditions.html">&nbsp;&nbsp;&nbsp;6.3. Race Conditions and Critical Sections</a>
<a class="dropdown-item" href="POSIXThreads.html">&nbsp;&nbsp;&nbsp;6.4. POSIX Thread Library</a>
<a class="dropdown-item" href="ThreadArgs.html">&nbsp;&nbsp;&nbsp;6.5. Thread Arguments and Return Values</a>
<a class="dropdown-item" href="ImplicitThreads.html">&nbsp;&nbsp;&nbsp;6.6. Implicit Threading and Language-based Threads</a>
<a class="dropdown-item" href="Extended6Input.html">&nbsp;&nbsp;&nbsp;6.7. Extended Example: Keyboard Input Listener</a>
<a class="dropdown-item" href="Extended6Primes.html">&nbsp;&nbsp;&nbsp;6.8. Extended Example: Concurrent Prime Number Search</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
<a class="dropdown-item" href="SynchOverview.html">&nbsp;&nbsp;&nbsp;7.1. Synchronization Primitives</a>
<a class="dropdown-item" href="CritSect.html">&nbsp;&nbsp;&nbsp;7.2. Critical Sections and Peterson's Solution</a>
<a class="dropdown-item" href="Locks.html">&nbsp;&nbsp;&nbsp;7.3. Locks</a>
<a class="dropdown-item" href="Semaphores.html">&nbsp;&nbsp;&nbsp;7.4. Semaphores</a>
<a class="dropdown-item" href="Barriers.html">&nbsp;&nbsp;&nbsp;7.5. Barriers</a>
<a class="dropdown-item" href="Condvars.html">&nbsp;&nbsp;&nbsp;7.6. Condition Variables</a>
<a class="dropdown-item" href="Deadlock.html">&nbsp;&nbsp;&nbsp;7.7. Deadlock</a>
<a class="dropdown-item" href="Extended7Events.html">&nbsp;&nbsp;&nbsp;7.8. Extended Example: Event Log File</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
<a class="dropdown-item" href="SynchProblemsOverview.html">&nbsp;&nbsp;&nbsp;8.1. Synchronization Patterns and Problems</a>
<a class="dropdown-item" href="SynchDesign.html">&nbsp;&nbsp;&nbsp;8.2. Basic Synchronization Design Patterns</a>
<a class="dropdown-item" href="ProdCons.html">&nbsp;&nbsp;&nbsp;8.3. Producer-Consumer Problem</a>
<a class="dropdown-item" href="ReadWrite.html">&nbsp;&nbsp;&nbsp;8.4. Readers-Writers Problem</a>
<a class="dropdown-item" href="DiningPhil.html">&nbsp;&nbsp;&nbsp;8.5. Dining Philosophers Problem and Deadlock</a>
<a class="dropdown-item" href="CigSmokers.html">&nbsp;&nbsp;&nbsp;8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
<a class="dropdown-item" href="Extended8ModExp.html">&nbsp;&nbsp;&nbsp;8.7. Extended Example: Parallel Modular Exponentiation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
<a class="dropdown-item" href="ParallelDistributedOverview.html">&nbsp;&nbsp;&nbsp;9.1. Parallel and Distributed Systems</a>
<a class="dropdown-item" href="ParVConc.html">&nbsp;&nbsp;&nbsp;9.2. Parallelism vs. Concurrency</a>
<a class="dropdown-item" href="ParallelDesign.html">&nbsp;&nbsp;&nbsp;9.3. Parallel Design Patterns</a>
<a class="dropdown-item" href="Scaling.html">&nbsp;&nbsp;&nbsp;9.4. Limits of Parallelism and Scaling</a>
<a class="dropdown-item" href="DistTiming.html">&nbsp;&nbsp;&nbsp;9.5. Timing in Distributed Environments</a>
<a class="dropdown-item" href="DistDataStorage.html">&nbsp;&nbsp;&nbsp;9.6. Reliable Data Storage and Location</a>
<a class="dropdown-item" href="DistConsensus.html">&nbsp;&nbsp;&nbsp;9.7. Consensus in Distributed Systems</a>
<a class="dropdown-item" href="Extended9Blockchain.html">&nbsp;&nbsp;&nbsp;9.8. Extended Example: Blockchain Proof-of-Work</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Appendix A</b></a>
<a class="dropdown-item" href="CLangOverview.html">&nbsp;&nbsp;&nbsp;A.1. C Language Reintroduction</a>
<a class="dropdown-item" href="Debugging.html">&nbsp;&nbsp;&nbsp;A.2. Documentation and Debugging</a>
<a class="dropdown-item" href="BasicTypes.html">&nbsp;&nbsp;&nbsp;A.3. Basic Types and Pointers</a>
<a class="dropdown-item" href="Arrays.html">&nbsp;&nbsp;&nbsp;A.4. Arrays, Structs, Enums, and Type Definitions</a>
<a class="dropdown-item" href="Functions.html">&nbsp;&nbsp;&nbsp;A.5. Functions and Scope</a>
<a class="dropdown-item" href="Pointers.html">&nbsp;&nbsp;&nbsp;A.6. Pointers and Dynamic Allocation</a>
<a class="dropdown-item" href="Strings.html">&nbsp;&nbsp;&nbsp;A.7. Strings</a>
<a class="dropdown-item" href="FunctionPointers.html">&nbsp;&nbsp;&nbsp;A.8. Function Pointers</a>
<a class="dropdown-item" href="Files.html">&nbsp;&nbsp;&nbsp;A.9. Files</a>
</div>
</li>
</ul>
</div>
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/Semaphores.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="Locks.html">7.3. Locks</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="Barriers.html">7.5. Barriers</a>&#160;&#160;»
</div>
<br />
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
<script type="text/javascript" src="_static/js/config.js"></script>
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
<div class="container">
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "Semaphores";ODSA.SETTINGS.MODULE_LONG_NAME = "Semaphores";ODSA.SETTINGS.MODULE_CHAPTER = "Synchronization Primitives"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 14:28:48"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="id1">
<h1>7.4. Semaphores<a class="headerlink" href="Semaphores.html#id1" title="Permalink to this headline"></a></h1>
<p><a class="reference internal" href="Glossary.html#term-semaphore"><span class="xref std std-term">Semaphores</span></a> are a flexible synchronization primitive that can
be used for many purposes. They can be used as a form of message-passing IPC to
allow processes to synchronize access to shared memory or memory-mapped files.
But in contrast to other forms of IPC, semaphores can be used for thread
synchronization, as well.</p>
<p>As described previously, a semaphore is a non-negative integer with atomic
operations for incrementing and decrementing its value. The POSIX function for
decrementing the semaphore is <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code>, while the <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code> function
increments the value. If the semaphores value is 0 prior to decrementing, then
the <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> operation will block the current thread. If a thread calls
<code class="docutils literal notranslate"><span class="pre">sem_post()</span></code> and there is at least one thread waiting on the semaphore, then
one of the threads becomes unblocked. The choice of which thread gets unblocked
is implementation dependent.</p>
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">C library functions &lt;semaphore.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_wait</span> <span class="pre">(sem_t</span> <span class="pre">*sem);</span></code></dt>
<dd>Decrement the semaphores value; block if the value is currently 0.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">sem_post</span> <span class="pre">(sem_t</span> <span class="pre">*sem);</span></code></dt>
<dd>Increment the semaphores value; resume another process if the value is 0.</dd>
</dl>
</div>
<p>In this section, well describe three basic techniques of using semaphores:
signaling, mutual exclusion, and multiplexing. In essence, all of these
techniques look identical, but with one exception: the initial value. For
signaling, the semaphore is initialized to 0; for mutual exclusion, the initial
value is 1; for multiplexing, the initial value is a positive number greater
than 1. To summarize, the general practice is that <strong>the initial value of the
semaphore is the desired number of initial allowed concurrent accesses</strong>.</p>
<div class="section" id="semaphores-as-signaling">
<h2>7.4.1. Semaphores as Signaling<a class="headerlink" href="Semaphores.html#semaphores-as-signaling" title="Permalink to this headline"></a></h2>
<p>Semaphores can be used to send general signals to other threads that some
application-specific event has occurred. Note that this use of semaphores is
different from the pre-defined <a class="reference internal" href="Glossary.html#term-signal"><span class="xref std std-term">signals</span></a> such as <code class="docutils literal notranslate"><span class="pre">SIGKILL</span></code>.
Events with semaphores have no pre-defined meaning and are simply indications
that <em>something</em> has occurred.</p>
<p>To illustrate signaling, consider the two threads shown in <a class="reference external" href="Semaphores.html#cl7-7">Code Listing 7.7</a>. One thread (<code class="docutils literal notranslate"><span class="pre">keyboard_listener()</span></code>) reads a line of input from
<code class="docutils literal notranslate"><span class="pre">STDIN</span></code> into a shared buffer. Once the input has been received, the thread
posts to the semaphore to alert the second thread that the event (receiving
input) has occurred. The second thread (<code class="docutils literal notranslate"><span class="pre">keyboard_echo()</span></code>) starts by waiting
on the semaphore before trying to read the input from the buffer. The semaphore
ensures that the echo thread cannot try to read from the buffer until the
listener has finished writing to the buffer.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-7"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.7:</span>
<span class="cm"> Two threads cooperating to echo input text</span>
<span class="cm"> */</span>
<span class="cm">/* Struct instance will contain pointers to semaphore and buffer */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="p">{</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">semaphore</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">buffer</span><span class="p">;</span>
<span class="p">};</span>
<span class="cp">#define MAX_LENGTH 40</span>
<span class="cm">/* Listener thread gets input, then ups the semaphore */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">keyboard_listener</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Cast the args to a usable struct type */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Enter your name here: &quot;</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">fgets</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="n">MAX_LENGTH</span><span class="p">,</span> <span class="n">stdin</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* After receiving input, up the semaphore and exit */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">keyboard_echo</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Cast the args to a usable struct type */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="cm">/* Wait on the signal from the semaphore */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="cm">/* Trim off at the newline character */</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">newline</span> <span class="o">=</span> <span class="n">strchr</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="sc">&#39;\n&#39;</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">newline</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">*</span><span class="n">newline</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span>
<span class="cm">/* Echo back the name and exit */</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Hello, %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">);</span>
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The key with signaling is that the semaphore must be created and initialized
with an initial value of 0 as shown in <a class="reference external" href="Semaphores.html#cl7-8">Code Listing 7.8</a>. By using
this initial value, the semaphore eliminates the issue of nondeterministic
thread scheduling. Specifically, if the <code class="docutils literal notranslate"><span class="pre">keyboard_echo()</span></code> thread runs first,
it must wait until the <code class="docutils literal notranslate"><span class="pre">keyboard_listener()</span></code> reads the input and ups the
semaphore. However, if <code class="docutils literal notranslate"><span class="pre">keyboard_listener()</span></code> runs first and ups the semaphore
before <code class="docutils literal notranslate"><span class="pre">keyboard_echo()</span></code> gets scheduled, then the semaphore will have a value
of 1 and the thread will not be blocked.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-8"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.8:</span>
<span class="cm"> Initializing a semaphore and passing it to threads</span>
<span class="cm"> */</span>
<span class="cm">/* Allocate the buffer and open the named semaphore */</span>
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="n">MAX_LENGTH</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">buffer</span><span class="p">));</span>
<span class="cm">/* For signaling, initialize the semaphore to 0 */</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">sem</span> <span class="o">=</span> <span class="n">sem_open</span> <span class="p">(</span><span class="s">&quot;/OpenCSF_Sema&quot;</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_EXCL</span><span class="p">,</span>
<span class="n">S_IRUSR</span> <span class="o">|</span> <span class="n">S_IWUSR</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">sem</span> <span class="o">!=</span> <span class="n">SEM_FAILED</span><span class="p">);</span>
<span class="cm">/* Set up struct instance with both pointers; pass it to threads */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="n">args</span> <span class="o">=</span> <span class="p">{</span> <span class="n">sem</span><span class="p">,</span> <span class="n">buffer</span> <span class="p">};</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">pthread_create</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">threads</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">keyboard_listener</span><span class="p">,</span>
<span class="o">&amp;</span><span class="n">args</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">pthread_create</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">threads</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">keyboard_echo</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">args</span><span class="p">)</span>
<span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
<span class="cm">/* Wait for both threads to finish, then unlink the semaphore */</span>
<span class="n">pthread_join</span> <span class="p">(</span><span class="n">threads</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">pthread_join</span> <span class="p">(</span><span class="n">threads</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">sem_unlink</span> <span class="p">(</span><span class="s">&quot;/OpenCSF_Sema&quot;</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<div class="topic border border-dark rounded-lg alert-danger px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-BugWarning.png"><img alt="Decorative bug warning" src="_images/CSF-Images-BugWarning.png" style="width: 90%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">Bug Warning</p><hr class="mt-1" />
<p>In this basic signaling pattern, it is possible to have the two threads
repeatedly post to or wait on a single semaphore. This approach is a common
technique for handling repeated events. However, it is fraught with peril. In
this example, there is only one buffer. So if the <code class="docutils literal notranslate"><span class="pre">keyboard_listener()</span></code>
repeatedly reads input (posting each time), the buffer would be repeatedly
overwritten, and there is no guarantee that the <code class="docutils literal notranslate"><span class="pre">keyboard_echo()</span></code> thread
would read any of the input.</p>
<p>Another complication arises if there are multiple threads repeatedly waiting on
the same semaphore. In the default implementation of POSIX semaphores, the
order in which threads are unblocked with <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code> is unspecified. As
such, it is possible that one thread might be repeatedly unblocked while the
other waiting thread is never unblocked.</p>
</div>
</div>
<div class="section" id="mutual-exclusion-with-semaphores">
<h2>7.4.2. Mutual Exclusion with Semaphores<a class="headerlink" href="Semaphores.html#mutual-exclusion-with-semaphores" title="Permalink to this headline"></a></h2>
<p>Semaphores can also be used to ensure mutually exclusive access to a shared
variable or resource. Consider the two threads, shown in <a class="reference external" href="Semaphores.html#cl7-9">Code Listing 7.9</a>, that atomically increment or decrement an int counter variable. Each
change to the shared variable is preceded by a call to <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> and
followed by a call to <code class="docutils literal notranslate"><span class="pre">sem_post()</span></code>. This wrapping is analogous to the mutual
exclusion style used with locks.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-9"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.9:</span>
<span class="cm"> Two threads that synchronize modifications to a shared variable</span>
<span class="cm"> */</span>
<span class="cm">/* Struct containing the semaphore and integer */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="p">{</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">semaphore</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">value</span><span class="p">;</span>
<span class="p">};</span>
<span class="cm">/* Adder thread that repeatedly adds 10 */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">add</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Cast the args to a usable struct type */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
<span class="cm">/* Atomically add 10 to value 100000 times */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">100000</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="n">args</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">+=</span> <span class="mi">10</span><span class="p">;</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* Subtracter thread that repeatedly subtracts 10 */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">subtract</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Cast the args to a usable struct type */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
<span class="cm">/* Atomically subtract 10 from value 100000 times */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">100000</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="n">args</span><span class="o">-&gt;</span><span class="n">value</span> <span class="o">-=</span> <span class="mi">10</span><span class="p">;</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">pthread_exit</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>As shown in <a class="reference external" href="Semaphores.html#cl7-10">Code Listing 7.10</a>, the difference between signaling and
mutual exclusion is the initial value of the semaphore. For mutual exclusion,
the semaphore is initialized to 1.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-10"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.10:</span>
<span class="cm"> Initializing a semaphore for mutual exclusion instead of signaling</span>
<span class="cm"> */</span>
<span class="cm">/* For mutual exclusion, initialize the semaphore to 1 */</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">sem</span> <span class="o">=</span> <span class="n">sem_open</span> <span class="p">(</span><span class="s">&quot;/OpenCSF_Sema&quot;</span><span class="p">,</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_EXCL</span><span class="p">,</span>
<span class="n">S_IRUSR</span> <span class="o">|</span> <span class="n">S_IWUSR</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">sem</span> <span class="o">!=</span> <span class="n">SEM_FAILED</span><span class="p">);</span>
<span class="cm">/* Set up a struct instance with semaphore and initial value 0 */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="n">args</span> <span class="o">=</span> <span class="p">{</span> <span class="n">sem</span><span class="p">,</span> <span class="mi">0</span> <span class="p">};</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">pthread_create</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">threads</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">add</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">args</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">pthread_create</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">threads</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">subtract</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">args</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p>As illustrated in <a class="reference external" href="Semaphores.html#cl7-9">Code Listing 7.9</a>, semaphores can be used
identically to mutex locks as shown previously. In fact, <a class="reference external" href="Semaphores.html#cl7-11">Code Listing 7.11</a> shows that we can use semaphores as a foundation to create locks.
Acquiring the lock involves waiting on the semaphore and setting oneself as the
lock owner. Releasing the lock clears the ownership field and posts to the
semaphore. If multiple threads try to acquire the lock, they all end up trying
to down the semaphore, and only one is successful. Once that thread releases the
lock, the semaphore is upped and a single thread is unblocked; that thread then
sets itself as the owner.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-11"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.11:</span>
<span class="cm"> Creating locks from semaphores</span>
<span class="cm"> */</span>
<span class="cm">/* We can create a lock with a semaphore and owner field */</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">lock</span> <span class="p">{</span>
<span class="n">sem_t</span> <span class="o">*</span><span class="n">semaphore</span><span class="p">;</span>
<span class="n">pthread_t</span> <span class="n">owner</span><span class="p">;</span>
<span class="p">}</span> <span class="n">lock_t</span><span class="p">;</span>
<span class="cm">/* To acquire the lock, wait on semaphore and set self as owner */</span>
<span class="kt">int</span>
<span class="nf">mutex_lock</span> <span class="p">(</span><span class="n">lock_t</span> <span class="o">*</span><span class="n">lock</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">retvalue</span> <span class="o">=</span> <span class="n">sem_wait</span> <span class="p">(</span><span class="n">lock</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="n">lock</span><span class="o">-&gt;</span><span class="n">owner</span> <span class="o">=</span> <span class="n">pthread_self</span> <span class="p">();</span>
<span class="k">return</span> <span class="n">retvalue</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* To release, clear the owner field and post to the semaphore */</span>
<span class="kt">int</span>
<span class="nf">mutex_unlock</span> <span class="p">(</span><span class="n">lock_t</span> <span class="o">*</span><span class="n">lock</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Only the owner can release the lock */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">lock</span><span class="o">-&gt;</span><span class="n">owner</span> <span class="o">!=</span> <span class="n">pthread_self</span> <span class="p">())</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="n">lock</span><span class="o">-&gt;</span><span class="n">owner</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">return</span> <span class="n">sem_post</span> <span class="p">(</span><span class="n">lock</span><span class="o">-&gt;</span><span class="n">semaphore</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The key difference between locks and semaphores is that a semaphore must be
explicitly initialized to the integer value 1, whereas the initialization for a
lock is opaque. Or, put a different way, <strong>mutex locks are preferred because
they adhere to the principles of encapsulation and information hiding</strong>. The
notion of <em>acquiring a lock</em> is more concrete than <em>waiting on a semaphore,</em> and
is a more appropriate abstraction for mutual exclusion.</p>
</div>
<div class="section" id="multiplexing-with-semaphores">
<h2>7.4.3. Multiplexing with Semaphores<a class="headerlink" href="Semaphores.html#multiplexing-with-semaphores" title="Permalink to this headline"></a></h2>
<p>Both locks and semaphores can be used for mutual exclusion, though locks are
typically the preferred abstraction. However, the mutual exclusion style of
semaphores can be extended to allow for multiple but limited shared accesses.
This concept is known as <a class="reference internal" href="Glossary.html#term-multiplexing-semaphore"><span class="xref std std-term">multiplexing</span></a>. That is, while a lock can only be
used to grant access to a single thread at a time, a semaphore can be set to
allow 5, 10, or any other number of concurrent accesses. Once this limited
number has been reached, any additional threads would become blocked, just as
they would if trying to acquire a locked mutex.</p>
<p>As a real-world example of multiplexing, consider a popular restaurant or club.
Building safety codes specify that there is a maximum occupancy, say 100 people.
As patrons start arriving when the place opens, they are allowed in one at a
time. However, once the 100th person has been allowed in, the management must
make sure that no one else enters (or risk legal trouble and fines). At that
point, a line forms out front. Once a single person leaves, the next patron is
allowed in. In this case, <strong>the employee enforcing this restriction at the
entrance is acting like a multiplexing semaphore with an initial value of 100</strong>.</p>
<p>Within the context of computing, multiplexing has many uses. One example is to
limit the number of concurrent accesses to a pool of resources where more than
one is required for each operation. For example, consider a networking hub that
has 10 incoming ports and 10 outgoing ports that can be locked independently.
Consider the scenario where 9 threads have already locked both an incoming and
an outgoing port. Two new threads arrive; one of them acquires an incoming port
and the second acquires an outgoing port. At this point, no ports of either kind
are available. If these last two threads then try to acquire the missing port,
they cannot. As a result, there are two ports (one incoming and one outgoing)
that are both locked but not in use. This waste of resources could be prevented
with the structure in <a class="reference external" href="Semaphores.html#cl7-12">Code Listing 7.12</a>.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-12"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.12:</span>
<span class="cm"> Using a semaphore to multiplex access to a thread pool</span>
<span class="cm"> */</span>
<span class="cm">/* Acquire access to the pool of resources */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">pool_semaphore</span><span class="p">);</span>
<span class="cm">/* Try to acquire incoming port. If taken, move on to the next. */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pthread_mutex_trylock</span> <span class="p">(</span><span class="n">incoming_mutex</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="p">{</span>
<span class="n">in</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Work with incoming port, even if no outgoing port is needed */</span>
<span class="cm">/* Once an outgoing port is needed, acquire it in the same way. */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pthread_mutex_trylock</span> <span class="p">(</span><span class="n">outgoing_mutex</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="p">{</span>
<span class="n">out</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* To finish, release both locks and up the semaphore */</span>
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">incoming_mutex</span><span class="p">[</span><span class="n">in</span><span class="p">]);</span>
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">outgoing_mutex</span><span class="p">[</span><span class="n">out</span><span class="p">]);</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">pool_semaphore</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<p>Assuming the <code class="docutils literal notranslate"><span class="pre">pool_semaphore</span></code> was initialized to 10, every thread granted
access to the pool of resources (ports in this example) will have access to one
of each type. Moreover, this structure makes it possible for the incoming and
outgoing ports to be acquired in any order; this flexibility is commonly
associated with the problem of <a class="reference internal" href="Glossary.html#term-deadlock"><span class="xref std std-term">deadlock</span></a>, but multiplexing in this manner
avoids that issue.</p>
<div
id="SynchSemsSumm"
class="embedContainer"
data-exer-name="SynchSemsSumm"
data-long-name="Semaphore questions"
data-short-name="SynchSemsSumm"
data-frame-src="../../../Exercises/Synch/SynchSemsSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=Semaphores&amp;JXOP-debug=true&amp;JOP-lang=en&amp;JXOP-code=java"
data-frame-width="950"
data-frame-height="550"
data-external="false"
data-points="1.0"
data-required="True"
data-showhide="show"
data-threshold="3"
data-type="ka"
data-exer-id="">
<div class="center">
<div id="SynchSemsSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="Locks.html">7.3. Locks</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="Barriers.html">7.5. Barriers</a>&#160;&#160;»
</div>
</div>
<br />
<div class="row jmu-dark-purple-bg">
<div class="col-md-12">
<center>
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
</center>
</div>
</div>
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>