Do massive overhaul and simplification of DN
This commit is contained in:
+766
-119
File diff suppressed because it is too large
Load Diff
+139
-54
@@ -2,8 +2,8 @@
|
||||
#define DN_OS_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
#define DN_H_WITH_OS 1
|
||||
#include "../dn.h"
|
||||
#endif
|
||||
|
||||
#include <new> // operator new
|
||||
@@ -123,7 +123,7 @@ struct DN_OSPath
|
||||
DN_OSPathLink *head;
|
||||
DN_OSPathLink *tail;
|
||||
DN_USize string_size;
|
||||
DN_U16 links_size;
|
||||
DN_U16 links_size;
|
||||
};
|
||||
|
||||
// NOTE: DN_OSExec
|
||||
@@ -197,8 +197,7 @@ typedef DN_I32(DN_OSThreadFunc)(struct DN_OSThread *);
|
||||
struct DN_OSThread
|
||||
{
|
||||
DN_Str8x64 name;
|
||||
DN_OSTLS tls;
|
||||
DN_OSTLSInitArgs tls_init_args;
|
||||
DN_TCCore context;
|
||||
void *handle;
|
||||
DN_U64 thread_id;
|
||||
void *user_context;
|
||||
@@ -229,7 +228,7 @@ struct DN_OSHttpResponse
|
||||
// Synchronous HTTP response uses the TLS scratch arena whereas async
|
||||
// calls use their own dedicated arena.
|
||||
DN_Arena tmp_arena;
|
||||
DN_Arena *tmem_arena;
|
||||
DN_Arena *scratch_arena;
|
||||
DN_Str8Builder builder;
|
||||
DN_OSSemaphore on_complete_semaphore;
|
||||
|
||||
@@ -245,10 +244,9 @@ struct DN_OSHttpResponse
|
||||
struct DN_OSCore
|
||||
{
|
||||
DN_CPUReport cpu_report;
|
||||
DN_OSTLS tls; // Thread local storage state for the main thread.
|
||||
|
||||
// NOTE: Logging
|
||||
DN_LOGEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine
|
||||
DN_LogEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine
|
||||
void * log_user_data; // User pointer passed into 'log_callback'
|
||||
bool log_to_file; // Output logs to file as well as standard out
|
||||
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
|
||||
@@ -280,14 +278,19 @@ struct DN_OSDiskSpace
|
||||
DN_U64 size;
|
||||
};
|
||||
|
||||
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet (DN_ArenaMemFuncType type);
|
||||
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults ();
|
||||
DN_API DN_Arena DN_ArenaFromHeap (DN_U64 size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_ArenaFromVMem (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
|
||||
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
|
||||
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder);
|
||||
|
||||
DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os);
|
||||
DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path);
|
||||
|
||||
DN_API DN_Str8 DN_OS_BytesFromHexPtrArenaFrame (void const *hex, DN_USize hex_count);
|
||||
DN_API DN_Str8 DN_OS_BytesFromHexStr8ArenaFrame (DN_Str8 hex);
|
||||
DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaFrame (void const *bytes, DN_USize bytes_count);
|
||||
DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS (void const *bytes, DN_USize bytes_count);
|
||||
|
||||
DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
|
||||
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags);
|
||||
DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size);
|
||||
@@ -312,7 +315,6 @@ DN_API bool DN_OS_SetEnvVar (D
|
||||
DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path);
|
||||
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
|
||||
#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena())
|
||||
DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
|
||||
|
||||
DN_API DN_U64 DN_OS_PerfCounterNow ();
|
||||
@@ -329,28 +331,28 @@ DN_API DN_F64 DN_OS_TimerUs (D
|
||||
DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer);
|
||||
DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency);
|
||||
|
||||
DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
|
||||
|
||||
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err);
|
||||
DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err);
|
||||
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err);
|
||||
DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_ErrSink *err);
|
||||
DN_API void DN_OS_FileClose (DN_OSFile *file);
|
||||
|
||||
DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllTLS (DN_Str8 path, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_ErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_ErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_ErrSink *err);
|
||||
|
||||
DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
|
||||
DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against);
|
||||
@@ -361,42 +363,25 @@ DN_API bool DN_OS_PathMakeDir (D
|
||||
DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it);
|
||||
|
||||
DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
||||
DN_API bool DN_OS_PathAddRefTLS (DN_OSPath *fs_path, DN_Str8 path);
|
||||
DN_API bool DN_OS_PathAddRefFrame (DN_OSPath *fs_path, DN_Str8 path);
|
||||
DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
||||
#define DN_OS_PathAddFromTLS(...) DN_OS_PathAdd(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathAddFromFrame(...) DN_OS_PathAdd(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_PathAddFFromTLS(...) DN_OS_PathAddF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathAddFFromFrame(...) DN_OS_PathAddF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_PathPop (DN_OSPath *fs_path);
|
||||
DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator);
|
||||
#define DN_OS_PathBuildWithSeperatorFromTLS(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathBuildWithSeperatorFromFrame(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor);
|
||||
#define DN_OS_PathToFromTLS(...) DN_OS_PathTo(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathToFromFrame(...) DN_OS_PathTo(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_PathToFFromTLS(...) DN_OS_PathToF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathToFFromFrame(...) DN_OS_PathToF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path);
|
||||
#define DN_OS_PathFromTLS(...) DN_OS_Path(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathFromFrame(...) DN_OS_Path(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_PathFFromTLS(...) DN_OS_PathF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathFFromFrame(...) DN_OS_PathF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
|
||||
|
||||
#define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("/"))
|
||||
#define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("\\"))
|
||||
#define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString)
|
||||
|
||||
DN_API void DN_OS_Exit (int32_t exit_code);
|
||||
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_ErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err);
|
||||
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_ErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_ErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
|
||||
#define DN_OS_ExecOrAbortFromTLS (...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena())
|
||||
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count);
|
||||
DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
|
||||
@@ -426,4 +411,104 @@ DN_API void DN_OS_HttpRequestAsync (D
|
||||
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
|
||||
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
|
||||
DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
|
||||
// NOTE: DN_OSPrint
|
||||
enum DN_OSPrintDest
|
||||
{
|
||||
DN_OSPrintDest_Out,
|
||||
DN_OSPrintDest_Err,
|
||||
};
|
||||
|
||||
// NOTE: Print Macros
|
||||
#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string)
|
||||
#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args)
|
||||
|
||||
#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string)
|
||||
#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args)
|
||||
|
||||
#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string)
|
||||
#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args)
|
||||
|
||||
#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string);
|
||||
#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args);
|
||||
|
||||
#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string)
|
||||
#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args)
|
||||
|
||||
#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string)
|
||||
#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args)
|
||||
|
||||
#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string)
|
||||
#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args)
|
||||
|
||||
#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string);
|
||||
#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args);
|
||||
|
||||
// NOTE: Print
|
||||
DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
// NOTE: DN_VArray
|
||||
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS.
|
||||
template <typename T> struct DN_VArray
|
||||
{
|
||||
T *data; // Pointer to the start of the array items in the block of memory
|
||||
DN_USize size; // Number of items currently in the array
|
||||
DN_USize max; // Maximum number of items this array can store
|
||||
DN_USize commit; // Bytes committed
|
||||
|
||||
T *begin() { return data; }
|
||||
T *end () { return data + size; }
|
||||
T const *begin() const { return data; }
|
||||
T const *end () const { return data + size; }
|
||||
};
|
||||
|
||||
template <typename T> DN_VArray<T> DN_OS_VArrayInitByteSize (DN_USize byte_size);
|
||||
template <typename T> DN_VArray<T> DN_OS_VArrayInit (DN_USize max);
|
||||
template <typename T> DN_VArray<T> DN_OS_VArrayInitSlice (DN_Slice<T> slice, DN_USize max);
|
||||
template <typename T, DN_USize N> DN_VArray<T> DN_OS_VArrayInitCArray (T const (&items)[N], DN_USize max);
|
||||
template <typename T> void DN_OS_VArrayDeinit (DN_VArray<T> *array);
|
||||
template <typename T> bool DN_OS_VArrayIsValid (DN_VArray<T> const *array);
|
||||
template <typename T> bool DN_OS_VArrayReserve (DN_VArray<T> *array, DN_USize count);
|
||||
template <typename T> T * DN_OS_VArrayAddArray (DN_VArray<T> *array, T const *items, DN_USize count);
|
||||
template <typename T, DN_USize N> T * DN_OS_VArrayAddCArray (DN_VArray<T> *array, T const (&items)[N]);
|
||||
template <typename T> T * DN_OS_VArrayAdd (DN_VArray<T> *array, T const &item);
|
||||
#define DN_OS_VArrayAddArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddArray(__VA_ARGS__))
|
||||
#define DN_OS_VArrayAddCArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddCArray(__VA_ARGS__))
|
||||
#define DN_OS_VArrayAddAssert(...) DN_HardAssert(DN_OS_VArrayAdd(__VA_ARGS__))
|
||||
template <typename T> T * DN_OS_VArrayMakeArray (DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem);
|
||||
template <typename T> T * DN_OS_VArrayMake (DN_VArray<T> *array, DN_ZMem z_mem);
|
||||
#define DN_OS_VArrayMakeArrayAssert(...) DN_HardAssert(DN_OS_VArrayMakeArray(__VA_ARGS__))
|
||||
#define DN_OS_VArrayMakeAssert(...) DN_HardAssert(DN_OS_VArrayMake(__VA_ARGS__))
|
||||
template <typename T> T * DN_OS_VArrayInsertArray (DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count);
|
||||
template <typename T, DN_USize N> T * DN_OS_VArrayInsertCArray (DN_VArray<T> *array, DN_USize index, T const (&items)[N]);
|
||||
template <typename T> T * DN_OS_VArrayInsert (DN_VArray<T> *array, DN_USize index, T const &item);
|
||||
#define DN_OS_VArrayInsertArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertArray(__VA_ARGS__))
|
||||
#define DN_OS_VArrayInsertCArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertCArray(__VA_ARGS__))
|
||||
#define DN_OS_VArrayInsertAssert(...) DN_HardAssert(DN_OS_VArrayInsert(__VA_ARGS__))
|
||||
template <typename T> T DN_OS_VArrayPopFront (DN_VArray<T> *array, DN_USize count);
|
||||
template <typename T> T DN_OS_VArrayPopBack (DN_VArray<T> *array, DN_USize count);
|
||||
template <typename T> DN_ArrayEraseResult DN_OS_VArrayEraseRange (DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
|
||||
template <typename T> void DN_OS_VArrayClear (DN_VArray<T> *array, DN_ZMem z_mem);
|
||||
#endif // !defined(DN_OS_H)
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#define DN_OS_ALLOCATOR_CPP
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
#include "../dn_inc.h"
|
||||
#endif
|
||||
|
||||
static void *DN_ArenaBasicAllocFromOSHeap(DN_USize size)
|
||||
{
|
||||
void *result = DN_OS_MemAlloc(size, DN_ZMem_Yes);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags)
|
||||
{
|
||||
DN_ArenaMemFuncs mem_funcs = {};
|
||||
mem_funcs.type = DN_ArenaMemFuncType_Basic;
|
||||
mem_funcs.basic_alloc = DN_ArenaBasicAllocFromOSHeap;
|
||||
mem_funcs.basic_dealloc = DN_OS_MemDealloc;
|
||||
DN_Arena result = DN_ArenaFromMemFuncs(size, size, flags, mem_funcs);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags)
|
||||
{
|
||||
DN_ArenaMemFuncs mem_funcs = {};
|
||||
mem_funcs.type = DN_ArenaMemFuncType_VMem;
|
||||
mem_funcs.vmem_page_size = g_dn_->os.page_size;
|
||||
mem_funcs.vmem_reserve = DN_OS_MemReserve;
|
||||
mem_funcs.vmem_commit = DN_OS_MemCommit;
|
||||
mem_funcs.vmem_release = DN_OS_MemRelease;
|
||||
DN_Arena result = DN_ArenaFromMemFuncs(reserve, commit, flags, mem_funcs);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#if !defined(DN_OS_ALLOCATOR_H)
|
||||
#define DN_OS_ALLOCATOR_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#endif
|
||||
|
||||
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
|
||||
|
||||
#endif // !defined(DN_OS_ALLOCATOR_H)
|
||||
@@ -1,204 +0,0 @@
|
||||
#define DN_OS_CONTAINERS_CPP
|
||||
|
||||
#include "dn_os_containers.h"
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$$\ $$$$$$\
|
||||
// $$ __$$\ $$ __$$\ $$$\ $$ |\__$$ __|$$ __$$\ \_$$ _|$$$\ $$ |$$ _____|$$ __$$\ $$ __$$\
|
||||
// $$ / \__|$$ / $$ |$$$$\ $$ | $$ | $$ / $$ | $$ | $$$$\ $$ |$$ | $$ | $$ |$$ / \__|
|
||||
// $$ | $$ | $$ |$$ $$\$$ | $$ | $$$$$$$$ | $$ | $$ $$\$$ |$$$$$\ $$$$$$$ |\$$$$$$\
|
||||
// $$ | $$ | $$ |$$ \$$$$ | $$ | $$ __$$ | $$ | $$ \$$$$ |$$ __| $$ __$$< \____$$\
|
||||
// $$ | $$\ $$ | $$ |$$ |\$$$ | $$ | $$ | $$ | $$ | $$ |\$$$ |$$ | $$ | $$ |$$\ $$ |
|
||||
// \$$$$$$ | $$$$$$ |$$ | \$$ | $$ | $$ | $$ |$$$$$$\ $$ | \$$ |$$$$$$$$\ $$ | $$ |\$$$$$$ |
|
||||
// \______/ \______/ \__| \__| \__| \__| \__|\______|\__| \__|\________|\__| \__| \______/
|
||||
//
|
||||
// dn_containers.cpp
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: DN_VArray /////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
DN_VArray<T> DN_VArray_InitByteSize(DN_USize byte_size)
|
||||
{
|
||||
DN_VArray<T> result = {};
|
||||
result.data = DN_Cast(T *) DN_OS_MemReserve(byte_size, DN_MemCommit_No, DN_MemPage_ReadWrite);
|
||||
if (result.data)
|
||||
result.max = byte_size / sizeof(T);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DN_VArray<T> DN_VArray_Init(DN_USize max)
|
||||
{
|
||||
DN_VArray<T> result = DN_VArray_InitByteSize<T>(max * sizeof(T));
|
||||
DN_Assert(result.max >= max);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DN_VArray<T> DN_VArray_InitSlice(DN_Slice<T> slice, DN_USize max)
|
||||
{
|
||||
DN_USize real_max = DN_Max(slice.size, max);
|
||||
DN_VArray<T> result = DN_VArray_Init<T>(real_max);
|
||||
if (DN_VArray_IsValid(&result))
|
||||
DN_VArray_AddArray(&result, slice.data, slice.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, DN_USize N>
|
||||
DN_VArray<T> DN_VArray_InitCArray(T const (&items)[N], DN_USize max)
|
||||
{
|
||||
DN_USize real_max = DN_Max(N, max);
|
||||
DN_VArray<T> result = DN_VArray_InitSlice(DN_Slice_Init(items, N), real_max);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DN_VArray_Deinit(DN_VArray<T> *array)
|
||||
{
|
||||
DN_OS_MemRelease(array->data, array->max * sizeof(T));
|
||||
*array = {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DN_VArray_IsValid(DN_VArray<T> const *array)
|
||||
{
|
||||
bool result = array->data && array->size <= array->max;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DN_Slice<T> DN_VArray_Slice(DN_VArray<T> const *array)
|
||||
{
|
||||
DN_Slice<T> result = {};
|
||||
if (array)
|
||||
result = DN_Slice_Init<T>(array->data, array->size);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_AddArray(DN_VArray<T> *array, T const *items, DN_USize count)
|
||||
{
|
||||
T *result = DN_VArray_MakeArray(array, count, DN_ZMem_No);
|
||||
if (result)
|
||||
DN_Memcpy(result, items, count * sizeof(T));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, DN_USize N>
|
||||
T *DN_VArray_AddCArray(DN_VArray<T> *array, T const (&items)[N])
|
||||
{
|
||||
T *result = DN_VArray_AddArray(array, items, N);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_Add(DN_VArray<T> *array, T const &item)
|
||||
{
|
||||
T *result = DN_VArray_AddArray(array, &item, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_MakeArray(DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem)
|
||||
{
|
||||
if (!DN_VArray_IsValid(array))
|
||||
return nullptr;
|
||||
|
||||
if (!DN_CheckF((array->size + count) < array->max, "Array is out of space (user requested +%zu items, array has %zu/%zu items)", count, array->size, array->max))
|
||||
return nullptr;
|
||||
|
||||
if (!DN_VArray_Reserve(array, count))
|
||||
return nullptr;
|
||||
|
||||
// TODO: Use placement new
|
||||
T *result = array->data + array->size;
|
||||
array->size += count;
|
||||
if (z_mem == DN_ZMem_Yes)
|
||||
DN_Memset(result, 0, count * sizeof(T));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_Make(DN_VArray<T> *array, DN_ZMem z_mem)
|
||||
{
|
||||
T *result = DN_VArray_MakeArray(array, 1, z_mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_InsertArray(DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count)
|
||||
{
|
||||
T *result = nullptr;
|
||||
if (!DN_VArray_IsValid(array))
|
||||
return result;
|
||||
if (DN_VArray_Reserve(array, array->size + count))
|
||||
result = DN_CArray_InsertArray(array->data, &array->size, array->max, index, items, count);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, DN_USize N>
|
||||
T *DN_VArray_InsertCArray(DN_VArray<T> *array, DN_USize index, T const (&items)[N])
|
||||
{
|
||||
T *result = DN_VArray_InsertArray(array, index, items, N);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_Insert(DN_VArray<T> *array, DN_USize index, T const &item)
|
||||
{
|
||||
T *result = DN_VArray_InsertArray(array, index, &item, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_PopFront(DN_VArray<T> *array, DN_USize count)
|
||||
{
|
||||
T *result = DN_CArray_PopFront(array->data, &array->size, count);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *DN_VArray_PopBack(DN_VArray<T> *array, DN_USize count)
|
||||
{
|
||||
T *result = DN_CArray_PopBack(array->data, &array->size, count);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DN_ArrayEraseResult DN_VArray_EraseRange(DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase)
|
||||
{
|
||||
DN_ArrayEraseResult result = {};
|
||||
if (!DN_VArray_IsValid(array))
|
||||
return result;
|
||||
result = DN_CArray_EraseRange<T>(array->data, &array->size, begin_index, count, erase);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DN_VArray_Clear(DN_VArray<T> *array, DN_ZMem z_mem)
|
||||
{
|
||||
if (array) {
|
||||
if (z_mem == DN_ZMem_Yes)
|
||||
DN_Memset(array->data, 0, array->size * sizeof(T));
|
||||
array->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DN_VArray_Reserve(DN_VArray<T> *array, DN_USize count)
|
||||
{
|
||||
if (!DN_VArray_IsValid(array) || count == 0)
|
||||
return false;
|
||||
|
||||
DN_USize real_commit = (array->size + count) * sizeof(T);
|
||||
DN_USize aligned_commit = DN_AlignUpPowerOfTwo(real_commit, g_dn_->os.page_size);
|
||||
if (array->commit >= aligned_commit)
|
||||
return true;
|
||||
bool result = DN_OS_MemCommit(array->data, aligned_commit, DN_MemPage_ReadWrite);
|
||||
array->commit = aligned_commit;
|
||||
return result;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#if !defined(DN_OS_CONTAINERS_H)
|
||||
#define DN_OS_CONTAINERS_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#endif
|
||||
|
||||
// NOTE: DN_VArray
|
||||
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS.
|
||||
template <typename T> struct DN_VArray
|
||||
{
|
||||
T *data; // Pointer to the start of the array items in the block of memory
|
||||
DN_USize size; // Number of items currently in the array
|
||||
DN_USize max; // Maximum number of items this array can store
|
||||
DN_USize commit; // Bytes committed
|
||||
|
||||
T *begin() { return data; }
|
||||
T *end () { return data + size; }
|
||||
T const *begin() const { return data; }
|
||||
T const *end () const { return data + size; }
|
||||
};
|
||||
|
||||
template <typename T> DN_VArray<T> DN_VArray_InitByteSize (DN_USize byte_size);
|
||||
template <typename T> DN_VArray<T> DN_VArray_Init (DN_USize max);
|
||||
template <typename T> DN_VArray<T> DN_VArray_InitSlice (DN_Slice<T> slice, DN_USize max);
|
||||
template <typename T, DN_USize N> DN_VArray<T> DN_VArray_InitCArray (T const (&items)[N], DN_USize max);
|
||||
template <typename T> void DN_VArray_Deinit (DN_VArray<T> *array);
|
||||
template <typename T> bool DN_VArray_IsValid (DN_VArray<T> const *array);
|
||||
template <typename T> DN_Slice<T> DN_VArray_Slice (DN_VArray<T> const *array);
|
||||
template <typename T> bool DN_VArray_Reserve (DN_VArray<T> *array, DN_USize count);
|
||||
template <typename T> T * DN_VArray_AddArray (DN_VArray<T> *array, T const *items, DN_USize count);
|
||||
template <typename T, DN_USize N> T * DN_VArray_AddCArray (DN_VArray<T> *array, T const (&items)[N]);
|
||||
template <typename T> T * DN_VArray_Add (DN_VArray<T> *array, T const &item);
|
||||
#define DN_VArray_AddArrayAssert(...) DN_HardAssert(DN_VArray_AddArray(__VA_ARGS__))
|
||||
#define DN_VArray_AddCArrayAssert(...) DN_HardAssert(DN_VArray_AddCArray(__VA_ARGS__))
|
||||
#define DN_VArray_AddAssert(...) DN_HardAssert(DN_VArray_Add(__VA_ARGS__))
|
||||
template <typename T> T * DN_VArray_MakeArray (DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem);
|
||||
template <typename T> T * DN_VArray_Make (DN_VArray<T> *array, DN_ZMem z_mem);
|
||||
#define DN_VArray_MakeArrayAssert(...) DN_HardAssert(DN_VArray_MakeArray(__VA_ARGS__))
|
||||
#define DN_VArray_MakeAssert(...) DN_HardAssert(DN_VArray_Make(__VA_ARGS__))
|
||||
template <typename T> T * DN_VArray_InsertArray (DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count);
|
||||
template <typename T, DN_USize N> T * DN_VArray_InsertCArray (DN_VArray<T> *array, DN_USize index, T const (&items)[N]);
|
||||
template <typename T> T * DN_VArray_Insert (DN_VArray<T> *array, DN_USize index, T const &item);
|
||||
#define DN_VArray_InsertArrayAssert(...) DN_HardAssert(DN_VArray_InsertArray(__VA_ARGS__))
|
||||
#define DN_VArray_InsertCArrayAssert(...) DN_HardAssert(DN_VArray_InsertCArray(__VA_ARGS__))
|
||||
#define DN_VArray_InsertAssert(...) DN_HardAssert(DN_VArray_Insert(__VA_ARGS__))
|
||||
template <typename T> T DN_VArray_PopFront (DN_VArray<T> *array, DN_USize count);
|
||||
template <typename T> T DN_VArray_PopBack (DN_VArray<T> *array, DN_USize count);
|
||||
template <typename T> DN_ArrayEraseResult DN_VArray_EraseRange (DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
|
||||
template <typename T> void DN_VArray_Clear (DN_VArray<T> *array, DN_ZMem z_mem);
|
||||
#endif // !defined(DN_OS_CONTAINERS_H)
|
||||
+89
-74
@@ -1,12 +1,14 @@
|
||||
#define DN_OS_POSIX_CPP
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
#define DN_H_WITH_OS 1
|
||||
#include "../dn.h"
|
||||
#include "dn_os_posix.h"
|
||||
#endif
|
||||
|
||||
#include <dirent.h> // readdir, opendir, closedir
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
// NOTE: DN_OSMem
|
||||
static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect)
|
||||
@@ -226,17 +228,20 @@ DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
|
||||
|
||||
DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
|
||||
DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_OSDiskSpace result = {};
|
||||
DN_Str8 path_z_terminated = DN_Str8FromStr8Arena(tmem.arena, path);
|
||||
|
||||
struct statvfs info = {};
|
||||
if (statvfs(path_z_terminated.data, &info) != 0)
|
||||
if (statvfs(path_z_terminated.data, &info) != 0) {
|
||||
DN_TCScratchEnd(&tmem);
|
||||
return result;
|
||||
}
|
||||
|
||||
result.success = true;
|
||||
result.avail = info.f_bavail * info.f_frsize;
|
||||
result.size = info.f_blocks * info.f_frsize;
|
||||
DN_TCScratchEnd(&tmem);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -313,23 +318,23 @@ DN_API DN_U64 DN_OS_PerfCounterFrequency()
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_POSIXCore *DN_OS_GetPOSIXCore_()
|
||||
static DN_OSPosixCore *DN_OS_GetPOSIXCore_()
|
||||
{
|
||||
DN_Assert(g_dn_ && g_dn_->os.platform_context);
|
||||
DN_POSIXCore *result = DN_Cast(DN_POSIXCore *)g_dn_->os.platform_context;
|
||||
DN_OSPosixCore *result = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U64 DN_OS_PerfCounterNow()
|
||||
{
|
||||
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_();
|
||||
DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
|
||||
struct timespec ts;
|
||||
clock_gettime(posix->clock_monotonic_raw ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &ts);
|
||||
DN_U64 result = DN_Cast(DN_U64) ts.tv_sec * 1'000'000'000 + DN_Cast(DN_U64) ts.tv_nsec;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error)
|
||||
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error)
|
||||
{
|
||||
bool result = false;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
@@ -385,9 +390,9 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
result = (bytes_written == stat_existing.st_size);
|
||||
if (!result) {
|
||||
int error_code = errno;
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 file_size_str8 = DN_Str8FromByteCount(tmem.arena, stat_existing.st_size, DN_ByteCountType_Auto);
|
||||
DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(tmem.arena, bytes_written, DN_ByteCountType_Auto);
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8 file_size_str8 = DN_Str8FromByteCount(scratch.arena, stat_existing.st_size, DN_ByteCountType_Auto);
|
||||
DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(scratch.arena, bytes_written, DN_ByteCountType_Auto);
|
||||
DN_OS_ErrSinkAppendF(error,
|
||||
error_code,
|
||||
"Failed to copy file '%.*s' to '%.*s', we copied %.*s but the file "
|
||||
@@ -398,13 +403,14 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
DN_Str8PrintFmt(file_size_str8),
|
||||
error_code,
|
||||
strerror(error_code));
|
||||
DN_TCScratchEnd(&scratch);
|
||||
}
|
||||
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error)
|
||||
DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error)
|
||||
{
|
||||
// See: https://github.com/gingerBill/gb/blob/master/gb.h
|
||||
bool result = false;
|
||||
@@ -435,7 +441,7 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
|
||||
DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path,
|
||||
DN_OSFileOpen open_mode,
|
||||
DN_OSFileAccess access,
|
||||
DN_OSErrSink *error)
|
||||
DN_ErrSink *error)
|
||||
{
|
||||
DN_OSFile result = {};
|
||||
if (path.size == 0 || path.size <= 0)
|
||||
@@ -506,7 +512,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path,
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err)
|
||||
DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err)
|
||||
{
|
||||
DN_OSFileRead result = {};
|
||||
if (!file || !file->handle || file->error || !buffer || size <= 0)
|
||||
@@ -514,9 +520,10 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
|
||||
|
||||
result.bytes_read = fread(buffer, 1, size, DN_Cast(FILE *) file->handle);
|
||||
if (feof(DN_Cast(FILE*)file->handle)) {
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
|
||||
DN_OS_ErrSinkAppendF(err, 1, "Failed to read %S from file", buffer_size_str8);
|
||||
DN_TCScratchEnd(&scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -524,7 +531,7 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_OSErrSink *err)
|
||||
DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_ErrSink *err)
|
||||
{
|
||||
if (!file || !file->handle || file->error || !buffer || size <= 0)
|
||||
return false;
|
||||
@@ -532,14 +539,15 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz
|
||||
fwrite(buffer, DN_Cast(DN_USize) size, 1 /*count*/, DN_Cast(FILE *) file->handle) ==
|
||||
1 /*count*/;
|
||||
if (!result) {
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
|
||||
DN_OS_ErrSinkAppendF(err, 1, "Failed to write buffer (%s) to file handle", DN_Str8PrintFmt(buffer_size_str8));
|
||||
DN_TCScratchEnd(&scratch);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_OSErrSink *err)
|
||||
DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err)
|
||||
{
|
||||
// TODO: errno is not thread safe
|
||||
int fd = fileno(DN_Cast(FILE *) file->handle);
|
||||
@@ -622,7 +630,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
|
||||
|
||||
DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
bool result = true;
|
||||
|
||||
// TODO(doyle): Implement this without using the path indexes, it's not
|
||||
@@ -630,7 +638,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
|
||||
DN_USize path_indexes_size = 0;
|
||||
uint16_t path_indexes[64] = {};
|
||||
|
||||
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, path);
|
||||
DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, path);
|
||||
for (DN_USize index = copy.size - 1; index < copy.size; index--) {
|
||||
bool first_char = index == (copy.size - 1);
|
||||
char ch = copy.data[index];
|
||||
@@ -649,6 +657,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
|
||||
// NOTE: There's something that exists in at this path, but
|
||||
// it's not a directory. This request to make a directory is
|
||||
// invalid.
|
||||
DN_TCScratchEnd(&scratch);
|
||||
return false;
|
||||
} else if (DN_OS_PathIsDir(copy)) {
|
||||
// NOTE: We found a directory, we can stop here and start
|
||||
@@ -673,6 +682,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
|
||||
if (index != 0)
|
||||
copy.data[path_index] = temp;
|
||||
}
|
||||
DN_TCScratchEnd(&scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -723,7 +733,7 @@ enum DN_OSPipeType_
|
||||
|
||||
DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
|
||||
DN_Arena *arena,
|
||||
DN_OSErrSink *error)
|
||||
DN_ErrSink *error)
|
||||
{
|
||||
DN_OSExecResult result = {};
|
||||
if (!handle.process || handle.os_error_code || handle.exit_code) {
|
||||
@@ -786,10 +796,10 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
|
||||
|
||||
// NOTE: Read the data from the read end of the pipe
|
||||
if (result.os_error_code == 0) {
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
|
||||
if (arena && handle.stdout_read) {
|
||||
char buffer[4096];
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
|
||||
for (;;) {
|
||||
ssize_t bytes_read =
|
||||
read(stdout_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer));
|
||||
@@ -803,7 +813,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
|
||||
|
||||
if (arena && handle.stderr_read) {
|
||||
char buffer[4096];
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
|
||||
for (;;) {
|
||||
ssize_t bytes_read =
|
||||
read(stderr_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer));
|
||||
@@ -814,6 +824,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
|
||||
|
||||
result.stderr_text = DN_Str8BuilderBuild(&builder, arena);
|
||||
}
|
||||
DN_TCScratchEnd(&scratch);
|
||||
}
|
||||
|
||||
close(stdout_pipe[DN_OSPipeType__Read]);
|
||||
@@ -823,7 +834,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
|
||||
|
||||
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
DN_OSExecArgs *args,
|
||||
DN_OSErrSink *error)
|
||||
DN_ErrSink *error)
|
||||
{
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
DN_InvalidCodePathF("Unsupported operation");
|
||||
@@ -834,12 +845,13 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
if (cmd_line.size == 0)
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 cmd_rendered = DN_Slice_Str8Render(tmem.arena, cmd_line, DN_Str8Lit(" "));
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_DEFER { DN_TCScratchEnd(&scratch); };
|
||||
DN_Str8 cmd_rendered = DN_Slice_Str8Render(scratch.arena, cmd_line, DN_Str8Lit(" "));
|
||||
int stdout_pipe[DN_OSPipeType__Count] = {};
|
||||
int stderr_pipe[DN_OSPipeType__Count] = {};
|
||||
|
||||
// NOTE: Open stdout pipe //////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Open stdout pipe
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
|
||||
if (pipe(stdout_pipe) == -1) {
|
||||
result.os_error_code = errno;
|
||||
@@ -929,7 +941,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
|
||||
// NOTE: Convert the command into something suitable for execvp
|
||||
char **argv =
|
||||
DN_ArenaNewArray(tmem.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes);
|
||||
DN_ArenaNewArray(scratch.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes);
|
||||
if (!argv) {
|
||||
result.exit_code = -1;
|
||||
DN_OS_ErrSinkAppendF(
|
||||
@@ -942,7 +954,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
|
||||
for (DN_ForIndexU(arg_index, cmd_line.size)) {
|
||||
DN_Str8 arg = cmd_line.data[arg_index];
|
||||
argv[arg_index] = DN_Str8FromStr8Arena(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated
|
||||
argv[arg_index] = DN_Str8FromStr8Arena(scratch.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated
|
||||
}
|
||||
|
||||
// NOTE: Change the working directory if there is one
|
||||
@@ -960,7 +972,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
|
||||
if (args->working_dir.size) {
|
||||
prev_working_dir = get_current_dir_name();
|
||||
DN_Str8 working_dir = DN_Str8FromStr8Arena(tmem.arena, args->working_dir);
|
||||
DN_Str8 working_dir = DN_Str8FromStr8Arena(scratch.arena, args->working_dir);
|
||||
if (chdir(working_dir.data) == -1) {
|
||||
result.os_error_code = errno;
|
||||
DN_OS_ErrSinkAppendF(
|
||||
@@ -1014,21 +1026,21 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
|
||||
char *stderr_buffer,
|
||||
size_t *stderr_size,
|
||||
DN_U32 timeout_ms,
|
||||
DN_OSErrSink *err)
|
||||
DN_ErrSink *err)
|
||||
{
|
||||
DN_InvalidCodePath;
|
||||
DN_OSExecResult result = {};
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_POSIXSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64)
|
||||
static DN_OSPosixSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64)
|
||||
{
|
||||
DN_POSIXSyncPrimitive *result = nullptr;
|
||||
DN_OSPosixSyncPrimitive *result = nullptr;
|
||||
DN_Memcpy(&result, &u64, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive)
|
||||
static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_OSPosixSyncPrimitive *primitive)
|
||||
{
|
||||
DN_U64 result = 0;
|
||||
static_assert(sizeof(result) >= sizeof(primitive), "Pointer size mis-match");
|
||||
@@ -1036,10 +1048,10 @@ static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive)
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
|
||||
static DN_OSPosixSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
|
||||
{
|
||||
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_();
|
||||
DN_POSIXSyncPrimitive *result = nullptr;
|
||||
DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
|
||||
DN_OSPosixSyncPrimitive *result = nullptr;
|
||||
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
|
||||
{
|
||||
if (posix->sync_primitive_free_list) {
|
||||
@@ -1048,17 +1060,17 @@ static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
|
||||
result->next = nullptr;
|
||||
} else {
|
||||
DN_OSCore *os = &g_dn_->os;
|
||||
result = DN_ArenaNew(&os->arena, DN_POSIXSyncPrimitive, DN_ZMem_Yes);
|
||||
result = DN_ArenaNew(&os->arena, DN_OSPosixSyncPrimitive, DN_ZMem_Yes);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive)
|
||||
static void DN_POSIX_DeallocSyncPrimitive_(DN_OSPosixSyncPrimitive *primitive)
|
||||
{
|
||||
if (primitive) {
|
||||
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_();
|
||||
DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
|
||||
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
|
||||
primitive->next = posix->sync_primitive_free_list;
|
||||
posix->sync_primitive_free_list = primitive;
|
||||
@@ -1070,7 +1082,7 @@ static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive)
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
|
||||
{
|
||||
DN_OSSemaphore result = {};
|
||||
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
if (primitive) {
|
||||
int pshared = 0; // Share the semaphore across all threads in the process
|
||||
if (sem_init(&primitive->sem, pshared, initial_count) == 0)
|
||||
@@ -1084,7 +1096,7 @@ DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
|
||||
DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore)
|
||||
{
|
||||
if (semaphore && semaphore->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
sem_destroy(&primitive->sem);
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
*semaphore = {};
|
||||
@@ -1094,7 +1106,7 @@ DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore)
|
||||
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount)
|
||||
{
|
||||
if (semaphore && semaphore->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
#if defined(DN_OS_WIN32)
|
||||
sem_post_multiple(&primitive->sem, amount); // mingw extension
|
||||
#else
|
||||
@@ -1111,7 +1123,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
|
||||
if (!semaphore || semaphore->handle == 0)
|
||||
return result;
|
||||
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) {
|
||||
int wait_result = 0;
|
||||
do {
|
||||
@@ -1138,7 +1150,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
|
||||
// NOTE: DN_OSMutex ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSMutex DN_OS_MutexInit()
|
||||
{
|
||||
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
DN_OSMutex result = {};
|
||||
if (primitive) {
|
||||
if (pthread_mutex_init(&primitive->mutex, nullptr) == 0)
|
||||
@@ -1152,7 +1164,7 @@ DN_API DN_OSMutex DN_OS_MutexInit()
|
||||
DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex)
|
||||
{
|
||||
if (mutex && mutex->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
pthread_mutex_destroy(&primitive->mutex);
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
*mutex = {};
|
||||
@@ -1162,7 +1174,7 @@ DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex)
|
||||
DN_API void DN_OS_MutexLock(DN_OSMutex *mutex)
|
||||
{
|
||||
if (mutex && mutex->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
pthread_mutex_lock(&primitive->mutex);
|
||||
}
|
||||
}
|
||||
@@ -1170,14 +1182,14 @@ DN_API void DN_OS_MutexLock(DN_OSMutex *mutex)
|
||||
DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex)
|
||||
{
|
||||
if (mutex && mutex->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
pthread_mutex_unlock(&primitive->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
|
||||
{
|
||||
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
DN_OSConditionVariable result = {};
|
||||
if (primitive) {
|
||||
if (pthread_cond_init(&primitive->cv, nullptr) == 0)
|
||||
@@ -1191,7 +1203,7 @@ DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
|
||||
DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv)
|
||||
{
|
||||
if (cv && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
pthread_cond_destroy(&primitive->cv);
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
*cv = {};
|
||||
@@ -1202,8 +1214,8 @@ DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMu
|
||||
{
|
||||
bool result = false;
|
||||
if (cv && mutex && mutex->handle != 0 && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
DN_POSIXSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
DN_OSPosixSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
DN_OSPosixSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
|
||||
struct timespec time = {};
|
||||
time.tv_sec = end_ts_ms / 1'000;
|
||||
@@ -1224,7 +1236,7 @@ DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex *
|
||||
DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv)
|
||||
{
|
||||
if (cv && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
pthread_cond_signal(&primitive->cv);
|
||||
}
|
||||
}
|
||||
@@ -1232,7 +1244,7 @@ DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv)
|
||||
DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv)
|
||||
{
|
||||
if (cv && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
pthread_cond_broadcast(&primitive->cv);
|
||||
}
|
||||
}
|
||||
@@ -1307,7 +1319,7 @@ DN_API DN_U32 DN_OS_ThreadID()
|
||||
return DN_Cast(DN_U32) result;
|
||||
}
|
||||
|
||||
DN_API void DN_Posix_Init(DN_POSIXCore *posix)
|
||||
DN_API void DN_OS_PosixInit(DN_OSPosixCore *posix)
|
||||
{
|
||||
int mutex_init = pthread_mutex_init(&posix->sync_primitive_free_list_mutex, nullptr);
|
||||
DN_Assert(mutex_init == 0);
|
||||
@@ -1320,21 +1332,22 @@ DN_API void DN_Posix_Init(DN_POSIXCore *posix)
|
||||
}
|
||||
}
|
||||
|
||||
DN_API void DN_Posix_ThreadSetName(DN_Str8 name)
|
||||
DN_API void DN_OS_PosixThreadSetName(DN_Str8 name)
|
||||
{
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
(void)name;
|
||||
#else
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
|
||||
DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, name);
|
||||
pthread_t thread = pthread_self();
|
||||
pthread_setname_np(thread, (char *)copy.data);
|
||||
DN_TCScratchEnd(&tmem);
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
|
||||
DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus()
|
||||
{
|
||||
DN_POSIXProcSelfStatus result = {};
|
||||
DN_OSPosixProcSelfStatus result = {};
|
||||
|
||||
// NOTE: Example
|
||||
//
|
||||
@@ -1346,11 +1359,11 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
|
||||
//
|
||||
// VmSize is the total virtual memory used
|
||||
DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/proc/self/status"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, nullptr);
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
|
||||
|
||||
if (!file.error) {
|
||||
DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
|
||||
char buf[256];
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
|
||||
for (;;) {
|
||||
DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr);
|
||||
if (!read.success || read.bytes_read == 0)
|
||||
@@ -1362,8 +1375,8 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
|
||||
DN_Str8 const PID = DN_Str8Lit("Pid:");
|
||||
DN_Str8 const VM_PEAK = DN_Str8Lit("VmPeak:");
|
||||
DN_Str8 const VM_SIZE = DN_Str8Lit("VmSize:");
|
||||
DN_Str8 status_buf = DN_Str8BuilderBuildFromTLS(&builder);
|
||||
DN_Str8SplitResult lines = DN_Str8SplitFromTLS(status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No);
|
||||
DN_Str8 status_buf = DN_Str8BuilderBuild(&builder, tmem.arena);
|
||||
DN_Str8SplitResult lines = DN_Str8Split(tmem.arena, status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No);
|
||||
|
||||
for (DN_ForItSize(line_it, DN_Str8, lines.data, lines.count)) {
|
||||
DN_Str8 line = DN_Str8TrimWhitespaceAround(*line_it.data);
|
||||
@@ -1392,6 +1405,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
|
||||
DN_Assert(to_u64.success);
|
||||
}
|
||||
}
|
||||
DN_TCScratchEnd(&tmem);
|
||||
}
|
||||
DN_OS_FileClose(&file);
|
||||
return result;
|
||||
@@ -1406,7 +1420,7 @@ static EM_BOOL EMWebSocketOnOpenCallback(int type, const EmscriptenWebSocketOpen
|
||||
(void)event;
|
||||
// EMSCRIPTEN_RESULT result = emscripten_websocket_send_utf8_text(event->socket, R"({"jsonrpc":"2.0","id":1,"method": "eth_subscribe","params":["newHeads"]})");
|
||||
// if (result)
|
||||
// DN_LOG_InfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result);
|
||||
// DN_LogInfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result);
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
@@ -1416,9 +1430,9 @@ static EM_BOOL EMWebSocketOnMsgCallback(int type, const EmscriptenWebSocketMessa
|
||||
(void)user_context;
|
||||
(void)event;
|
||||
if (event->isText) {
|
||||
DN_LOG_InfoF("Received: %.*s", event->numBytes, event->data);
|
||||
DN_LogInfoF("Received: %.*s", event->numBytes, event->data);
|
||||
} else {
|
||||
DN_LOG_InfoF("Received: %d bytes", event->numBytes);
|
||||
DN_LogInfoF("Received: %d bytes", event->numBytes);
|
||||
}
|
||||
return EM_TRUE;
|
||||
}
|
||||
@@ -1486,12 +1500,13 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
|
||||
|
||||
response->arena = arena;
|
||||
response->builder.arena =
|
||||
response->tmem_arena ? response->tmem_arena : &response->tmp_arena;
|
||||
response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
|
||||
|
||||
DN_Arena *tmem = response->tmem_arena;
|
||||
DN_OSTLSTMem tmem_ = DN_OS_TLSTMem(arena);
|
||||
if (!tmem)
|
||||
tmem = tmem_.arena;
|
||||
DN_Arena *scratch = response->scratch_arena;
|
||||
DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
|
||||
DN_DEFER { DN_TCScratchEnd(&scratch_); };
|
||||
if (!scratch)
|
||||
scratch = scratch_.arena;
|
||||
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
emscripten_fetch_attr_t fetch_attribs = {};
|
||||
@@ -1521,8 +1536,8 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
|
||||
fetch_attribs.onerror = DN_OS_HttpRequestEMFetchOnErrorCallback;
|
||||
fetch_attribs.userData = response;
|
||||
|
||||
DN_Str8 url = DN_Str8FromFmtArena(tmem, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path));
|
||||
DN_LOG_InfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'",
|
||||
DN_Str8 url = DN_Str8FromFmtArena(scratch, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path));
|
||||
DN_LogInfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'",
|
||||
fetch_attribs.requestMethod,
|
||||
DN_Str8PrintFmt(url),
|
||||
DN_Str8PrintFmt(body));
|
||||
|
||||
+15
-33
@@ -2,30 +2,13 @@
|
||||
#define DN_OS_POSIX_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// $$$$$$\ $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\
|
||||
// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ \_$$ _|$$ | $$ |
|
||||
// $$ / $$ |$$ / \__| $$ | $$ |$$ / $$ |$$ / \__| $$ | \$$\ $$ |
|
||||
// $$ | $$ |\$$$$$$\ $$$$$$$ |$$ | $$ |\$$$$$$\ $$ | \$$$$ /
|
||||
// $$ | $$ | \____$$\ $$ ____/ $$ | $$ | \____$$\ $$ | $$ $$<
|
||||
// $$ | $$ |$$\ $$ | $$ | $$ | $$ |$$\ $$ | $$ | $$ /\$$\
|
||||
// $$$$$$ |\$$$$$$ | $$ | $$$$$$ |\$$$$$$ |$$$$$$\ $$ / $$ |
|
||||
// \______/ \______/ \__| \______/ \______/ \______|\__| \__|
|
||||
//
|
||||
// dn_os_posix.h
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
struct DN_POSIXProcSelfStatus
|
||||
struct DN_OSPosixProcSelfStatus
|
||||
{
|
||||
char name[64];
|
||||
DN_U8 name_size;
|
||||
@@ -52,15 +35,14 @@ struct DN_POSIXProcSelfStatus
|
||||
// unlocking, or destroying the object is undefined. [...] The effect of
|
||||
// referring to a copy of the object when locking, unlocking, or destroying it
|
||||
// is undefined.
|
||||
|
||||
enum DN_POSIXSyncPrimitiveType
|
||||
enum DN_OSPosixSyncPrimitiveType
|
||||
{
|
||||
DN_OSPOSIXSyncPrimitiveType_Semaphore,
|
||||
DN_OSPOSIXSyncPrimitiveType_Mutex,
|
||||
DN_OSPOSIXSyncPrimitiveType_ConditionVariable,
|
||||
DN_OSPosixSyncPrimitiveType_Semaphore,
|
||||
DN_OSPosixSyncPrimitiveType_Mutex,
|
||||
DN_OSPosixSyncPrimitiveType_ConditionVariable,
|
||||
};
|
||||
|
||||
struct DN_POSIXSyncPrimitive
|
||||
struct DN_OSPosixSyncPrimitive
|
||||
{
|
||||
union
|
||||
{
|
||||
@@ -68,17 +50,17 @@ struct DN_POSIXSyncPrimitive
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cv;
|
||||
};
|
||||
DN_POSIXSyncPrimitive *next;
|
||||
DN_OSPosixSyncPrimitive *next;
|
||||
};
|
||||
|
||||
struct DN_POSIXCore
|
||||
struct DN_OSPosixCore
|
||||
{
|
||||
DN_POSIXSyncPrimitive *sync_primitive_free_list;
|
||||
pthread_mutex_t sync_primitive_free_list_mutex;
|
||||
bool clock_monotonic_raw;
|
||||
DN_OSPosixSyncPrimitive *sync_primitive_free_list;
|
||||
pthread_mutex_t sync_primitive_free_list_mutex;
|
||||
bool clock_monotonic_raw;
|
||||
};
|
||||
|
||||
DN_API void DN_Posix_Init(DN_POSIXCore *posix);
|
||||
DN_API void DN_Posix_ThreadSetName(DN_Str8 name);
|
||||
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus();
|
||||
DN_API void DN_OS_PosixInit (DN_OSPosixCore *posix);
|
||||
DN_API void DN_OS_PosixThreadSetName (DN_Str8 name);
|
||||
DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus();
|
||||
#endif // !defined(DN_OS_POSIX_H)
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
#define DN_OS_PRINT_CPP
|
||||
|
||||
DN_API DN_LOGStyle DN_OS_PrintStyleColour(uint8_t r, uint8_t g, uint8_t b, DN_LOGBold bold)
|
||||
{
|
||||
DN_LOGStyle result = {};
|
||||
result.bold = bold;
|
||||
result.colour = true;
|
||||
result.r = r;
|
||||
result.g = g;
|
||||
result.b = b;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_LOGStyle DN_OS_PrintStyleColourU32(uint32_t rgb, DN_LOGBold bold)
|
||||
{
|
||||
uint8_t r = (rgb >> 24) & 0xFF;
|
||||
uint8_t g = (rgb >> 16) & 0xFF;
|
||||
uint8_t b = (rgb >> 8) & 0xFF;
|
||||
DN_LOGStyle result = DN_OS_PrintStyleColour(r, g, b, bold);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_LOGStyle DN_OS_PrintStyleBold()
|
||||
{
|
||||
DN_LOGStyle result = {};
|
||||
result.bold = DN_LOGBold_Yes;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_Print(DN_OSPrintDest dest, DN_Str8 string)
|
||||
{
|
||||
DN_Assert(dest == DN_OSPrintDest_Out || dest == DN_OSPrintDest_Err);
|
||||
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
// NOTE: Get the output handles from kernel ////////////////////////////////////////////////////
|
||||
DN_THREAD_LOCAL void *std_out_print_handle = nullptr;
|
||||
DN_THREAD_LOCAL void *std_err_print_handle = nullptr;
|
||||
DN_THREAD_LOCAL bool std_out_print_to_console = false;
|
||||
DN_THREAD_LOCAL bool std_err_print_to_console = false;
|
||||
|
||||
if (!std_out_print_handle) {
|
||||
unsigned long mode = 0;
|
||||
(void)mode;
|
||||
std_out_print_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
std_out_print_to_console = GetConsoleMode(std_out_print_handle, &mode) != 0;
|
||||
|
||||
std_err_print_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
std_err_print_to_console = GetConsoleMode(std_err_print_handle, &mode) != 0;
|
||||
}
|
||||
|
||||
// NOTE: Select the output handle //////////////////////////////////////////////////////////////
|
||||
void *print_handle = std_out_print_handle;
|
||||
bool print_to_console = std_out_print_to_console;
|
||||
if (dest == DN_OSPrintDest_Err) {
|
||||
print_handle = std_err_print_handle;
|
||||
print_to_console = std_err_print_to_console;
|
||||
}
|
||||
|
||||
// NOTE: Write the string //////////////////////////////////////////////////////////////////////
|
||||
DN_Assert(string.size < DN_Cast(unsigned long) - 1);
|
||||
unsigned long bytes_written = 0;
|
||||
(void)bytes_written;
|
||||
if (print_to_console)
|
||||
WriteConsoleA(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr);
|
||||
else
|
||||
WriteFile(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr);
|
||||
#else
|
||||
fprintf(dest == DN_OSPrintDest_Out ? stdout : stderr, "%.*s", DN_Str8PrintFmt(string));
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_OS_PrintFV(dest, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_OS_PrintFVStyle(dest, style, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string)
|
||||
{
|
||||
if (string.data && string.size) {
|
||||
if (style.colour)
|
||||
DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b));
|
||||
if (style.bold == DN_LOGBold_Yes)
|
||||
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode));
|
||||
DN_OS_Print(dest, string);
|
||||
if (style.colour || style.bold == DN_LOGBold_Yes)
|
||||
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode));
|
||||
}
|
||||
}
|
||||
|
||||
static char *DN_OS_PrintVSPrintfChunker_(const char *buf, void *user, int len)
|
||||
{
|
||||
DN_Str8 string = {};
|
||||
string.data = DN_Cast(char *) buf;
|
||||
string.size = len;
|
||||
|
||||
DN_OSPrintDest dest = DN_Cast(DN_OSPrintDest) DN_Cast(uintptr_t) user;
|
||||
DN_OS_Print(dest, string);
|
||||
return (char *)buf;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
char buffer[STB_SPRINTF_MIN];
|
||||
STB_SPRINTF_DECORATE(vsprintfcb)
|
||||
(DN_OS_PrintVSPrintfChunker_, DN_Cast(void *) DN_Cast(uintptr_t) dest, buffer, fmt, args);
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
if (fmt) {
|
||||
if (style.colour)
|
||||
DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b));
|
||||
if (style.bold == DN_LOGBold_Yes)
|
||||
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode));
|
||||
DN_OS_PrintFV(dest, fmt, args);
|
||||
if (style.colour || style.bold == DN_LOGBold_Yes)
|
||||
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode));
|
||||
}
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintLn(DN_OSPrintDest dest, DN_Str8 string)
|
||||
{
|
||||
DN_OS_Print(dest, string);
|
||||
DN_OS_Print(dest, DN_Str8Lit("\n"));
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintLnF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_OS_PrintLnFV(dest, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintLnFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_OS_PrintFV(dest, fmt, args);
|
||||
DN_OS_Print(dest, DN_Str8Lit("\n"));
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintLnStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string)
|
||||
{
|
||||
DN_OS_PrintStyle(dest, style, string);
|
||||
DN_OS_Print(dest, DN_Str8Lit("\n"));
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintLnFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_OS_PrintLnFVStyle(dest, style, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
DN_API void DN_OS_PrintLnFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_OS_PrintFVStyle(dest, style, fmt, args);
|
||||
DN_OS_Print(dest, DN_Str8Lit("\n"));
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#if !defined(DN_OS_PRINT_H)
|
||||
#define DN_OS_PRINT_H
|
||||
|
||||
enum DN_OSPrintDest
|
||||
{
|
||||
DN_OSPrintDest_Out,
|
||||
DN_OSPrintDest_Err,
|
||||
};
|
||||
|
||||
// NOTE: Print Macros
|
||||
#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string)
|
||||
#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args)
|
||||
|
||||
#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string)
|
||||
#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args)
|
||||
|
||||
#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string)
|
||||
#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args)
|
||||
|
||||
#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string);
|
||||
#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args);
|
||||
|
||||
#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string)
|
||||
#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args)
|
||||
|
||||
#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string)
|
||||
#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args)
|
||||
|
||||
#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string)
|
||||
#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args)
|
||||
|
||||
#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string);
|
||||
#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args);
|
||||
|
||||
// NOTE: Print
|
||||
DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string);
|
||||
DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
#endif // !defined(DN_OS_PRINT_H)
|
||||
@@ -1,211 +0,0 @@
|
||||
#define DN_CORE_DEBUG_CPP
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#define DN_H_WITH_OS 1
|
||||
#include "../dn.h"
|
||||
#endif
|
||||
|
||||
DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, uint16_t limit)
|
||||
{
|
||||
DN_StackTraceWalkResult result = {};
|
||||
#if defined(DN_OS_WIN32)
|
||||
if (!arena)
|
||||
return result;
|
||||
|
||||
static DN_TicketMutex mutex = {};
|
||||
DN_TicketMutex_Begin(&mutex);
|
||||
|
||||
HANDLE thread = GetCurrentThread();
|
||||
result.process = GetCurrentProcess();
|
||||
|
||||
DN_W32Core *w32 = DN_OS_GetW32Core_();
|
||||
if (!w32->sym_initialised) {
|
||||
w32->sym_initialised = true;
|
||||
SymSetOptions(SYMOPT_LOAD_LINES);
|
||||
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
|
||||
DN_W32Error error = DN_W32_LastError(tmem.arena);
|
||||
DN_LOG_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg));
|
||||
}
|
||||
}
|
||||
|
||||
CONTEXT context;
|
||||
RtlCaptureContext(&context);
|
||||
|
||||
STACKFRAME64 frame = {};
|
||||
frame.AddrPC.Offset = context.Rip;
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
frame.AddrFrame.Offset = context.Rbp;
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
frame.AddrStack.Offset = context.Rsp;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
|
||||
DN_FArray<uint64_t, 256> raw_frames = {};
|
||||
while (raw_frames.size < limit) {
|
||||
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64,
|
||||
result.process,
|
||||
thread,
|
||||
&frame,
|
||||
&context,
|
||||
nullptr /*ReadMemoryRoutine*/,
|
||||
SymFunctionTableAccess64,
|
||||
SymGetModuleBase64,
|
||||
nullptr /*TranslateAddress*/))
|
||||
break;
|
||||
|
||||
// NOTE: It might be useful one day to use frame.AddrReturn.Offset.
|
||||
// If AddrPC.Offset == AddrReturn.Offset then we can detect recursion.
|
||||
DN_FArray_Add(&raw_frames, frame.AddrPC.Offset);
|
||||
}
|
||||
DN_TicketMutex_End(&mutex);
|
||||
|
||||
result.base_addr = DN_ArenaNewArray(arena, uint64_t, raw_frames.size, DN_ZMem_No);
|
||||
result.size = DN_Cast(uint16_t) raw_frames.size;
|
||||
DN_Memcpy(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0]));
|
||||
#else
|
||||
(void)limit;
|
||||
(void)arena;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DN_StackTraceAddWalkToStr8Builder(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip)
|
||||
{
|
||||
DN_StackTraceRawFrame raw_frame = {};
|
||||
raw_frame.process = walk->process;
|
||||
for (DN_USize index = skip; index < walk->size; index++) {
|
||||
raw_frame.base_addr = walk->base_addr[index];
|
||||
DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(builder->arena, raw_frame);
|
||||
DN_Str8BuilderAppendF(builder, "%.*s(%zu): %.*s%s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name), (DN_Cast(int) index == walk->size - 1) ? "" : "\n");
|
||||
}
|
||||
}
|
||||
|
||||
DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk)
|
||||
{
|
||||
bool result = false;
|
||||
if (!it || !walk || !walk->base_addr || !walk->process)
|
||||
return result;
|
||||
|
||||
if (it->index >= walk->size)
|
||||
return false;
|
||||
|
||||
result = true;
|
||||
it->raw_frame.process = walk->process;
|
||||
it->raw_frame.base_addr = walk->base_addr[it->index++];
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip)
|
||||
{
|
||||
DN_Str8 result{};
|
||||
if (!walk || !arena)
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
|
||||
DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip);
|
||||
result = DN_Str8BuilderBuild(&builder, arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, uint16_t limit, uint16_t skip)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
|
||||
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit);
|
||||
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap(uint16_t limit, uint16_t skip)
|
||||
{
|
||||
// NOTE: We don't use WalkResultToStr8 because that uses the TLS arenas which
|
||||
// does not use the OS heap.
|
||||
DN_Arena arena = DN_ArenaFromHeap(DN_Kilobytes(64), DN_ArenaFlags_NoAllocTrack);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena);
|
||||
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit);
|
||||
DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip);
|
||||
DN_Str8 result = DN_Str8BuilderBuildFromOSHeap(&builder);
|
||||
DN_ArenaDeinit(&arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Slice<DN_StackTraceFrame> DN_StackTraceGetFrames(DN_Arena *arena, uint16_t limit)
|
||||
{
|
||||
DN_Slice<DN_StackTraceFrame> result = {};
|
||||
if (!arena)
|
||||
return result;
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
|
||||
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit);
|
||||
if (!walk.size)
|
||||
return result;
|
||||
|
||||
DN_USize slice_index = 0;
|
||||
result = DN_Slice_Alloc<DN_StackTraceFrame>(arena, walk.size, DN_ZMem_No);
|
||||
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);)
|
||||
result.data[slice_index++] = DN_StackTraceRawFrameToFrame(arena, it.raw_frame);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame(DN_Arena *arena, DN_StackTraceRawFrame raw_frame)
|
||||
{
|
||||
#if defined(DN_OS_WIN32)
|
||||
// NOTE: Get line+filename
|
||||
|
||||
// TODO: Why does zero-initialising this with `line = {};` cause
|
||||
// SymGetLineFromAddr64 function to fail once we are at
|
||||
// __scrt_commain_main_seh and hit BaseThreadInitThunk frame? The
|
||||
// line and file number are still valid in the result which we use, so,
|
||||
// we silently ignore this error.
|
||||
IMAGEHLP_LINEW64 line;
|
||||
line.SizeOfStruct = sizeof(line);
|
||||
DWORD line_displacement = 0;
|
||||
if (!SymGetLineFromAddrW64(raw_frame.process, raw_frame.base_addr, &line_displacement, &line))
|
||||
line = {};
|
||||
|
||||
// NOTE: Get function name
|
||||
|
||||
alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {};
|
||||
SYMBOL_INFOW *symbol = DN_Cast(SYMBOL_INFOW *) buffer;
|
||||
symbol->SizeOfStruct = sizeof(*symbol);
|
||||
symbol->MaxNameLen = sizeof(buffer) - sizeof(*symbol);
|
||||
|
||||
uint64_t symbol_displacement = 0; // Offset to the beginning of the symbol to the address
|
||||
SymFromAddrW(raw_frame.process, raw_frame.base_addr, &symbol_displacement, symbol);
|
||||
|
||||
// NOTE: Construct result
|
||||
|
||||
DN_Str16 file_name16 = DN_Str16{line.FileName, DN_CStr16Size(line.FileName)};
|
||||
DN_Str16 function_name16 = DN_Str16{symbol->Name, symbol->NameLen};
|
||||
|
||||
DN_StackTraceFrame result = {};
|
||||
result.address = raw_frame.base_addr;
|
||||
result.line_number = line.LineNumber;
|
||||
result.file_name = DN_W32_Str16ToStr8(arena, file_name16);
|
||||
result.function_name = DN_W32_Str16ToStr8(arena, function_name16);
|
||||
|
||||
if (result.function_name.size == 0)
|
||||
result.function_name = DN_Str8Lit("<unknown function>");
|
||||
if (result.file_name.size == 0)
|
||||
result.file_name = DN_Str8Lit("<unknown file>");
|
||||
#else
|
||||
DN_StackTraceFrame result = {};
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_StackTracePrint(uint16_t limit)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Slice<DN_StackTraceFrame> stack_trace = DN_StackTraceGetFrames(tmem.arena, limit);
|
||||
for (DN_StackTraceFrame &frame : stack_trace)
|
||||
DN_OS_PrintErrLnF("%.*s(%I64u): %.*s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name));
|
||||
}
|
||||
|
||||
DN_API void DN_StackTraceReloadSymbols()
|
||||
{
|
||||
#if defined(DN_OS_WIN32)
|
||||
HANDLE process = GetCurrentProcess();
|
||||
SymRefreshModuleList(process);
|
||||
#endif
|
||||
}
|
||||
@@ -1,305 +0,0 @@
|
||||
#define DN_OS_STRING_CPP
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
#endif
|
||||
|
||||
// NOTE: DN_Str8
|
||||
DN_API DN_Str8 DN_Str8FromFmtArenaFrame(DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
|
||||
DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromFmtVArenaFrame(DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
|
||||
DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromArenaFrame(DN_USize size, DN_ZMem z_mem)
|
||||
{
|
||||
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
|
||||
DN_Str8 result = DN_Str8FromArena(frame_arena, size, z_mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromHeapF(DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_USize size = DN_FmtVSize(fmt, args);
|
||||
DN_Str8 result = DN_Str8FromHeap(size, DN_ZMem_No);
|
||||
DN_VSNPrintF(result.data, DN_Cast(int)(result.size + 1), fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromHeap(DN_USize size, DN_ZMem z_mem)
|
||||
{
|
||||
DN_Str8 result = {};
|
||||
result.data = DN_Cast(char *)DN_OS_MemAlloc(size + 1, z_mem);
|
||||
if (result.data) {
|
||||
result.size = size;
|
||||
result.data[result.size] = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromTLSFV(DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromTLSF(DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromTLS(DN_USize size, DN_ZMem z_mem)
|
||||
{
|
||||
DN_Str8 result = DN_Str8FromArena(DN_OS_TLSTopArena(), size, z_mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromStr8Frame(DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSGet()->frame_arena, string);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromStr8TLS(DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSTopArena(), string);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8SplitResult DN_Str8SplitFromFrame(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode)
|
||||
{
|
||||
DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSGet()->frame_arena, string, delimiter, mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8SplitResult DN_Str8SplitFromTLS(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode)
|
||||
{
|
||||
DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSTopArena(), string, delimiter, mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8SegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char)
|
||||
{
|
||||
DN_Str8 result = DN_Str8Segment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8SegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char)
|
||||
{
|
||||
DN_Str8 result = DN_Str8Segment(DN_OS_TLSTopArena(), src, segment_size, segment_char);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char)
|
||||
{
|
||||
DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char)
|
||||
{
|
||||
DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSTopArena(), src, segment_size, segment_char);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8AppendFFromFrame(DN_Str8 string, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSGet()->frame_arena, string, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8AppendFFromTLS(DN_Str8 string, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSTopArena(), string, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FillFFromFrame(DN_USize count, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_Str8 result = DN_Str8FillFV(DN_OS_TLSGet()->frame_arena, count, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8FillFFromTLS(DN_USize count, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_Str8 result = DN_Str8FillFV(DN_OS_TLSTopArena(), count, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator)
|
||||
{
|
||||
DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSGet()->frame_arena, str8, side_size, truncator);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator)
|
||||
{
|
||||
DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSTopArena(), str8, side_size, truncator);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad)
|
||||
{
|
||||
// TODO: Implement this without requiring TLS so it can go into base strings
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
|
||||
|
||||
DN_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n"));
|
||||
while (split.lhs.size) {
|
||||
DN_Str8BuilderAppendRef(&builder, pad);
|
||||
DN_Str8BuilderAppendRef(&builder, split.lhs);
|
||||
split = DN_Str8BSplit(split.rhs, DN_Str8Lit("\n"));
|
||||
if (split.lhs.size)
|
||||
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
|
||||
}
|
||||
|
||||
DN_Str8 result = DN_Str8BuilderBuild(&builder, arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8PadNewLinesFromFrame(DN_Str8 src, DN_Str8 pad)
|
||||
{
|
||||
DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSGet()->frame_arena, src, pad);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8PadNewLinesFromTLS(DN_Str8 src, DN_Str8 pad)
|
||||
{
|
||||
DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSTopArena(), src, pad);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8UpperFromFrame(DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8Upper(DN_OS_TLSGet()->frame_arena, string);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8UpperFromTLS(DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8Upper(DN_OS_TLSTopArena(), string);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8LowerFromFrame(DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8Lower(DN_OS_TLSGet()->frame_arena, string);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8LowerFromTLS(DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8Lower(DN_OS_TLSTopArena(), string);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8Replace(DN_Str8 string,
|
||||
DN_Str8 find,
|
||||
DN_Str8 replace,
|
||||
DN_USize start_index,
|
||||
DN_Arena *arena,
|
||||
DN_Str8EqCase eq_case)
|
||||
{
|
||||
// TODO: Implement this without requiring TLS so it can go into base strings
|
||||
DN_Str8 result = {};
|
||||
if (string.size == 0 || find.size == 0 || find.size > string.size || find.size == 0 || string.size == 0) {
|
||||
result = DN_Str8FromStr8Arena(arena, string);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
|
||||
DN_Str8Builder string_builder = DN_Str8BuilderFromArena(tmem.arena);
|
||||
DN_USize max = string.size - find.size;
|
||||
DN_USize head = start_index;
|
||||
|
||||
for (DN_USize tail = head; tail <= max; tail++) {
|
||||
DN_Str8 check = DN_Str8Slice(string, tail, find.size);
|
||||
if (!DN_Str8Eq(check, find, eq_case))
|
||||
continue;
|
||||
|
||||
if (start_index > 0 && string_builder.string_size == 0) {
|
||||
// User provided a hint in the string to start searching from, we
|
||||
// need to add the string up to the hint. We only do this if there's
|
||||
// a replacement action, otherwise we have a special case for no
|
||||
// replacements, where the entire string gets copied.
|
||||
DN_Str8 slice = DN_Str8FromPtr(string.data, head);
|
||||
DN_Str8BuilderAppendRef(&string_builder, slice);
|
||||
}
|
||||
|
||||
DN_Str8 range = DN_Str8Slice(string, head, (tail - head));
|
||||
DN_Str8BuilderAppendRef(&string_builder, range);
|
||||
DN_Str8BuilderAppendRef(&string_builder, replace);
|
||||
head = tail + find.size;
|
||||
tail += find.size - 1; // NOTE: -1 since the for loop will post increment us past the end of the find string
|
||||
}
|
||||
|
||||
if (string_builder.string_size == 0) {
|
||||
// NOTE: No replacement possible, so we just do a full-copy
|
||||
result = DN_Str8FromStr8Arena(arena, string);
|
||||
} else {
|
||||
DN_Str8 remainder = DN_Str8FromPtr(string.data + head, string.size - head);
|
||||
DN_Str8BuilderAppendRef(&string_builder, remainder);
|
||||
result = DN_Str8BuilderBuild(&string_builder, arena);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_Str8ReplaceInsensitive(DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena)
|
||||
{
|
||||
DN_Str8 result = DN_Str8Replace(string, find, replace, start_index, arena, DN_Str8EqCase_Insensitive);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: DN_Str8Builder ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str8 DN_Str8BuilderBuildFromOSHeap(DN_Str8Builder const *builder)
|
||||
{
|
||||
DN_Str8 result = DN_ZeroInit;
|
||||
if (!builder || builder->string_size <= 0 || builder->count <= 0)
|
||||
return result;
|
||||
|
||||
result.data = DN_Cast(char *) DN_OS_MemAlloc(builder->string_size + 1, DN_ZMem_No);
|
||||
if (!result.data)
|
||||
return result;
|
||||
|
||||
for (DN_Str8Link *link = builder->head; link; link = link->next) {
|
||||
DN_Memcpy(result.data + result.size, link->string.data, link->string.size);
|
||||
result.size += link->string.size;
|
||||
}
|
||||
|
||||
result.data[result.size] = 0;
|
||||
DN_Assert(result.size == builder->string_size);
|
||||
return result;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
#if !defined(DN_OS_STRING_H)
|
||||
#define DN_OS_STRING_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
#endif
|
||||
|
||||
// NOTE: DN_Str8
|
||||
|
||||
DN_API DN_Str8 DN_Str8FromFmtVArenaFrame (DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Str8 DN_Str8FromFmtArenaFrame (DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Str8FromArenaFrame (DN_USize size, DN_ZMem z_mem);
|
||||
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
|
||||
DN_API DN_Str8 DN_Str8FromTLSFV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Str8 DN_Str8FromTLSF (DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Str8FromTLS (DN_USize size, DN_ZMem z_mem);
|
||||
DN_API DN_Str8 DN_Str8FromStr8Frame (DN_Str8 string);
|
||||
DN_API DN_Str8 DN_Str8FromStr8TLS (DN_Str8 string);
|
||||
|
||||
DN_API DN_Str8SplitResult DN_Str8SplitFromFrame (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
|
||||
DN_API DN_Str8SplitResult DN_Str8SplitFromTLS (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
|
||||
|
||||
DN_API DN_Str8 DN_Str8SegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char);
|
||||
DN_API DN_Str8 DN_Str8SegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char);
|
||||
|
||||
DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char);
|
||||
DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char);
|
||||
|
||||
DN_API DN_Str8 DN_Str8AppendFFromFrame (DN_Str8 string, char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Str8AppendFFromTLS (DN_Str8 string, char const *fmt, ...);
|
||||
|
||||
DN_API DN_Str8 DN_Str8FillFFromFrame (DN_Str8 string, char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Str8FillFFromTLS (DN_Str8 string, char const *fmt, ...);
|
||||
|
||||
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator);
|
||||
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator);
|
||||
|
||||
DN_API DN_Str8 DN_Str8PadNewLines (DN_Arena *arena, DN_Str8 src, DN_Str8 pad);
|
||||
DN_API DN_Str8 DN_Str8PadNewLinesFromFrame (DN_Str8 src, DN_Str8 pad);
|
||||
DN_API DN_Str8 DN_Str8PadNewLinesFromTLS (DN_Str8 src, DN_Str8 pad);
|
||||
|
||||
DN_API DN_Str8 DN_Str8UpperFromFrame (DN_Str8 string);
|
||||
DN_API DN_Str8 DN_Str8UpperFromTLS (DN_Str8 string);
|
||||
|
||||
DN_API DN_Str8 DN_Str8LowerFromFrame (DN_Str8 string);
|
||||
DN_API DN_Str8 DN_Str8LowerFromTLS (DN_Str8 string);
|
||||
|
||||
DN_API DN_Str8 DN_Str8Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
||||
DN_API DN_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
|
||||
|
||||
// NOTE: DN_Str8Builder ////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromArena () { return DN_Str8BuilderFromArena(DN_OS_TLSGet()->frame_arena); }
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromTLS () { return DN_Str8BuilderFromArena(DN_OS_TLSTopArena()); }
|
||||
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSGet()->frame_arena, strings, size); }
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSTopArena(), strings, size); }
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSGet()->frame_arena, strings, size); }
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSTopArena(), strings, size); }
|
||||
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromBuilderFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSGet()->frame_arena, builder); }
|
||||
DN_API DN_Str8Builder DN_Str8BuilderFromBuilderTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSTopArena(), builder); }
|
||||
|
||||
DN_API DN_Str8 DN_Str8BuilderBuildFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSGet()->frame_arena); }
|
||||
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder, DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_Str8BuilderBuildFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSTopArena()); }
|
||||
|
||||
DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromFrame(DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSGet()->frame_arena); }
|
||||
DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromTLS (DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSTopArena()); }
|
||||
|
||||
DN_API DN_Slice<DN_Str8> DN_Str8BuilderBuildSliceFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSGet()->frame_arena); }
|
||||
DN_API DN_Slice<DN_Str8> DN_Str8BuilderBuildSliceFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSTopArena()); }
|
||||
|
||||
#endif // !defined(DN_OS_STRING_H)
|
||||
@@ -1,418 +0,0 @@
|
||||
#define DN_OS_TLSCPP
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "dn_os_tls.h"
|
||||
#endif
|
||||
|
||||
// NOTE: DN_OSTLS ////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_OSTLSTMem::DN_OSTLSTMem(DN_OSTLS *tls, DN_U8 arena_index, DN_OSTLSPushTMem push_tmem)
|
||||
{
|
||||
DN_Assert(arena_index == DN_OSTLSArena_TMem0 || arena_index == DN_OSTLSArena_TMem1);
|
||||
arena = tls->arenas + arena_index;
|
||||
temp_mem = DN_ArenaTempMemBegin(arena);
|
||||
destructed = false;
|
||||
push_arena = push_tmem;
|
||||
if (push_arena)
|
||||
DN_OS_TLSPushArena(arena);
|
||||
}
|
||||
|
||||
DN_OSTLSTMem::~DN_OSTLSTMem()
|
||||
{
|
||||
DN_Assert(destructed == false);
|
||||
DN_ArenaTempMemEnd(temp_mem);
|
||||
destructed = true;
|
||||
if (push_arena)
|
||||
DN_OS_TLSPopArena();
|
||||
}
|
||||
|
||||
DN_API void DN_OS_TLSInit(DN_OSTLS *tls, DN_OSTLSInitArgs args)
|
||||
{
|
||||
DN_Check(tls);
|
||||
if (tls->init)
|
||||
return;
|
||||
|
||||
DN_U64 reserve = args.reserve ? args.reserve : DN_Kilobytes(64);
|
||||
DN_U64 err_sink_reserve = args.err_sink_reserve ? args.err_sink_reserve : DN_Kilobytes(64);
|
||||
|
||||
#if !defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
DN_U64 commit = args.commit ? args.commit : DN_Kilobytes(4);
|
||||
DN_U64 err_sink_commit = args.err_sink_commit ? args.err_sink_commit : DN_Kilobytes(4);
|
||||
#endif
|
||||
|
||||
// TODO: We shouldn't have the no alloc track flag here but the initial TLS
|
||||
// init on OS init happens before CORE init. CORE init is the one responsible
|
||||
// for setting up the alloc tracking data structures.
|
||||
for (DN_ForItCArray(it, DN_Arena, tls->arenas)) {
|
||||
DN_Arena *arena = it.data;
|
||||
switch (DN_Cast(DN_OSTLSArena) it.index) {
|
||||
default: {
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
*arena = DN_ArenaFromHeap(reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
|
||||
#else
|
||||
*arena = DN_ArenaFromVMem(reserve, commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case DN_OSTLSArena_ErrorSink: {
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
*arena = DN_ArenaFromHeap(err_sink_reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
|
||||
#else
|
||||
*arena = DN_ArenaFromVMem(err_sink_reserve, err_sink_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case DN_OSTLSArena_Count: DN_InvalidCodePath; break;
|
||||
}
|
||||
}
|
||||
|
||||
tls->thread_id = DN_OS_ThreadID();
|
||||
tls->err_sink.arena = tls->arenas + DN_OSTLSArena_ErrorSink;
|
||||
tls->init = true;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_TLSDeinit(DN_OSTLS *tls)
|
||||
{
|
||||
tls->init = false;
|
||||
tls->err_sink = {};
|
||||
tls->arena_stack_index = {};
|
||||
for (DN_ForItCArray(it, DN_Arena, tls->arenas))
|
||||
DN_ArenaDeinit(it.data);
|
||||
}
|
||||
|
||||
DN_THREAD_LOCAL DN_OSTLS *g_dn_curr_thread_tls;
|
||||
DN_API void DN_OS_TLSSetCurrentThreadTLS(DN_OSTLS *tls)
|
||||
{
|
||||
g_dn_curr_thread_tls = tls;
|
||||
}
|
||||
|
||||
DN_API DN_OSTLS *DN_OS_TLSGet()
|
||||
{
|
||||
DN_RawAssert(g_dn_curr_thread_tls &&
|
||||
"DN must be initialised (via DN_Core_Init) before calling any functions depending on "
|
||||
"TLS if this is the main thread, OR, the created thread has not called "
|
||||
"SetCurrentThreadTLS yet so the TLS data structure hasn't been assigned yet");
|
||||
return g_dn_curr_thread_tls;
|
||||
}
|
||||
|
||||
DN_API DN_Arena *DN_OS_TLSArena()
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_Arena *result = tls->arenas + DN_OSTLSArena_Main;
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: Is there a way to handle conflict arenas without the user needing to
|
||||
// manually pass it in?
|
||||
DN_API DN_OSTLSTMem DN_OS_TLSGetTMem(void const *conflict_arena, DN_OSTLSPushTMem push_tmem)
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_U8 tls_index = (DN_U8)-1;
|
||||
for (DN_U8 index = DN_OSTLSArena_TMem0; index <= DN_OSTLSArena_TMem1; index++) {
|
||||
DN_Arena *arena = tls->arenas + index;
|
||||
if (!conflict_arena || arena != conflict_arena) {
|
||||
tls_index = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DN_Assert(tls_index != (DN_U8)-1);
|
||||
return DN_OSTLSTMem(tls, tls_index, push_tmem);
|
||||
}
|
||||
|
||||
DN_API void DN_OS_TLSPushArena(DN_Arena *arena)
|
||||
{
|
||||
DN_Assert(arena);
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_Assert(tls->arena_stack_index < DN_ArrayCountU(tls->arena_stack));
|
||||
tls->arena_stack[tls->arena_stack_index++] = arena;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_TLSPopArena()
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_Assert(tls->arena_stack_index > 0);
|
||||
tls->arena_stack_index--;
|
||||
}
|
||||
|
||||
DN_API DN_Arena *DN_OS_TLSTopArena()
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_Arena *result = nullptr;
|
||||
if (tls->arena_stack_index)
|
||||
result = tls->arena_stack[tls->arena_stack_index - 1];
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_TLSBeginFrame(DN_Arena *frame_arena)
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
tls->frame_arena = frame_arena;
|
||||
}
|
||||
|
||||
DN_API DN_Arena *DN_OS_TLSFrameArena()
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_Arena *result = tls->frame_arena;
|
||||
DN_AssertF(result, "Frame arena must be set by calling DN_OS_TLSBeginFrame at the beginning of the frame");
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: DN_OSErrSink ////////////////////////////////////////////////////////////////////////////////
|
||||
static void DN_OS_ErrSinkCheck_(DN_OSErrSink const *err)
|
||||
{
|
||||
DN_AssertF(err->arena, "Arena should be assigned in TLS init");
|
||||
if (err->stack_size == 0)
|
||||
return;
|
||||
|
||||
DN_OSErrSinkNode const *node = err->stack + (err->stack_size - 1);
|
||||
DN_Assert(node->mode >= DN_OSErrSinkMode_Nil && node->mode <= DN_OSErrSinkMode_ExitOnError);
|
||||
DN_Assert(node->msg_sentinel);
|
||||
|
||||
// NOTE: Walk the list ensuring we eventually terminate at the sentinel (e.g. we have a
|
||||
// well formed doubly-linked-list terminated by a sentinel, or otherwise we will hit the
|
||||
// walk limit or dereference a null pointer and assert)
|
||||
size_t WALK_LIMIT = 99'999;
|
||||
size_t walk = 0;
|
||||
for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next, walk++) {
|
||||
DN_AssertF(it, "Encountered null pointer which should not happen in a sentinel DLL");
|
||||
DN_Assert(walk < WALK_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
DN_API DN_OSErrSink *DN_OS_ErrSinkBegin_(DN_OSErrSinkMode mode, DN_CallSite call_site)
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_OSErrSink *err = &tls->err_sink;
|
||||
DN_OSErrSink *result = err;
|
||||
DN_USize arena_pos = DN_ArenaPos(result->arena);
|
||||
|
||||
if (tls->err_sink.stack_size == DN_ArrayCountU(err->stack)) {
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
|
||||
DN_USize counter = 0;
|
||||
for (DN_ForItSize(it, DN_OSErrSinkNode, err->stack, err->stack_size)) {
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(4) when a string is required in call to 'DN_Str8BuilderAppendF' Actual type: 'struct DN_Str8'.
|
||||
DN_Str8BuilderAppendF(&builder, " [%04zu] %S:%u %S\n", counter++, it.data->call_site.file, it.data->call_site.line, it.data->call_site.function);
|
||||
DN_MSVC_WARNING_POP
|
||||
}
|
||||
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(6) when a string is required in call to 'DN_LOG_EmitFromType' Actual type: 'struct DN_Str8'.
|
||||
DN_AssertF(tls->err_sink.stack_size < DN_ArrayCountU(err->stack),
|
||||
"Error sink has run out of error scopes, potential leak. Scopes were\n%S", DN_Str8BuilderBuildFromTLS(&builder));
|
||||
DN_MSVC_WARNING_POP
|
||||
}
|
||||
|
||||
DN_OSErrSinkNode *node = tls->err_sink.stack + tls->err_sink.stack_size++;
|
||||
node->arena_pos = arena_pos;
|
||||
node->mode = mode;
|
||||
node->call_site = call_site;
|
||||
DN_DLList_InitArena(node->msg_sentinel, DN_OSErrSinkMsg, result->arena);
|
||||
|
||||
// NOTE: Handle allocation error
|
||||
if (!DN_Check(node && node->msg_sentinel)) {
|
||||
DN_ArenaPopTo(result->arena, arena_pos);
|
||||
node->msg_sentinel = nullptr;
|
||||
tls->err_sink.stack_size--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_ErrSinkHasError(DN_OSErrSink *err)
|
||||
{
|
||||
bool result = false;
|
||||
if (err && err->stack_size) {
|
||||
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
|
||||
result = DN_DLList_HasItems(node->msg_sentinel);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSErrSinkMsg *DN_OS_ErrSinkEnd(DN_Arena *arena, DN_OSErrSink *err)
|
||||
{
|
||||
DN_OSErrSinkMsg *result = nullptr;
|
||||
DN_OS_ErrSinkCheck_(err);
|
||||
if (!err || err->stack_size == 0)
|
||||
return result;
|
||||
|
||||
DN_AssertF(arena != err->arena,
|
||||
"You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost");
|
||||
// NOTE: Walk the list and allocate it onto the user's arena
|
||||
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
|
||||
DN_OSErrSinkMsg *prev = nullptr;
|
||||
for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next) {
|
||||
DN_OSErrSinkMsg *entry = DN_ArenaNew(arena, DN_OSErrSinkMsg, DN_ZMem_Yes);
|
||||
entry->msg = DN_Str8FromStr8Arena(arena, it->msg);
|
||||
entry->call_site = it->call_site;
|
||||
entry->error_code = it->error_code;
|
||||
if (!result)
|
||||
result = entry; // Assign first entry if we haven't yet
|
||||
if (prev)
|
||||
prev->next = entry; // Link the prev message to the current one
|
||||
prev = entry; // Update prev to latest
|
||||
}
|
||||
|
||||
// NOTE: Deallocate all the memory for this scope
|
||||
err->stack_size--;
|
||||
DN_ArenaPopTo(err->arena, node->arena_pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DN_OS_ErrSinkAddMsgToStr8Builder(DN_Str8Builder *builder, DN_OSErrSinkMsg *msg, DN_OSErrSinkMsg *end)
|
||||
{
|
||||
if (msg == end) // NOTE: No error messages to add
|
||||
return;
|
||||
|
||||
if (msg->next == end) {
|
||||
DN_OSErrSinkMsg *it = msg;
|
||||
DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file);
|
||||
DN_Str8BuilderAppendF(builder,
|
||||
"%.*s:%05I32u:%.*s %.*s",
|
||||
DN_Str8PrintFmt(file_name),
|
||||
it->call_site.line,
|
||||
DN_Str8PrintFmt(it->call_site.function),
|
||||
DN_Str8PrintFmt(it->msg));
|
||||
} else {
|
||||
// NOTE: More than one message
|
||||
for (DN_OSErrSinkMsg *it = msg; it != end; it = it->next) {
|
||||
DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file);
|
||||
DN_Str8BuilderAppendF(builder,
|
||||
"%s - %.*s:%05I32u:%.*s%s%.*s",
|
||||
it == msg ? "" : "\n",
|
||||
DN_Str8PrintFmt(file_name),
|
||||
it->call_site.line,
|
||||
DN_Str8PrintFmt(it->call_site.function),
|
||||
it->msg.size ? " " : "",
|
||||
DN_Str8PrintFmt(it->msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_OS_ErrSinkEndStr8(DN_Arena *arena, DN_OSErrSink *err)
|
||||
{
|
||||
DN_Str8 result = {};
|
||||
DN_OS_ErrSinkCheck_(err);
|
||||
if (!err || err->stack_size == 0)
|
||||
return result;
|
||||
|
||||
DN_AssertF(arena != err->arena,
|
||||
"You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost");
|
||||
|
||||
// NOTE: Walk the list and allocate it onto the user's arena
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
|
||||
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
|
||||
DN_OS_ErrSinkAddMsgToStr8Builder(&builder, node->msg_sentinel->next, node->msg_sentinel);
|
||||
|
||||
// NOTE: Deallocate all the memory for this scope
|
||||
err->stack_size--;
|
||||
DN_U64 arena_pos = node->arena_pos;
|
||||
DN_ArenaPopTo(err->arena, arena_pos);
|
||||
|
||||
result = DN_Str8BuilderBuild(&builder, arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_ErrSinkEndAndIgnore(DN_OSErrSink *err)
|
||||
{
|
||||
DN_OS_ErrSinkEnd(nullptr, err);
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogError_(DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 err_msg)
|
||||
{
|
||||
DN_AssertF(err->stack_size, "Begin must be called before calling end");
|
||||
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
|
||||
DN_AssertF(node->msg_sentinel, "Begin must be called before calling end");
|
||||
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
|
||||
DN_OSErrSinkMode mode = node->mode;
|
||||
DN_OSErrSinkMsg *msg = DN_OS_ErrSinkEnd(tmem.arena, err);
|
||||
if (!msg)
|
||||
return false;
|
||||
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
|
||||
if (err_msg.size) {
|
||||
DN_Str8BuilderAppendRef(&builder, err_msg);
|
||||
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit(":"));
|
||||
} else {
|
||||
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("Error(s) encountered:"));
|
||||
}
|
||||
|
||||
if (msg->next) // NOTE: More than 1 message
|
||||
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
|
||||
DN_OS_ErrSinkAddMsgToStr8Builder(&builder, msg, nullptr);
|
||||
|
||||
DN_Str8 log = DN_Str8BuilderBuildFromTLS(&builder);
|
||||
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), call_site, "%.*s", DN_Str8PrintFmt(log));
|
||||
|
||||
if (mode == DN_OSErrSinkMode_DebugBreakOnEndAndLog)
|
||||
DN_DebugBreak;
|
||||
return true;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
|
||||
bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
|
||||
DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
|
||||
bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
if (DN_OS_ErrSinkEndAndLogErrorFV_(err, call_site, fmt, args)) {
|
||||
DN_DebugBreak;
|
||||
DN_OS_Exit(exit_val);
|
||||
}
|
||||
}
|
||||
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_OS_ErrSinkEndAndExitIfErrorFV_(err, call_site, exit_val, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
DN_API void DN_OS_ErrSinkAppendFV_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
if (!err)
|
||||
return;
|
||||
DN_Assert(err && err->stack_size);
|
||||
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
|
||||
DN_AssertF(node, "Error sink must be begun by calling 'Begin' before using this function.");
|
||||
|
||||
DN_OSErrSinkMsg *msg = DN_ArenaNew(err->arena, DN_OSErrSinkMsg, DN_ZMem_Yes);
|
||||
if (DN_Check(msg)) {
|
||||
msg->msg = DN_Str8FromFmtVArena(err->arena, fmt, args);
|
||||
msg->error_code = error_code;
|
||||
msg->call_site = DN_OS_TLSGet()->call_site;
|
||||
DN_DLList_Prepend(node->msg_sentinel, msg);
|
||||
|
||||
if (node->mode == DN_OSErrSinkMode_ExitOnError)
|
||||
DN_OS_ErrSinkEndAndExitIfErrorF_(err, msg->call_site, error_code, "Fatal error %u", error_code);
|
||||
}
|
||||
}
|
||||
|
||||
DN_API void DN_OS_ErrSinkAppendF_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
if (!err)
|
||||
return;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DN_OS_ErrSinkAppendFV_(err, error_code, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
#if !defined(DN_OS_TLS_H)
|
||||
#define DN_OS_TLS_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
#endif
|
||||
|
||||
// NOTE: DN_OSErrSink
|
||||
enum DN_OSErrSinkMode
|
||||
{
|
||||
DN_OSErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
|
||||
DN_OSErrSinkMode_DebugBreakOnEndAndLog, // Debug break (int3) when error is encountered and the sink is ended by the 'end and log' functions.
|
||||
DN_OSErrSinkMode_ExitOnError, // When an error is encountered, exit the program with the error code of the error that was caught.
|
||||
};
|
||||
|
||||
struct DN_OSErrSinkMsg
|
||||
{
|
||||
DN_I32 error_code;
|
||||
DN_Str8 msg;
|
||||
DN_CallSite call_site;
|
||||
DN_OSErrSinkMsg *next;
|
||||
DN_OSErrSinkMsg *prev;
|
||||
};
|
||||
|
||||
struct DN_OSErrSinkNode
|
||||
{
|
||||
DN_CallSite call_site; // Call site that the node was created
|
||||
DN_OSErrSinkMode mode; // Controls how the sink behaves when an error is registered onto the sink.
|
||||
DN_OSErrSinkMsg *msg_sentinel; // List of error messages accumulated for the current scope
|
||||
DN_U64 arena_pos; // Position to reset the arena when the scope is ended
|
||||
};
|
||||
|
||||
struct DN_OSErrSink
|
||||
{
|
||||
DN_Arena * arena; // Dedicated allocator from the thread's local storage
|
||||
DN_OSErrSinkNode stack[128]; // Each entry contains errors accumulated between a [begin, end] region of the active sink.
|
||||
DN_USize stack_size;
|
||||
};
|
||||
|
||||
enum DN_OSTLSArena
|
||||
{
|
||||
DN_OSTLSArena_Main, // NOTE: Arena for permanent allocations
|
||||
DN_OSTLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread
|
||||
|
||||
// NOTE: Per-thread scratch arenas (2 to prevent aliasing)
|
||||
DN_OSTLSArena_TMem0,
|
||||
DN_OSTLSArena_TMem1,
|
||||
|
||||
DN_OSTLSArena_Count,
|
||||
};
|
||||
|
||||
struct DN_OSTLS
|
||||
{
|
||||
DN_B32 init; // Flag to track if TLS has been initialised
|
||||
DN_U64 thread_id;
|
||||
DN_CallSite call_site; // Stores call-site information when requested by thread
|
||||
DN_OSErrSink err_sink; // Error handling state
|
||||
DN_Arena arenas[DN_OSTLSArena_Count]; // Default arenas that the thread has access to implicitly
|
||||
DN_Arena * arena_stack[8]; // Active stack of arenas push/popped arenas on into the TLS
|
||||
DN_USize arena_stack_index;
|
||||
|
||||
DN_Arena * frame_arena;
|
||||
char name[64];
|
||||
DN_U8 name_size;
|
||||
};
|
||||
|
||||
// Push the temporary memory arena when retrieved, popped when the arena goes
|
||||
// out of scope. Pushed arenas are used automatically as the allocator in TLS
|
||||
// suffixed function.
|
||||
enum DN_OSTLSPushTMem
|
||||
{
|
||||
DN_OSTLSPushTMem_No,
|
||||
DN_OSTLSPushTMem_Yes,
|
||||
};
|
||||
|
||||
struct DN_OSTLSTMem
|
||||
{
|
||||
DN_OSTLSTMem(DN_OSTLS *context, uint8_t context_index, DN_OSTLSPushTMem push_scratch);
|
||||
~DN_OSTLSTMem();
|
||||
DN_Arena *arena;
|
||||
DN_B32 destructed;
|
||||
DN_OSTLSPushTMem push_arena;
|
||||
DN_ArenaTempMem temp_mem;
|
||||
};
|
||||
|
||||
struct DN_OSTLSInitArgs
|
||||
{
|
||||
DN_U64 reserve;
|
||||
DN_U64 commit;
|
||||
DN_U64 err_sink_reserve;
|
||||
DN_U64 err_sink_commit;
|
||||
};
|
||||
|
||||
DN_API void DN_OS_TLSInit (DN_OSTLS *tls, DN_OSTLSInitArgs args);
|
||||
DN_API void DN_OS_TLSDeinit (DN_OSTLS *tls);
|
||||
DN_API DN_OSTLS * DN_OS_TLSGet ();
|
||||
DN_API void DN_OS_TLSSetCurrentThreadTLS (DN_OSTLS *tls);
|
||||
DN_API DN_Arena * DN_OS_TLSArena ();
|
||||
DN_API DN_OSTLSTMem DN_OS_TLSGetTMem (void const *conflict_arena, DN_OSTLSPushTMem push_tmp_mem);
|
||||
DN_API void DN_OS_TLSPushArena (DN_Arena *arena);
|
||||
DN_API void DN_OS_TLSPopArena ();
|
||||
DN_API DN_Arena * DN_OS_TLSTopArena ();
|
||||
DN_API void DN_OS_TLSBeginFrame (DN_Arena *frame_arena);
|
||||
DN_API DN_Arena * DN_OS_TLSFrameArena ();
|
||||
#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0)
|
||||
#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No)
|
||||
#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes)
|
||||
|
||||
DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site);
|
||||
#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE)
|
||||
#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil)
|
||||
DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err);
|
||||
DN_API DN_OSErrSinkMsg * DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err);
|
||||
DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg)
|
||||
#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args)
|
||||
#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args)
|
||||
#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DN_OS_ErrSinkAppendFV(error, error_code, fmt, args) \
|
||||
do { \
|
||||
DN_OS_TLSSaveCallSite; \
|
||||
DN_OS_ErrSinkAppendFV_(error, error_code, fmt, args); \
|
||||
} while (0)
|
||||
|
||||
#define DN_OS_ErrSinkAppendF(error, error_code, fmt, ...) \
|
||||
do { \
|
||||
DN_OS_TLSSaveCallSite; \
|
||||
DN_OS_ErrSinkAppendF_(error, error_code, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#endif // defined(DN_OS_TLS_H)
|
||||
+291
-263
File diff suppressed because it is too large
Load Diff
+34
-32
@@ -1,32 +1,33 @@
|
||||
#if !defined(DN_OS_WIN32_H)
|
||||
#define DN_OS_WIN32_H
|
||||
#if !defined(DN_OS_W32_H)
|
||||
#define DN_OS_W32_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#define DN_H_WITH_OS 1
|
||||
#include "../dn.h"
|
||||
#include "dn_os_windows.h"
|
||||
#endif
|
||||
|
||||
struct DN_W32Error
|
||||
struct DN_OSW32Error
|
||||
{
|
||||
unsigned long code;
|
||||
DN_Str8 msg;
|
||||
};
|
||||
|
||||
struct DN_W32FolderIteratorW
|
||||
struct DN_OSW32FolderIteratorW
|
||||
{
|
||||
void *handle;
|
||||
DN_Str16 file_name;
|
||||
wchar_t file_name_buf[512];
|
||||
};
|
||||
|
||||
enum DN_W32SyncPrimitiveType
|
||||
enum DN_OSW32SyncPrimitiveType
|
||||
{
|
||||
DN_OSW32SyncPrimitiveType_Semaphore,
|
||||
DN_OSW32SyncPrimitiveType_Mutex,
|
||||
DN_OSW32SyncPrimitiveType_ConditionVariable,
|
||||
};
|
||||
|
||||
struct DN_W32SyncPrimitive
|
||||
struct DN_OSW32SyncPrimitive
|
||||
{
|
||||
union
|
||||
{
|
||||
@@ -35,42 +36,43 @@ struct DN_W32SyncPrimitive
|
||||
CONDITION_VARIABLE cv;
|
||||
};
|
||||
|
||||
DN_W32SyncPrimitive *next;
|
||||
DN_OSW32SyncPrimitive *next;
|
||||
};
|
||||
|
||||
typedef HRESULT DN_W32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
|
||||
struct DN_W32Core
|
||||
typedef HRESULT DN_OSW32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
|
||||
struct DN_OSW32Core
|
||||
{
|
||||
DN_W32SetThreadDescriptionFunc *set_thread_description;
|
||||
DN_OSW32SetThreadDescriptionFunc *set_thread_description;
|
||||
LARGE_INTEGER qpc_frequency;
|
||||
void *bcrypt_rng_handle;
|
||||
bool bcrypt_init_success;
|
||||
bool sym_initialised;
|
||||
|
||||
CRITICAL_SECTION sync_primitive_free_list_mutex;
|
||||
DN_W32SyncPrimitive *sync_primitive_free_list;
|
||||
DN_OSW32SyncPrimitive *sync_primitive_free_list;
|
||||
};
|
||||
|
||||
DN_API void DN_W32_ThreadSetName (DN_Str8 name);
|
||||
DN_API DN_OSW32Core* DN_OS_W32GetCore ();
|
||||
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
|
||||
|
||||
DN_API DN_Str16 DN_W32_ErrorCodeToMsg16Alloc(DN_U32 error_code);
|
||||
DN_API DN_W32Error DN_W32_ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
|
||||
DN_API DN_W32Error DN_W32_ErrorCodeToMsgAlloc (DN_U32 error_code);
|
||||
DN_API DN_W32Error DN_W32_LastError (DN_Arena *arena);
|
||||
DN_API DN_W32Error DN_W32_LastErrorAlloc ();
|
||||
DN_API void DN_W32_MakeProcessDPIAware ();
|
||||
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsgAlloc (DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32LastError (DN_Arena *arena);
|
||||
DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc ();
|
||||
DN_API void DN_OS_W32MakeProcessDPIAware ();
|
||||
|
||||
// NOTE: Windows Str8 <-> Str16 ////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str16 DN_W32_Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
|
||||
DN_API int DN_W32_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_W32_Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
|
||||
DN_API int DN_W32_Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_W32_Str16ToStr8FromHeap(DN_Str16 src);
|
||||
// NOTE: Windows Str8 <-> Str16
|
||||
DN_API DN_Str16 DN_OS_W32Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
|
||||
DN_API int DN_OS_W32Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_OS_W32Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
|
||||
DN_API int DN_OS_W32Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap (DN_Str16 src);
|
||||
|
||||
// NOTE: Path navigation ///////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str16 DN_W32_EXEPathW (DN_Arena *arena);
|
||||
DN_API DN_Str16 DN_W32_EXEDirW (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_W32_WorkingDir (DN_Arena *arena, DN_Str8 suffix);
|
||||
DN_API DN_Str16 DN_W32_WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
|
||||
DN_API bool DN_W32_DirWIterate (DN_Str16 path, DN_W32FolderIteratorW *it);
|
||||
#endif // !defined(DN_OS_WIN32)
|
||||
// NOTE: Path navigation
|
||||
DN_API DN_Str16 DN_OS_W32EXEPathW (DN_Arena *arena);
|
||||
DN_API DN_Str16 DN_OS_W32EXEDirW (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_OS_W32WorkingDir (DN_Arena *arena, DN_Str8 suffix);
|
||||
DN_API DN_Str16 DN_OS_W32WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
|
||||
DN_API bool DN_OS_W32DirWIterate (DN_Str16 path, DN_OSW32FolderIteratorW *it);
|
||||
#endif // !defined(DN_OS_W32_H)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define DN_OS_WINDOWS_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn.h"
|
||||
#endif
|
||||
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
|
||||
Reference in New Issue
Block a user