-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathGDD_Sync.txt
266 lines (223 loc) · 6.71 KB
/
GDD_Sync.txt
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
GDD Parallel Programming Simulator
MAIN MENU
=========
"Parallel Programming Simulator"
Left menu:
1. Tutorial
2. First Level
3. Second Level
...
8. Last Level
A. Bonus Level: Peterson's Algorithm
Right menu:
1. Manual -> Shows Princess Civilization-like manual screen.
2. Quit Game -> Quits game without confirmation
LEVEL SCREEN
============
Objective: Your objective, in a single line, is displayed at the top.
Hint: Hints are displayed underneath the objective, along with the button, "Additional Hints", which gives additional hints in another GamePhase.
Then, there are 2 to 3 source codes.
Source codes have lines. Each line is a single instruction. Source codes have an active instruction.
When you mouse over a line, a tooltip is given.
Manipulations:
- Undo Last Action [Backspace]
- Advance, but inside (use non-atomicity).
- Advance [Space / 1 / 2 / 3 (a numeral advances the thread, Space advances current thread]
- Context Switch [Tab]
- Spurious wakeup
- Cache write-through.
- Move instruction up.
- Move instruction down.
- Reset.
- Expand instruction into atomic instructions.
Tutorial: Tutorial hints are displayed at the bottom of the screen. There is a button "Next [K]" to proceed.
Tutorial will come later.
== LEVELS ==
1. Tutorial: Advancing.
Objective: Execute the failure instruction.
Hint: In all levels of this game, your objective is to demonstrate the program is not thread-safe by doing one of three things: having two threads enter the critical section simulatenously, by causing a deadlock or by executing the failure instruction which represents a position in the source the program should never reach. This is the tutorial level so all you need to do is to advance execution in this single-thread program until you execute the failure instruction. To do this, keep pressing 'Space'.
a = 1;
a = a * 2;
if (a == 2) {
failure_instruction();
}
2. Tutorial: Multithreading.
Objective: Make both threads be in the critical section at the same time.
Hint: In multithreaded programming, a "critical section" is a piece of code that should be executed by only one thread at a time. If two threads are in a critical section at the same time, errors may result. In this level, your goal is to execute the context switches in such a way that both threads can both be in the critical section at the same time.
GLOBAL:
int a = 0;
ONE:
while (a != 0) {
null-instruction;
}
a = 1;
critical_section();
a = 0;
TWO:
while (a != 0) {
null-instruction;
}
a = 1;
critical_section();
a = 0;
3. Tutorial: Deadlocks.
Objective: Make sure a deadlock occurs.
GLOBAL:
object mutex = new object();
object mutex2 = new object();
ONE:
Debug.Print("Locking one.");
Monitor.Enter(mutex);
Debug.Print("Locking two.");
Monitor.Enter(mutex2);
critical_section();
Debug.Print("Unlocking two.");
Monitor.Exit(mutex2);
Debug.Print("Unlocking one.");
Monitor.Exit(mutex);
TWO:
Debug.Print("Locking two.");
Monitor.Enter(mutex2);
Debug.Print("Locking one.");
Monitor.Enter(mutex);
critical_section();
Debug.Print("Unlocking one.");
Monitor.Exit(mutex);
Debug.Print("Unlocking two.");
Monitor.Exit(mutex2);
4. Confused Counter
Objective: Make sure that at the end of execution, the variable "counter" does not contain the value "2".
GLOBAL:
int counter = 0;
int second = 0;
ONE:
business_logic();
counter = counter + 1;
second = second + 1;
if (second == 2 && counter != 2) {
failure;
}
TWO:
business_logic();
counter = counter + 1;
second = second + 1;
if (second == 2 && counter != 2) {
failure;
}
5. Peterson's Algorithm Extended
Objective: Make it so that at least two threads are in the critical section simultaneously.
GLOBAL:
bool flagOne = false;
bool flagTwo = false;
bool flagThree = false;
int turn = 0;
ONE:
flagOne = true;
turn = 1;
while ( (flagTwo || flagThree) && turn == 1 ) {
null-instruction;
}
critical_section();
flagOne = false;
TWO:
flagTwo = true;
turn = 2;
while ( (flagOne || flagThree) && turn == 2 ) {
null-instruction;
}
critical_section();
flagTwo = false;
THREE:
flagThree = true;
turn = 3;
while ( (flagTwo || flagOne) && turn == 3 ) {
null-instruction;
}
critical_section();
flagThree = false;
6. Producer-Consumer
Objective: Attempt something that is not thread-safe.
GLOBAL:
Queue<int> queue;
ONE:
while (true) {
queue.Enqueue(1);
}
TWO:
while (true) {
if (queue.Count > 0) {
int value = queue.Dequeue();
Debug.Print(value);
}
}
7. Producer-Consumer 2
Objective: Produce an exception.
GLOBAL:
ConcurrentQueue<int> queue;
ONE:
while (true) {
queue.Enqueue(1);
}
TWO:
while (true) {
if (queue.Count > 0) {
int value = queue.Dequeue();
Debug.Print(value);
}
}
THREE:
while (true) {
if (queue.Count > 0) {
int value = queue.Dequeue();
Debug.Print(value);
}
}
8. Producer-Consumer with Condition Variables
ONE:
Monitor.Enter(mutex);
while (queue.Count == 10) {
Monitor.Wait(mutex);
}
queue.Enqueue(2);
Monitor.Pulse();
Monitor.Exit(mutex);
TWO:
Monitor.Enter(mutex);
while (queue.Count == 0) {
Monitor.Wait(mutex);
}
int a = queue.Dequeue();
Debug.Print(a);
Monitor.Pulse();
Monitor.Exit(mutex);
(again correctly, but with IFs instead of WHILEs)
(again, but with spurious wakeups)
== INSTRUCTIONS ==
- Failure Instruction
Atomic.
If this instruction is executed, the program crashes or otherwise fails. If you manage to execute this instruction in a level, you win the level immediately.
- Assignment (VARIABLE, EXPRESSION)
Expands to Read(NEW_TEMP_VAR, EXPRESSION) and Write(VARIABLE, NEW_TEMP_VAR).
This instruction evaluates the expression EXPRESSION, stores the result in a temporary variable, then assigns the result to the variable VARIABLE.
- Read (TEMPORARY_VARIABLE, EXPRESSION)
Atomic if expression is atomic, otherwise non-atomic.
Stores the value of the expression into temporary variable.
- Write (VARIABLE, TEMPORARY_VARIABLE)
Atomic if not double not struct, otherwise non-atomic.
Copies the value.
- Compute (TEMPORARY_VARIABLE, TEMPORARY_VARIABLE, TEMPORARY_VARIABLE)
Atomic if not double not struct, otherwise non-atomic.
Performs an arithmetic operation and returns the result.
- If (EXPRESSION, THEN)
Non-atomic.
Evaluates EXPRESSION. If it evaluates to true, moves the program counter to THEN, otherwise skips THEN.
== TYPES ==
- TEMPORARY_VARIABLE (name, value)
- VARIABLE (name, value, volatility)
== EXPRESSIONS ==
- Literal (VALUE).
Atomic. Has a value.
- Variable (NAME).
Atomic if not double not struct, otherwise non-atomic.
- Binary operator (ARG1, ARG2).
Expands to Read(NEW_VAR_1, ARG1), Read(NEW_VAR_2, ARG2), Compute(RESULT, NEW_VAR_1, NEW_VAR_2).