Skip to content

Commit 9b46ed1

Browse files
committed
tracemultiplexer sample: revise README.md
also add test_viewer.py also revise comment header in tracemultiplexer.py
1 parent 48f1f95 commit 9b46ed1

3 files changed

Lines changed: 61 additions & 19 deletions

File tree

samples/tracemultiplexer/README.md

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,48 @@
22
tracemultiplexer
33
================
44

5-
This model simulates a multi-threaded program that has been
6-
instrumented to save traces of its API calls in a log.
5+
Simulate a program where two threads write to the same log file.
6+
Investigate synchronization to ensure that only one thread at a
7+
time can write to the log.
78

8-
When multiple threads are writing the trace log, there can be
9-
nondeterminism in the order in which API calls and returns are made, and
10-
the order they appear in the trace log. The purpose of this sample is
11-
to demonstrate that nondeterminism.
9+
States where both threads may write to the log are considered unsafe
10+
states. Marked log messages may have been corrupted by unsynchronized
11+
writes from both threads.
1212

1313
More details appear in the *tracemultiplexer* comment header.
1414

15-
- *tracemultiplexer*: simulates a multi-threaded program that has been
16-
instrumented to save traces of its API calls in a log.
15+
- *tracemultiplexer*: model program that simulates a multi-threaded
16+
program with and without synchronization.
1717

18-
- *test_graphics* - generate a graph that shows the behavior of *tracemultiplexer*
18+
- *test_viewer* - generate a graph that shows the behavior of
19+
*tracemultiplexer* using a lock to synchronize write access to the
20+
log file, and a second graph showing the behavior of
21+
*tracemultiplexer* with the *unsynchronized* configuration that
22+
ignores the lock.
1923

20-
- *fsmpy*, *svg* - directories of output from the test scripts
24+
- *fsmpy*, *svg* - directories of output from *test_viewer*
2125

22-
View the generated graphics file in a browser. Hover the
23-
pointer over any state bubble to see a tooltip that shows the state
24-
variables in that state.
26+
View the generated *.svg* files in a browser. Hover the pointer over
27+
any state bubble to see a tooltip that shows the state variables in
28+
that state.
29+
30+
The *log* variable represents the log file: it is a list of tuples
31+
where each tuple represents a log message. Messages that end with
32+
*'XXX'* were logged when both threads may have written to the log,
33+
so the message may have been corrupted by unsynchronized writes.
2534

2635
- *tracemultiplexerFSM* - graph that shows the behavior of *tracemultiplexer*
36+
using the lock. None of the states in this graph are unsafe. None of the
37+
log messages are marked with *'XXX'*.
38+
39+
- *unsynchronizedFSM* - graph that shows the behavior of *tracemultiplexer*
40+
ignoring the lock. There are many more transitions and states in this
41+
graph because the threads are unsynchronized, so many more interleavings are
42+
possible. There are many unsafe states (colored red) where both threads may
43+
write to the log. In every unsafe state, the most recently written message in
44+
*log* ends with *'XXX'* to indicate it may have been corrupted by
45+
unsynchronized writes. These corrupted messages persist in *log* in
46+
subsequent states.
2747

2848
There is no stepper in this sample.
2949

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""
2+
tracemultiplexer test - with graphics because this is a model for analysis
3+
"""
4+
5+
cases = [
6+
('Generate graph for synchronized threads that use tracelock',
7+
'pmv.py tracemultiplexer'),
8+
9+
('Generate graph for *un*synchronized threads that *ignore* tracelock',
10+
'pmv.py -m 300 unsynchronized tracemultiplexer'),
11+
]
12+

samples/tracemultiplexer/tracemultiplexer.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
"""
2-
Simulate a multi-threaded program that has been
3-
instrumented to save traces of its API calls in a log.
2+
Simulate a program where two threads write to the same log file.
3+
Investigate synchronization to ensure that only one thread at a time
4+
can write to the log.
45
5-
Instead of simply calling the API functions, each thread instead calls
6-
the *tracecapture* function, which calls the API function but also
7-
saves the call (with arguments) and return (with return value) in the
8-
trace log. The tracecapture function uses a lock:
6+
States where both threads may write to the log are considered unsafe
7+
states. Log messages that may have been corrupted by unsynchronized
8+
writes from both threads are marked.
9+
10+
The simulated multi-threaded program has been instrumented to save
11+
traces of its API calls in a log. Instead of simply calling the API
12+
functions, each thread instead calls the *tracecapture* function,
13+
which calls the API function but also saves the call (with arguments)
14+
and return (with return value) in the trace log. The tracecapture
15+
function uses a lock:
916
1017
tracelock = lock()
1118
@@ -35,6 +42,9 @@ def tracecapture(thread_id, call, args): # call is action name
3542
call ids (action ids) for each thread, first index is thread id,
3643
second index is thread pc.
3744
45+
unsynchronized: set False to use tracelock, True to ignore tracelock
46+
47+
3848
State:
3949
4050
pc: program counter for each thread, indexed by thread_id

0 commit comments

Comments
 (0)