os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

alloc.om (1790B)


      1 struct page {
      2 	ptr: *byte;
      3 	fill: int;
      4 	size: int;
      5 }
      6 
      7 struct alloc {
      8 	page: *page;
      9 }
     10 
     11 func setup_alloc(c: *alloc) {
     12 	c.page = nil;
     13 }
     14 
     15 func assert_zero(b: *byte, size: int) {
     16 	var i: int;
     17 	i = 0;
     18 	loop {
     19 		if i == size {
     20 			break;
     21 		}
     22 		if b[i] {
     23 			fxxd(nil, b, size);
     24 			die("HEAP CORRUPTION");
     25 		}
     26 		i = i + 1;
     27 	}
     28 }
     29 
     30 func alloc(c: *alloc, size: int): *byte {
     31 	var page: *page;
     32 	var mret: int;
     33 	var ret: *byte;
     34 	var psize: int;
     35 
     36 	if (size < 0) {
     37 		die("invalid alloc");
     38 	}
     39 
     40 	if size == 0 {
     41 		return nil;
     42 	}
     43 
     44 	if (size >= 2048) {
     45 		size = size + 4095;
     46 		size = size & ~4095;
     47 		mret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
     48 		if (mret == -1) {
     49 			die("out of memory");
     50 		}
     51 		ret = mret as *byte;
     52 		assert_zero(ret, size);
     53 		return ret;
     54 	}
     55 
     56 	page = c.page;
     57 	if (page) {
     58 		if (size <= page.size - page.fill) {
     59 			mret = page.ptr as int + page.fill;
     60 			page.fill = page.fill + size;
     61 			ret = mret as *byte;
     62 			assert_zero(ret, size);
     63 			return ret;
     64 		}
     65 	}
     66 
     67 	psize = 64 * 1024;
     68 
     69 	mret = mmap(0, psize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
     70 	if (mret == -1) {
     71 		die("out of memory");
     72 	}
     73 
     74 	page = mret as *page;
     75 	page.ptr = (&page[1]) as *byte;
     76 	ret = page.ptr;
     77 	page.size = psize - sizeof(*page);
     78 	page.fill = size;
     79 
     80 	c.page = page;
     81 
     82 	assert_zero(ret, size);
     83 	return ret;
     84 }
     85 
     86 func free(a: *alloc, p: *byte): void {
     87 }
     88 
     89 func ensure_arr(a: *alloc, arr: **void, cap: *int, need: int, elen: int) {
     90 	var new_arr: *byte;
     91 	var new_cap: int;
     92 
     93 	need = need * elen;
     94 
     95 	new_cap = *cap;
     96 	if need < new_cap {
     97 		return;
     98 	}
     99 
    100 	loop {
    101 		if need <= new_cap {
    102 			break;
    103 		}
    104 		new_cap = new_cap * 2 + 16;
    105 	}
    106 
    107 	new_arr = alloc(a, new_cap);
    108 
    109 	if *cap {
    110 		memcpy(new_arr, (*arr) as *byte, *cap);
    111 		free(a, (*arr) as *byte);
    112 	}
    113 
    114 	*arr = new_arr as *void;
    115 	*cap = new_cap;
    116 }