ogl_beamforming

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

os_unix.c (6216B)


      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 <pthread.h>
     12 #include <semaphore.h>
     13 #include <sys/inotify.h>
     14 #include <sys/mman.h>
     15 #include <sys/stat.h>
     16 #include <unistd.h>
     17 
     18 #ifdef _DEBUG
     19 static void *
     20 os_get_module(char *name, Stream *e)
     21 {
     22 	void *result = dlopen(name, RTLD_NOW|RTLD_LOCAL|RTLD_NOLOAD);
     23 	if (!result && e) {
     24 		s8 errs[] = {s8("os_get_module(\""), c_str_to_s8(name), s8("\"): "),
     25 		             c_str_to_s8(dlerror()), s8("\n")};
     26 		stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
     27 	}
     28 	return result;
     29 }
     30 #endif
     31 
     32 static OS_WRITE_FILE_FN(os_write_file)
     33 {
     34 	while (raw.len) {
     35 		iz r = write(file, raw.data, raw.len);
     36 		if (r < 0) return 0;
     37 		raw = s8_cut_head(raw, r);
     38 	}
     39 	return 1;
     40 }
     41 
     42 static void __attribute__((noreturn))
     43 os_fatal(s8 msg)
     44 {
     45 	os_write_file(STDERR_FILENO, msg);
     46 	_exit(1);
     47 	unreachable();
     48 }
     49 
     50 static OS_ALLOC_ARENA_FN(os_alloc_arena)
     51 {
     52 	Arena result;
     53 	iz pagesize = sysconf(_SC_PAGESIZE);
     54 	if (capacity % pagesize != 0)
     55 		capacity += pagesize - capacity % pagesize;
     56 
     57 	iz oldsize = old.end - old.beg;
     58 	if (oldsize > capacity)
     59 		return old;
     60 
     61 	if (old.beg)
     62 		munmap(old.beg, oldsize);
     63 
     64 	result.beg = mmap(0, capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
     65 	if (result.beg == MAP_FAILED)
     66 		os_fatal(s8("os_alloc_arena: couldn't allocate memory\n"));
     67 	result.end = result.beg + capacity;
     68 	return result;
     69 }
     70 
     71 static OS_CLOSE_FN(os_close)
     72 {
     73 	close(file);
     74 }
     75 
     76 static OS_OPEN_FOR_WRITE_FN(os_open_for_write)
     77 {
     78 	iptr result = open(fname, O_WRONLY|O_TRUNC);
     79 	if (result == -1)
     80 		result = INVALID_FILE;
     81 	return result;
     82 }
     83 
     84 static OS_READ_WHOLE_FILE_FN(os_read_whole_file)
     85 {
     86 	s8 result = {0};
     87 
     88 	struct stat sb;
     89 	i32 fd = open(file, O_RDONLY);
     90 	if (fd >= 0 && fstat(fd, &sb) >= 0) {
     91 		result = s8_alloc(arena, sb.st_size);
     92 		iz rlen = read(fd, result.data, result.len);
     93 		if (rlen != result.len)
     94 			result = (s8){0};
     95 	}
     96 	if (fd >= 0) close(fd);
     97 
     98 	return result;
     99 }
    100 
    101 static OS_WRITE_NEW_FILE_FN(os_write_new_file)
    102 {
    103 	iptr fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0600);
    104 	if (fd == INVALID_FILE)
    105 		return 0;
    106 	b32 ret = os_write_file(fd, raw);
    107 	close(fd);
    108 	return ret;
    109 }
    110 
    111 static b32
    112 os_file_exists(char *path)
    113 {
    114 	struct stat st;
    115 	b32 result = stat(path, &st) == 0;
    116 	return result;
    117 }
    118 
    119 static Pipe
    120 os_open_named_pipe(char *name)
    121 {
    122 	mkfifo(name, 0660);
    123 	return (Pipe){.file = open(name, O_RDONLY|O_NONBLOCK), .name = name};
    124 }
    125 
    126 static OS_READ_FILE_FN(os_read_file)
    127 {
    128 	iz r = 0, total_read = 0;
    129 	do {
    130 		if (r != -1)
    131 			total_read += r;
    132 		r = read(file, buf + total_read, size - total_read);
    133 	} while (r);
    134 	return total_read;
    135 }
    136 
    137 static void *
    138 os_open_shared_memory_area(char *name, iz cap)
    139 {
    140 	i32 fd = shm_open(name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
    141 	if (fd == -1)
    142 		return NULL;
    143 
    144 	if (ftruncate(fd, cap) == -1) {
    145 		close(fd);
    146 		return NULL;
    147 	}
    148 
    149 	void *new = mmap(NULL, cap, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    150 	close(fd);
    151 
    152 	if (new == MAP_FAILED)
    153 		return NULL;
    154 
    155 	return new;
    156 }
    157 
    158 /* NOTE: complete garbage because there is no standarized copyfile() in POSix */
    159 static b32
    160 os_copy_file(char *name, char *new)
    161 {
    162 	b32 result = 0;
    163 	struct stat sb;
    164 	if (stat(name, &sb) < 0)
    165 		return 0;
    166 
    167 	i32 fd_old = open(name, O_RDONLY);
    168 	i32 fd_new = open(new, O_WRONLY|O_TRUNC, sb.st_mode);
    169 
    170 	if (fd_old < 0 || fd_new < 0)
    171 		goto ret;
    172 	u8 buf[4096];
    173 	iz copied = 0;
    174 	while (copied != sb.st_size) {
    175 		iz r = read(fd_old, buf, ARRAY_COUNT(buf));
    176 		if (r < 0) goto ret;
    177 		iz w = write(fd_new, buf, r);
    178 		if (w < 0) goto ret;
    179 		copied += w;
    180 	}
    181 	result = 1;
    182 ret:
    183 	if (fd_old != -1) close(fd_old);
    184 	if (fd_new != -1) close(fd_new);
    185 	return result;
    186 }
    187 
    188 static void *
    189 os_load_library(char *name, char *temp_name, Stream *e)
    190 {
    191 	if (temp_name) {
    192 		if (os_copy_file(name, temp_name))
    193 			name = temp_name;
    194 	}
    195 
    196 	void *result = dlopen(name, RTLD_NOW|RTLD_LOCAL);
    197 	if (!result && e) {
    198 		s8 errs[] = {s8("os_load_library(\""), c_str_to_s8(name), s8("\"): "),
    199 		             c_str_to_s8(dlerror()), s8("\n")};
    200 		stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
    201 	}
    202 
    203 	if (temp_name)
    204 		unlink(temp_name);
    205 
    206 	return result;
    207 }
    208 
    209 static void *
    210 os_lookup_dynamic_symbol(void *h, char *name, Stream *e)
    211 {
    212 	void *result = 0;
    213 	if (h) {
    214 		result = dlsym(h, name);
    215 		if (!result && e) {
    216 			s8 errs[] = {s8("os_lookup_dynamic_symbol(\""), c_str_to_s8(name),
    217 			             s8("\"): "), c_str_to_s8(dlerror()), s8("\n")};
    218 			stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
    219 		}
    220 	}
    221 	return result;
    222 }
    223 
    224 static void
    225 os_unload_library(void *h)
    226 {
    227 	/* NOTE: glibc is buggy gnuware so we need to check this */
    228 	if (h)
    229 		dlclose(h);
    230 }
    231 
    232 static OS_ADD_FILE_WATCH_FN(os_add_file_watch)
    233 {
    234 	s8 directory  = path;
    235 	directory.len = s8_scan_backwards(path, '/');
    236 	ASSERT(directory.len > 0);
    237 
    238 	u64 hash = s8_hash(directory);
    239 	FileWatchContext *fwctx = &os->file_watch_context;
    240 	FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash);
    241 	if (!dir) {
    242 		ASSERT(path.data[directory.len] == '/');
    243 
    244 		dir         = fwctx->directory_watches + fwctx->directory_watch_count++;
    245 		dir->hash   = hash;
    246 		dir->name   = push_s8_zero(a, directory);
    247 		i32 mask    = IN_MOVED_TO|IN_CLOSE_WRITE;
    248 		dir->handle = inotify_add_watch(fwctx->handle, (c8 *)dir->name.data, mask);
    249 	}
    250 
    251 	insert_file_watch(dir, s8_cut_head(path, dir->name.len + 1), user_data, callback);
    252 }
    253 
    254 i32 pthread_setname_np(pthread_t, char *);
    255 static iptr
    256 os_create_thread(Arena arena, iptr user_context, s8 name, os_thread_entry_point_fn *fn)
    257 {
    258 	pthread_t result;
    259 	pthread_create(&result, 0, (void *(*)(void *))fn, (void *)user_context);
    260 	pthread_setname_np(result, (char *)name.data);
    261 	return (iptr)result;
    262 }
    263 
    264 static iptr
    265 os_create_sync_object(Arena *arena)
    266 {
    267 	sem_t *result = push_struct(arena, sem_t);
    268 	sem_init(result, 0, 0);
    269 	return (iptr)result;
    270 }
    271 
    272 static void
    273 os_sleep_thread(iptr sync_handle)
    274 {
    275 	sem_wait((sem_t *)sync_handle);
    276 }
    277 
    278 static OS_WAKE_THREAD_FN(os_wake_thread)
    279 {
    280 	sem_post((sem_t *)sync_handle);
    281 }
    282 
    283 /* TODO(rnp): what do if not X11? */
    284 iptr glfwGetGLXContext(iptr);
    285 
    286 static iptr
    287 os_get_native_gl_context(iptr window)
    288 {
    289 	return glfwGetGLXContext(window);
    290 }