1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/Extended7Events.html

813 lines
52 KiB
HTML
Raw Normal View History

2025-01-28 10:11:14 +01:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>7.8. Extended Example: Event Log File &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="1. Synchronization Patterns and Problems" href="SynchProblemsOverview.html" />
<link rel="prev" title="7. Deadlock" href="Deadlock.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="Extended7Events.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="Extended7Events.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/Extended7Events.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="Deadlock.html">7.7. Deadlock</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="SynchProblemsOverview.html">8.1. Synchronization Patterns and Problems</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 = "Extended7Events";ODSA.SETTINGS.MODULE_LONG_NAME = "Extended Example: Event Log File";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="extended-example-event-log-file">
<h1>7.8. Extended Example: Event Log File<a class="headerlink" href="Extended7Events.html#extended-example-event-log-file" title="Permalink to this headline"></a></h1>
<p>Many concurrent systems use a common log file to store records of key events.
For instance, journaling file systems use a log to keep track of changes that
can be validated in case of a system crash. This Extended Example uses multiple
threads that create random fake events that then get written to the common log
file. Access to the log file is synchronized to ensure that the writes do not
interfere with each other.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#include</span> <span class="cpf">&lt;assert.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;fcntl.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;pthread.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;sys/stat.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;time.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp"></span>
<span class="cp">#define SHALENGTH 64</span>
<span class="cp">#define LOGFILE &quot;var.log&quot;</span>
<span class="cm">/* Change these to increase the number of threads and events */</span>
<span class="cp">#define NUM_THREADS 5</span>
<span class="cp">#define NUM_ITERATIONS 10</span>
<span class="kt">void</span> <span class="nf">append_log_message</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">,</span> <span class="kt">size_t</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span> <span class="nf">compute_log_hash</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">,</span> <span class="kt">size_t</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">create_initial_log</span> <span class="p">(</span><span class="kt">void</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span> <span class="nf">generate_random_log</span> <span class="p">(</span><span class="kt">int</span><span class="p">);</span>
<span class="kt">bool</span> <span class="nf">verify_log</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">);</span>
<span class="cm">/* Thread parameter struct */</span>
<span class="k">struct</span> <span class="n">log_params</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">tid</span><span class="p">;</span> <span class="cm">/* thread ID */</span>
<span class="n">pthread_mutex_t</span> <span class="o">*</span><span class="n">mutex</span><span class="p">;</span> <span class="cm">/* shared mutex */</span>
<span class="kt">size_t</span> <span class="o">*</span><span class="n">log_index</span><span class="p">;</span> <span class="cm">/* shared log index */</span>
<span class="kt">size_t</span> <span class="n">iterations</span><span class="p">;</span> <span class="cm">/* number of events */</span>
<span class="p">};</span>
<span class="cm">/* Event-generating thread. Each copy of this thread will</span>
<span class="cm"> sleep for a random amount of time, then wake up to generate</span>
<span class="cm"> an event. When that happens, the thread acquires the lock</span>
<span class="cm"> for the log file, verifies that the log is still valid,</span>
<span class="cm"> appends a new log message, and closes the file. After a</span>
<span class="cm"> certain number of iterations has occurred, the thread exits */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">event_thread</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_params</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">log_params</span> <span class="o">*</span><span class="n">params</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">log_params</span> <span class="o">*</span><span class="p">)</span> <span class="n">_params</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="n">seed</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span><span class="p">)</span> <span class="n">params</span><span class="o">-&gt;</span><span class="n">tid</span><span class="p">;</span>
<span class="kt">size_t</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">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">params</span><span class="o">-&gt;</span><span class="n">iterations</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">usleep</span> <span class="p">((</span><span class="n">rand_r</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">seed</span><span class="p">)</span> <span class="o">%</span> <span class="mi">500000</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">pthread_mutex_lock</span> <span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">mutex</span><span class="p">);</span>
<span class="cm">/* Here begins the critical section */</span>
<span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span> <span class="o">=</span> <span class="n">fopen</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="s">&quot;a+&quot;</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">fp</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">mutex</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="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="n">verify_log</span> <span class="p">(</span><span class="n">fp</span><span class="p">))</span>
<span class="p">{</span>
<span class="n">perror</span> <span class="p">(</span><span class="s">&quot;Failed to validate log file&quot;</span><span class="p">);</span>
<span class="n">fclose</span> <span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">mutex</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">/* All previous log messages have hashed correctly. Append</span>
<span class="cm"> a new message, which includes an updated hash value. */</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">log_message</span> <span class="o">=</span> <span class="n">generate_random_log</span> <span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">tid</span><span class="p">);</span>
<span class="n">append_log_message</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="o">*</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">log_index</span><span class="p">,</span> <span class="n">log_message</span><span class="p">);</span>
<span class="n">free</span> <span class="p">(</span><span class="n">log_message</span><span class="p">);</span>
<span class="cm">/* Increment shared log index number and close the file */</span>
<span class="p">(</span><span class="o">*</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">log_index</span><span class="p">)</span><span class="o">++</span><span class="p">;</span>
<span class="n">fclose</span> <span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="cm">/* End of critical section */</span>
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">params</span><span class="o">-&gt;</span><span class="n">mutex</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">/* Main entry point */</span>
<span class="kt">int</span>
<span class="nf">main</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Create a bogus initial log to start with */</span>
<span class="n">create_initial_log</span> <span class="p">();</span>
<span class="kt">size_t</span> <span class="n">log_index</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span>
<span class="n">pthread_mutex_init</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* Create the thread parameters and the threads */</span>
<span class="n">pthread_t</span> <span class="n">threads</span><span class="p">[</span><span class="n">NUM_THREADS</span><span class="p">];</span>
<span class="k">struct</span> <span class="n">log_params</span> <span class="n">params</span><span class="p">[</span><span class="n">NUM_THREADS</span><span class="p">];</span>
<span class="kt">size_t</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">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">NUM_THREADS</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">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">tid</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">mutex</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">mutex</span><span class="p">;</span>
<span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">log_index</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">log_index</span><span class="p">;</span>
<span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">iterations</span> <span class="o">=</span> <span class="n">NUM_ITERATIONS</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="n">i</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">event_thread</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">params</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="cm">/* Join the threads then destroy the mutex and exit */</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="n">NUM_THREADS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</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="n">i</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">pthread_mutex_destroy</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</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">/* Log file verification routine */</span>
<span class="kt">bool</span>
<span class="nf">verify_log</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Compute the hash value from all lines except the last bytes</span>
<span class="cm"> that contain the final hash */</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">computed</span> <span class="o">=</span> <span class="n">compute_log_hash</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">2</span><span class="p">);</span>
<span class="cm">/* Now read the final hash and confirm that it matches */</span>
<span class="kt">char</span> <span class="n">expected</span><span class="p">[</span><span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">3</span><span class="p">];</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">expected</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">expected</span><span class="p">));</span>
<span class="n">fread</span> <span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">),</span> <span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="n">fp</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">strncmp</span> <span class="p">(</span><span class="n">computed</span><span class="p">,</span> <span class="n">expected</span><span class="p">,</span> <span class="n">SHALENGTH</span><span class="p">))</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">free</span> <span class="p">(</span><span class="n">computed</span><span class="p">);</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Append a message to the log file */</span>
<span class="kt">void</span>
<span class="nf">append_log_message</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Add the message at the end of the file and flush the data</span>
<span class="cm"> to ensure it gets written to disk */</span>
<span class="n">fseek</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
<span class="n">fprintf</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="s">&quot;%zd: %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">index</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span>
<span class="n">fflush</span> <span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="cm">/* Re-compute the hash with the new message and append it to</span>
<span class="cm"> the end of the file */</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">computed</span> <span class="o">=</span> <span class="n">compute_log_hash</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">fseek</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
<span class="n">fprintf</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="s">&quot;%s</span><span class="se">\n\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">computed</span><span class="p">);</span>
<span class="n">free</span> <span class="p">(</span><span class="n">computed</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* For a given file, compute the SHA-256 hash sum of the contents.</span>
<span class="cm"> The trailing parameter indicates the number of bytes at the</span>
<span class="cm"> end of the file to omit from the computation. Returns a</span>
<span class="cm"> dynamically allocated string that must be freed. */</span>
<span class="kt">char</span> <span class="o">*</span>
<span class="nf">compute_log_hash</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="n">fp</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">trailing</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Allocate pipes for parent-to-child communication and create</span>
<span class="cm"> a child process */</span>
<span class="kt">int</span> <span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
<span class="n">pipe</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">);</span>
<span class="n">pipe</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">);</span>
<span class="kt">pid_t</span> <span class="n">child_pid</span> <span class="o">=</span> <span class="n">fork</span> <span class="p">();</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">child_pid</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
<span class="cm">/* Child process will read data from the pipe, redirecting this</span>
<span class="cm"> data as stdin to the shasum program. The stdout will be</span>
<span class="cm"> redirected through the pipe back to the parent. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">child_pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">close</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="n">dup2</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">STDIN_FILENO</span><span class="p">);</span>
<span class="n">dup2</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">STDOUT_FILENO</span><span class="p">);</span>
<span class="n">execlp</span> <span class="p">(</span><span class="s">&quot;shasum&quot;</span><span class="p">,</span> <span class="s">&quot;shasum&quot;</span><span class="p">,</span> <span class="s">&quot;-a&quot;</span><span class="p">,</span> <span class="s">&quot;256&quot;</span><span class="p">,</span> <span class="s">&quot;-&quot;</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* Parent resumes from here by closing the unused pipe ends */</span>
<span class="n">close</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="cm">/* Determine the size of the file without the last two lines</span>
<span class="cm"> (containing a shasum and a blank line) */</span>
<span class="k">struct</span> <span class="n">stat</span> <span class="n">file_info</span><span class="p">;</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">stat</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">file_info</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
<span class="kt">size_t</span> <span class="n">remaining</span> <span class="o">=</span> <span class="n">file_info</span><span class="p">.</span><span class="n">st_size</span> <span class="o">-</span> <span class="n">trailing</span><span class="p">;</span>
<span class="n">fseek</span> <span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
<span class="cm">/* Instead of reading the entire file contents (which could be</span>
<span class="cm"> large), read a chunk at a time and write the contents into</span>
<span class="cm"> the pipe for the child to access */</span>
<span class="kt">size_t</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">1024</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="n">size</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
<span class="k">while</span> <span class="p">(</span><span class="n">remaining</span> <span class="o">&gt;</span> <span class="n">size</span><span class="p">)</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="n">fread</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">),</span> <span class="n">size</span><span class="p">,</span> <span class="n">fp</span><span class="p">);</span>
<span class="n">write</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="n">remaining</span> <span class="o">-=</span> <span class="n">size</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* If there is any left over, read those bytes and send them to</span>
<span class="cm"> the child */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">remaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</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="n">fread</span> <span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">),</span> <span class="n">remaining</span><span class="p">,</span> <span class="n">fp</span><span class="p">);</span>
<span class="n">write</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">remaining</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* All data have been written, so close the pipe so the child</span>
<span class="cm"> can finalize its calculation */</span>
<span class="n">close</span> <span class="p">(</span><span class="n">p2c_pipe</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="cm">/* Read the computed shasum back and compare it with the last</span>
<span class="cm"> shasum in the file */</span>
<span class="kt">char</span> <span class="n">shabuf</span><span class="p">[</span><span class="n">SHALENGTH</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">shabuf</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">shabuf</span><span class="p">));</span>
<span class="n">read</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">shabuf</span><span class="p">,</span> <span class="n">SHALENGTH</span><span class="p">);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">c2p_pipe</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="k">return</span> <span class="n">strdup</span> <span class="p">(</span><span class="n">shabuf</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* asctime_r returns 24 characters plus \n and \0 */</span>
<span class="cp">#define ASCTIME_BUFSIZE 26</span>
<span class="kt">char</span> <span class="o">*</span>
<span class="nf">generate_random_log</span> <span class="p">(</span><span class="kt">int</span> <span class="n">tid</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Determine the current local time and convert it to an</span>
<span class="cm"> ASCII-printable format */</span>
<span class="kt">char</span> <span class="n">timebuf</span><span class="p">[</span><span class="n">ASCTIME_BUFSIZE</span><span class="p">];</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">timebuf</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">timebuf</span><span class="p">));</span>
<span class="k">struct</span> <span class="n">tm</span> <span class="n">localbuf</span><span class="p">;</span>
<span class="n">memset</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">localbuf</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">localbuf</span><span class="p">));</span>
<span class="kt">time_t</span> <span class="n">current</span> <span class="o">=</span> <span class="n">time</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="k">struct</span> <span class="n">tm</span> <span class="o">*</span><span class="n">local</span> <span class="o">=</span> <span class="n">localtime_r</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">current</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">localbuf</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">timemsg</span> <span class="o">=</span> <span class="n">asctime_r</span> <span class="p">(</span><span class="n">local</span><span class="p">,</span> <span class="n">timebuf</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">message</span> <span class="o">=</span> <span class="n">calloc</span> <span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="kt">char</span><span class="p">));</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">message</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="cm">/* Use the ASCII-formatted time to create a log message like:</span>
<span class="cm"> [Wed Jun 26 10:32:15 1996] Event from thread 5</span>
<span class="cm"> */</span>
<span class="n">message</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;[&#39;</span><span class="p">;</span>
<span class="n">strncpy</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">message</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">timemsg</span><span class="p">,</span> <span class="n">ASCTIME_BUFSIZE</span> <span class="o">-</span> <span class="mi">2</span><span class="p">);</span>
<span class="n">strncat</span> <span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="s">&quot;] Event from thread &quot;</span><span class="p">,</span> <span class="mi">100</span> <span class="o">-</span> <span class="n">ASCTIME_BUFSIZE</span><span class="p">);</span>
<span class="n">snprintf</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">message</span><span class="p">[</span><span class="n">ASCTIME_BUFSIZE</span> <span class="o">+</span> <span class="mi">19</span><span class="p">],</span> <span class="mi">100</span> <span class="o">-</span> <span class="n">strlen</span> <span class="p">(</span><span class="n">message</span><span class="p">),</span> <span class="s">&quot;%d&quot;</span><span class="p">,</span> <span class="n">tid</span><span class="p">);</span>
<span class="cm">/* Return a heap-allocated copy of the string */</span>
<span class="k">return</span> <span class="n">strdup</span> <span class="p">(</span><span class="n">message</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* Create bogus initial commit message to have a starting point */</span>
<span class="kt">void</span>
<span class="nf">create_initial_log</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">unlink</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">);</span>
<span class="k">struct</span> <span class="n">stat</span> <span class="n">file_info</span><span class="p">;</span>
<span class="n">stat</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">file_info</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">file</span> <span class="o">=</span> <span class="n">open</span> <span class="p">(</span><span class="n">LOGFILE</span><span class="p">,</span> <span class="n">O_RDWR</span> <span class="o">|</span> <span class="n">O_CREAT</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">file</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">fchmod</span> <span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="mo">0644</span><span class="p">);</span>
<span class="n">write</span> <span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s">&quot;0: [Tue Jun 25 22:09:41 2019] Initial commit</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="mi">45</span><span class="p">);</span>
<span class="n">write</span> <span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s">&quot;6231aaee038b4ab9b3fd50e5bf604f26&quot;</span>
<span class="s">&quot;97af98b5c126f4f86f5aaca809439c65</span><span class="se">\n\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">SHALENGTH</span> <span class="o">+</span> <span class="mi">2</span><span class="p">);</span>
<span class="n">close</span> <span class="p">(</span><span class="n">file</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="Deadlock.html">7.7. Deadlock</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="SynchProblemsOverview.html">8.1. Synchronization Patterns and Problems</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>