ogl_beamformer_lib.c (4297B)
1 #include "ogl_beamformer_lib.h" 2 typedef struct { 3 BeamformerParameters raw; 4 enum compute_shaders compute_stages[16]; 5 u32 compute_stages_count; 6 b32 upload; 7 } BeamformerParametersFull; 8 9 #define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) 10 11 #if defined(__unix__) 12 #include <fcntl.h> 13 #include <sys/mman.h> 14 #include <sys/stat.h> 15 #include <unistd.h> 16 17 #define OS_INVALID_FILE (-1) 18 typedef i32 os_file; 19 typedef struct { 20 os_file file; 21 char *name; 22 } os_pipe; 23 #elif defined(_WIN32) 24 #include <windows.h> 25 26 #define OS_INVALID_FILE (INVALID_HANDLE_VALUE) 27 typedef HANDLE os_file; 28 typedef struct { 29 os_file file; 30 char *name; 31 } os_pipe; 32 33 #else 34 #error Unsupported Platform 35 #endif 36 37 static volatile BeamformerParametersFull *g_bp; 38 static os_pipe g_pipe = {.file = OS_INVALID_FILE}; 39 40 #if defined(__unix__) 41 static os_pipe 42 os_open_named_pipe(char *name) 43 { 44 return (os_pipe){.file = open(name, O_WRONLY), .name = name}; 45 } 46 47 static size 48 os_write_to_pipe(os_pipe p, void *data, size len) 49 { 50 size written = 0, w = 0; 51 do { 52 written += w; 53 w = write(p.file, data, len); 54 } while(written != len && w != 0); 55 return written; 56 } 57 58 static void 59 os_close_pipe(void) 60 { 61 close(g_pipe.file); 62 } 63 64 static BeamformerParametersFull * 65 os_open_shared_memory_area(char *name) 66 { 67 i32 fd = shm_open(name, O_RDWR, S_IRUSR|S_IWUSR); 68 if (fd == -1) 69 return NULL; 70 71 BeamformerParametersFull *new; 72 new = mmap(NULL, sizeof(*new), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 73 close(fd); 74 75 if (new == MAP_FAILED) 76 return NULL; 77 78 return new; 79 } 80 81 #elif defined(_WIN32) 82 83 static os_pipe 84 os_open_named_pipe(char *name) 85 { 86 HANDLE pipe = CreateFileA(name, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 87 return (os_pipe){.file = pipe, .name = name}; 88 } 89 90 static size 91 os_write_to_pipe(os_pipe p, void *data, size len) 92 { 93 DWORD bytes_written; 94 WriteFile(p.file, data, len, &bytes_written, 0); 95 return bytes_written; 96 } 97 98 static void 99 os_close_pipe(void) 100 { 101 CloseHandle(g_pipe.file); 102 } 103 104 static BeamformerParametersFull * 105 os_open_shared_memory_area(char *name) 106 { 107 HANDLE h = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, name); 108 if (h == OS_INVALID_FILE) 109 return NULL; 110 111 BeamformerParametersFull *new; 112 new = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*new)); 113 CloseHandle(h); 114 115 return new; 116 } 117 #endif 118 119 static void 120 check_shared_memory(char *name) 121 { 122 if (g_bp) 123 return; 124 g_bp = os_open_shared_memory_area(name); 125 if (g_bp == NULL) 126 mexErrMsgIdAndTxt("ogl_beamformer:shared_memory", 127 "failed to open shared memory area"); 128 } 129 130 void 131 set_beamformer_pipeline(char *shm_name, i32 *stages, i32 stages_count) 132 { 133 if (stages_count > ARRAY_COUNT(g_bp->compute_stages)) { 134 mexErrMsgIdAndTxt("ogl_beamformer:config", "maximum stage count is %u", 135 ARRAY_COUNT(g_bp->compute_stages)); 136 return; 137 } 138 139 check_shared_memory(shm_name); 140 141 for (i32 i = 0; i < stages_count; i++) { 142 switch (stages[i]) { 143 case CS_CUDA_DECODE: 144 case CS_CUDA_HILBERT: 145 case CS_DEMOD: 146 case CS_HADAMARD: 147 case CS_HERCULES: 148 case CS_MIN_MAX: 149 case CS_UFORCES: 150 g_bp->compute_stages[i] = stages[i]; 151 break; 152 default: 153 mexErrMsgIdAndTxt("ogl_beamformer:config", "invalid shader stage: %d", 154 stages[i]); 155 return; 156 } 157 } 158 159 g_bp->compute_stages_count = stages_count; 160 } 161 162 void 163 send_data(char *pipe_name, char *shm_name, i16 *data, uv2 data_dim) 164 { 165 if (g_pipe.file == OS_INVALID_FILE) { 166 g_pipe = os_open_named_pipe(pipe_name); 167 if (g_pipe.file == OS_INVALID_FILE) { 168 mexErrMsgIdAndTxt("ogl_beamformer:pipe_error", "failed to open pipe"); 169 return; 170 } 171 } 172 173 check_shared_memory(shm_name); 174 /* TODO: this probably needs a mutex around it if we want to change it here */ 175 g_bp->raw.rf_raw_dim = data_dim; 176 size data_size = data_dim.x * data_dim.y * sizeof(i16); 177 size written = os_write_to_pipe(g_pipe, data, data_size); 178 if (written != data_size) 179 mexWarnMsgIdAndTxt("ogl_beamformer:write_error", 180 "failed to write full data to pipe: wrote: %ld", written); 181 g_bp->upload = 1; 182 } 183 184 void 185 set_beamformer_parameters(char *shm_name, BeamformerParameters *new_bp) 186 { 187 check_shared_memory(shm_name); 188 189 if (!g_bp) 190 return; 191 192 u8 *src = (u8 *)new_bp, *dest = (u8 *)&g_bp->raw; 193 for (size i = 0; i < sizeof(BeamformerParameters); i++) 194 dest[i] = src[i]; 195 g_bp->upload = 1; 196 }