platform_core.c (5794B)
1 ////////////////////////////////////////////////////////////////// 2 // platform_core.c 3 4 ////////////////////////////////////////////////////////////////// 5 // Utils 6 7 RV_GLOBAL void rv_abort_msg_(const char* file, const char* func, s32 line_no, s32 exit_code, const char* message, ...) 8 { 9 10 char buf[512] = {0}; 11 va_list args; 12 va_start(args, message); 13 vsnprintf(buf, sizeof(buf), message, args); 14 va_end(args); 15 16 fprintf(stderr, "rv_abort[%d]: '%s' at %s:%d (%s)\n", exit_code, buf, file, line_no, func); 17 18 19 20 #if RV_OS_WINDOWS 21 ExitProcess(exit_code); 22 #else 23 _exit(exit_code); 24 #endif 25 } 26 27 RV_GLOBAL f64 rv_time(void) { 28 f64 res = 0; 29 30 #if RV_OS_WINDOWS 31 s64 wintime; 32 GetSystemTimeAsFileTime((FILETIME*)&wintime); 33 wintime -= 116444736000000000i64; // 1jan1601 to 1jan1970 34 res += wintime / 10000000i64; // seconds 35 res += (wintime % 10000000i64 * 100) * 1e-9; // nano-seconds 36 #else 37 struct timespec ts_now; 38 clock_gettime(CLOCK_MONOTONIC, &ts_now); 39 40 res = ts_now.tv_sec; 41 res += ts_now.tv_nsec * 1e-9; 42 #endif 43 return res; 44 } 45 46 ////////////////////////////////////////////////////////////////// 47 // Memory 48 49 RV_GLOBAL void* rv_mem_reserve(s64 size) 50 { 51 void* result = NULL; 52 #if RV_OS_WINDOWS 53 result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); 54 #else 55 result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, (off_t)0); 56 if (result == MAP_FAILED) result = 0; 57 #endif 58 return result; 59 } 60 RV_GLOBAL void* rv_mem_reserve_large(s64 size) 61 { 62 void* result = NULL; 63 #if RV_OS_WINDOWS 64 // we commit on reserve because windows 65 result = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_LARGE_PAGES, PAGE_READWRITE); 66 #else 67 result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, (off_t)0); 68 if (result == MAP_FAILED) result = 0; 69 #endif 70 return result; 71 } 72 73 RV_GLOBAL void rv_mem_commit(void* ptr, s64 size) 74 { 75 #if RV_OS_WINDOWS 76 VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE); 77 #else 78 mprotect(ptr, size, PROT_READ|PROT_WRITE); 79 #endif 80 } 81 RV_GLOBAL void rv_mem_commit_large(void* ptr, s64 size) 82 { 83 #if RV_OS_WINDOWS 84 // do nothing, already commited 85 #else 86 mprotect(ptr, size, PROT_READ|PROT_WRITE); 87 #endif 88 } 89 90 RV_GLOBAL void rv_mem_decommit(void* ptr, s64 size) 91 { 92 #if RV_OS_WINDOWS 93 VirtualFree(ptr, size, MEM_DECOMMIT); 94 #else 95 mprotect(ptr, size, PROT_NONE); 96 madvise(ptr, size, MADV_DONTNEED); 97 #endif 98 } 99 100 RV_GLOBAL void rv_mem_release(void* ptr, s64 size) 101 { 102 #if RV_OS_WINDOWS 103 VirtualFree(ptr, 0, MEM_RELEASE); 104 #else 105 munmap(ptr, size); 106 #endif 107 } 108 109 RV_GLOBAL s64 rv_mem_get_page_size(bool32 is_large) 110 { 111 s64 result = 0; 112 113 #if RV_OS_WINDOWS 114 115 if (is_large) { 116 result = GetLargePageMinimum(); 117 } else { 118 SYSTEM_INFO sysinfo = {0}; 119 GetSystemInfo(&sysinfo); 120 result = sysinfo.dwPageSiz; 121 } 122 123 #else 124 125 if (is_large) { 126 // I hate this 127 128 rv_str8 filename = S("/proc/meminfo"); 129 130 int readerr; 131 long val; 132 133 rv_temp_arena scratch = rv_scratch_begin(0, 0); 134 135 char* buffer = rv_push_array(scratch.arena, char, KB(4)); 136 FILE* f = fopen("/proc/meminfo", "rb"); 137 if (f) { 138 fread(buffer, KB(4) - 1, 1, f); 139 } 140 rv_str8 proc_meminfo = rv_str8_from_cstr(buffer); 141 142 rv_str8 tag = S("Hugepagesize:"); 143 rv_str8 found = rv_str8_skip(proc_meminfo, rv_str8_find_needle(proc_meminfo, 0, tag, 0) + tag.len); 144 145 // chop around number + byte size 146 found = rv_str8_skip_chop_whitespace(found); 147 found = rv_str8_prefix(found, rv_str8_find_needle(found, 0, S("\n"), 0)); 148 149 bool32 kb = rv_str8_find_needle(found, 0, S("kb"), rv_str8_match_flag_case_insensetive) < found.len; 150 bool32 mb = rv_str8_find_needle(found, 0, S("mb"), rv_str8_match_flag_case_insensetive) < found.len; 151 bool32 gb = rv_str8_find_needle(found, 0, S("gb"), rv_str8_match_flag_case_insensetive) < found.len; 152 153 // remove byte part 154 found = rv_str8_prefix(found, rv_str8_find_needle(found, 0, S(" "), 0)); 155 156 result = rv_s64_from_str8(found, 10); 157 if (kb) result = KB(result); 158 if (mb) result = MB(result); 159 if (gb) result = GB(result); 160 161 rv_scratch_end(scratch); 162 } else { 163 result = getpagesize(); 164 } 165 #endif 166 return result; 167 } 168 169 RV_GLOBAL void* rv_mem_set(void* mem, u8 set_byte, s64 size) 170 { 171 u8* bytes = mem; 172 for (s64 i = 0; i < size; i++) { 173 bytes[i] = set_byte; 174 } 175 return mem; 176 } 177 178 RV_GLOBAL void* rv_mem_zero(void* mem, s64 size) 179 { 180 return rv_mem_set(mem, 0, size); 181 } 182 183 RV_GLOBAL void* rv_mem_copy(void* restrict target, const void* restrict source, s64 size) 184 { 185 u8* t = target; 186 const u8* s = source; 187 for (s64 i = 0; i < size; i++) { 188 t[i] = s[i]; 189 } 190 return target; 191 } 192 193 RV_GLOBAL void* rv_mem_move(void* target, const void* source, s64 size) 194 { 195 rv_temp_arena scratch = rv_scratch_begin(0, 0); 196 197 u8* temp = rv_push_array_no_zero(scratch.arena, u8, size); 198 199 rv_mem_copy(temp, source, size); 200 rv_mem_copy(target, temp, size); 201 202 rv_scratch_end(scratch); 203 204 return target; 205 } 206 207 RV_GLOBAL bool32 rv_mem_eq(const void* a, const void* b, s64 size) 208 { 209 const u8* a_char = a; 210 const u8* b_char = b; 211 for (s64 i = 0; i < size; i++) { 212 if (a_char[i] != b_char[i]) 213 return false; 214 } 215 return true; 216 } 217 218 #if !defined(RV_NO_GLOBAL_ALLOC) 219 RV_GLOBAL void* rv_mem_global_alloc_nz_(s64 size, s64 align) { return malloc(size); } 220 RV_GLOBAL void* rv_mem_global_realloc_nz_(void* old_ptr, s64 new_size, s64 align) { return realloc(old_ptr, new_size);} 221 RV_GLOBAL void rv_mem_global_alloc_free(void* ptr, s64 size) { free(ptr); } 222 #endif