-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathipa_sync.c
More file actions
129 lines (121 loc) · 4.16 KB
/
Copy pathipa_sync.c
File metadata and controls
129 lines (121 loc) · 4.16 KB
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
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include "stack.h"
#include "ipa.h"
#include "ipa_sync.h"
#include "ipa_utils.h"
#include "memmap.h"
extern size_t my_growth;
extern shared_data_t * shared;
extern header_page_t * seq_headers;
extern header_page_t * seq_headers_last;
extern volatile header_page_t * first_full;
void beginspec() {
assert(speculating()); // TODO -- probably special case this function
// void * end_ds = sbrk(0);
// printf("sbrk pre-spec 0x%p\n", end_ds);
my_growth = 0;
ipa_init();
shared->spec_base = sbrk(0);
map_missing_pages();
synch_lists();
set_large_perm(MAP_PRIVATE);
first_full = NULL;
}
void endspec(bool ppr_won) {
assert(speculating()); // TODO -- probably special case this function
if (my_growth < shared->spec_growth) {
inc_heap(shared->spec_growth - my_growth);
}
map_missing_pages();
free_delayed();
if (ppr_won) {
promote_list();
// Fix up the header lists
if (seq_headers_last != NULL) {
seq_headers_last->next_header = (volatile struct header_page_t *) shared->header_pg;
shared->header_pg = NULL;
}
first_full = NULL;
}
// Note: pages are auto unmapped by the kernel on failure
}
static inline void set_large_perm(int flags) {
volatile huge_block_t * block;
huge_block_t data = {0};
for (block = (volatile huge_block_t *) shared->large_block; block != NULL; block = (volatile huge_block_t *) block->next_block) {
if (block->is_shared) {
int fd = mmap_existing_fd(block->file_name);
data = *block;
fsync(fd);
if (!mmap((void *) block, data.huge_block_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) {
ipa_perror("Unable to reconfigure permissions.");
}
close(fd);
block->is_shared = false;
}
}
}
void synch_lists() {
size_t i;
volatile header_page_t * page;
volatile header_t * header;
// Set the heads of the stacks to the corresponding elements
for (i = 0; i < NUM_CLASSES; i++) {
if(shared->seq_free[i].head != NULL) {
shared->spec_free[i].head = (node_t *) &seq_node_to_header(shared->seq_free[i].head)->spec_next;
} else {
shared->spec_free[i].head = NULL;
}
}
// Set the stack elements
for (page = seq_headers; page != NULL; page = (header_page_t *) page->next_header) {
for (i = 0; i < MIN(HEADERS_PER_PAGE, page->next_free); i++) {
header = &page->headers[i];
if (!seq_alloced(header) && header->seq_next.next != NULL) {
volatile header_t * next_header = seq_node_to_header((node_t*) header->seq_next.next);
header->spec_next.next = (volatile struct node_t *) &next_header->spec_next;
} else {
header->spec_next.next = NULL;
}
}
}
}
// This step can (may?) be eliminated by sticking the two items in an array and swaping the index
// mapping to spec / seq free lists
// pre-spec is still needed OR 3x wide CAS operations -- 2 for the pointers
// (which need to be adjacent to each other) and another for the counter
void promote_list() {
size_t i;
volatile header_page_t * page;
volatile header_t * header;
map_missing_pages();
// Set the heads of the stacks to the corresponding elements
for (i = 0; i < NUM_CLASSES; i++) {
if(shared->spec_free[i].head != NULL) {
shared->seq_free[i].head = (node_t *) &spec_node_to_header(shared->spec_free[i].head)->seq_next;
} else {
shared->seq_free[i].head = NULL;
}
}
// Set the stack elements
for (page = shared->header_pg; page != NULL; page = (header_page_t *) page->next_header) {
for (i = 0; i < MIN(HEADERS_PER_PAGE, page->next_free); i++) {
header = &page->headers[i];
assert(payload(header) != NULL);
if (!spec_alloced(header) && header->seq_next.next != NULL) {
volatile header_t * next_header = spec_node_to_header((node_t *) header->spec_next.next);
header->seq_next.next = (volatile struct node_t *) &next_header->seq_next;
} else {
header->seq_next.next = NULL;
}
header->payload = (void *) (((intptr_t) header->payload) & ~(SEQ_ALLOC_B | SPEC_ALLOC_B));
header->allocator = 0;
}
}
}