25
25
#include < execinfo.h>
26
26
#include < unistd.h>
27
27
28
- #ifdef __riscv
29
- #define write_csr (reg, val ) \
30
- ({ asm volatile (" csrw " #reg " , %0" ::" rK" ((uint64_t )val) : " memory" ); })
31
- #else
32
- #define write_csr (reg, val )
33
- // #warning YUKON expects riscv
34
- #endif
35
-
36
- static alaska::ThreadCache *tc = NULL ;
37
-
38
- static void set_ht_addr (void *addr) {
39
- alaska::printf (" set htbase to %p\n " , addr);
40
- uint64_t value = (uint64_t )addr;
41
- if (value != 0 and getenv (" YUKON_PHYS" ) != nullptr ) {
42
- value |= (1LU << 63 );
43
- }
44
- write_csr (0xc2 , value);
45
- }
46
-
47
- static alaska::Runtime *the_runtime = NULL ;
48
-
49
-
50
-
51
- #define BACKTRACE_SIZE 100
52
-
53
- static bool dead = false ;
28
+ #include < yukon/yukon.hpp>
54
29
55
- static bool is_initialized () { return the_runtime != NULL ; }
56
30
57
-
58
- static void print_hex (const char *msg, uint64_t val) {
59
- char buf[512 ];
60
- snprintf (buf, 512 , " %s 0x%zx\n " , msg, val);
61
- write (STDOUT_FILENO, buf, strlen (buf));
62
- }
63
-
64
- static void print_words (unsigned *words, int n) {
65
- char buf[512 ];
66
- for (int i = 0 ; i < n; i++) {
67
- snprintf (buf, 512 , " %08x \n " , words[i]);
68
- write (STDOUT_FILENO, buf, strlen (buf));
69
- }
70
- write (STDOUT_FILENO, " \n " , 1 );
71
- }
72
-
73
-
74
- static void print_string (const char *msg) { write (STDOUT_FILENO, msg, strlen (msg)); }
75
-
76
- static char stdout_buf[BUFSIZ];
77
- static char stderr_buf[BUFSIZ];
31
+ #define write_csr (reg, val ) \
32
+ ({ asm volatile (" csrw %0, %1" ::" i" (reg), " rK" ((uint64_t )val) : " memory" ); })
78
33
79
34
35
+ #define read_csr (csr, val ) \
36
+ __asm__ __volatile__ (" csrr %0, %1" : " =r" (val) : "n"(csr) : /* clobbers: none */ );
80
37
81
- static void wait_for_csr_zero (void ) {
82
- volatile uint32_t csr_value = 0x1 ;
83
- do {
84
- __asm__ volatile (" csrr %0, 0xc3\n\t " : " =r" (csr_value) : : " memory" );
85
- } while (csr_value != 0 );
86
- }
87
38
39
+ #define wait_for_csr_zero (reg ) \
40
+ do { \
41
+ volatile uint32_t csr_value = 0x1 ; \
42
+ do { \
43
+ read_csr (reg, csr_value); \
44
+ } while (csr_value != 0 ); \
45
+ } while (0 );
88
46
89
47
90
- #define BACKTRACE_SIZE 100
48
+ #define CSR_HTBASE 0xc2
49
+ #define CSR_HTDUMP 0xc3
50
+ #define CSR_HTINVAL 0xc4
91
51
52
+ static alaska::ThreadCache *tc = NULL ;
53
+ static alaska::Runtime *the_runtime = NULL ;
92
54
93
55
94
- static void handle_sig (int sig) {
95
- printf (" Caught signal %d (%s)\n " , sig, strsignal (sig));
96
- void *buffer[BACKTRACE_SIZE];
97
- // Get the backtrace
98
- int nptrs = backtrace (buffer, BACKTRACE_SIZE);
99
- // Print the backtrace symbols
100
- backtrace_symbols_fd (buffer, nptrs, STDOUT_FILENO);
101
- exit (0 );
56
+ static inline uint64_t read_cycle_counter () {
57
+ uint64_t cycles;
58
+ asm volatile (" rdcycle %0" : " =r" (cycles));
59
+ return cycles;
102
60
}
103
61
104
62
@@ -108,84 +66,108 @@ static void handle_sig(int sig) {
108
66
// stores the fact that it will cause an exception until you
109
67
// invalidate the entry.
110
68
static void segv_handler (int sig, siginfo_t *info, void *ucontext) {
111
- printf (" Caught segfault to address %p\n " , info->si_addr );
69
+ printf (" Caught segfault to address %p. Clearing htlb and trying again! \n " , info->si_addr );
112
70
113
- // void *buffer[BACKTRACE_SIZE];
114
- // // Get the backtrace
115
- // int nptrs = backtrace(buffer, BACKTRACE_SIZE);
116
- // // Print the backtrace symbols
117
- // backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO);
118
- // alaska_dump_backtrace();
119
-
120
- __asm__ volatile (" csrw 0xc4, %0" ::" rK" ((1LU << (64 - ALASKA_SIZE_BITS)) - 1 ) : " memory" );
71
+ write_csr (CSR_HTINVAL, ((1LU << (64 - ALASKA_SIZE_BITS)) - 1 ));
121
72
__asm__ volatile (" fence" ::: " memory" );
122
73
// exit(0);
123
74
return ;
124
75
}
125
76
126
77
127
- static void init (void ) {
128
- setvbuf (stdout, stdout_buf, _IOLBF, BUFSIZ);
129
- setvbuf (stderr, stderr_buf, _IOLBF, BUFSIZ);
78
+ static pthread_t yukon_dump_daemon_thread;
79
+ static void *yukon_dump_daemon (void *) {
80
+ auto *tc = yukon::get_tc ();
81
+ while (1 ) {
82
+ // Sleep
130
83
131
- alaska::Configuration config;
132
- // Use the "malloc" backend to operate cleanly w/ libc's malloc
133
- config.huge_strategy = alaska::HugeAllocationStrategy::CUSTOM_MMAP_BACKED;
84
+ auto start = read_cycle_counter ();
85
+ usleep (10 * 1000 );
86
+ auto end = read_cycle_counter ();
87
+ printf (" Slept for %lu cycles\n " , end - start);
88
+ yukon::dump_htlb (tc);
89
+ }
134
90
135
- the_runtime = new alaska::Runtime (config);
136
- void *handle_table_base = the_runtime->handle_table .get_base ();
137
- // printf("Handle table at %p\n", handle_table_base);
138
- // Make sure the handle table performs mlocks
139
- the_runtime->handle_table .enable_mlock ();
91
+ return NULL ;
92
+ }
140
93
141
- asm volatile (" fence" ::: " memory" );
142
- set_ht_addr (handle_table_base);
143
94
144
- struct sigaction act = {0 };
145
- act.sa_sigaction = segv_handler;
146
- act.sa_flags = SA_SIGINFO;
147
- sigaction (SIGSEGV, &act, NULL );
148
95
149
96
150
- // signal(SIGABRT, handle_sig);
151
- // signal(SIGSEGV, handle_sig);
152
- // signal(SIGBUS, handle_sig);
153
- // signal(SIGILL, handle_sig);
154
- }
97
+ namespace yukon {
98
+ void set_handle_table_base (void *addr) {
99
+ alaska::printf (" set htbase to %p\n " , addr);
100
+ uint64_t value = (uint64_t )addr;
101
+ if (value != 0 and getenv (" YUKON_PHYS" ) != nullptr ) {
102
+ value |= (1LU << 63 );
103
+ }
104
+ write_csr (CSR_HTBASE, value);
105
+ }
155
106
156
107
157
108
158
109
159
- static alaska::ThreadCache *get_tc () {
160
- if (the_runtime == NULL ) init ();
161
- if (tc == NULL ) tc = the_runtime->new_threadcache ();
162
- return tc;
163
- }
110
+ void dump_htlb (alaska::ThreadCache *tc) {
111
+ auto size = 576 ;
112
+ auto *space = tc->localizer .get_hotness_buffer (size);
113
+ memset (space, 0 , size * sizeof (alaska::handle_id_t ));
114
+
115
+ asm volatile (" fence" ::: " memory" );
116
+
117
+ auto start = read_cycle_counter ();
118
+ write_csr (CSR_HTDUMP, (uint64_t )space);
119
+ wait_for_csr_zero (CSR_HTDUMP);
120
+ auto end = read_cycle_counter ();
121
+ asm volatile (" fence" ::: " memory" );
122
+ tc->localizer .feed_hotness_buffer (size, space);
123
+ asm volatile (" fence" ::: " memory" );
124
+ printf (" Dumping htlb took %lu cycles\n " , end - start);
125
+ }
164
126
127
+ alaska::ThreadCache *get_tc () {
128
+ if (the_runtime == NULL ) init ();
129
+ if (tc == NULL ) tc = the_runtime->new_threadcache ();
130
+ return tc;
131
+ }
165
132
166
- static void dump_htlb () {
167
- auto tc = get_tc ();
168
- auto size = 576 ;
169
- auto *space = tc->localizer .get_hotness_buffer (size);
170
- memset (space, 0 , size * sizeof (alaska::handle_id_t ));
171
133
172
- asm volatile (" fence" ::: " memory" );
134
+ static char stdout_buf[BUFSIZ];
135
+ static char stderr_buf[BUFSIZ];
136
+ void init (void ) {
137
+ setvbuf (stdout, stdout_buf, _IOLBF, BUFSIZ);
138
+ setvbuf (stderr, stderr_buf, _IOLBF, BUFSIZ);
139
+
140
+ alaska::Configuration config;
141
+ // Use the "malloc" backend to operate cleanly w/ libc's malloc
142
+ config.huge_strategy = alaska::HugeAllocationStrategy::CUSTOM_MMAP_BACKED;
143
+
144
+ the_runtime = new alaska::Runtime (config);
145
+ void *handle_table_base = the_runtime->handle_table .get_base ();
146
+ // printf("Handle table at %p\n", handle_table_base);
147
+ // Make sure the handle table performs mlocks
148
+ the_runtime->handle_table .enable_mlock ();
149
+
150
+ asm volatile (" fence" ::: " memory" );
151
+ yukon::set_handle_table_base (handle_table_base);
152
+
153
+ struct sigaction act = {0 };
154
+ act.sa_sigaction = segv_handler;
155
+ act.sa_flags = SA_SIGINFO;
156
+ sigaction (SIGSEGV, &act, NULL );
157
+
158
+ pthread_create (&yukon_dump_daemon_thread, NULL , yukon_dump_daemon, NULL );
159
+ }
160
+ } // namespace yukon
173
161
174
- write_csr (0xc3 , (uint64_t )space);
175
- wait_for_csr_zero ();
176
- asm volatile (" fence" ::: " memory" );
177
- tc->localizer .feed_hotness_buffer (size, space);
178
- asm volatile (" fence" ::: " memory" );
179
- }
180
162
181
163
182
164
void __attribute__ ((constructor(102 ))) alaska_init(void ) {
183
165
unsetenv (" LD_PRELOAD" ); // make it so we don't run alaska in subprocesses!
184
- get_tc ();
166
+ yukon:: get_tc ();
185
167
186
168
atexit ([]() {
187
169
printf (" Setting ht addr to zero!\n " );
188
- set_ht_addr ( 0 );
170
+ yukon::set_handle_table_base ( NULL );
189
171
printf (" set!\n " );
190
172
});
191
173
}
@@ -195,32 +177,22 @@ void __attribute__((destructor)) alaska_deinit(void) {}
195
177
static void *_halloc (size_t sz, int zero) {
196
178
// HACK: make it so we *always* zero the data to avoid pagefaults
197
179
// *this is slow*
198
- zero = 1 ;
180
+ // zero = 1;
199
181
void *result = NULL ;
200
182
201
- result = get_tc ()->halloc (sz, zero);
183
+ result = yukon:: get_tc ()->halloc (sz, zero);
202
184
auto m = (uintptr_t )alaska::Mapping::translate (result);
203
185
if (result == NULL ) errno = ENOMEM;
204
186
205
- // dump_htlb();
206
-
207
-
208
187
return result;
209
188
}
210
189
211
-
212
- // #define halloc malloc
213
- // #define hcalloc calloc
214
- // #define hrealloc realloc
215
- // #define hfree free
216
-
217
190
extern " C" void *halloc (size_t sz) noexcept { return _halloc (sz, 0 ); }
218
-
219
191
extern " C" void *hcalloc (size_t nmemb, size_t size) { return _halloc (nmemb * size, 1 ); }
220
192
221
193
// Reallocate a handle
222
194
extern " C" void *hrealloc (void *handle, size_t new_size) {
223
- auto *tc = get_tc ();
195
+ auto *tc = yukon:: get_tc ();
224
196
225
197
// If the handle is null, then this call is equivalent to malloc(size)
226
198
if (handle == NULL ) {
@@ -251,13 +223,11 @@ extern "C" void *hrealloc(void *handle, size_t new_size) {
251
223
extern " C" void hfree (void *ptr) {
252
224
// no-op if NULL is passed
253
225
if (unlikely (ptr == NULL )) return ;
254
-
255
- // Simply ask the thread cache to free it!
256
- get_tc ()->hfree (ptr);
226
+ yukon::get_tc ()->hfree (ptr);
257
227
}
258
228
259
229
260
- extern " C" size_t halloc_usable_size (void *ptr) { return get_tc ()->get_size (ptr); }
230
+ extern " C" size_t halloc_usable_size (void *ptr) { return yukon:: get_tc ()->get_size (ptr); }
261
231
262
232
263
233
0 commit comments