ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

base_linux.c (4912B)


      1 /* See LICENSE for license details. */
      2 
      3 /* NOTE(rnp): provides the platform layer for everything in this repo. */
      4 
      5 #define OS_SHARED_MEMORY_NAME  "/ogl_beamformer_shared_memory"
      6 
      7 #define OS_PATH_SEPARATOR_CHAR '/'
      8 #define OS_PATH_SEPARATOR      "/"
      9 
     10 #include "base_platform.h"
     11 
     12 #include "util.h"
     13 
     14 #include <errno.h>
     15 #include <fcntl.h>
     16 #include <linux/futex.h>
     17 #include <poll.h>
     18 #include <pthread.h>
     19 #include <sys/auxv.h>
     20 #include <sys/inotify.h>
     21 #include <sys/mman.h>
     22 #include <sys/stat.h>
     23 #include <sys/syscall.h>
     24 #include <sys/sysinfo.h>
     25 #include <unistd.h>
     26 
     27 global OSSystemInfo linux_system_info;
     28 
     29 function b32
     30 os_write_file(i32 file, void *data, i64 length)
     31 {
     32 	i64 offset = 0;
     33 	while (offset < length) {
     34 		i64 r = write(file, (u8 *)data + offset, (u64)(length - offset));
     35 		if (r < 0 && errno != EINTR) break;
     36 		if (r >= 0) offset += r;
     37 	}
     38 	return offset == length;
     39 }
     40 
     41 BASE_EXPORT no_return void
     42 os_exit(i32 code)
     43 {
     44 	_exit(code);
     45 	unreachable();
     46 }
     47 
     48 function u64
     49 os_timer_frequency(void)
     50 {
     51 	return 1000000000ULL;
     52 }
     53 
     54 BASE_EXPORT u64
     55 os_timer_count(void)
     56 {
     57 	struct timespec time = {0};
     58 	clock_gettime(CLOCK_MONOTONIC, &time);
     59 	u64 result = (u64)time.tv_sec * 1000000000ULL + (u64)time.tv_nsec;
     60 	return result;
     61 }
     62 
     63 function u64
     64 os_number_of_processors(void)
     65 {
     66 	u64 set[128 / sizeof(u64)] = {0};
     67 	syscall(SYS_sched_getaffinity, 0, sizeof(set), set);
     68 
     69 	u64 result = 0;
     70 	for EachElement(set, it)
     71 		result += popcount_u64(set[it]);
     72 	return result > 0 ? result : 1;
     73 }
     74 
     75 function void
     76 os_system_info_init(void)
     77 {
     78 	linux_system_info.timer_frequency         = os_timer_frequency();
     79 	linux_system_info.logical_processor_count = os_number_of_processors();
     80 	linux_system_info.page_size               = ARCH_X64? KB(4) : getauxval(AT_PAGESZ);
     81 	linux_system_info.path_separator_byte     = '/';
     82 }
     83 
     84 BASE_EXPORT OSSystemInfo *
     85 os_system_info(void)
     86 {
     87 	#if BASE_PLATFORM_NO_MAIN
     88 	if unlikely(linux_system_info.path_separator_byte == 0)
     89 		os_system_info_init();
     90 	#endif
     91 	return &linux_system_info;
     92 }
     93 
     94 BASE_EXPORT void *
     95 os_memory_reserve(u64 size)
     96 {
     97 	void *result = mmap(0, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
     98 	if (result == MAP_FAILED)
     99 		result = 0;
    100 	return result;
    101 }
    102 
    103 BASE_EXPORT void
    104 os_memory_release(void *base, u64 size)
    105 {
    106 	munmap(base, size);
    107 }
    108 
    109 BASE_EXPORT b32
    110 os_memory_commit(void *base, u64 size)
    111 {
    112 	mprotect(base, size, PROT_READ|PROT_WRITE);
    113 	return 1;
    114 }
    115 
    116 BASE_EXPORT void
    117 os_memory_uncommit(void *base, u64 size)
    118 {
    119 	madvise(base, size, MADV_DONTNEED);
    120 	mprotect(base, size, PROT_NONE);
    121 }
    122 
    123 BASE_EXPORT void
    124 os_memory_seal(void *base, u64 size)
    125 {
    126 	mprotect(base, size, PROT_READ);
    127 }
    128 
    129 BASE_EXPORT str8
    130 os_read_entire_file(Arena *arena, const char *file)
    131 {
    132 	str8 result = {0};
    133 	struct stat sb;
    134 	i32 fd = open(file, O_RDONLY);
    135 	if (fd >= 0 && fstat(fd, &sb) >= 0) {
    136 		result.data = push_array(arena, u8, sb.st_size);
    137 		do {
    138 			i64 rlen = read(fd, result.data + result.length, (u64)(sb.st_size - result.length));
    139 			if (rlen > 0) result.length += rlen;
    140 		} while (result.length != sb.st_size && errno != EINTR);
    141 		if (result.length != sb.st_size) {
    142 			arena_pop(arena, sb.st_size);
    143 			zero_struct(&result);
    144 		}
    145 	}
    146 	if (fd >= 0) close(fd);
    147 
    148 	return result;
    149 }
    150 
    151 function b32
    152 os_write_new_file(char *fname, str8 raw)
    153 {
    154 	b32 result = 0;
    155 	i32 fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0600);
    156 	if (fd != INVALID_FILE) {
    157 		result = os_write_file(fd, raw.data, raw.length);
    158 		close(fd);
    159 	}
    160 	return result;
    161 }
    162 
    163 function b32
    164 os_file_exists(char *path)
    165 {
    166 	struct stat st;
    167 	b32 result = stat(path, &st) == 0;
    168 	return result;
    169 }
    170 
    171 /* NOTE: complete garbage because there is no standarized copyfile() in POSix */
    172 function b32
    173 os_copy_file(char *name, char *new)
    174 {
    175 	b32 result = 0;
    176 	struct stat sb;
    177 	if (stat(name, &sb) == 0) {
    178 		i32 fd_old = open(name, O_RDONLY);
    179 		i32 fd_new = open(new,  O_WRONLY|O_CREAT, sb.st_mode);
    180 		if (fd_old >= 0 && fd_new >= 0) {
    181 			u8 buf[4096];
    182 			i64 copied = 0;
    183 			while (copied != sb.st_size) {
    184 				i64 r = read(fd_old, buf, countof(buf));
    185 				if (r < 0) break;
    186 				i64 w = write(fd_new, buf, (u64)r);
    187 				if (w < 0) break;
    188 				copied += w;
    189 			}
    190 			result = copied == sb.st_size;
    191 		}
    192 		if (fd_old != -1) close(fd_old);
    193 		if (fd_new != -1) close(fd_new);
    194 	}
    195 	return result;
    196 }
    197 
    198 BASE_EXPORT b32
    199 os_wait_on_address(i32 *value, i32 current, u32 timeout_ms)
    200 {
    201 	struct timespec *timeout = 0, timeout_value;
    202 	if (timeout_ms != (u32)-1) {
    203 		timeout_value.tv_sec  = timeout_ms / 1000;
    204 		timeout_value.tv_nsec = (timeout_ms % 1000) * 1000000;
    205 		timeout = &timeout_value;
    206 	}
    207 	return syscall(SYS_futex, value, FUTEX_WAIT, current, timeout, 0, 0) == 0;
    208 }
    209 
    210 BASE_EXPORT void
    211 os_wake_all_waiters(i32 *sync)
    212 {
    213 	if (sync) {
    214 		atomic_store_u32(sync, 0);
    215 		syscall(SYS_futex, sync, FUTEX_WAKE, I32_MAX, 0, 0, 0);
    216 	}
    217 }
    218 
    219 #if !BASE_PLATFORM_NO_MAIN
    220 BASE_IMPORT void entry_point(i32 argc, char *argv[]);
    221 
    222 extern i32
    223 main(i32 argc, char *argv[])
    224 {
    225 	os_system_info_init();
    226 
    227 	entry_point(argc, argv);
    228 
    229 	return 0;
    230 }
    231 #endif