-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdict_value.c
More file actions
82 lines (68 loc) · 1.66 KB
/
dict_value.c
File metadata and controls
82 lines (68 loc) · 1.66 KB
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
// Simplified model for storing dict values.
// Demonstrates that we need "release" for assigning the value even if
// we lock the dict mutex.
#include <stdio.h>
#include <threads.h>
#include <stdatomic.h>
#include <model-assert.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "librace.h"
struct PyMutex {
atomic_int v;
};
struct PyLongObject {
atomic_int ob_value;
};
struct PyDictObject {
struct PyMutex mutex;
atomic_address value;
};
struct PyLongObject long_obj;
struct PyDictObject dict;
static void
LOCK(struct PyMutex *mutex)
{
int expected;
do {
expected = 0;
}
while (!atomic_compare_exchange_strong(&mutex->v, &expected, 1));
}
static void
UNLOCK(struct PyMutex *mutex)
{
int old = atomic_exchange(&mutex->v, 0);
MODEL_ASSERT(old == 1);
}
static void
thread1(void *arg)
{
atomic_store_explicit(&long_obj.ob_value, 1234, memory_order_relaxed);
LOCK(&dict.mutex);
atomic_store_explicit(&dict.value, &long_obj, memory_order_release); // This needs to be RELEASE!
UNLOCK(&dict.mutex);
}
static void
thread2(void *arg)
{
struct PyLongObject *value = atomic_load_explicit(&dict.value, memory_order_acquire);
if (value != NULL) {
int field = atomic_load_explicit(&value->ob_value, memory_order_relaxed);
MODEL_ASSERT(field == 1234);
}
}
int
user_main(int argc, char **argv)
{
atomic_init(&dict.mutex.v, 0);
atomic_init(&dict.value, 0);
atomic_init(&long_obj.ob_value, 0);
thrd_t threads[2];
thrd_create(&threads[0], thread1, NULL);
thrd_create(&threads[1], thread2, NULL);
thrd_join(threads[0]);
thrd_join(threads[1]);
return 0;
}