-
Notifications
You must be signed in to change notification settings - Fork 0
/
mem.h
112 lines (88 loc) · 2.45 KB
/
mem.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
#ifndef _MEM_H
#define _MEM_H
#ifdef __cplusplus
extern "C" {
#else
// In order for racey to compile.
// Only gcc requires this, g++ enables _GNU_SOURCE by default.
#define _GNU_SOURCE
#endif
#include <stdint.h>
// Note RTM cluster can't use DEBUG_ACCESS.
//#define DEBUG_ACCESS
//#define RTM_STAT
#define RTM_BATCH_N 7
#ifdef RTM_STAT
// Count RTM aborts.
extern __thread int g_rtm_abort_cnt;
#endif
// Number of shared objects, must be initialized first.
extern int g_nobj;
typedef long version_t;
typedef int objid_t;
typedef long memop_t;
typedef int8_t tid_t;
// wait_memop is used when recording.
struct wait_memop {
objid_t objid;
version_t version;
memop_t memop;
};
// Version log does not need preprocessing during replay.
struct wait_version {
memop_t memop;
version_t version;
};
#ifdef DEBUG_ACCESS
// Record memory access information.
struct mem_acc {
char acc;
objid_t objid;
uint32_t val;
version_t version;
memop_t memop; // necessary?
};
#endif
/*extern int struct wait_memop_wrong_size[sizeof(struct wait_memop) ==
(sizeof(objid_t) + sizeof(version_t) + sizeof(memop_t)) ? 1 : -1];*/
// Used during replay.
struct replay_wait_memop {
// Order of field must match with binary log
version_t version;
memop_t memop;
tid_t tid;
};
// Test program should provide obj_id implementation.
extern objid_t (*calc_objid)(void *addr);
// Initialization function. Must called after nthr and thread
// data storage is initialized.
#ifndef DUMMY
void mem_init(tid_t nthr, int nobj);
void mem_init_thr(tid_t tid);
void mem_finish(tid_t nthr, int nobj);
void mem_finish_thr();
uint32_t mem_read(tid_t tid, uint32_t *addr);
void mem_write(tid_t tid, uint32_t *addr, uint32_t val);
#else // DUMMY
static inline uint32_t mem_read(tid_t tid, uint32_t *addr) {
return *addr;
}
static inline void mem_write(tid_t tid, uint32_t *addr, uint32_t val) {
*addr = val;
}
static inline void mem_init(tid_t nthr, int nobj) {}
static inline void mem_init_thr(tid_t tid) {}
static inline void mem_finish_thr() {}
#endif
// gcc on linux supports __thread. It's much pleasant to use than using
// global array and pthread_getspecific etc.
extern __thread tid_t g_tid;
// Utility function
void *calloc_check(long nmemb, long size, const char *err_msg);
#define likely(x) __builtin_expect(!!(x), 0)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define __constructor__ __attribute__((constructor))
#ifdef __cplusplus
}
#endif
#endif