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

576 lines
No EOL
40 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.5. Barriers &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="6. Condition Variables" href="Condvars.html" />
<link rel="prev" title="4. Semaphores" href="Semaphores.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="Barriers.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="Barriers.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/Barriers.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="Semaphores.html">7.4. Semaphores</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="Condvars.html">7.6. Condition Variables</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 = "Barriers";ODSA.SETTINGS.MODULE_LONG_NAME = "Barriers";ODSA.SETTINGS.MODULE_CHAPTER = "Synchronization Primitives"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 15:31:50"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="id1">
<h1>7.5. Barriers<a class="headerlink" href="Barriers.html#id1" title="Permalink to this headline"></a></h1>
<p>Semaphores provide a general mechanism that allows one thread to indicate that a
particular event has happened. One type of event that arises quite commonly in
concurrent applications is the need to make sure all threads reach some common
point before any of them continues on. That is, multiple threads may perform
some initial computation then pause; at that point some manager thread checks
these initial results and allows the threads to continue once their results have been approved.</p>
<p>As an example, consider the case of an autonomous car or flying drone. These
types of systems require accurate measurements of real-world phenomena like
speed, position, and acceleration. However, these measurements involve
floating-point calculations that may encounter rounding errors. To improve the
accuracy of the vehicles autonomous controls, multiple threads may be
simultaneously and independently performing these calculations. The manager
control thread will occasionally require these threads to reach a common point
in time where each thread reports on its best guess of the measurements. The
manager may then correct errors in some threads, then allow them to continue.</p>
<p>Achieving this kind of synchronization with semaphores is complex and
error-prone. One approach would be to use two semaphores: the manager thread
would repeatedly wait on one of them as the threads were finishing their
calculations; the manager would then signal on a different semaphore that each
thread was waiting on. However, if all threads agree but one crashes, then the
entire system would fail; the manager thread would continue to wait on that last
thread to finish (which will never happen).</p>
<p>As an alternative, <a class="reference internal" href="Glossary.html#term-barrier"><span class="xref std std-term">synchronization barriers</span></a>
allow programs to specify a <em>minimum</em> number of threads that must reach a common
point before any can continue. For instance, if the autonomous vehicle manager
thread receives reports from 7 out of 10 threads about the current position,
then the system may be designed to consider this measurement <em>good enough</em> and
let the threads continue rather than requiring the last three threads to
finish.</p>
<p>The base functionality of barriers is specified with thread functions. The
barrier is initialized with <code class="docutils literal notranslate"><span class="pre">pthread_barrier_init()</span></code>, with the last parameter
indicating the <em>minimum</em> number of threads that must reach the barrier before
any can be allowed to continue. Threads use the <code class="docutils literal notranslate"><span class="pre">pthread_barrier_wait()</span></code>
function to indicate that they have reached the common point. If the minimum
number of threads have not yet reached the barrier, then the current thread will
become blocked. Once the minimum number has been reached, all threads waiting at
the barrier become unblocked; any future thread that calls
<code class="docutils literal notranslate"><span class="pre">pthread_barrier_wait()</span></code> will pass right through the barrier without any
delay. Finally, <code class="docutils literal notranslate"><span class="pre">pthread_barrier_destroy()</span></code> is used to clean up any resources
associated with the barrier.</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;pthread.h&gt;</p><hr class="mt-1" />
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">pthread_barrier_init</span> <span class="pre">(pthread_barrier_t</span> <span class="pre">*barrier,</span> <span class="pre">const</span> <span class="pre">pthread_barrierattr_t</span> <span class="pre">*attr,</span> <span class="pre">unsigned</span> <span class="pre">count);</span></code></dt>
<dd>Initialize a synchronization barrier with the specified attributes.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">pthread_barrier_destroy</span> <span class="pre">(pthread_barrier_t</span> <span class="pre">*barrier);</span></code></dt>
<dd>Delete a synchronization barrier.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">pthread_barrier_wait</span> <span class="pre">(pthread_barrier_t</span> <span class="pre">*barrier);</span></code></dt>
<dd>Make a thread wait until enough have reached the barrier.</dd>
</dl>
</div>
<div class="section" id="concurrent-calculations-with-barriers">
<h2>7.5.1. Concurrent Calculations with Barriers<a class="headerlink" href="Barriers.html#concurrent-calculations-with-barriers" title="Permalink to this headline"></a></h2>
<p>To show how barriers work, consider using two threads to determine which
function grows faster: the Fibonnacci sequence or the exponential function. That
is, is the 100th Fibonacci number greater than $c^{100}$ for some constant $c$? <a class="footnote-reference" href="Barriers.html#f43" id="id2">[1]</a>
It can be shown that each Fibonacci number is slightly less than double
the previous value, so the answer would be no for any constant integer greater
than 1. But what if the constant is 1.6? <a class="footnote-reference" href="Barriers.html#f44" id="id3">[2]</a> Then the answer is not obvious,
but it is easy enough to calculate.</p>
<p><a class="reference external" href="Barriers.html#cl7-13">Code Listing 7.13</a> shows how barriers can address this problem. The
<code class="docutils literal notranslate"><span class="pre">fibonacci()</span></code> and <code class="docutils literal notranslate"><span class="pre">exponential()</span></code> threads take a struct that contains a
shared <code class="docutils literal notranslate"><span class="pre">pthread_barrier_t</span></code>, a digit that specifies how far into the sequence
and what exponent to calculate, and a base value that specifies the base of the
exponent. That is, if digit is specified as 30 and base is 1.6, <code class="docutils literal notranslate"><span class="pre">fibonacci()</span></code>
will calculate the 30th Fibonacci number, while <code class="docutils literal notranslate"><span class="pre">exponent()</span></code> will calculate
(approximately) $1.6^{30}$.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-13"><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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.13:</span>
<span class="cm"> Using a barrier to pause multiple threads</span>
<span class="cm"> */</span>
<span class="cm">/* Use a common struct with the barrier and parameters */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="p">{</span>
<span class="n">pthread_barrier_t</span> <span class="o">*</span><span class="n">barrier</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">digit</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">base</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">fib</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">exp</span><span class="p">;</span>
<span class="p">};</span>
<span class="cm">/* Iterative version of the Fibonacci calculation */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">fibonacci</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="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">unsigned</span> <span class="kt">long</span> <span class="n">previous</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">current</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">digit</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">current</span> <span class="o">+=</span> <span class="n">previous</span><span class="p">;</span>
<span class="n">previous</span> <span class="o">=</span> <span class="n">current</span> <span class="o">-</span> <span class="n">previous</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* current is the i-th Fibonacci number */</span>
<span class="n">args</span><span class="o">-&gt;</span><span class="n">fib</span> <span class="o">=</span> <span class="n">current</span><span class="p">;</span>
<span class="cm">/* Wait at the barrier and compare results */</span>
<span class="n">pthread_barrier_wait</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">barrier</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">fib</span> <span class="o">&gt;</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">exp</span><span class="p">)</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Fibonacci wins: %lu &gt; %lu</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">fib</span><span class="p">,</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">exp</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">/* Calculate base^digit using repeated multiplication */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">exponential</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="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">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
<span class="cm">/* WARNING: Don&#39;t actually do this in real code that needs</span>
<span class="cm"> Accurate calculations. Repeated floating point arithmetic</span>
<span class="cm"> inherently has rounding errors that will compound. */</span>
<span class="cm">/* Calculate base^digit; cast to unsigned long for comparison */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">digit</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">result</span> <span class="o">*=</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">base</span><span class="p">;</span>
<span class="n">args</span><span class="o">-&gt;</span><span class="n">exp</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span> <span class="n">result</span><span class="p">;</span>
<span class="cm">/* Wait on threads to reach the barrier and check the result */</span>
<span class="n">pthread_barrier_wait</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">barrier</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">exp</span> <span class="o">&gt;</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">fib</span><span class="p">)</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Exponential wins: %lu &gt; %lu</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">exp</span><span class="p">,</span> <span class="n">args</span><span class="o">-&gt;</span><span class="n">fib</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>
<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>As indicated in the code, you should not try to calculate the exponential value
as shown in this code. For one thing, this code is (intentionally) inefficient
and could be easily optimized. More importantly, though, the result is
guaranteed to be inaccurate. Floating-point arithmetic is susceptible to
rounding errors, particularly with repeated calculations and large values.
Consequently, this example should primarily be considered for its use of
barriers rather than its accuracy regarding the comparison of Fibonacci and
exponential growth.</p>
</div>
<p>The key lines to note regarding these threads are the calls to
<code class="docutils literal notranslate"><span class="pre">pthread_barrier_wait()</span></code> and the references to the fields <code class="docutils literal notranslate"><span class="pre">fib</span></code> and <code class="docutils literal notranslate"><span class="pre">exp</span></code>,
which store the results of each calculation. Specifically, note that there is no
race condition regarding these fields because the threads only <em>read</em> the values
after the barrier. That is, nothing changes after the barrier, so there is no
concern that the values checked are inaccurate. This guarantee arises from the
fact that both threads must reach the barrier (i.e., the
<code class="docutils literal notranslate"><span class="pre">pthread_barrier_wait()</span></code> call) before either can proceed.</p>
<p>One question that cannot be answered with this code is which thread runs faster.
With barriers, all we can say for sure is that both threads reach the barrier
before either proceeds. We have no information about which one arrived first.
From the perspective of the barrier, such a question is irrelevant. The only
thing that matters is that both finish before they each check the results.</p>
<p><a class="reference external" href="Barriers.html#cl7-14">Code Listing 7.14</a> shows the initialization required. The main
thread initializes the barrier so that 2 threads are required, then creates the
threads. Notice that both threads receive pointers to the same <code class="docutils literal notranslate"><span class="pre">struct</span></code>
instance, so they share the same <code class="docutils literal notranslate"><span class="pre">barrier</span></code>, <code class="docutils literal notranslate"><span class="pre">fib</span></code>, and <code class="docutils literal notranslate"><span class="pre">exp</span></code> fields. The
main thread joins both of the helper threads, but the join must occur after the
threads have called <code class="docutils literal notranslate"><span class="pre">pthread_exit()</span></code>. Since both threads call
<code class="docutils literal notranslate"><span class="pre">pthread_barrier_wait()</span></code> before that, the main thread is guaranteed to clean
up the barrier only <em>after</em> it is no longer needed.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-14"><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.14:</span>
<span class="cm"> Initializing the barrier and data structures for Code Listing 7.13</span>
<span class="cm"> */</span>
<span class="cm">/* Initialize the barrier so that both threads must wait */</span>
<span class="n">pthread_barrier_t</span> <span class="n">barrier</span><span class="p">;</span>
<span class="n">pthread_barrier_init</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">barrier</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
<span class="cm">/* Set up parameters to get the 30th Fibonacci and 1.6^30 */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="n">args</span><span class="p">;</span>
<span class="n">args</span><span class="p">.</span><span class="n">barrier</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">barrier</span><span class="p">;</span>
<span class="n">args</span><span class="p">.</span><span class="n">digit</span> <span class="o">=</span> <span class="mi">30</span><span class="p">;</span>
<span class="n">args</span><span class="p">.</span><span class="n">base</span> <span class="o">=</span> <span class="mf">1.6</span><span class="p">;</span>
<span class="n">args</span><span class="p">.</span><span class="n">fib</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">args</span><span class="p">.</span><span class="n">exp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="cm">/* Create and join the threads, then destroy the barrier */</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">fibonacci</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">exponential</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">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">pthread_barrier_destroy</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">barrier</span><span class="p">);</span>
</pre></div>
</td></tr></table></div>
<table class="docutils footnote" frame="void" id="f43" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="Barriers.html#id2">[1]</a></td><td>To be clear, the <code class="docutils literal notranslate"><span class="pre">exponential()</span></code> function is truly the exponential
$c^n$ rather than the polynomial $n^c$. In both <code class="docutils literal notranslate"><span class="pre">exponential()</span></code> and
<code class="docutils literal notranslate"><span class="pre">fibonacci(),</span></code> we are using $n = 100$.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="f44" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="Barriers.html#id3">[2]</a></td><td>The selection of 1.6 as the value was not an arbitrary choice. There
is a closed-form solution known as Binets formula, and calculations based on
this formula can be done to show that each Fibonacci number is approximately
1.6 times the value of the previous number.</td></tr>
</tbody>
</table>
<div
id="SynchBarrierSumm"
class="embedContainer"
data-exer-name="SynchBarrierSumm"
data-long-name="Barrier questions"
data-short-name="SynchBarrierSumm"
data-frame-src="../../../Exercises/Synch/SynchBarrierSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=Barriers"
data-frame-width="950"
data-frame-height="550"
data-external="false"
data-points="0"
data-required="False"
data-showhide="show"
data-threshold="2"
data-type="ka"
data-exer-id="">
<div class="center">
<div id="SynchBarrierSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="Semaphores.html">7.4. Semaphores</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="Condvars.html">7.6. Condition Variables</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>