ogl_beamforming

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

os_linux.c (3871B)


      1 /* See LICENSE for license details. */
      2 
      3 /* NOTE(rnp): provides the platform layer for the beamformer. This code must
      4  * be provided by any platform the beamformer is ported to. */
      5 
      6 #define OS_SHARED_MEMORY_NAME "/ogl_beamformer_shared_memory"
      7 
      8 #define OS_PATH_SEPARATOR_CHAR '/'
      9 #define OS_PATH_SEPARATOR      "/"
     10 
     11 #include "util.h"
     12 
     13 #include <errno.h>
     14 #include <fcntl.h>
     15 #include <linux/futex.h>
     16 #include <poll.h>
     17 #include <pthread.h>
     18 #include <sys/auxv.h>
     19 #include <sys/inotify.h>
     20 #include <sys/mman.h>
     21 #include <sys/stat.h>
     22 #include <sys/syscall.h>
     23 #include <sys/sysinfo.h>
     24 #include <unistd.h>
     25 
     26 function b32
     27 os_write_file(i32 file, void *data, i64 length)
     28 {
     29 	i64 offset = 0;
     30 	while (offset < length) {
     31 		iz r = write(file, (u8 *)data + offset, length - offset);
     32 		if (r < 0 && errno != EINTR) break;
     33 		if (r >= 0) offset += r;
     34 	}
     35 	return offset == length;
     36 }
     37 
     38 function no_return void
     39 os_exit(i32 code)
     40 {
     41 	_exit(code);
     42 	unreachable();
     43 }
     44 
     45 function u64
     46 os_get_timer_frequency(void)
     47 {
     48 	return 1000000000ULL;
     49 }
     50 
     51 function u64
     52 os_get_timer_counter(void)
     53 {
     54 	struct timespec time = {0};
     55 	clock_gettime(CLOCK_MONOTONIC, &time);
     56 	u64 result = (u64)time.tv_sec * 1000000000ULL + (u64)time.tv_nsec;
     57 	return result;
     58 }
     59 
     60 function u64
     61 os_number_of_processors(void)
     62 {
     63 	u64 set[128 / sizeof(u64)] = {0};
     64 	syscall(SYS_sched_getaffinity, 0, sizeof(set), set);
     65 
     66 	u64 result = 0;
     67 	for EachElement(set, it)
     68 		result += popcount_u64(set[it]);
     69 	return result > 0 ? result : 1;
     70 }
     71 
     72 function OS_ALLOC_ARENA_FN(os_alloc_arena)
     73 {
     74 	Arena result = {0};
     75 	capacity     = round_up_to(capacity, ARCH_X64? KB(4) : getauxval(AT_PAGESZ));
     76 	void *memory = mmap(0, (uz)capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
     77 	if (memory != MAP_FAILED) {
     78 		result.beg = memory;
     79 		result.end = result.beg + capacity;
     80 		asan_poison_region(result.beg, result.end - result.beg);
     81 	}
     82 	return result;
     83 }
     84 
     85 BEAMFORMER_IMPORT OS_READ_ENTIRE_FILE_FN(os_read_entire_file)
     86 {
     87 	i64 result = 0;
     88 	struct stat sb;
     89 	i32 fd = open(file, O_RDONLY);
     90 	if (fd >= 0 && fstat(fd, &sb) >= 0) {
     91 		if (buffer_capacity >= sb.st_size) {
     92 			do {
     93 				i64 rlen = read(fd, (u8 *)buffer + result, sb.st_size - result);
     94 				if (rlen > 0) result += rlen;
     95 			} while (result != sb.st_size && errno != EINTR);
     96 			if (result != sb.st_size) result = 0;
     97 		}
     98 	}
     99 	if (fd >= 0) close(fd);
    100 
    101 	return result;
    102 }
    103 
    104 function OS_WRITE_NEW_FILE_FN(os_write_new_file)
    105 {
    106 	b32 result = 0;
    107 	i32 fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0600);
    108 	if (fd != INVALID_FILE) {
    109 		result = os_write_file(fd, raw.data, raw.len);
    110 		close(fd);
    111 	}
    112 	return result;
    113 }
    114 
    115 function b32
    116 os_file_exists(char *path)
    117 {
    118 	struct stat st;
    119 	b32 result = stat(path, &st) == 0;
    120 	return result;
    121 }
    122 
    123 /* NOTE: complete garbage because there is no standarized copyfile() in POSix */
    124 function b32
    125 os_copy_file(char *name, char *new)
    126 {
    127 	b32 result = 0;
    128 	struct stat sb;
    129 	if (stat(name, &sb) == 0) {
    130 		i32 fd_old = open(name, O_RDONLY);
    131 		i32 fd_new = open(new,  O_WRONLY|O_CREAT, sb.st_mode);
    132 		if (fd_old >= 0 && fd_new >= 0) {
    133 			u8 buf[4096];
    134 			iz copied = 0;
    135 			while (copied != sb.st_size) {
    136 				iz r = read(fd_old, buf, countof(buf));
    137 				if (r < 0) break;
    138 				iz w = write(fd_new, buf, (uz)r);
    139 				if (w < 0) break;
    140 				copied += w;
    141 			}
    142 			result = copied == sb.st_size;
    143 		}
    144 		if (fd_old != -1) close(fd_old);
    145 		if (fd_new != -1) close(fd_new);
    146 	}
    147 	return result;
    148 }
    149 
    150 BEAMFORMER_IMPORT OS_WAIT_ON_ADDRESS_FN(os_wait_on_address)
    151 {
    152 	struct timespec *timeout = 0, timeout_value;
    153 	if (timeout_ms != (u32)-1) {
    154 		timeout_value.tv_sec  = timeout_ms / 1000;
    155 		timeout_value.tv_nsec = (timeout_ms % 1000) * 1000000;
    156 		timeout = &timeout_value;
    157 	}
    158 	return syscall(SYS_futex, value, FUTEX_WAIT, current, timeout, 0, 0) == 0;
    159 }
    160 
    161 BEAMFORMER_IMPORT OS_WAKE_ALL_WAITERS_FN(os_wake_all_waiters)
    162 {
    163 	if (sync) {
    164 		atomic_store_u32(sync, 0);
    165 		syscall(SYS_futex, sync, FUTEX_WAKE, I32_MAX, 0, 0, 0);
    166 	}
    167 }