adjusting repo for removing extra features not part of the original library

This commit is contained in:
ed
2025-02-12 13:57:45 -05:00
parent ea67e889e0
commit d569b93bbd
59 changed files with 4 additions and 202 deletions
File diff suppressed because it is too large Load Diff
+220
View File
@@ -0,0 +1,220 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "base/debug.h"
# include "base/strings.h"
# include "base/thread_context.h"
# include "os/os.h"
# include "os/linux/os_linux_includes.h"
#endif
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
int pthread_setname_np(pthread_t thread, const char* name);
int pthread_getname_np(pthread_t thread, char* name, size_t size);
typedef struct tm tm;
typedef struct timespec timespec;
////////////////////////////////
//~ rjf: File Iterator
typedef struct OS_LNX_FileIter OS_LNX_FileIter;
struct OS_LNX_FileIter
{
DIR* dir;
struct dirent* dp;
String8 path;
};
md_assert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
////////////////////////////////
//~ rjf: Safe Call Handler Chain
typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain;
struct OS_LNX_SafeCallChain
{
OS_LNX_SafeCallChain* next;
OS_ThreadFunctionType* fail_handler;
void *ptr;
};
////////////////////////////////
//~ rjf: Entities
typedef enum OS_LNX_EntityKind OS_LNX_EntityKind
enum OS_LNX_EntityKind
{
OS_LNX_EntityKind_Thread,
OS_LNX_EntityKind_Mutex,
OS_LNX_EntityKind_RWMutex,
OS_LNX_EntityKind_ConditionVariable,
};
typedef struct OS_LNX_EntityThread OS_LNX_EntityThread;
struct OS_LNX_EntityThread
{
pthread_t handle;
OS_ThreadFunctionType* func;
void* ptr;
};
typedef struct OS_LNX_Entity OS_LNX_Entity;
struct OS_LNX_Entity
{
OS_LNX_Entity* next;
OS_LNX_EntityKind kind;
union
{
OS_LNX_EntityThread thread;
pthread_mutex_t mutex_handle;
pthread_rwlock_t rwmutex_handle;
struct {
pthread_cond_t cond_handle;
pthread_mutex_t rwlock_mutex_handle;
} cv;
};
};
////////////////////////////////
//~ rjf: State
typedef struct OS_LNX_State OS_LNX_State;
struct OS_LNX_State
{
Arena* arena;
OS_SystemInfo system_info;
OS_ProcessInfo process_info;
pthread_mutex_t entity_mutex;
Arena* entity_arena;
OS_LNX_Entity* entity_free;
};
////////////////////////////////
//~ rjf: Helpers
DateTime os_lnx_date_time_from_tm (tm in, U32 msec);
tm os_lnx_tm_from_date_time (DateTime dt);
timespec os_lnx_timespec_from_date_time (DateTime dt);
DenseTime os_lnx_dense_time_from_timespec (timespec in);
FileProperties os_lnx_file_properties_from_stat(struct stat* s);
void os_lnx_safe_call_sig_handler (int x);
inline DateTime
os_lnx_date_time_from_tm(tm in, U32 msec) {
DateTime dt = {0};
dt.sec = in.tm_sec;
dt.min = in.tm_min;
dt.hour = in.tm_hour;
dt.day = in.tm_mday-1;
dt.mon = in.tm_mon;
dt.year = in.tm_year+1900;
dt.msec = msec;
return dt;
}
inline tm
os_lnx_tm_from_date_time(DateTime dt) {
tm result = {0};
result.tm_sec = dt.sec;
result.tm_min = dt.min;
result.tm_hour= dt.hour;
result.tm_mday= dt.day+1;
result.tm_mon = dt.mon;
result.tm_year= dt.year-1900;
return result;
}
inline timespec
os_lnx_timespec_from_date_time(DateTime dt) {
tm tm_val = os_lnx_tm_from_date_time(dt);
time_t seconds = timegm(&tm_val);
timespec result = {0};
result.tv_sec = seconds;
return result;
}
inline DenseTime
os_lnx_dense_time_from_timespec(timespec in) {
DenseTime result = 0; {
struct tm tm_time = {0};
gmtime_r(&in.tv_sec, &tm_time);
DateTime date_time = os_lnx_date_time_from_tm(tm_time, in.tv_nsec/Million(1));
result = dense_time_from_date_time(date_time);
}
return result;
}
inline FileProperties
os_lnx_file_properties_from_stat(struct stat* s) {
FileProperties props = {0};
props.size = s->st_size;
props.created = os_lnx_dense_time_from_timespec(s->st_ctim);
props.modified = os_lnx_dense_time_from_timespec(s->st_mtim);
if (s->st_mode & S_IFDIR) {
props.flags |= FilePropertyFlag_IsFolder;
}
return props;
}
inline void
os_lnx_safe_call_sig_handler(int x) {
OS_LNX_SafeCallChain* chain = os_lnx_safe_call_chain;
if (chain != 0 && chain->fail_handler != 0) {
chain->fail_handler(chain->ptr);
}
abort();
}
////////////////////////////////
//~ rjf: Entities
MD_API OS_LNX_Entity* os_lnx_entity_alloc (OS_LNX_EntityKind kind);
MD_API void os_lnx_entity_release(OS_LNX_Entity* entity);
////////////////////////////////
//~ rjf: Thread Entry Point
MD_API void* os_lnx_thread_entry_point(void* ptr);
////////////////////////////////
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
inline String8
os_get_current_path__ainfo(AllocatorInfo ainfo) {
char* cwdir = getcwd(0, 0);
String8 string = str8_copy(ainfo, str8_cstring(cwdir));
return string;
}
////////////////////////////////
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
//- rjf: basic
inline void* os_reserve ( U64 size) { void* result = mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); return result; }
inline B32 os_commit (void *ptr, U64 size) { mprotect(ptr, size, PROT_READ | PROT_WRITE); return 1; }
inline void os_decommit(void *ptr, U64 size) { madvise(ptr, size, MADV_DONTNEED); mprotect(ptr, size, PROT_NONE); }
inline void os_release (void *ptr, U64 size) { munmap(ptr, size); }
//- rjf: large pages
inline void* os_reserve_large( U64 size) { void* result = mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); return result; }
inline B32 os_commit_large (void *ptr, U64 size) { mprotect(ptr, size, PROT_READ | PROT_WRITE); return 1; }
////////////////////////////////
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
inline U32
os_tid(void) {
U32 result = 0;
#if defined(SYS_gettid)
result = syscall(SYS_gettid);
#else
result = gettid();
#endif
return result;
}
+25
View File
@@ -0,0 +1,25 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
#endif
////////////////////////////////
//~ rjf: Includes
#define _GNU_SOURCE
#include <features.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <time.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <signal.h>
#include <errno.h>
#include <dlfcn.h>
#include <sys/sysinfo.h>
#include <sys/random.h>
+88
View File
@@ -0,0 +1,88 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "os.h"
#endif
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
B32
os_write_data_to_file_path(String8 path, String8 data)
{
B32 good = 0;
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
if(! os_handle_match(file, os_handle_zero()))
{
good = 1;
os_file_write(file, r1u64(0, data.size), data.str);
os_file_close(file);
}
return good;
}
B32
os_write_data_list_to_file_path(String8 path, String8List list)
{
B32 good = 0;
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
if( ! os_handle_match(file, os_handle_zero()))
{
good = 1;
U64 off = 0;
for(String8Node* n = list.first; n != 0; n = n->next)
{
os_file_write(file, r1u64(off, off+n->string.size), n->string.str);
off += n->string.size;
}
os_file_close(file);
}
return good;
}
B32
os_append_data_to_file_path(String8 path, String8 data)
{
B32 good = 0;
if(data.size != 0)
{
OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path);
if( ! os_handle_match(file, os_handle_zero()))
{
good = 1;
U64 pos = os_properties_from_file(file).size;
os_file_write(file, r1u64(pos, pos+data.size), data.str);
os_file_close(file);
}
}
return good;
}
String8
os_string_from_file_range__arena(Arena* arena, OS_Handle file, Rng1U64 range)
{
U64 pre_pos = arena_pos(arena);
String8 result;
result.size = dim_1u64(range);
result.str = push_array_no_zero(arena, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if(actual_read_size < result.size) {
arena_pop_to(arena, pre_pos + actual_read_size);
result.size = actual_read_size;
}
return result;
}
String8
os_string_from_file_range__ainfo(AllocatorInfo ainfo, OS_Handle file, Rng1U64 range) {
String8 result;
result.size = dim_1u64(range);
result.str = alloc_array_no_zero(ainfo, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if ((allocator_query_support(ainfo) & AllocatorQuery_ResizeShrink) && actual_read_size < result.size) {
resize(ainfo, result.str, result.size, actual_read_size);
result.size = actual_read_size;
}
return result;
}
+471
View File
@@ -0,0 +1,471 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "base/debug.h"
# include "base/strings.h"
# include "base/thread_context.h"
# include "base/file.h"
#endif
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: System Info
typedef struct OS_SystemInfo OS_SystemInfo;
struct OS_SystemInfo
{
U32 logical_processor_count;
U64 page_size;
U64 large_page_size;
U64 allocation_granularity;
String8 machine_name;
};
////////////////////////////////
//~ rjf: Process Info
typedef struct OS_ProcessInfo OS_ProcessInfo;
struct OS_ProcessInfo
{
U32 pid;
String8 binary_path;
String8 initial_path;
String8 user_program_data_path;
String8List module_load_paths;
String8List environment;
};
////////////////////////////////
//~ rjf: Access Flags
typedef U32 OS_AccessFlags;
enum
{
OS_AccessFlag_Read = (1 << 0),
OS_AccessFlag_Write = (1 << 1),
OS_AccessFlag_Execute = (1 << 2),
OS_AccessFlag_Append = (1 << 3),
OS_AccessFlag_ShareRead = (1 << 4),
OS_AccessFlag_ShareWrite = (1 << 5),
};
////////////////////////////////
//~ rjf: Files
typedef U32 OS_FileIterFlags;
enum
{
OS_FileIterFlag_SkipFolders = (1 << 0),
OS_FileIterFlag_SkipFiles = (1 << 1),
OS_FileIterFlag_SkipHiddenFiles = (1 << 2),
OS_FileIterFlag_Done = (1 << 31),
};
typedef struct OS_FileIter OS_FileIter;
struct OS_FileIter
{
OS_FileIterFlags flags;
U8 memory[800];
};
typedef struct OS_FileInfo OS_FileInfo;
struct OS_FileInfo
{
String8 name;
FileProperties props;
};
// nick: on-disk file identifier
typedef struct OS_FileID OS_FileID;
struct OS_FileID
{
U64 v[3];
};
////////////////////////////////
//~ rjf: Process Launch Parameters
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
struct OS_ProcessLaunchParams
{
String8List cmd_line;
String8 path;
String8List env;
B32 inherit_env;
B32 consoleless;
};
////////////////////////////////
//~ rjf: Handle Type
typedef struct OS_Handle OS_Handle;
struct OS_Handle
{
U64 u64[1];
};
typedef struct OS_HandleNode OS_HandleNode;
struct OS_HandleNode
{
OS_HandleNode* next;
OS_Handle v;
};
typedef struct OS_HandleList OS_HandleList;
struct OS_HandleList
{
OS_HandleNode* first;
OS_HandleNode* last;
U64 count;
};
typedef struct OS_HandleArray OS_HandleArray;
struct OS_HandleArray
{
OS_Handle* v;
U64 count;
};
////////////////////////////////
//~ rjf: Globally Unique IDs
typedef struct OS_Guid OS_Guid;
struct OS_Guid
{
U32 data1;
U16 data2;
U16 data3;
U8 data4[8];
};
md_static_assert(size_of(OS_Guid) == 16, os_guid_check);
////////////////////////////////
//~ rjf: Thread Types
typedef void OS_ThreadFunctionType(void *ptr);
////////////////////////////////
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
force_inline OS_Handle os_handle_zero (void) { OS_Handle handle = {0}; return handle; }
force_inline B32 os_handle_match(OS_Handle a, OS_Handle b) { return a.u64[0] == b.u64[0]; }
void os_handle_list_push__arena (Arena* arena, OS_HandleList* handles, OS_Handle handle);
void os_handle_list_push__ainfo (AllocatorInfo ainfo, OS_HandleList* handles, OS_Handle handle);
OS_HandleArray os_handle_array_from_list__arena(Arena* arena, OS_HandleList* list);
OS_HandleArray os_handle_array_from_list__ainfo(AllocatorInfo ainfo, OS_HandleList* list);
#define os_handle_ist_push(arena, handles, handle) _Generic(allocator, Arena*: os_handle_list_push__arena, AllocatorInfo: os_handle_list_push__ainfo, default: assert_generic_sel_fail) generic_call(allocator, handles, handle)
#define os_handle_array_from_list(allocator, list) _Generic(allocator, Arena*: os_handle_array_from_list__arena, AllocatorInfo: os_handle_list_push__ainfo, default: assert_generic_sel_fail) generic_call(allocator, list)
force_inline void os_handle_list_push__arena (Arena* arena, OS_HandleList* handles, OS_Handle handle) { os_handle_list__push_ainfo (arena_allocator(arena), handles, handle); }
force_inline OS_HandleArray os_handle_array_from_list__arena(Arena* arena, OS_HandleList* list) { return os_handle_array_from_list__ainfo(arena_allocator(arena), list); }
inline void
os_handle_list_alloc(AllocatorInfo ainfo, OS_HandleList* handles, OS_Handle handle) {
OS_HandleNode* n = alloc_array(ainfo, OS_HandleNode, 1);
n->v = handle;
sll_queue_push(handles->first, handles->last, n);
handles->count += 1;
}
inline OS_HandleArray
os_handle_array_from_list_alloc(AllocatorInfo ainfo, OS_HandleList* list) {
OS_HandleArray result = {0};
result.count = list->count;
result.v = alloc_array_no_zero(ainfo, OS_Handle, result.count);
U64 idx = 0;
for(OS_HandleNode* n = list->first; n != 0; n = n->next, idx += 1) {
result.v[idx] = n->v;
}
return result;
}
////////////////////////////////
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
String8List os_string_list_from_argcv__arena(Arena* arena, int argc, char** argv);
String8List os_string_list_from_argcv__ainfo(AllocatorInfo ainfo, int argc, char** argv);
inline String8List
os_string_list_from_argcv__ainfo(AllocatorInfo ainfo, int argc, char** argv) {
String8List result = {0};
for(int i = 0; i < argc; i += 1)
{
String8 str = str8_cstring(argv[i]);
str8_list_push(ainfo, &result, str);
}
return result;
}
#define os_string_list_from_argcv(allocator, argc, argv) _Generic(allocator, Arena*: os_string_list_from_argcv__arena, AllocatorInfo: os_string_list_from_argcv__ainfo, default: assert_generic_sel_fail) generic_call(allocator, argc, argv)
force_inline String8List os_string_list_from_argcv__arena(Arena* arena, int argc, char** argv) { return os_string_list_from_argcv__ainfo(arena_allocator(arena), argc, argv); }
////////////////////////////////
//~ rjf: @os_hooks File System (Implemented Per-OS)
//- rjf: files
MD_API OS_Handle os_file_open (OS_AccessFlags flags, String8 path);
MD_API void os_file_close (OS_Handle file);
MD_API U64 os_file_read (OS_Handle file, Rng1U64 rng, void *out_data);
MD_API U64 os_file_write (OS_Handle file, Rng1U64 rng, void *data);
MD_API B32 os_file_set_times (OS_Handle file, DateTime time);
MD_API FileProperties os_properties_from_file (OS_Handle file);
MD_API OS_FileID os_id_from_file (OS_Handle file);
MD_API B32 os_delete_file_at_path (String8 path);
MD_API B32 os_copy_file_path (String8 dst, String8 src);
MD_API B32 os_file_path_exists (String8 path);
MD_API FileProperties os_properties_from_file_path (String8 path);
MD_API String8 os_full_path_from_path__arena(Arena* arena, String8 path);
MD_API String8 os_full_path_from_path__ainfo(AllocatorInfo arena, String8 path);
#define os_full_path_from_path(allocator, path) _Generic(allocator, Arena*: os_full_path_from_path__arena, AllocatorInfo: os_full_path_from_path__ainfo, default: assert_generic_sel_fail) generic_call(allocator, path)
force_inline String8 os_full_path_from_path__arena(Arena* arena, String8 path) { return os_full_path_from_path__ainfo(arena_allocator(arena), path); }
//- rjf: file maps
MD_API OS_Handle os_file_map_open (OS_AccessFlags flags, OS_Handle file);
MD_API void os_file_map_close (OS_Handle map);
MD_API void* os_file_map_view_open (OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
MD_API void os_file_map_view_close(OS_Handle map, void* ptr, Rng1U64 range);
//- rjf: directory iteration
OS_FileIter* os_file_iter_begin__arena(Arena* arena, String8 path, OS_FileIterFlags flags);
MD_API OS_FileIter* os_file_iter_begin__ainfo(AllocatorInfo ainfo, String8 path, OS_FileIterFlags flags);
B32 os_file_iter_next__arena (Arena* arena, OS_FileIter* iter, OS_FileInfo* info_out);
MD_API B32 os_file_iter_next__ainfo (AllocatorInfo arena, OS_FileIter* iter, OS_FileInfo* info_out);
MD_API void os_file_iter_end ( OS_FileIter* iter);
#define os_file_iter_begin(allocator, path, flags) _Generic(allocator, Arena*: os_file_iter_begin__arena, AllocatorInfo: os_file_iter_begin__ainfo, default: assert_generic_sel_fail) generic_call(allocator, path)
#define os_file_iter_next(allocator, iter, info_out) _Generic(allocator, Arena*: os_file_iter_next__arena, AllocatorInfo: os_file_iter_next__ainfo, default: assert_generic_sel_fail) generic_call(allocator, path)
force_inline OS_FileIter* os_file_iter_begin__arena(Arena* arena, String8 path, OS_FileIterFlags flags) { reutrn (); }
force_inline B32 os_file_iter_next__arena (Arena* arena, OS_FileIter* iter, OS_FileInfo* info_out) { reutrn (); }
//- rjf: directory creation
MD_API B32 os_make_directory(String8 path);
////////////////////////////////
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
MD_API B32 os_write_data_to_file_path (String8 path, String8 data);
MD_API B32 os_write_data_list_to_file_path(String8 path, String8List list);
MD_API B32 os_append_data_to_file_path (String8 path, String8 data);
OS_FileID os_id_from_file_path (String8 path);
S64 os_file_id_compare (OS_FileID a, OS_FileID b);
String8 os_data_from_file_path__arena (Arena* arena, String8 path);
String8 os_data_from_file_path__ainfo (AllocatorInfo ainfo, String8 path);
MD_API String8 os_string_from_file_range__arena(Arena* arena, OS_Handle file, Rng1U64 range);
MD_API String8 os_string_from_file_range__ainfo(AllocatorInfo ainfo, OS_Handle file, Rng1U64 range);
#define os_data_from_file_path(allocator, path) _Generic(allocator, Arena*: os_data_from_file_path__arena, AllocatorInfo: os_data_from_file_path__ainfo, default: assert_generic_sel_fail) generic_call(allocator, path)
#define os_string_from_file_range(allocator, file, range) _Generic(allocator, Arena*: os_string_from_file_range__arena, AllocatorInfo: os_string_from_file_range__ainfo, default: assert_generic_sel_fail) generic_call(allocator, file, range)
force_inline String8 os_data_from_file_path__arena(Arena* arena, String8 path) { return os_data_from_file_path__ainfo(arena_allocator(arena), path); }
inline String8
os_data_from_file_path__ainfo(AllocatorInfo ainfo, String8 path)
{
OS_Handle file = os_file_open(OS_AccessFlag_Read | OS_AccessFlag_ShareRead, path);
FileProperties props = os_properties_from_file(file);
String8 data = os_string_from_file_range(ainfo, file, r1u64(0, props.size));
os_file_close(file);
return data;
}
inline OS_FileID
os_id_from_file_path(String8 path) {
OS_Handle file = os_file_open(OS_AccessFlag_Read | OS_AccessFlag_ShareRead, path);
OS_FileID id = os_id_from_file(file);
os_file_close(file);
return id;
}
inline S64 os_file_id_compare(OS_FileID a, OS_FileID b) { S64 cmp = memory_compare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v)); return cmp; }
////////////////////////////////
//~ rjf: GUID Helpers (Helpers, Implemented Once)
String8 os_string_from_guid__arena(Arena* arena, OS_Guid guid);
String8 os_string_from_guid__ainfo(AllocatorInfo ainfo, OS_Guid guid);
#define os_string_from_guid(allocator, guid) _Generic(allocator, Arena*: os_string_from_guid__arena, AllocatorInfo: os_string_from_guid__ainfo, default: assert_generic_sel_fail) generic_call(allocator, guid)
force_inline String8 os_string_from_guid__arena(Arena* arena, OS_Guid guid) { os_string_from_guid__ainfo(arena_allocator(arena), guid); }
inline String8
os_string_from_guid_alloc(AllocatorInfo ainfo, OS_Guid guid) {
String8 result = str8f(ainfo,
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.data1,
guid.data2,
guid.data3,
guid.data4[0],
guid.data4[1],
guid.data4[2],
guid.data4[3],
guid.data4[4],
guid.data4[5],
guid.data4[6],
guid.data4[7]
);
return result;
}
////////////////////////////////
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
MD_API OS_SystemInfo* os_get_system_info (void);
MD_API OS_ProcessInfo* os_get_process_info(void);
String8 os_get_current_path__arena(Arena* arena);
String8 os_get_current_path__ainfo(AllocatorInfo arena);
#define os_get_current_path(allocator) _Generic(allocator, Arena*: os_get_current_path__arena, AllocatorInfo: os_get_current_path__ainfo) generic_call(allocator)
force_inline String8 os_get_current_path__arena(Arena* arena) { return os_get_current_path__ainfo(arena_allocator(arena)); }
////////////////////////////////
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
//- rjf: basic
void* os_reserve ( U64 size);
B32 os_commit (void* ptr, U64 size);
void os_decommit(void* ptr, U64 size);
void os_release (void* ptr, U64 size);
//- rjf: large pages
void* os_reserve_large( U64 size);
B32 os_commit_large (void* ptr, U64 size);
////////////////////////////////
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
U32 os_tid(void);
MD_API void os_set_thread_name(String8 string);
////////////////////////////////
//~ rjf: @os_hooks Aborting (Implemented Per-OS)
MD_API void os_abort(S32 exit_code);
////////////////////////////////
//~ rjf: @os_hooks Shared Memory (Implemented Per-OS)
MD_API OS_Handle os_shared_memory_alloc (U64 size, String8 name);
MD_API OS_Handle os_shared_memory_open (String8 name);
MD_API void os_shared_memory_close (OS_Handle handle);
MD_API void* os_shared_memory_view_open (OS_Handle handle, Rng1U64 range);
MD_API void os_shared_memory_view_close(OS_Handle handle, void* ptr, Rng1U64 range);
////////////////////////////////
//~ rjf: @os_hooks Time (Implemented Per-OS)
MD_API U64 os_now_microseconds (void);
MD_API U32 os_now_unix (void);
MD_API DateTime os_now_universal_time (void);
MD_API DateTime os_universal_time_from_local(DateTime* local_time);
MD_API DateTime os_local_time_from_universal(DateTime* universal_time);
MD_API void os_sleep_milliseconds (U32 msec);
////////////////////////////////
//~ rjf: @os_hooks Child Processes (Implemented Per-OS)
MD_API OS_Handle os_process_launch(OS_ProcessLaunchParams* params);
MD_API B32 os_process_join (OS_Handle handle, U64 endt_us);
MD_API void os_process_detach(OS_Handle handle);
////////////////////////////////
//~ rjf: @os_hooks Threads (Implemented Per-OS)
MD_API OS_Handle os_thread_launch(OS_ThreadFunctionType* func, void* ptr, void* params);
MD_API B32 os_thread_join (OS_Handle handle, U64 endt_us);
MD_API void os_thread_detach(OS_Handle handle);
////////////////////////////////
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
//- rjf: recursive mutexes
MD_API OS_Handle os_mutex_alloc (void);
MD_API void os_mutex_release(OS_Handle mutex);
MD_API void os_mutex_take (OS_Handle mutex);
MD_API void os_mutex_drop (OS_Handle mutex);
//- rjf: reader/writer mutexes
MD_API OS_Handle os_rw_mutex_alloc (void);
MD_API void os_rw_mutex_release(OS_Handle rw_mutex);
MD_API void os_rw_mutex_take_r (OS_Handle mutex);
MD_API void os_rw_mutex_drop_r (OS_Handle mutex);
MD_API void os_rw_mutex_take_w (OS_Handle mutex);
MD_API void os_rw_mutex_drop_w (OS_Handle mutex);
//- rjf: condition variables
MD_API OS_Handle os_condition_variable_alloc (void);
MD_API void os_condition_variable_release(OS_Handle cv);
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
MD_API B32 os_condition_variable_wait (OS_Handle cv, OS_Handle mutex, U64 endt_us);
MD_API B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
MD_API B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
MD_API void os_condition_variable_signal (OS_Handle cv);
MD_API void os_condition_variable_broadcast(OS_Handle cv);
//- rjf: cross-process semaphores
MD_API OS_Handle os_semaphore_alloc (U32 initial_count, U32 max_count, String8 name);
MD_API void os_semaphore_release(OS_Handle semaphore);
MD_API OS_Handle os_semaphore_open (String8 name);
MD_API void os_semaphore_close (OS_Handle semaphore);
MD_API B32 os_semaphore_take (OS_Handle semaphore, U64 endt_us);
MD_API void os_semaphore_drop (OS_Handle semaphore);
//- rjf: scope macros
#define os_mutex_scope(mutex) defer_loop( os_mutex_take (mutex), os_mutex_drop (mutex))
#define os_mutex_scope_r(mutex) defer_loop( os_rw_mutex_take_r(mutex), os_rw_mutex_drop_r(mutex))
#define os_mutex_scope_W(mutex) defer_loop( os_rw_mutex_take_w(mutex), os_rw_mutex_drop_w(mutex))
#define os_mutex_scope_rw_promote(mutex) defer_loop((os_rw_mutex_drop_r(mutex), os_rw_mutex_take_w(mutex)), (os_rw_mutex_drop_w(mutex), os_rw_mutex_take_r(mutex)))
////////////////////////////////
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
MD_API OS_Handle os_library_open (String8 path);
MD_API void os_library_close (OS_Handle lib);
MD_API VoidProc* os_library_load_proc(OS_Handle lib, String8 name);
////////////////////////////////
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
MD_API void os_safe_call(OS_ThreadFunctionType* func, OS_ThreadFunctionType* fail_handler, void* ptr);
////////////////////////////////
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
MD_API OS_Guid os_make_guid(void);
////////////////////////////////
//~ rjf: @os_hooks Entry Points (Implemented Per-OS)
// NOTE(rjf): The implementation of `os_core` will define low-level entry
// points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call
// into the standard codebase program entry points, named "entry_point".
#if BUILD_ENTRY_DEFINING_UNIT
void entry_point(CmdLine* cmdline);
#endif
////////////////////////////////
//~ Ed: Manual OS Bootstrap (Implemented Per-OS)
typedef struct OS_Context OS_Context;
struct OS_Context
{
Arena* state_arena;
Arena* entity_arena;
B32 enable_large_pages;
};
// OS layer initialization
MD_API void os_init(OS_Context* ctx, TCTX* thread_ctx);
+28
View File
@@ -0,0 +1,28 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "base/context_cracking.h"
# include "base/namespace.h"
#endif
#if !defined(OS_FEATURE_GRAPHICAL)
# define OS_FEATURE_GRAPHICAL 0
#endif
#if !defined(OS_GFX_STUB)
# define OS_GFX_STUB 0
#endif
#if OS_WINDOWS
# include "os/win32/os_win32_includes.h"
MD_NS_BEGIN
# include "os/win32/os_win32.h"
MD_NS_END
#elif OS_LINUX
# include "os/linux/os_linux_includes.h"
MD_NS_BEGIN
# include "os/linux/os_linux.h"
MD_NS_END
# error OS core layer not implemented for this operating system.
#endif
File diff suppressed because it is too large Load Diff
+209
View File
@@ -0,0 +1,209 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "base/strings.h"
# include "base/thread_context.h"
# include "os.h"
# include "os_win32_includes.h"
#endif
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: File Iterator Types
typedef struct OS_W32_FileIter OS_W32_FileIter;
struct OS_W32_FileIter
{
HANDLE handle;
WIN32_FIND_DATAW find_data;
B32 is_volume_iter;
String8Array drive_strings;
U64 drive_strings_iter_idx;
};
md_static_assert(sizeof(member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size);
////////////////////////////////
//~ rjf: Entity Types
typedef enum OS_W32_EntityKind OS_W32_EntityKind;
enum OS_W32_EntityKind
{
OS_W32_EntityKind_Null,
OS_W32_EntityKind_Thread,
OS_W32_EntityKind_Mutex,
OS_W32_EntityKind_RWMutex,
OS_W32_EntityKind_ConditionVariable,
};
typedef struct OS_W32_EntityThread OS_W32_EntityThread;
struct OS_W32_EntityThread
{
OS_ThreadFunctionType* func;
void* ptr;
HANDLE handle;
DWORD tid;
};
typedef struct OS_W32_Entity OS_W32_Entity;
struct OS_W32_Entity
{
OS_W32_Entity* next;
OS_W32_EntityKind kind;
union
{
OS_W32_EntityThread thread;
CRITICAL_SECTION mutex;
SRWLOCK rw_mutex;
CONDITION_VARIABLE cv;
};
};
////////////////////////////////
//~ rjf: State
typedef struct OS_W32_State OS_W32_State;
struct OS_W32_State
{
Arena* arena;
// rjf: info
OS_SystemInfo system_info;
OS_ProcessInfo process_info;
U64 microsecond_resolution;
// rjf: entity storage
CRITICAL_SECTION entity_mutex;
Arena* entity_arena;
OS_W32_Entity* entity_free;
};
////////////////////////////////
//~ rjf: Globals
MD_API extern OS_W32_State os_w32_state;
////////////////////////////////
//~ rjf: Time Conversion Helpers
void os_w32_date_time_from_system_time(DateTime* out, SYSTEMTIME* in);
void os_w32_system_time_from_date_time(SYSTEMTIME* out, DateTime* in);
void os_w32_dense_time_from_file_time (DenseTime* out, FILETIME* in);
MD_API U32 os_w32_sleep_ms_from_endt_us(U64 endt_us);
inline void
os_w32_date_time_from_system_time(DateTime* out, SYSTEMTIME* in)
{
out->year = in->wYear;
out->mon = in->wMonth - 1;
out->wday = in->wDayOfWeek;
out->day = in->wDay;
out->hour = in->wHour;
out->min = in->wMinute;
out->sec = in->wSecond;
out->msec = in->wMilliseconds;
}
inline void
os_w32_system_time_from_date_time(SYSTEMTIME* out, DateTime* in)
{
out->wYear = (WORD)(in->year);
out->wMonth = in->mon + 1;
out->wDay = in->day;
out->wHour = in->hour;
out->wMinute = in->min;
out->wSecond = in->sec;
out->wMilliseconds = in->msec;
}
inline void
os_w32_dense_time_from_file_time(DenseTime* out, FILETIME* in) {
SYSTEMTIME systime = {0};
DateTime date_time = {0};
FileTimeToSystemTime(in, &systime);
os_w32_date_time_from_system_time(&date_time, &systime);
*out = dense_time_from_date_time(date_time);
}
////////////////////////////////
//~ rjf: File Info Conversion Helpers
inline FilePropertyFlags
os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes)
{
FilePropertyFlags flags = 0;
if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
flags |= FilePropertyFlag_IsFolder;
}
return flags;
}
inline void
os_w32_file_properties_from_attribute_data(FileProperties* properties, WIN32_FILE_ATTRIBUTE_DATA* attributes) {
properties->size = compose_64bit(attributes->nFileSizeHigh, attributes->nFileSizeLow);
os_w32_dense_time_from_file_time(&properties->created, &attributes->ftCreationTime);
os_w32_dense_time_from_file_time(&properties->modified, &attributes->ftLastWriteTime);
properties->flags = os_w32_file_property_flags_from_dwFileAttributes(attributes->dwFileAttributes);
}
////////////////////////////////
//~ rjf: Entity Functions
MD_API OS_W32_Entity* os_w32_entity_alloc (OS_W32_EntityKind kind);
MD_API void os_w32_entity_release(OS_W32_Entity* entity);
////////////////////////////////
//~ rjf: Thread Entry Point
MD_API DWORD os_w32_thread_entry_point(void* ptr);
////////////////////////////////
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
inline String8
os_get_current_path__ainfo(AllocatorInfo ainfo) {
String8 name;
TempArena scratch = scratch_begin(ainfo);
{
DWORD length = GetCurrentDirectoryW(0, 0);
U16* memory = push_array_no_zero(scratch.arena, U16, length + 1);
length = GetCurrentDirectoryW(length + 1, (WCHAR*)memory);
name = str8_from(ainfo, str16(memory, length));
}
scratch_end(scratch);
return name;
}
////////////////////////////////
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
//- rjf: basic
inline void* os_reserve ( U64 size) { void* result = VirtualAlloc( 0, size, MEM_RESERVE, PAGE_READWRITE); return result; }
inline B32 os_commit (void* ptr, U64 size) { B32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); return result; }
inline void os_decommit(void* ptr, U64 size) { VirtualFree (ptr, size, MEM_DECOMMIT); }
inline void
os_release(void* ptr, U64 size) {
// NOTE(rjf): size not used - not necessary on Windows, but necessary for other OSes.
VirtualFree(ptr, 0, MEM_RELEASE);
}
//- rjf: large pages
inline void*
os_reserve_large(U64 size) {
// we commit on reserve because windows
void* result = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_LARGE_PAGES, PAGE_READWRITE);
return result;
}
inline B32 os_commit_large(void* ptr, U64 size) { return 1; }
////////////////////////////////
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
inline U32 os_tid(void) { DWORD id = GetCurrentThreadId(); return (U32)id; }
+31
View File
@@ -0,0 +1,31 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
#endif
////////////////////////////////
//~ rjf: Includes / Libraries
#ifndef NOMINMAX
#define NOMINMAX
#endif
#define WIN32_LEAN_AND_MEAN
#define WIN32_MEAN_AND_LEAN
#define VC_EXTRALEAN
#include <windows.h>
#include <windowsx.h>
#include <timeapi.h>
#include <tlhelp32.h>
#include <Shlobj.h>
#include <processthreadsapi.h>
#pragma comment(lib, "user32")
#pragma comment(lib, "winmm")
#pragma comment(lib, "shell32")
#pragma comment(lib, "advapi32")
#pragma comment(lib, "rpcrt4")
#pragma comment(lib, "shlwapi")
#pragma comment(lib, "comctl32")
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // this is required for loading correct comctl32 dll file
#undef NOMINMAX
#undef WIN32_LEAN_AND_MEAN
#undef WIN32_MEAN_AND_LEAN
#undef VC_EXTRALEAN