annotate libsanitizer/sanitizer_common/sanitizer_lfstack.h @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 //===-- sanitizer_lfstack.h -=-----------------------------------*- C++ -*-===//
kono
parents:
diff changeset
2 //
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
111
kono
parents:
diff changeset
6 //
kono
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
kono
parents:
diff changeset
8 //
kono
parents:
diff changeset
9 // Lock-free stack.
kono
parents:
diff changeset
10 // Uses 32/17 bits as ABA-counter on 32/64-bit platforms.
kono
parents:
diff changeset
11 // The memory passed to Push() must not be ever munmap'ed.
kono
parents:
diff changeset
12 // The type T must contain T *next field.
kono
parents:
diff changeset
13 //
kono
parents:
diff changeset
14 //===----------------------------------------------------------------------===//
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 #ifndef SANITIZER_LFSTACK_H
kono
parents:
diff changeset
17 #define SANITIZER_LFSTACK_H
kono
parents:
diff changeset
18
kono
parents:
diff changeset
19 #include "sanitizer_internal_defs.h"
kono
parents:
diff changeset
20 #include "sanitizer_common.h"
kono
parents:
diff changeset
21 #include "sanitizer_atomic.h"
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 namespace __sanitizer {
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 template<typename T>
kono
parents:
diff changeset
26 struct LFStack {
kono
parents:
diff changeset
27 void Clear() {
kono
parents:
diff changeset
28 atomic_store(&head_, 0, memory_order_relaxed);
kono
parents:
diff changeset
29 }
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 bool Empty() const {
kono
parents:
diff changeset
32 return (atomic_load(&head_, memory_order_relaxed) & kPtrMask) == 0;
kono
parents:
diff changeset
33 }
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 void Push(T *p) {
kono
parents:
diff changeset
36 u64 cmp = atomic_load(&head_, memory_order_relaxed);
kono
parents:
diff changeset
37 for (;;) {
kono
parents:
diff changeset
38 u64 cnt = (cmp & kCounterMask) + kCounterInc;
kono
parents:
diff changeset
39 u64 xch = (u64)(uptr)p | cnt;
kono
parents:
diff changeset
40 p->next = (T*)(uptr)(cmp & kPtrMask);
kono
parents:
diff changeset
41 if (atomic_compare_exchange_weak(&head_, &cmp, xch,
kono
parents:
diff changeset
42 memory_order_release))
kono
parents:
diff changeset
43 break;
kono
parents:
diff changeset
44 }
kono
parents:
diff changeset
45 }
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 T *Pop() {
kono
parents:
diff changeset
48 u64 cmp = atomic_load(&head_, memory_order_acquire);
kono
parents:
diff changeset
49 for (;;) {
kono
parents:
diff changeset
50 T *cur = (T*)(uptr)(cmp & kPtrMask);
kono
parents:
diff changeset
51 if (!cur)
kono
parents:
diff changeset
52 return nullptr;
kono
parents:
diff changeset
53 T *nxt = cur->next;
kono
parents:
diff changeset
54 u64 cnt = (cmp & kCounterMask);
kono
parents:
diff changeset
55 u64 xch = (u64)(uptr)nxt | cnt;
kono
parents:
diff changeset
56 if (atomic_compare_exchange_weak(&head_, &cmp, xch,
kono
parents:
diff changeset
57 memory_order_acquire))
kono
parents:
diff changeset
58 return cur;
kono
parents:
diff changeset
59 }
kono
parents:
diff changeset
60 }
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 // private:
kono
parents:
diff changeset
63 static const int kCounterBits = FIRST_32_SECOND_64(32, 17);
kono
parents:
diff changeset
64 static const u64 kPtrMask = ((u64)-1) >> kCounterBits;
kono
parents:
diff changeset
65 static const u64 kCounterMask = ~kPtrMask;
kono
parents:
diff changeset
66 static const u64 kCounterInc = kPtrMask + 1;
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 atomic_uint64_t head_;
kono
parents:
diff changeset
69 };
kono
parents:
diff changeset
70 } // namespace __sanitizer
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 #endif // SANITIZER_LFSTACK_H