ogl_beamforming

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

os_unix.c (5410B)


      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 #include "util.h"
      7 
      8 #include <dlfcn.h>
      9 #include <fcntl.h>
     10 #include <poll.h>
     11 #include <sys/inotify.h>
     12 #include <sys/mman.h>
     13 #include <sys/stat.h>
     14 #include <unistd.h>
     15 
     16 static PLATFORM_WRITE_FILE_FN(os_write_file)
     17 {
     18 	while (raw.len) {
     19 		size r = write(file, raw.data, raw.len);
     20 		if (r < 0) return 0;
     21 		raw = s8_cut_head(raw, r);
     22 	}
     23 	return 1;
     24 }
     25 
     26 static void
     27 os_write_err_msg(s8 msg)
     28 {
     29 	os_write_file(STDERR_FILENO, msg);
     30 }
     31 
     32 static void __attribute__((noreturn))
     33 os_fatal(s8 msg)
     34 {
     35 	os_write_err_msg(msg);
     36 	_exit(1);
     37 	unreachable();
     38 }
     39 
     40 static PLATFORM_ALLOC_ARENA_FN(os_alloc_arena)
     41 {
     42 	Arena result;
     43 	size pagesize = sysconf(_SC_PAGESIZE);
     44 	if (capacity % pagesize != 0)
     45 		capacity += pagesize - capacity % pagesize;
     46 
     47 	size oldsize = old.end - old.beg;
     48 	if (oldsize > capacity)
     49 		return old;
     50 
     51 	if (old.beg)
     52 		munmap(old.beg, oldsize);
     53 
     54 	result.beg = mmap(0, capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
     55 	if (result.beg == MAP_FAILED)
     56 		os_fatal(s8("os_alloc_arena: couldn't allocate memory\n"));
     57 	result.end = result.beg + capacity;
     58 	return result;
     59 }
     60 
     61 static PLATFORM_CLOSE_FN(os_close)
     62 {
     63 	close(file);
     64 }
     65 
     66 static PLATFORM_OPEN_FOR_WRITE_FN(os_open_for_write)
     67 {
     68 	iptr result = open(fname, O_WRONLY|O_TRUNC);
     69 	if (result == -1)
     70 		result = INVALID_FILE;
     71 	return result;
     72 }
     73 
     74 static s8
     75 os_read_file(Arena *a, char *file, size filesize)
     76 {
     77 	s8 result = {0};
     78 
     79 	i32 fd = open(file, O_RDONLY);
     80 	if (fd >= 0) {
     81 		result = s8alloc(a, filesize);
     82 		size rlen = read(fd, result.data, result.len);
     83 		if (rlen != result.len) {
     84 			result = (s8){0};
     85 		}
     86 		close(fd);
     87 	}
     88 
     89 	return result;
     90 }
     91 
     92 static PLATFORM_WRITE_NEW_FILE_FN(os_write_new_file)
     93 {
     94 	iptr fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0600);
     95 	if (fd == INVALID_FILE)
     96 		return 0;
     97 	b32 ret = os_write_file(fd, raw);
     98 	close(fd);
     99 	return ret;
    100 }
    101 
    102 static FileStats
    103 os_get_file_stats(char *fname)
    104 {
    105 	struct stat st;
    106 
    107 	if (stat(fname, &st) < 0) {
    108 		return ERROR_FILE_STATS;
    109 	}
    110 
    111 	return (FileStats){
    112 		.filesize  = st.st_size,
    113 		.timestamp = (f64)st.st_mtim.tv_sec + (f64)st.st_mtim.tv_nsec * 1e-9,
    114 	};
    115 }
    116 
    117 static Pipe
    118 os_open_named_pipe(char *name)
    119 {
    120 	mkfifo(name, 0660);
    121 	return (Pipe){.file = open(name, O_RDONLY|O_NONBLOCK), .name = name};
    122 }
    123 
    124 static PLATFORM_READ_PIPE_FN(os_read_pipe)
    125 {
    126 	size r = 0, total_read = 0;
    127 	do {
    128 		if (r != -1)
    129 			total_read += r;
    130 		r = read(pipe, buf + total_read, len - total_read);
    131 	} while (r);
    132 	return total_read;
    133 }
    134 
    135 static void *
    136 os_open_shared_memory_area(char *name, size cap)
    137 {
    138 	i32 fd = shm_open(name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
    139 	if (fd == -1)
    140 		return NULL;
    141 
    142 	if (ftruncate(fd, cap) == -1) {
    143 		close(fd);
    144 		return NULL;
    145 	}
    146 
    147 	void *new = mmap(NULL, cap, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    148 	close(fd);
    149 
    150 	if (new == MAP_FAILED)
    151 		return NULL;
    152 
    153 	return new;
    154 }
    155 
    156 /* NOTE: complete garbage because there is no standarized copyfile() in POSix */
    157 static b32
    158 os_copy_file(char *name, char *new)
    159 {
    160 	b32 result = 0;
    161 	struct stat sb;
    162 	if (stat(name, &sb) < 0)
    163 		return 0;
    164 
    165 	i32 fd_old = open(name, O_RDONLY);
    166 	i32 fd_new = open(new, O_WRONLY|O_TRUNC, sb.st_mode);
    167 
    168 	if (fd_old < 0 || fd_new < 0)
    169 		goto ret;
    170 	u8 buf[4096];
    171 	size copied = 0;
    172 	while (copied != sb.st_size) {
    173 		size r = read(fd_old, buf, ARRAY_COUNT(buf));
    174 		if (r < 0) goto ret;
    175 		size w = write(fd_new, buf, r);
    176 		if (w < 0) goto ret;
    177 		copied += w;
    178 	}
    179 	result = 1;
    180 ret:
    181 	if (fd_old != -1) close(fd_old);
    182 	if (fd_new != -1) close(fd_new);
    183 	return result;
    184 }
    185 
    186 static void *
    187 os_load_library(char *name, char *temp_name, Stream *e)
    188 {
    189 	if (temp_name) {
    190 		if (os_copy_file(name, temp_name))
    191 			name = temp_name;
    192 	}
    193 	void *res = dlopen(name, RTLD_NOW|RTLD_LOCAL);
    194 	if (!res && e) {
    195 		s8 errs[] = {s8("WARNING: os_load_library("), cstr_to_s8(name), s8("): "),
    196 		             cstr_to_s8(dlerror()), s8("\n")};
    197 		stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
    198 		os_write_err_msg(stream_to_s8(e));
    199 		e->widx = 0;
    200 	}
    201 
    202 	if (temp_name)
    203 		unlink(temp_name);
    204 
    205 	return res;
    206 }
    207 
    208 static void *
    209 os_lookup_dynamic_symbol(void *h, char *name, Stream *e)
    210 {
    211 	if (!h)
    212 		return 0;
    213 	void *res = dlsym(h, name);
    214 	if (!res && e) {
    215 		s8 errs[] = {s8("WARNING: os_lookup_dynamic_symbol("), cstr_to_s8(name), s8("): "),
    216 		             cstr_to_s8(dlerror()), s8("\n")};
    217 		stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
    218 		os_write_err_msg(stream_to_s8(e));
    219 		e->widx = 0;
    220 	}
    221 
    222 	return res;
    223 }
    224 
    225 static void
    226 os_unload_library(void *h)
    227 {
    228 	/* NOTE: glibc is buggy gnuware so we need to check this */
    229 	if (h)
    230 		dlclose(h);
    231 }
    232 
    233 static PLATFORM_ADD_FILE_WATCH_FN(os_add_file_watch)
    234 {
    235 	s8 directory  = path;
    236 	directory.len = s8_scan_backwards(path, '/');
    237 	ASSERT(directory.len > 0);
    238 
    239 	u64 hash = s8_hash(directory);
    240 	FileWatchContext *fwctx = &platform->file_watch_context;
    241 	FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash);
    242 	if (!dir) {
    243 		ASSERT(path.data[directory.len] == '/');
    244 
    245 		dir         = fwctx->directory_watches + fwctx->directory_watch_count++;
    246 		dir->hash   = hash;
    247 
    248 		dir->name   = push_s8(a, directory);
    249 		arena_commit(a, 1);
    250 		dir->name.data[dir->name.len] = 0;
    251 
    252 		i32 mask    = IN_MOVED_TO|IN_CLOSE_WRITE;
    253 		dir->handle = inotify_add_watch(fwctx->handle, (c8 *)dir->name.data, mask);
    254 	}
    255 
    256 	insert_file_watch(dir, s8_cut_head(path, dir->name.len + 1), user_data, callback);
    257 }