4 /** @DeclareState: IntMap *map; */
6 int HashMap::get(int key) {
8 int hash = hashKey(key);
10 // Try first without locking...
11 atomic<Entry*> *tab = table;
12 int index = hash & (capacity - 1);
13 atomic<Entry*> *first = &tab[index];
17 // Should be a load acquire
18 // This load action here makes it problematic for the SC analysis, what
19 // we need to do is as follows: if the get() method ever acquires the
20 // lock, we ignore this operation for the SC analysis, and otherwise we
21 // take it into consideration
23 // XXX-injection-#1: Weaken the parameter "mo_acquire" to
24 // "memory_order_relaxed", run "make" to recompile, and then run:
25 // "./run.sh ./concurrent-hashmap/testcase2 -m2 -y -u3 -tSPEC"
26 /********** Detected UL (testcase2) **********/
27 Entry *firstPtr = first->load(mo_acquire);
31 if (e->hash == hash && eq(key, e->key)) {
32 // XXX-injection-#2: Weaken the parameter "mo_seqcst" to
33 // "memory_order_acq_rel", run "make" to recompile, and then run:
34 // "./run.sh ./concurrent-hashmap/testcase1 -m2 -y -u3 -tSPEC"
35 /********** Detected Correctness (testcase1) **********/
36 res = e->value.load(mo_seqcst);
37 /** @OPClearDefine: res != 0 */
43 // Loading the next entry, this can be relaxed because the
44 // synchronization has been established by the load of head
45 e = e->next.load(mo_relaxed);
48 // Recheck under synch if key apparently not there or interference
49 Segment *seg = segments[hash & SEGMENT_MASK];
50 seg->lock(); // Critical region begins
51 /** @OPClearDefine: true */
52 // Not considering resize now, so ignore the reload of table...
54 // Synchronized by locking, no need to be load acquire
55 Entry *newFirstPtr = first->load(mo_relaxed);
56 if (e != NULL || firstPtr != newFirstPtr) {
59 if (e->hash == hash && eq(key, e->key)) {
60 // Protected by lock, no need to be SC
61 res = e->value.load(mo_relaxed);
62 seg->unlock(); // Critical region ends
65 // Synchronized by locking
66 e = e->next.load(mo_relaxed);
69 seg->unlock(); // Critical region ends
73 int HashMap::put(int key, int value) {
74 // Don't allow NULL key or value
75 MODEL_ASSERT (key && value);
77 int hash = hashKey(key);
78 Segment *seg = segments[hash & SEGMENT_MASK];
81 seg->lock(); // Critical region begins
83 int index = hash & (capacity - 1);
85 atomic<Entry*> *first = &tab[index];
89 // The written of the entry is synchronized by locking
90 Entry *firstPtr = first->load(mo_relaxed);
93 if (e->hash == hash && eq(key, e->key)) {
94 // FIXME: This could be a relaxed (because locking synchronize
95 // with the previous put())?? no need to be acquire
96 oldValue = e->value.load(relaxed);
97 // XXX-injection-#3: Weaken the parameter "mo_seqcst" to
98 // "memory_order_acq_rel", run "make" to recompile, and then run:
99 // "./run.sh ./concurrent-hashmap/testcase1 -m2 -y -u3 -tSPEC"
100 /********** Detected Correctness (testcase1) **********/
101 e->value.store(value, mo_seqcst);
102 /** @OPClearDefine: true */
103 seg->unlock(); // Don't forget to unlock before return
106 // Synchronized by locking
107 e = e->next.load(mo_relaxed);
110 // Add to front of list
111 Entry *newEntry = new Entry();
112 newEntry->hash = hash;
114 newEntry->value.store(value, relaxed);
115 /** @OPClearDefine: true */
116 newEntry->next.store(firstPtr, relaxed);
117 // XXX-injection-#4: Weaken the parameter "mo_release" to
118 // "memory_order_acquire", run "make" to recompile, and then run:
119 // "./run.sh ./concurrent-hashmap/testcase2 -m2 -y -u3 -tSPEC"
120 /********** Detected UL (testcase2) **********/
121 // Publish the newEntry to others
122 first->store(newEntry, mo_release);
123 seg->unlock(); // Critical region ends
127 /** @PreCondition: return STATE(map)->get(key) == C_RET; */
128 int get(HashMap *map, int key) {
129 return map->get(key);
132 /** @PreCondition: return STATE(map)->get(key) == C_RET;
133 @Transition: STATE(map)->put(key, value); */
134 int put(HashMap *map, int key, int value) {
135 return map->put(key, value);