#ifndef SYS_H #define SYS_H struct snc_counter; /* ========================== * * Wait * ========================== */ /* Futex-like wait & wake */ void sys_wait(void *addr, void *cmp, u32 size, i64 timeout_ns); void sys_wake(void *addr, i32 count); /* ========================== * * Fiber * ========================== */ #define SYS_MAX_FIBERS 4096 i16 sys_current_fiber_id(void); /* ========================== * * Job * ========================== */ /* Work pools contain their own worker threads with their own thread priority/affinity based on the intended context of the pool. */ enum sys_pool { SYS_POOL_INHERIT = -1, /* The floating pool contains a large number of lower priority threads that have affinity over the entire CPU. * Other pools should push jobs that only block and do no work here so that they can yield on the blocking job rather than blocking themselves. */ SYS_POOL_FLOATING = 0, SYS_POOL_BACKGROUND = 1, SYS_POOL_AUDIO = 2, SYS_POOL_USER = 3, SYS_POOL_SIM = 4, NUM_SYS_POOLS }; /* Job execution order within a pool is based on priority. */ enum sys_priority { SYS_PRIORITY_INHERIT = -1, SYS_PRIORITY_HIGH = 0, SYS_PRIORITY_NORMAL = 1, SYS_PRIORITY_LOW = 2, NUM_SYS_PRIORITIES }; struct sys_job_data { i32 id; void *sig; }; #define SYS_JOB_DEF(job_name, arg_name) void job_name(struct sys_job_data arg_name) typedef SYS_JOB_DEF(sys_job_func, job_data); void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_pool pool_kind, enum sys_priority priority, struct snc_counter *counter); /* ========================== * * Scratch context * ========================== */ #define SYS_SCRATCH_ARENAS_PER_CTX 2 struct sys_scratch_ctx { struct arena *arenas[SYS_SCRATCH_ARENAS_PER_CTX]; }; struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i16 fiber_id); /* ========================== * * Memory * ========================== */ /* Reserve a continuous block of virtual address space. Shouldn't be * read / written to until memory is committed. * NOTE: Guaranteed to be 16 byte aligned. */ void *sys_memory_reserve(u64 size); /* Release a continuous block of virtual address space. Before releasing, * decommit any committed memory within the reserved space to be safe. */ void sys_memory_release(void *address); /* Commit a region of reserved address space to make it readable / writable */ void *sys_memory_commit(void *address, u64 size); /* Decommit a region of committed memory (does not release the reserved * address space) */ void sys_memory_decommit(void *address, u64 size); /* Mark committed pages as readonly */ void sys_memory_set_committed_readonly(void *address, u64 size); /* Mark committed pages as readable & writeable (default for committed memory) */ void sys_memory_set_committed_readwrite(void *address, u64 size); /* ========================== * * Time * ========================== */ struct sys_datetime { u32 year; u32 month; u32 day_of_week; u32 day; u32 hour; u32 minute; u32 second; u32 milliseconds; }; struct sys_datetime sys_local_time(void); i64 sys_time_ns(void); /* ========================== * * File system * * NOTE: File paths use forward slash '/' as delimiter * ========================== */ struct sys_file { u64 handle; b32 valid; }; struct sys_file_time { struct sys_datetime created; struct sys_datetime accessed; struct sys_datetime modified; }; struct string sys_get_write_path(struct arena *arena); b32 sys_is_file(struct string path); b32 sys_is_dir(struct string path); void sys_mkdir(struct string path); struct sys_file sys_file_open_read(struct string path); struct sys_file sys_file_open_read_wait(struct string path); /* Waits until file is not being used by another program */ struct sys_file sys_file_open_write(struct string path); struct sys_file sys_file_open_append(struct string path); void sys_file_close(struct sys_file file); struct string sys_file_read_all(struct arena *arena, struct sys_file file); void sys_file_write(struct sys_file file, struct string data); u64 sys_file_get_size(struct sys_file file); struct sys_file_time sys_file_get_time(struct sys_file file); /* ========================== * * File map * ========================== */ struct sys_file_map { struct string mapped_memory; u64 handle; b32 valid; }; struct sys_file_map sys_file_map_open_read(struct sys_file file); void sys_file_map_close(struct sys_file_map map); struct string sys_file_map_data(struct sys_file_map map); /* ========================== * * Dir iter * ========================== */ struct sys_file_filter_result { struct string filename; b32 is_dir; }; struct sys_file_filter { struct sys_file_filter_result info; u64 handle; }; /* Iterate all files in a directory */ struct sys_file_filter sys_file_filter_begin(struct arena *arena, struct string pattern); b32 sys_file_filter_next(struct arena *arena, struct sys_file_filter *iter); void sys_file_filter_end(struct sys_file_filter *iter); /* ========================== * * Watch * ========================== */ enum sys_watch_info_kind { SYS_WATCH_INFO_KIND_UNKNOWN, SYS_WATCH_INFO_KIND_ADDED, SYS_WATCH_INFO_KIND_REMOVED, SYS_WATCH_INFO_KIND_MODIFIED, SYS_WATCH_INFO_KIND_RENAMED_OLD, SYS_WATCH_INFO_KIND_RENAMED_NEW }; struct sys_watch_info { enum sys_watch_info_kind kind; struct string name; struct sys_watch_info *next; struct sys_watch_info *prev; }; struct sys_watch_info_list { struct sys_watch_info *first; struct sys_watch_info *last; u64 count; }; struct sys_watch *sys_watch_alloc(struct string path); void sys_watch_release(struct sys_watch *dw); struct sys_watch_info_list sys_watch_read_wait(struct arena *arena, struct sys_watch *dw); void sys_watch_wake(struct sys_watch *dw); struct sys_watch_info_list sys_watch_info_copy(struct arena *arena, struct sys_watch_info_list src); /* ========================== * * Window * ========================== */ enum sys_btn { SYS_BTN_NONE, SYS_BTN_M1, SYS_BTN_M2, SYS_BTN_M3, SYS_BTN_M4, SYS_BTN_M5, SYS_BTN_MWHEELUP, SYS_BTN_MWHEELDOWN, SYS_BTN_ESC, SYS_BTN_F1, SYS_BTN_F2, SYS_BTN_F3, SYS_BTN_F4, SYS_BTN_F5, SYS_BTN_F6, SYS_BTN_F7, SYS_BTN_F8, SYS_BTN_F9, SYS_BTN_F10, SYS_BTN_F11, SYS_BTN_F12, SYS_BTN_F13, SYS_BTN_F14, SYS_BTN_F15, SYS_BTN_F16, SYS_BTN_F17, SYS_BTN_F18, SYS_BTN_F19, SYS_BTN_F20, SYS_BTN_F21, SYS_BTN_F22, SYS_BTN_F23, SYS_BTN_F24, SYS_BTN_GRAVE_ACCENT, SYS_BTN_0, SYS_BTN_1, SYS_BTN_2, SYS_BTN_3, SYS_BTN_4, SYS_BTN_5, SYS_BTN_6, SYS_BTN_7, SYS_BTN_8, SYS_BTN_9, SYS_BTN_MINUS, SYS_BTN_EQUAL, SYS_BTN_BACKSPACE, SYS_BTN_DELETE, SYS_BTN_TAB, SYS_BTN_A, SYS_BTN_B, SYS_BTN_C, SYS_BTN_D, SYS_BTN_E, SYS_BTN_F, SYS_BTN_G, SYS_BTN_H, SYS_BTN_I, SYS_BTN_J, SYS_BTN_K, SYS_BTN_L, SYS_BTN_M, SYS_BTN_N, SYS_BTN_O, SYS_BTN_P, SYS_BTN_Q, SYS_BTN_R, SYS_BTN_S, SYS_BTN_T, SYS_BTN_U, SYS_BTN_V, SYS_BTN_W, SYS_BTN_X, SYS_BTN_Y, SYS_BTN_Z, SYS_BTN_SPACE, SYS_BTN_ENTER, SYS_BTN_CTRL, SYS_BTN_SHIFT, SYS_BTN_ALT, SYS_BTN_UP, SYS_BTN_LEFT, SYS_BTN_DOWN, SYS_BTN_RIGHT, SYS_BTN_PAGE_UP, SYS_BTN_PAGE_DOWN, SYS_BTN_HOME, SYS_BTN_END, SYS_BTN_FORWARD_SLASH, SYS_BTN_PERIOD, SYS_BTN_COMMA, SYS_BTN_QUOTE, SYS_BTN_LEFT_BRACKET, SYS_BTN_RIGHT_BRACKET, SYS_BTN_INSERT, SYS_BTN_SEMICOLON, SYS_BTN_COUNT }; enum sys_window_event_kind { SYS_EVENT_KIND_NONE, SYS_EVENT_KIND_BUTTON_DOWN, SYS_EVENT_KIND_BUTTON_UP, SYS_EVENT_KIND_CURSOR_MOVE, SYS_EVENT_KIND_MOUSE_MOVE, SYS_EVENT_KIND_TEXT, SYS_EVENT_KIND_QUIT, SYS_EVENT_KIND_COUNT }; struct sys_window_event { enum sys_window_event_kind kind; /* SYS_EVENT_KIND_BUTTON_DOWN */ /* SYS_EVENT_KIND_BUTTON_UP */ enum sys_btn button; b32 is_repeat; /* SYS_EVENT_KIND_TEXT */ u32 text_codepoint; /* SYS_EVENT_KIND_CURSOR_MOVE */ struct v2 cursor_position; /* SYS_EVENT_KIND_MOUSE_MOVE */ struct v2 mouse_delta; }; struct sys_window_event_array { u64 count; struct sys_window_event *events; }; /* NOTE: * A window object can only be interacted with by the thread that created it. * This restriction is in place because of how Win32 works, IE you cannot * create a Win32 window in one thread and process its messages on another. */ enum sys_window_settings_flags { SYS_WINDOW_SETTINGS_FLAG_NONE = 0x00, SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN = 0x01, /* NOTE: Both maximized and minimized can be true at the same time. This * means that the window was minimized from a maximized state, and will * restore to being maximized once it's un-minimized. */ SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED = 0x02, SYS_WINDOW_SETTINGS_FLAG_MINIMIZED = 0x04 }; enum sys_window_flags { SYS_WINDOW_FLAG_NONE = 0x00, SYS_WINDOW_FLAG_SHOWING = 0x02 }; /* sys_window_update_settings should be used when altering settings values */ struct sys_window_settings { char title[256]; u32 flags; /* NOTE: Below fields are NOT representative of actual window dimensions. * These values represent the window dimensions when the window is not * maximized, minimized, or fullscreen. AKA 'floating'. Use * `sys_window_get_size` for rendering instead. */ i32 floating_x; i32 floating_y; i32 floating_width; i32 floating_height; }; struct sys_window *sys_window_alloc(void); void sys_window_release(struct sys_window *sys_window); struct sys_window_event_array sys_window_pop_events(struct arena *arena, struct sys_window *sys_window); void sys_window_update_settings(struct sys_window *sys_window, struct sys_window_settings *settings); struct sys_window_settings sys_window_get_settings(struct sys_window *sys_window); void sys_window_show(struct sys_window *sys_window); struct v2 sys_window_get_size(struct sys_window *sys_window); struct v2 sys_window_get_monitor_size(struct sys_window *sys_window); /* Returns a platform specific representation of the window. E.g. `hwnd` on win32. */ u64 sys_window_get_internal_handle(struct sys_window *sys_window); void sys_window_cursor_set_pos(struct sys_window *sys_window, struct v2 pos); void sys_window_cursor_show(struct sys_window *sys_window); void sys_window_cursor_hide(struct sys_window *sys_window); void sys_window_cursor_enable_clip(struct sys_window *sys_window, struct rect bounds); void sys_window_cursor_disable_clip(struct sys_window *sys_window); /* ========================== * * Address * ========================== */ enum sys_address_family { SYS_ADDRESS_FAMILY_IPV4, SYS_ADDRESS_FAMILY_IPV6 }; struct sys_address { b32 valid; enum sys_address_family family; /* NOTE: ipnb & portnb are stored in network byte order */ u8 ipnb[16]; u16 portnb; }; struct sys_address sys_address_from_string(struct string str); struct sys_address sys_address_from_port(u16 port); struct string sys_string_from_address(struct arena *arena, struct sys_address address); b32 sys_address_eq(struct sys_address a, struct sys_address b); /* ========================== * * Sock * ========================== */ struct sys_sock_read_result { b32 valid; /* Since data.len = 0 can be valid */ struct sys_address address; struct string data; }; struct sys_sock *sys_sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size); void sys_sock_release(struct sys_sock *sock); struct sys_sock_read_result sys_sock_read(struct arena *arena, struct sys_sock *sock); void sys_sock_write(struct sys_sock *sock, struct sys_address address, struct string data); /* ========================== * * Util * ========================== */ enum sys_message_box_kind { SYS_MESSAGE_BOX_KIND_OK, SYS_MESSAGE_BOX_KIND_WARNING, SYS_MESSAGE_BOX_KIND_ERROR, SYS_MESSAGE_BOX_KIND_FATAL }; void sys_message_box(enum sys_message_box_kind kind, struct string message); void sys_set_clipboard_text(struct string str); struct string sys_get_clipboard_text(struct arena *arena); void sys_true_rand(struct string b); u32 sys_num_logical_processors(void); u32 sys_current_thread_id(void); i64 sys_current_scheduler_period_ns(void); /* ========================== * * Exit * ========================== */ #define SYS_EXIT_FUNC(name) void name(void) typedef SYS_EXIT_FUNC(sys_exit_func); /* Registers a function to be called during graceful shutdown (in reverse order) */ void sys_on_exit(sys_exit_func *func); /* Signals the program to shut down gracefully and run exit callbacks */ void sys_exit(void); /* Forcefully exits the program and displays `msg` to the user */ void sys_panic(struct string msg); /* ========================== * * App entry point * ========================== */ /* Must be defined by app */ void sys_app_startup(struct string args_str); #endif