-
Notifications
You must be signed in to change notification settings - Fork 0
/
qcc_lib_cpp.h
310 lines (230 loc) · 5.62 KB
/
qcc_lib_cpp.h
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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#ifdef __cplusplus
#ifndef _QCC_LIB_CPP_H
#define _QCC_LIB_CPP_H
#include <atomic>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <pthread.h>
#include <immintrin.h>
#include <execinfo.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <errno.h>
#define PGSZ ((4096lu))
// {{{ types
#define typeof __typeof__
typedef char s8;
typedef short s16;
typedef int s32;
typedef long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long u64;
typedef std::atomic<bool> abool;
typedef std::atomic<uint8_t> au8;
typedef std::atomic<uint16_t> au16;
typedef std::atomic<uint32_t> au32;
typedef std::atomic<uint64_t> au64;
typedef std::atomic<int8_t> as8;
typedef std::atomic<int16_t> as16;
typedef std::atomic<int32_t> as32;
typedef std::atomic<int64_t> as64;
#define MO_RELAXED std::memory_order_relaxed
#define MO_CONSUME std::memory_order_consume
#define MO_ACQUIRE std::memory_order_acquire
#define MO_RELEASE std::memory_order_release
#define MO_ACQ_REL std::memory_order_acq_rel
#define MO_SEQ_CST std::memory_order_seq_cst
// }}} types
// timing {{{
inline u64
time_nsec(void)
{
struct timespec ts;
// MONO_RAW is 5x to 10x slower than MONO
clock_gettime(CLOCK_MONOTONIC, &ts);
return ((u64)ts.tv_sec) * 1000000000lu + ((u64)ts.tv_nsec);
}
inline double
time_sec(void)
{
const u64 nsec = time_nsec();
return ((double)nsec) * 1.0e-9;
}
inline u64
time_diff_nsec(const u64 last)
{
return time_nsec() - last;
}
inline double
time_diff_sec(const double last)
{
return time_sec() - last;
}
extern void
time_stamp(char * str, const size_t size);
extern void
time_stamp2(char * str, const size_t size);
// }}} timing
// cpucache {{{
inline void
cpu_pause(void)
{
#if defined(__x86_64__)
_mm_pause();
#elif defined(__aarch64__)
// nop
#endif
}
extern void
cpu_mfence(void);
extern void
cpu_cfence(void);
extern void
cpu_prefetch0(const void * const ptr);
extern void
cpu_prefetch1(const void * const ptr);
extern void
cpu_prefetch2(const void * const ptr);
extern void
cpu_prefetch3(const void * const ptr);
extern void
cpu_prefetchw(const void * const ptr);
// }}} cpucache
// bits {{{
extern u32
bits_reverse_u32(const u32 v);
extern u64
bits_reverse_u64(const u64 v);
extern u64
bits_rotl_u64(const u64 v, const u8 n);
extern u64
bits_rotr_u64(const u64 v, const u8 n);
extern u32
bits_rotl_u32(const u32 v, const u8 n);
extern u32
bits_rotr_u32(const u32 v, const u8 n);
extern u64
bits_p2_up_u64(const u64 v);
extern u32
bits_p2_up_u32(const u32 v);
extern u64
bits_p2_down_u64(const u64 v);
extern u32
bits_p2_down_u32(const u32 v);
extern u64
bits_round_up(const u64 v, const u8 power);
extern u64
bits_round_up_a(const u64 v, const u64 a);
extern u64
bits_round_down(const u64 v, const u8 power);
extern u64
bits_round_down_a(const u64 v, const u64 a);
// }}} bits
// oalloc {{{
struct oalloc;
extern struct oalloc *
oalloc_create(const size_t blksz);
extern void *
oalloc_alloc(struct oalloc * const o, const size_t size);
extern void
oalloc_clean(struct oalloc * const o);
extern void
oalloc_destroy(struct oalloc * const o);
// }}} oalloc
// mm {{{
#ifdef ALLOCFAIL
extern bool
alloc_fail(void);
#endif
extern void *
xalloc(const size_t align, const size_t size);
extern void *
yalloc(const size_t size);
extern void **
malloc_2d(const size_t nr, const size_t size);
extern void **
calloc_2d(const size_t nr, const size_t size);
extern void
pages_unmap(void * const ptr, const size_t size);
extern void
pages_lock(void * const ptr, const size_t size);
/* hugepages */
// force posix allocators: -DVALGRIND_MEMCHECK
extern void *
pages_alloc_4kb(const size_t nr_4kb);
extern void *
pages_alloc_2mb(const size_t nr_2mb);
extern void *
pages_alloc_1gb(const size_t nr_1gb);
extern void *
pages_alloc_best(const size_t size, const bool try_1gb, u64 * const size_out);
// }}} mm
// locking {{{
typedef union {
u32 opaque;
} spinlock;
extern void
spinlock_init(spinlock * const lock);
extern void
spinlock_lock(spinlock * const lock);
extern bool
spinlock_trylock(spinlock * const lock);
extern void
spinlock_unlock(spinlock * const lock);
typedef union {
u32 opaque;
} rwlock;
extern void
rwlock_init(rwlock * const lock);
extern bool
rwlock_trylock_read(rwlock * const lock);
// low-priority reader-lock; use with trylock_write_hp
extern bool
rwlock_trylock_read_lp(rwlock * const lock);
extern bool
rwlock_trylock_read_nr(rwlock * const lock, u16 nr);
extern void
rwlock_lock_read(rwlock * const lock);
extern void
rwlock_unlock_read(rwlock * const lock);
extern bool
rwlock_trylock_write(rwlock * const lock);
extern bool
rwlock_trylock_write_nr(rwlock * const lock, u16 nr);
extern void
rwlock_lock_write(rwlock * const lock);
// writer has higher priority; new readers are blocked
extern bool
rwlock_trylock_write_hp(rwlock * const lock);
extern bool
rwlock_trylock_write_hp_nr(rwlock * const lock, u16 nr);
extern void
rwlock_lock_write_hp(rwlock * const lock);
extern void
rwlock_unlock_write(rwlock * const lock);
extern void
rwlock_write_to_read(rwlock * const lock);
typedef union {
u64 opqaue[8];
} mutex;
extern void
mutex_init(mutex * const lock);
extern void
mutex_lock(mutex * const lock);
extern bool
mutex_trylock(mutex * const lock);
extern void
mutex_unlock(mutex * const lock);
extern void
mutex_deinit(mutex * const lock);
// }}} locking
#define debug_assert(expr) ((void)0)
#endif
#endif