LF OS
Hobby operating system for amd64 with high ambitions
Loading...
Searching...
No Matches
tpa.c
Go to the documentation of this file.
1
19#include <tpa.h>
20#include <stdbool.h>
21#include <string.h>
22
32
47
48tpa_t* tpa_new(allocator_t* alloc, uint64_t entry_size, uint64_t page_size, tpa_t* tpa) {
49 if(!tpa) {
50 tpa = (tpa_t*)alloc->alloc(alloc, sizeof(struct tpa));
51 }
52
54 tpa->entry_size = entry_size;
55 tpa->page_size = page_size;
56 tpa->first = 0;
57
58 return tpa;
59}
60
62 struct tpa_page_header* current = tpa->first;
63 while(current) {
64 struct tpa_page_header* next = current->next;
65 tpa->allocator->dealloc(tpa->allocator, current);
66 current = next;
67 }
68
70}
71
72size_t tpa_size(tpa_t* tpa) {
73 size_t res = tpa->page_size; // for the header
74 struct tpa_page_header* current = tpa->first;
75 while(current) {
76 res += tpa->page_size;
77 current = current->next;
78 }
79
80 return res;
81}
82
84 return ((tpa->page_size - sizeof(struct tpa_page_header)) / (tpa->entry_size + 8));
85}
86
88 if(!tpa->first) return -1;
89
90 struct tpa_page_header* current = tpa->first;
91 while(current->next) {
92 current = current->next;
93 }
94
95 return current->start_idx + tpa_entries_per_page(tpa);
96}
97
99 return sizeof(struct tpa_page_header) + ((tpa->entry_size + 8) * idx);
100}
101
103 return (uint64_t*)((uint64_t)page + tpa_offset_in_page(tpa, idx));
104}
105
107 return *(tpa_get_marker(tpa, page, idx)) != 0;
108}
109
111 size_t res = 0;
112
113 struct tpa_page_header* current = tpa->first;
114 while(current) {
115 for(uint64_t i = 0; i < tpa_entries_per_page(tpa); ++i) {
116 if(tpa_entry_exists_in_page(tpa, current, i)) {
117 ++res;
118 }
119 }
120
121 current = current->next;
122 }
123
124 return res;
125}
126
128 struct tpa_page_header* current = tpa->first;
129 while(current) {
130 if(current->start_idx <= idx && current->start_idx + tpa_entries_per_page(tpa) > idx) {
131 return current;
132 }
133
134 if(current->start_idx > idx) {
135 break;
136 }
137
138 current = current->next;
139 }
140
141 return 0;
142}
143
144void* tpa_get(tpa_t* tpa, uint64_t idx) {
145 struct tpa_page_header* page = tpa_get_page_for_idx(tpa, idx);
146
147 if(page) {
148 if(tpa_entry_exists_in_page(tpa, page, idx - page->start_idx)) {
149 return (void*)((uint64_t)page + tpa_offset_in_page(tpa, idx - page->start_idx) + 8); // 8: skip marker
150 }
151 }
152
153 return 0;
154}
155
157 for(uint64_t idx = 0; idx < tpa_entries_per_page(tpa); ++idx) {
158 // if an entry is in use we cannot delete the page
159 if(tpa_entry_exists_in_page(tpa, page, idx)) {
160 return;
161 }
162 }
163
164 if(page->prev) {
165 page->prev->next = page->next;
166 }
167 else {
168 tpa->first = page->next;
169 }
170
172}
173
174void tpa_set(tpa_t* tpa, uint64_t idx, void* data) {
175 struct tpa_page_header* page = tpa_get_page_for_idx(tpa, idx);
176
177 if(!data) {
178 if(page) {
179 *(tpa_get_marker(tpa, page, idx - page->start_idx)) = 0;
180 tpa_clean_page(tpa, page);
181 return;
182 }
183 }
184 else {
185 if(!page) {
187 memset(page, 0, tpa->page_size);
189
190 struct tpa_page_header* current = tpa->first;
191 while(current && current->next && current->next->start_idx < page->start_idx) {
192 current = current->next;
193 }
194
195 if(current && current->start_idx < page->start_idx) {
196 struct tpa_page_header* next = current->next;
197 page->next = next;
198
199 current->next = page;
200 page->prev = current;
201
202 if(next) {
203 next->prev = page;
204 }
205 }
206 else {
207 if(current && current->start_idx > page->start_idx) {
208 page->next = current;
209 page->prev = current->prev;
210 current->prev = page;
211 }
212
213 tpa->first = page;
214
215 }
216 }
217
218 *(tpa_get_marker(tpa, page, idx - page->start_idx)) = 1;
219 memcpy((void*)((uint64_t)page + tpa_offset_in_page(tpa, idx - page->start_idx) + 8), data, tpa->entry_size);
220 }
221}
222
223size_t tpa_next(tpa_t* tpa, size_t cur) {
224 struct tpa_page_header* page;
225
226 // seek to first page where our next entry could be in
227 for(page = tpa->first; page && page->start_idx + tpa_entries_per_page(tpa) < cur; page = page->next) { }
228
229 while(page) {
230 for (size_t page_idx = (cur - page->start_idx); page_idx < tpa_entries_per_page(tpa); ++page_idx) {
231 if(*(tpa_get_marker(tpa, page, page_idx))) {
232 return page->start_idx + page_idx;
233 }
234 }
235
236 page = page->next;
237
238 if(page) {
239 cur = page->start_idx;
240 }
241 }
242
243 return 0;
244}
unsigned long uint64_t
Definition arch.h:14
int64_t ssize_t
Definition arch.h:19
void * memcpy(void *dest, void const *source, size_t size)
Definition string.c:80
void * memset(void *dest, int c, size_t size)
Definition string.c:72
allocator_t * alloc
void(* dealloc)(struct allocator *alloc, void *mem)
Definition allocator.h:10
void *(* alloc)(struct allocator *alloc, size_t size)
Definition allocator.h:9
tpa_t * tpa_new(allocator_t *alloc, uint64_t entry_size, uint64_t page_size, tpa_t *tpa)
Definition tpa.c:48
struct tpa_page_header * prev
Definition tpa.c:27
void tpa_delete(tpa_t *tpa)
Definition tpa.c:61
uint64_t entry_size
Size of each entry.
Definition tpa.c:39
uint64_t * tpa_get_marker(tpa_t *tpa, struct tpa_page_header *page, uint64_t idx)
Definition tpa.c:102
allocator_t * allocator
Allocator for new tpa pages.
Definition tpa.c:36
size_t tpa_size(tpa_t *tpa)
Definition tpa.c:72
uint64_t start_idx
First index in this page.
Definition tpa.c:30
struct tpa_page_header * next
Pointer to the next page.
Definition tpa.c:26
uint64_t tpa_offset_in_page(tpa_t *tpa, uint64_t idx)
Definition tpa.c:98
size_t tpa_next(tpa_t *tpa, size_t cur)
Definition tpa.c:223
bool tpa_entry_exists_in_page(tpa_t *tpa, struct tpa_page_header *page, uint64_t idx)
Definition tpa.c:106
void * tpa_get(tpa_t *tpa, uint64_t idx)
Definition tpa.c:144
ssize_t tpa_length(tpa_t *tpa)
Definition tpa.c:87
void tpa_set(tpa_t *tpa, uint64_t idx, void *data)
Definition tpa.c:174
size_t tpa_entries(tpa_t *tpa)
Definition tpa.c:110
struct tpa_page_header * first
Pointer to the first data page.
Definition tpa.c:45
uint64_t page_size
Size of each data page.
Definition tpa.c:42
size_t tpa_entries_per_page(tpa_t *tpa)
Definition tpa.c:83
void tpa_clean_page(tpa_t *tpa, struct tpa_page_header *page)
Definition tpa.c:156
struct tpa_page_header * tpa_get_page_for_idx(tpa_t *tpa, uint64_t idx)
Definition tpa.c:127
Header of a TPA.
Definition tpa.c:34
Header of a tpa page. Data follows after this until &tpa_page_header+tpa->page_size.
Definition tpa.c:24