Skip to content

Commit 1514a07

Browse files
committedSep 10, 2024··
runtime: integrate an optional "sim" api for simulating htlb
1 parent b6c03e3 commit 1514a07

12 files changed

+181
-60
lines changed
 

‎runtime/core/LocalityPage.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ namespace alaska {
3636

3737
log_trace("setting md to %p", &m);
3838
md->mapping = const_cast<alaska::Mapping *>(&m);
39+
md->size = size;
40+
md->allocated = true;
3941
log_trace("set md!");
4042

4143
return data;
@@ -46,6 +48,8 @@ namespace alaska {
4648
// Don't do anything other than
4749
auto md = find_md(ptr);
4850
md->mapping = nullptr;
51+
md->data_raw = ptr;
52+
md->allocated = false;
4953
return true;
5054
}
5155

@@ -84,8 +88,8 @@ namespace alaska {
8488

8589

8690
size_t LocalityPage::size_of(void *data) {
87-
abort();
88-
return 0;
91+
auto md = find_md(data);
92+
return md->size;
8993
}
9094

9195
} // namespace alaska

‎runtime/core/Runtime.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
#include "alaska/alaska.hpp"
1717
#include "alaska/utils.h"
1818
#include <stdlib.h>
19+
#include <alaska/utils.h>
1920

2021
namespace alaska {
2122
// The default instance of a barrier manager.
2223
static BarrierManager global_nop_barrier_manager;
2324
// The current global instance of the runtime, since we can only have one at a time
2425
static Runtime *g_runtime = nullptr;
26+
static volatile bool runtime_initialized = false;
2527

2628

2729
Runtime::Runtime() {
@@ -33,6 +35,7 @@ namespace alaska {
3335
this->barrier_manager = &global_nop_barrier_manager;
3436

3537
log_debug("Created a new Alaska Runtime @ %p", this);
38+
atomic_set(runtime_initialized, true);
3639
}
3740

3841
Runtime::~Runtime() {
@@ -73,4 +76,17 @@ namespace alaska {
7376
}
7477

7578

79+
void wait_for_initialization(void) {
80+
printf("waiting for initialization!\n");
81+
while (not is_initialized()) {
82+
sched_yield();
83+
}
84+
printf("Initialized!\n");
85+
}
86+
87+
88+
bool is_initialized(void) {
89+
return atomic_get(runtime_initialized);
90+
}
91+
7692
} // namespace alaska

‎runtime/core/ThreadCache.cpp

+41-22
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,12 @@ namespace alaska {
7676

7777
// And set the owner
7878
heap->set_owner(this);
79-
log_info("ThreadCache::halloc got new heap: %p. Avail = %lu", heap, heap->available());
8079

8180
// Swap the heaps in the thread cache
8281
if (size_classes[cls] != nullptr) runtime.heap.put_page(size_classes[cls]);
8382
size_classes[cls] = heap;
8483

8584
ALASKA_ASSERT(heap->available() > 0, "New heap must have space");
86-
log_info("new heaps avail = %lu", heap->available());
8785
return heap;
8886
}
8987

@@ -97,7 +95,6 @@ namespace alaska {
9795
this->locality_page = lp;
9896

9997
ALASKA_ASSERT(lp->available() > 0, "New heap must have space");
100-
log_info("new heaps avail = %lu", heap->available());
10198
return lp;
10299
}
103100

@@ -240,43 +237,65 @@ namespace alaska {
240237
}
241238

242239

243-
244240
bool ThreadCache::localize(void *handle, uint64_t epoch) {
245241
alaska::Mapping *m = alaska::Mapping::from_handle_safe(handle);
246-
if (unlikely(m == nullptr)) return false;
242+
if (unlikely(m == nullptr)) {
243+
printf("%p No because not handle\n", handle);
244+
return false;
245+
}
247246

247+
return localize(*m, epoch);
248+
}
248249

249-
void *ptr = m->get_pointer();
250+
251+
bool ThreadCache::localize(alaska::Mapping &m, uint64_t epoch) {
252+
if (m.is_pinned() or m.is_free()) {
253+
return false;
254+
}
255+
void *ptr = m.get_pointer();
250256
auto *source_page = this->runtime.heap.pt.get_unaligned(ptr);
251257
// if there wasn't a page for some reason, we can't localize.
252-
if (unlikely(source_page == nullptr)) return false;
258+
if (unlikely(source_page == nullptr)) {
259+
// printf("no because no page for %p\n", (void*)m.encode());
260+
return false;
261+
}
253262
// if the page has recently been localized into, don't try again
254-
if (unlikely(!source_page->should_localize_from(epoch))) return false;
255-
263+
if (unlikely(!source_page->should_localize_from(epoch))) {
264+
// printf("no because shouldnt localize\n");
265+
return false;
266+
}
256267

257-
auto size = source_page->size_of(ptr);
258-
if (locality_page == nullptr || locality_page->available() < size * 2) {
259-
locality_page = new_locality_page(size);
268+
auto size = source_page->size_of(ptr);
269+
if (locality_page == nullptr or locality_page->available() < size * 2) {
270+
locality_page = new_locality_page(size + 32);
260271
}
261272

262273
// If we are moving an object within the locality page, don't.
263274
if (unlikely(source_page == locality_page)) return false;
264275

276+
// void *dst = NULL;
265277

266-
void *d = locality_page->alloc(*m, size);
278+
// while (dst == NULL) {
279+
// dst = locality_page->alloc(m, size);
280+
// if (dst == nullptr) locality_page = new_locality_page(size);
281+
// }
282+
283+
void *d = locality_page->alloc(m, size);
267284
locality_page->last_localization_epoch = epoch;
268285
memcpy(d, ptr, size);
286+
memset(ptr, 0xFA, size);
269287

270288
// TODO: invalidate!
271-
m->set_pointer(d);
272-
273-
if (source_page->is_owned_by(this)) {
274-
log_trace("Free handle %p locally (ptr = %p)", &m, ptr);
275-
source_page->release_local(*m, ptr);
276-
} else {
277-
log_trace("Free handle %p remotely (ptr = %p)", &m, ptr);
278-
source_page->release_remote(*m, ptr);
279-
}
289+
m.set_pointer(d);
290+
291+
// if (source_page->is_owned_by(this)) {
292+
// log_trace("Free handle %p locally (ptr = %p)", &m, ptr);
293+
// source_page->release_local(m, ptr);
294+
// } else {
295+
// log_trace("Free handle %p remotely (ptr = %p)", &m, ptr);
296+
// source_page->release_remote(m, ptr);
297+
// }
298+
source_page->release_remote(m, ptr);
280299

281300
return true;
282301
}

‎runtime/include/alaska/Heap.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ namespace alaska {
152152
// Dump the state of the global heap to some file stream.
153153
void dump(FILE *stream);
154154

155+
long jumble();
156+
155157
private:
156158
template <typename T, typename Fn>
157159
T *find_or_alloc_page(
@@ -197,7 +199,6 @@ namespace alaska {
197199

198200
// Allocate a new sized page
199201
void *memory = this->pm.alloc_page();
200-
log_trace("Heap::get(%zu) :: allocating new SizedPage to manage %p", size, memory);
201202
T *p = new T(memory);
202203
// Map it in the page table for fast lookup
203204
pt.set(memory, p);

‎runtime/include/alaska/LocalityPage.hpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,17 @@ namespace alaska {
2828
class LocalityPage final : public alaska::HeapPage {
2929
public:
3030
struct Metadata {
31-
alaska::Mapping *mapping;
31+
union {
32+
alaska::Mapping *mapping;
33+
void *data_raw;
34+
};
35+
bool allocated;
36+
uint32_t size;
37+
38+
void *get_data(void) const {
39+
if (not allocated) return data_raw;
40+
return mapping->get_pointer();
41+
}
3242
};
3343

3444
LocalityPage(void *backing_memory)
@@ -43,9 +53,10 @@ namespace alaska {
4353
void *alloc(const alaska::Mapping &m, alaska::AlignedSize size) override;
4454
bool release_local(const alaska::Mapping &m, void *ptr) override;
4555
size_t size_of(void *) override;
46-
inline size_t available() const { return get_free_space(); }
56+
inline size_t available() const { return get_free_space() - sizeof(Metadata); }
4757

4858
bool should_localize_from(uint64_t current_epoch) const override {
59+
return false;
4960
return current_epoch - last_localization_epoch > localization_epoch_hysteresis;
5061
}
5162

@@ -56,12 +67,10 @@ namespace alaska {
5667
return (Metadata *)((uintptr_t)data + page_size) - (offset + 1);
5768
}
5869

59-
inline void *get_ptr(uint32_t index) { return get_mapping(index)->get_pointer(); }
70+
inline void *get_ptr(uint32_t index) { return get_md(index)->get_data(); }
6071

6172
inline int num_allocated(void) { return get_md(0) - (md_bump_next); }
6273

63-
inline alaska::Mapping *get_mapping(uint32_t offset) { return get_md(offset)->mapping; }
64-
6574
inline size_t get_free_space() const { return (off_t)md_bump_next - (off_t)data_bump_next; }
6675
inline size_t used_space() const { return (off_t)data_bump_next - (off_t)data; }
6776

@@ -73,6 +82,6 @@ namespace alaska {
7382

7483
public:
7584
uint64_t last_localization_epoch = 0;
76-
uint64_t localization_epoch_hysteresis = 1;
85+
uint64_t localization_epoch_hysteresis = 10;
7786
};
7887
}; // namespace alaska

‎runtime/include/alaska/Runtime.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ namespace alaska {
6161
// These are of an arbitrary unit.
6262
uint64_t localization_epoch = 0;
6363

64+
bool in_barrier = false;
65+
6466

6567
Runtime();
6668
~Runtime();
@@ -74,12 +76,20 @@ namespace alaska {
7476
template <typename Fn>
7577
void with_barrier(Fn &&cb) {
7678
barrier_manager->begin();
79+
in_barrier = true;
7780
barrier_manager->barrier_count++;
7881
cb();
82+
in_barrier = false;
7983
barrier_manager->end();
8084
}
8185

8286
private:
8387
int next_thread_cache_id = 0;
8488
};
89+
90+
91+
// Spin until the runtime has been initialized somehow
92+
void wait_for_initialization(void);
93+
// Has the runtime been initialized?
94+
bool is_initialized(void);
8595
} // namespace alaska

‎runtime/include/alaska/ThreadCache.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace alaska {
3838
size_t get_size(void *handle);
3939

4040

41+
bool localize(alaska::Mapping &m, uint64_t epoch);
4142
bool localize(void *handle, uint64_t epoch);
4243

4344
private:

‎runtime/include/alaska/sim/StatisticsManager.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ namespace alaska::sim {
3939
class StatisticsManager {
4040
std::array<uint64_t, statistic::COUNT> stats;
4141

42+
public:
4243
float l1_tlb_hr = 0;
4344
float l2_tlb_hr = 0;
4445
float l1_htlb_hr = 0;
4546
float l2_htlb_hr = 0;
4647

47-
public:
4848
StatisticsManager(void);
4949
~StatisticsManager();
5050

‎runtime/rt/halloc.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
// TODO: don't have this be global!
2020
static __thread alaska::ThreadCache *g_tc = nullptr;
2121

22-
static auto get_tc(void) {
22+
alaska::ThreadCache *get_tc(void) {
2323
if (unlikely(g_tc == nullptr)) {
2424
g_tc = alaska::Runtime::get().new_threadcache();
2525
}

‎runtime/rt/init.cpp

+13-7
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ extern "C" void alaska_dump(void) { the_runtime->dump(stderr); }
3939

4040
static pthread_t barrier_thread;
4141
static void *barrier_thread_func(void *) {
42-
// while (1) {
43-
// usleep(250 * 1000);
44-
// alaska::barrier::begin();
45-
// printf("Barrier.\n");
46-
// alaska::barrier::end();
47-
// }
42+
return NULL;
43+
while (1) {
44+
usleep(50 * 1000);
45+
46+
alaska::Runtime::get().with_barrier([]() {
47+
long swapped = alaska::Runtime::get().heap.jumble();
48+
printf("Swapped %ld\n", swapped);
49+
});
50+
// alaska::barrier::begin();
51+
// printf("Barrier.\n");
52+
// alaska::barrier::end();
53+
}
4854

4955
return NULL;
5056
}
@@ -57,7 +63,7 @@ void __attribute__((constructor(102))) alaska_init(void) {
5763
// Attach the runtime's barrier manager
5864
the_runtime->barrier_manager = &the_barrier_manager;
5965

60-
pthread_create(&barrier_thread, NULL, barrier_thread_func, NULL);
66+
// pthread_create(&barrier_thread, NULL, barrier_thread_func, NULL);
6167
}
6268

6369
void __attribute__((destructor)) alaska_deinit(void) {

‎runtime/rt/sim.cpp

+71-18
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#include <ck/lock.h>
2+
#include <pthread.h>
23
#include <unistd.h>
34
#include <stdlib.h>
45
#include <stdint.h>
56
#include <stdio.h>
67

8+
#include <alaska/Runtime.hpp>
79
#include <alaska/sim/HTLB.hpp>
10+
#include "alaska/config.h"
11+
#include <semaphore.h>
812

913

1014
#define L1_ENTS 96
@@ -15,44 +19,93 @@
1519
#define L2_SETS 32
1620
#define TOTAL_ENTRIES (L1_WAYS * L1_SETS + L2_WAYS * L2_SETS)
1721

18-
19-
#define RATE 100'000'000
22+
#define RATE 10'000
2023

2124
static long access_count = 0;
22-
static alaska::sim::HTLB *htlb;
25+
static alaska::sim::HTLB *g_htlb = NULL;
2326
static ck::mutex htlb_lock;
27+
static thread_local volatile bool track_on_this_thread = true;
28+
29+
30+
static pthread_mutex_t dump_mutex = PTHREAD_MUTEX_INITIALIZER;
31+
static pthread_cond_t dump_cond = PTHREAD_COND_INITIALIZER;
32+
static uint64_t dump_buf[TOTAL_ENTRIES * 2];
2433

25-
static alaska::sim::HTLB &get_htlb() {
26-
if (unlikely(htlb == nullptr)) {
27-
htlb = new alaska::sim::HTLB(L1_SETS, L1_WAYS, L2_SETS, L2_WAYS);
34+
extern alaska::ThreadCache *get_tc(void);
35+
36+
static alaska::sim::HTLB &get_htlb(void) {
37+
if (g_htlb == NULL) {
38+
g_htlb = new alaska::sim::HTLB(L1_SETS, L1_WAYS, L2_SETS, L2_WAYS);
2839
}
2940

30-
return *htlb;
41+
return *g_htlb;
3142
}
3243

44+
static pthread_t sim_background_thread;
45+
static void *sim_background_thread_func(void *) {
46+
track_on_this_thread = false;
47+
48+
alaska::wait_for_initialization();
49+
50+
while (true) {
51+
pthread_mutex_lock(&dump_mutex);
52+
pthread_cond_wait(&dump_cond, &dump_mutex);
53+
54+
55+
// // Got a dump!
56+
auto &rt = alaska::Runtime::get();
57+
58+
rt.with_barrier([&]() {
59+
unsigned long moved_objects = 0;
60+
for (int i = 0; i < TOTAL_ENTRIES; i++) {
61+
if (dump_buf[i] == 0) continue;
62+
uint64_t val = dump_buf[i] << ALASKA_SIZE_BITS;
63+
if (get_tc()->localize((void *)val, rt.localization_epoch)) {
64+
moved_objects++;
65+
}
66+
}
67+
auto sm = get_htlb().get_stats();
68+
sm.compute();
69+
// sm.dump();
70+
rt.localization_epoch++;
71+
printf("Objects moved: %lu\n", moved_objects);
72+
printf("TLB Hitrates: %f%% %f%%\n", sm.l1_tlb_hr, sm.l2_tlb_hr);
73+
});
74+
pthread_mutex_unlock(&dump_mutex);
75+
}
76+
77+
78+
return NULL;
79+
}
80+
81+
static void __attribute__((constructor)) sim_init(void) {
82+
pthread_create(&sim_background_thread, NULL, sim_background_thread_func, NULL);
83+
}
84+
85+
86+
3387
void alaska_htlb_sim_track(uintptr_t maybe_handle) {
88+
if (not alaska::is_initialized()) return;
3489
ck::scoped_lock l(htlb_lock);
3590
auto m = alaska::Mapping::from_handle_safe((void *)maybe_handle);
91+
auto &htlb = get_htlb();
3692
if (m) {
37-
auto &htlb = get_htlb();
3893
htlb.access(*m);
3994
access_count++;
4095

4196
if (access_count > RATE) {
4297
access_count = 0;
4398

44-
// uint64_t *buf = (uint64_t *)calloc(TOTAL_ENTRIES, sizeof(uint64_t));
45-
// htlb.dump_entries(buf);
46-
// free(buf);
99+
// dump, and notify the movement thread!
100+
pthread_mutex_lock(&dump_mutex);
47101

48-
auto sm = htlb.get_stats();
49-
sm.compute();
50-
sm.dump();
51-
// Reset the htlb for this run
52-
htlb.reset();
102+
htlb.dump_entries(dump_buf);
103+
// htlb.reset();
104+
105+
pthread_cond_signal(&dump_cond);
106+
pthread_mutex_unlock(&dump_mutex);
53107
}
54108
} else {
55-
auto &htlb = get_htlb();
56-
htlb.access_non_handle((void*)maybe_handle);
109+
htlb.access_non_handle((void *)maybe_handle);
57110
}
58111
}

‎runtime/yukon/yukon.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void segfault_handler(int sig) {
7373

7474
for (size_t i = 0; i < size; i++) {
7575
print_hex("bt:", (uint64_t)array[i]);
76-
print_words((unsigned*)array[i], 4);
76+
print_words((unsigned *)array[i], 4);
7777
}
7878
exit(0);
7979

@@ -83,7 +83,6 @@ void segfault_handler(int sig) {
8383
// for (int i = 0; i < size; i++) {
8484
// write_int(
8585
// }
86-
8786
}
8887

8988
static void init(void) {
@@ -185,3 +184,6 @@ extern "C" void free(void *ptr) {
185184
// Simply ask the thread cache to free it!
186185
get_tc()->hfree(ptr);
187186
}
187+
188+
189+
extern "C" size_t malloc_usable_size(void *ptr) { return get_tc()->get_size(ptr); }

0 commit comments

Comments
 (0)
Please sign in to comment.