ogl_beamforming

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

os_unix.c (4503B)


      1 #include <dlfcn.h>
      2 #include <fcntl.h>
      3 #include <poll.h>
      4 #include <sys/mman.h>
      5 #include <sys/stat.h>
      6 #include <unistd.h>
      7 
      8 #define OS_INVALID_FILE (-1)
      9 typedef i32 os_file;
     10 typedef struct {
     11 	os_file  file;
     12 	char    *name;
     13 } os_pipe;
     14 
     15 typedef struct timespec os_filetime;
     16 
     17 typedef void *os_library_handle;
     18 
     19 #define ERROR_FILE_STATS (os_file_stats){.timestamp = (os_filetime){0}, .filesize = -1}
     20 typedef struct {
     21 	size        filesize;
     22 	os_filetime timestamp;
     23 } os_file_stats;
     24 
     25 static Arena
     26 os_alloc_arena(Arena a, size capacity)
     27 {
     28 	size pagesize = sysconf(_SC_PAGESIZE);
     29 	if (capacity % pagesize != 0)
     30 		capacity += pagesize - capacity % pagesize;
     31 
     32 	size oldsize = a.end - a.beg;
     33 	if (oldsize > capacity)
     34 		return a;
     35 
     36 	if (a.beg)
     37 		munmap(a.beg, oldsize);
     38 
     39 	a.beg = mmap(0, capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
     40 	if (a.beg == MAP_FAILED)
     41 		die("os_alloc_arena: couldn't allocate memory\n");
     42 	a.end = a.beg + capacity;
     43 	return a;
     44 }
     45 
     46 static s8
     47 os_read_file(Arena *a, char *fname, size fsize)
     48 {
     49 	i32 fd = open(fname, O_RDONLY);
     50 	if (fd < 0)
     51 		die("os_read_file: couldn't open file: %s\n", fname);
     52 
     53 	s8 ret = s8alloc(a, fsize);
     54 
     55 	size rlen = read(fd, ret.data, ret.len);
     56 	close(fd);
     57 
     58 	if (rlen != ret.len)
     59 		die("os_read_file: couldn't read file: %s\n", fname);
     60 
     61 	return ret;
     62 }
     63 
     64 static b32
     65 os_write_file(char *fname, s8 raw)
     66 {
     67 	i32 fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0600);
     68 	if (fd < 0)
     69 		return 0;
     70 	size wlen = write(fd, raw.data, raw.len);
     71 	close(fd);
     72 	return wlen == raw.len;
     73 }
     74 
     75 static os_file_stats
     76 os_get_file_stats(char *fname)
     77 {
     78 	struct stat st;
     79 
     80 	if (stat(fname, &st) < 0) {
     81 		return ERROR_FILE_STATS;
     82 	}
     83 
     84 	return (os_file_stats){
     85 		.filesize  = st.st_size,
     86 		.timestamp = st.st_mtim,
     87 	};
     88 }
     89 
     90 static os_pipe
     91 os_open_named_pipe(char *name)
     92 {
     93 	mkfifo(name, 0660);
     94 	return (os_pipe){.file = open(name, O_RDONLY|O_NONBLOCK), .name = name};
     95 }
     96 
     97 static void
     98 os_close_named_pipe(os_pipe p)
     99 {
    100 	close(p.file);
    101 	unlink(p.name);
    102 }
    103 
    104 static b32
    105 os_poll_pipe(os_pipe p)
    106 {
    107 	struct pollfd pfd = {.fd = p.file, .events = POLLIN};
    108 	poll(&pfd, 1, 0);
    109 	return !!(pfd.revents & POLLIN);
    110 }
    111 
    112 static size
    113 os_read_pipe_data(os_pipe p, void *buf, size len)
    114 {
    115 	size r = 0, total_read = 0;
    116 	do {
    117 		if (r != -1)
    118 			total_read += r;
    119 		r = read(p.file, buf + total_read, len - total_read);
    120 	} while (r);
    121 	return total_read;
    122 }
    123 
    124 static BeamformerParametersFull *
    125 os_open_shared_memory_area(char *name)
    126 {
    127 	i32 fd = shm_open(name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
    128 	if (fd == -1)
    129 		return NULL;
    130 
    131 	if (ftruncate(fd, sizeof(BeamformerParametersFull)) == -1) {
    132 		close(fd);
    133 		return NULL;
    134 	}
    135 
    136 	BeamformerParametersFull *new;
    137 	new = mmap(NULL, sizeof(*new), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    138 	close(fd);
    139 
    140 	if (new == MAP_FAILED)
    141 		return NULL;
    142 
    143 	return new;
    144 }
    145 
    146 static void
    147 os_remove_shared_memory(char *name)
    148 {
    149 	shm_unlink(name);
    150 }
    151 
    152 /* NOTE: complete garbage because there is no standarized copyfile() in POSix */
    153 static b32
    154 os_copy_file(char *name, char *new)
    155 {
    156 	b32 result = 0;
    157 	struct stat sb;
    158 	if (stat(name, &sb) < 0)
    159 		return 0;
    160 
    161 	i32 fd_old = open(name, O_RDONLY);
    162 	i32 fd_new = open(new, O_WRONLY|O_TRUNC, sb.st_mode);
    163 
    164 	if (fd_old < 0 || fd_new < 0)
    165 		goto ret;
    166 	u8 buf[4096];
    167 	size copied = 0;
    168 	while (copied != sb.st_size) {
    169 		size r = read(fd_old, buf, ARRAY_COUNT(buf));
    170 		if (r < 0) goto ret;
    171 		size w = write(fd_new, buf, r);
    172 		if (w < 0) goto ret;
    173 		copied += w;
    174 	}
    175 	result = 1;
    176 ret:
    177 	if (fd_old != -1) close(fd_old);
    178 	if (fd_new != -1) close(fd_new);
    179 	return result;
    180 }
    181 
    182 static os_library_handle
    183 os_load_library(char *name, char *temp_name)
    184 {
    185 	if (temp_name) {
    186 		if (os_copy_file(name, temp_name))
    187 			name = temp_name;
    188 	}
    189 	os_library_handle res = dlopen(name, RTLD_NOW|RTLD_LOCAL);
    190 	if (!res)
    191 		TraceLog(LOG_WARNING, "os_load_library(%s): %s\n", name, dlerror());
    192 
    193 	if (temp_name)
    194 		unlink(temp_name);
    195 
    196 	return res;
    197 }
    198 
    199 static void *
    200 os_lookup_dynamic_symbol(os_library_handle h, char *name)
    201 {
    202 	if (!h)
    203 		return 0;
    204 	void *res = dlsym(h, name);
    205 	if (!res)
    206 		TraceLog(LOG_WARNING, "os_lookup_dynamic_symbol(%s): %s\n", name, dlerror());
    207 	return res;
    208 }
    209 
    210 static void
    211 os_unload_library(os_library_handle h)
    212 {
    213 	/* NOTE: glibc is buggy gnuware so we need to check this */
    214 	if (h)
    215 		dlclose(h);
    216 }
    217 
    218 static b32
    219 os_filetime_is_newer(os_filetime a, os_filetime b)
    220 {
    221 	os_filetime result;
    222 	result.tv_sec  = a.tv_sec - b.tv_sec;
    223 	result.tv_nsec = a.tv_nsec - b.tv_nsec;
    224 	if (result.tv_nsec < 0) {
    225 		result.tv_sec--;
    226 		result.tv_nsec += 1000000000L;
    227 	}
    228 	return result.tv_sec + result.tv_nsec > 0;
    229 }