1 /* 2 * Copyright 2014-2018, Björn Ståhl 3 * License: 3-Clause BSD, see COPYING file in arcan source repository. 4 * Reference: http://arcan-fe.com 5 */ 6 7 /* 8 * This file should define the generic types (and possibly header files) needed 9 * for building / porting to a different platform. A working combination of all 10 * platform/.h defined headers are needed for system integration. 11 */ 12 #ifndef HAVE_PLATFORM_HEADER 13 #define HAVE_PLATFORM_HEADER 14 15 #include "platform_types.h" 16 #include "agp_platform.h" 17 #include "video_platform.h" 18 #include "fsrv_platform.h" 19 #include "os_platform.h" 20 #include "event_platform.h" 21 22 /* 23 * Retrieve the current time (in milliseconds or microseconds) based on some 24 * unknown system defined epoch. Invoked frequently. 25 */ 26 unsigned long long arcan_timemillis(); 27 unsigned long long arcan_timemicros(); 28 29 /* 30 * Both these functions expect [argv / envv] to be modifiable and their 31 * internal contents dynamically allocated (hence will possible replace / free 32 * existing ones due to platform specific expansion rules 33 */ 34 35 /* 36 * Updated in the conductor stage with the latest known timestamp, Checked in 37 * the platform/posix/psep_open and is used to either send SIGINT (first) then 38 * if another timeout arrives, SIGKILL. 39 * 40 * The SIGINT is used in arcan_lua.c and used to trigger wraperr, which in turn 41 * will log the event and rebuild the VM. 42 * 43 * This serves to protect against livelocks in general, but in particular for 44 * the worst sinners, lua scripts getting stuck in while- loops from bad 45 * programming, and complex interactions in the egl-dri platform. 46 */ 47 extern _Atomic uint64_t* volatile arcan_watchdog_ping; 48 #define WATCHDOG_ANR_TIMEOUT_MS 5000 49 50 /* 51 * default, probed / replaced on some systems 52 */ 53 extern int system_page_size; 54 55 /* 56 * Execute and wait- for completion for the specified target. This will shut 57 * down as much engine- locked resources as possible while still possible to 58 * revert to the state- pre exection. 59 * 60 * It returns the time spent waiting (in milliseconds) and the 61 * return-code/exit-status in exitc. 62 */ 63 struct arcan_strarr; 64 struct arcan_evctx; 65 66 unsigned long arcan_target_launch_external( 67 const char* fname, 68 struct arcan_strarr* argv, 69 struct arcan_strarr* env, 70 struct arcan_strarr* libs, 71 int* exitc 72 ); 73 74 /* 75 * Launch the specified program and bind its resources and control to the 76 * returned frameserver instance (NULL if spawn was not possible for some 77 * reason, e.g. missing binaries). 78 */ 79 struct arcan_frameserver; 80 struct arcan_frameserver* arcan_target_launch_internal( 81 const char* fname, 82 struct arcan_strarr* argv, 83 struct arcan_strarr* env, 84 struct arcan_strarr* libs 85 ); 86 87 /* 88 * Used by event and video platforms to query for configuration keys according 89 * to some implementation defined mechanism. 90 * 91 * Returns true if the key was found. If the key carried some associated value, 92 * *val (if provided) will be set to a dynamically allocated string that the 93 * caller assumes responsibility for, otherwise NULL. 94 * 95 * For keys that have multiple set values, [ind] can be walked and is assumed 96 * to be densly packed (first failed index means that there are no more values) 97 * 98 * [tag] must match the value provided by platform_config_lookup. 99 */ 100 typedef bool (*cfg_lookup_fun)( 101 const char* const key, unsigned short ind, char** val, uintptr_t tag); 102 103 /* 104 * Retrieve a pointer to a function that can be used to query for key=val string 105 * packed arguments according with shmif_arg- style packing, along with a token 106 * that the caller is expected to provide when doing lookups. If no [tag] store 107 * is provided, the returned function will be NULL. 108 */ 109 cfg_lookup_fun platform_config_lookup(uintptr_t* tag); 110 111 /* 112 * return a string (can be empty) matching the existing and allowed frameserver 113 * archetypes (a filtered version of the FRAMSESERVER_MODESTRING buildtime var. 114 * and which ones that resolve to valid and existing executables) 115 */ 116 const char* arcan_frameserver_atypes(); 117 118 /* estimated time-waster in milisecond resolution, little reason for this 119 * to be exact, but undershooting rather than overshooting is important */ 120 void arcan_timesleep(unsigned long); 121 122 /* [BLOCKING, THREAD_SAFE] 123 * Generate [sz] cryptographically secure pseudo-random bytes and store 124 * into [dst]. 125 */ 126 void arcan_random(uint8_t* dst, size_t sz); 127 128 /* 129 * A lot of frameserver/client communication is on the notion that we can 130 * push and fetch some kind of context handle between processes. The exact 131 * means and mechanics vary with operating system, but typically through a 132 * special socket or as a member of the event queue. 133 */ 134 file_handle arcan_fetchhandle(int insock, bool block); 135 bool arcan_pushhandle(int fd, int channel); 136 137 /* 138 * This is a nasty little function, but used as a safe-guard in the fork()+ 139 * exec() case ONLY. There should be no risk of syslog or other things 140 * corrupting future descriptors. On linux etc. this is implemented as an empty 141 * poll on a rlimit- full set and using that to close() 142 */ 143 void arcan_closefrom(int num); 144 145 /* 146 * Update the process title to better identify the current process 147 */ 148 void arcan_process_title(const char* new_title); 149 150 /* 151 * Don't have much need for more fine-grained data model in regards to the 152 * filesystem other than 'is it possible that this, at the moment, refers 153 * to a file (loadable resource) or a container of files? Trace calls to this 154 * function for verifying against TOCTU vulns. 155 * Depending on how the windows platform develops, we should consider moving 156 * this in hardening phase to return descriptor to dir/file instead 157 */ 158 bool arcan_isfile(const char*); 159 bool arcan_isdir(const char*); 160 161 /* 162 * implemented in <platform>/warning.c regular fprintf(stderr, style trace 163 * output logging. slated for REDESIGN/REFACTOR. 164 */ 165 void arcan_warning(const char* msg, ...); 166 void arcan_fatal(const char* msg, ...); 167 168 /* replace the thread_local logging output destination with outf. 169 * This can be null (and by default is null) in order to disable log output */ 170 void arcan_log_destination(FILE* outf, int minlevel); 171 172 /* 173 * returns a [caller-managed COPY] of a OS- specific safe (read/writeable) path 174 * to the database to use unless one has been provided at the command-line. 175 */ 176 char* platform_dbstore_path(); 177 178 /* 179 * On some platforms, this is simply a wrapper around open() - and for others 180 * there might be an intermediate process that act as a device proxy. 181 */ 182 int platform_device_open(const char* identifier, int flags); 183 184 /* 185 * special devices, typically gpu nodes and ttys, need and explicit privilege 186 * side release- action as well. The idhint is special for TTY-swap 187 */ 188 void platform_device_release(const char* identifier, int idhint); 189 190 /* 191 * detects if any new devices have appeared, and stores a copy into identifier 192 * (caller assumes ownership) that can then be used in conjunction with _open 193 * in order to get a handle to the device. 194 * 195 * -1 : discovery not possible, connection severed 196 * 0 : no new device events 197 * 1 : new input device provided in identifier 198 * 2 : display device event pending (monitor hotplug) 199 * 3 : suspend/release 200 * 4 : restore/rebuild 201 * 5 : terminate 202 */ 203 int platform_device_poll(char** identifier); 204 205 /* 206 * retrieve a handle that can be used to I/O multiplex device discovery 207 * instead of periodically calling _poll and checking the return state. 208 */ 209 int platform_device_pollfd(); 210 211 /* 212 * run before any other platform function, make sure that we are in a state 213 * where we can negotiate access to device nodes for the event and video layers 214 */ 215 void platform_device_init(); 216 217 /* 218 * Used by the conductor to determine the dominant clock to use for 219 * scheduling. The cost_us is an estimate of the overhead of a timesleep 220 * or other yield- like actions. In time.c 221 */ 222 struct platform_timing platform_hardware_clockcfg(); 223 224 /* 225 * Support function for implementing threaded platform devices. 226 * This will return a non-blocking read-end of a pipe where arcan_events 227 * can be read from. 228 * 229 * [infd] data source descriptor 230 * [block_sz] desired fixed-size event chunk (if applicable, or 0) 231 * [callback] bool (int out_fd, uint8_t* in_buf, size_t nb, void* tag) 232 * [tag] caller provided data, passed to tag 233 * 234 * If callback returns [false], the thread will be closed and resources 235 * freed. If callback is provided a NULL [in_buf] it means the [infd] has 236 * failed and the thread will terminate. 237 */ 238 int platform_producer_thread(int infd, 239 size_t block_sz, bool(*callback)(int, uint8_t*, size_t, void*), void* tag); 240 #endif 241