fix clang build

This commit is contained in:
Ryan Fleury
2025-03-25 16:54:12 -07:00
parent 213091cf75
commit ab9885bc7d
10 changed files with 549 additions and 267 deletions
+1 -1
View File
@@ -313,7 +313,7 @@ struct E_TypeState
////////////////////////////////
//~ rjf: Globals
global read_only E_Member e_member_nil = {E_MemberKind_Null, zero_struct, {0}, {0}, 0, {0}};
global read_only E_Member e_member_nil = {E_MemberKind_Null};
global read_only E_Type e_type_nil = {E_TypeKind_Null};
thread_static E_TypeState *e_type_state = 0;
@@ -150,9 +150,27 @@ os_get_current_path(Arena *arena)
{
char *cwdir = getcwd(0, 0);
String8 string = push_str8_copy(arena, str8_cstring(cwdir));
free(cwdir);
return string;
}
internal U32
os_get_process_start_time_unix(void)
{
Temp scratch = scratch_begin(0,0);
U64 start_time = 0;
pid_t pid = getpid();
String8 path = push_str8f(scratch.arena, "/proc/%u", pid);
struct stat st;
int err = stat((char*)path.str, &st);
if(err == 0)
{
start_time = st.st_mtime;
}
scratch_end(scratch);
return (U32)start_time;
}
////////////////////////////////
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
@@ -162,6 +180,10 @@ internal void *
os_reserve(U64 size)
{
void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(result == MAP_FAILED)
{
result = 0;
}
return result;
}
@@ -191,6 +213,10 @@ internal void *
os_reserve_large(U64 size)
{
void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0);
if(result == MAP_FAILED)
{
result = 0;
}
return result;
}
@@ -207,12 +233,7 @@ os_commit_large(void *ptr, U64 size)
internal U32
os_tid(void)
{
U32 result = 0;
#if defined(SYS_gettid)
result = syscall(SYS_gettid);
#else
result = gettid();
#endif
U32 result = gettid();
return result;
}
@@ -246,7 +267,7 @@ os_file_open(OS_AccessFlags flags, String8 path)
Temp scratch = scratch_begin(0, 0);
String8 path_copy = push_str8_copy(scratch.arena, path);
int lnx_flags = 0;
if(flags & (OS_AccessFlag_Read|OS_AccessFlag_Write))
if(flags & OS_AccessFlag_Read && flags & OS_AccessFlag_Write)
{
lnx_flags = O_RDWR;
}
@@ -262,7 +283,11 @@ os_file_open(OS_AccessFlags flags, String8 path)
{
lnx_flags |= O_APPEND;
}
int fd = open((char *)path_copy.str, lnx_flags);
if(flags & (OS_AccessFlag_Write|OS_AccessFlag_Append))
{
lnx_flags |= O_CREAT;
}
int fd = open((char *)path_copy.str, lnx_flags, 0755);
OS_Handle handle = {0};
if(fd != -1)
{
@@ -285,16 +310,12 @@ os_file_read(OS_Handle file, Rng1U64 rng, void *out_data)
{
if(os_handle_match(file, os_handle_zero())) { return 0; }
int fd = (int)file.u64[0];
if(rng.min != 0)
{
lseek(fd, rng.min, SEEK_SET);
}
U64 total_num_bytes_to_read = dim_1u64(rng);
U64 total_num_bytes_read = 0;
U64 total_num_bytes_left_to_read = total_num_bytes_to_read;
for(;total_num_bytes_left_to_read > 0;)
{
int read_result = read(fd, (U8 *)out_data + total_num_bytes_read, total_num_bytes_left_to_read);
int read_result = pread(fd, (U8 *)out_data + total_num_bytes_read, total_num_bytes_left_to_read, rng.min + total_num_bytes_read);
if(read_result >= 0)
{
total_num_bytes_read += read_result;
@@ -313,16 +334,12 @@ os_file_write(OS_Handle file, Rng1U64 rng, void *data)
{
if(os_handle_match(file, os_handle_zero())) { return 0; }
int fd = (int)file.u64[0];
if(rng.min != 0)
{
lseek(fd, rng.min, SEEK_SET);
}
U64 total_num_bytes_to_write = dim_1u64(rng);
U64 total_num_bytes_written = 0;
U64 total_num_bytes_left_to_write = total_num_bytes_to_write;
for(;total_num_bytes_left_to_write > 0;)
{
int write_result = write(fd, (U8 *)data + total_num_bytes_written, total_num_bytes_left_to_write);
int write_result = pwrite(fd, (U8 *)data + total_num_bytes_written, total_num_bytes_left_to_write, rng.min + total_num_bytes_written);
if(write_result >= 0)
{
total_num_bytes_written += write_result;
@@ -402,25 +419,23 @@ os_copy_file_path(String8 dst, String8 src)
if(!os_handle_match(src_h, os_handle_zero()) &&
!os_handle_match(dst_h, os_handle_zero()))
{
int src_fd = (int)src_h.u64[0];
int dst_fd = (int)dst_h.u64[0];
FileProperties src_props = os_properties_from_file(src_h);
U64 size = src_props.size;
U64 total_bytes_copied = 0;
U64 bytes_left_to_copy = size;
for(;bytes_left_to_copy > 0;)
{
Temp scratch = scratch_begin(0, 0);
U64 buffer_size = Min(bytes_left_to_copy, MB(8));
U8 *buffer = push_array_no_zero(scratch.arena, U8, buffer_size);
U64 bytes_read = os_file_read(src_h, r1u64(total_bytes_copied, total_bytes_copied+buffer_size), buffer);
U64 bytes_written = os_file_write(dst_h, r1u64(total_bytes_copied, total_bytes_copied+bytes_read), buffer);
U64 bytes_copied = Min(bytes_read, bytes_written);
bytes_left_to_copy -= bytes_copied;
total_bytes_copied += bytes_copied;
scratch_end(scratch);
if(bytes_copied == 0)
off_t sendfile_off = total_bytes_copied;
int send_result = sendfile(dst_fd, src_fd, &sendfile_off, bytes_left_to_copy);
if(send_result <= 0)
{
break;
}
U64 bytes_copied = (U64)send_result;
bytes_left_to_copy -= bytes_copied;
total_bytes_copied += bytes_copied;
}
}
os_file_close(src_h);
@@ -428,6 +443,12 @@ os_copy_file_path(String8 dst, String8 src)
return result;
}
internal B32
os_move_file_path(String8 dst, String8 src)
{
// TODO(rjf)
}
internal String8
os_full_path_from_path(Arena *arena, String8 path)
{
@@ -455,6 +476,22 @@ os_file_path_exists(String8 path)
return result;
}
internal B32
os_folder_path_exists(String8 path)
{
Temp scratch = scratch_begin(0, 0);
B32 exists = 0;
String8 path_copy = push_str8_copy(scratch.arena, path);
DIR *handle = opendir((char*)path_copy.str);
if(handle)
{
closedir(handle);
exists = 1;
}
scratch_end(scratch);
return exists;
}
internal FileProperties
os_properties_from_file_path(String8 path)
{
@@ -497,6 +534,10 @@ os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range)
if(flags & OS_AccessFlag_Read) { prot_flags |= PROT_READ; }
int map_flags = MAP_PRIVATE;
void *base = mmap(0, dim_1u64(range), prot_flags, map_flags, fd, range.min);
if(base == MAP_FAILED)
{
base = 0;
}
return base;
}
@@ -589,7 +630,7 @@ os_make_directory(String8 path)
Temp scratch = scratch_begin(0, 0);
B32 result = 0;
String8 path_copy = push_str8_copy(scratch.arena, path);
if(mkdir((char*)path_copy.str, 0777) != -1)
if(mkdir((char*)path_copy.str, 0755) != -1)
{
result = 1;
}
@@ -637,6 +678,10 @@ os_shared_memory_view_open(OS_Handle handle, Rng1U64 range)
if(os_handle_match(handle, os_handle_zero())){return 0;}
int id = (int)handle.u64[0];
void *base = mmap(0, dim_1u64(range), PROT_READ|PROT_WRITE, MAP_SHARED, id, range.min);
if(base == MAP_FAILED)
{
base = 0;
}
return base;
}
@@ -744,10 +789,7 @@ os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params)
entity->thread.func = func;
entity->thread.ptr = ptr;
{
pthread_attr_t attr;
pthread_attr_init(&attr);
int pthread_result = pthread_create(&entity->thread.handle, &attr, os_lnx_thread_entry_point, entity);
pthread_attr_destroy(&attr);
int pthread_result = pthread_create(&entity->thread.handle, 0, os_lnx_thread_entry_point, entity);
if(pthread_result == -1)
{
os_lnx_entity_release(entity);
@@ -1025,13 +1067,26 @@ os_condition_variable_broadcast(OS_Handle cv)
internal OS_Handle
os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name)
{
NotImplemented;
OS_Handle result = {0};
if (name.size > 0) {
// TODO: we need to allocate shared memory to store sem_t
NotImplemented;
} else {
sem_t *s = mmap(0, sizeof(*s), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
AssertAlways(s != MAP_FAILED);
int err = sem_init(s, 0, initial_count);
if (err == 0) {
result.u64[0] = (U64)s;
}
}
return result;
}
internal void
os_semaphore_release(OS_Handle semaphore)
{
NotImplemented;
int err = munmap((void*)semaphore.u64[0], sizeof(sem_t));
AssertAlways(err == 0);
}
internal OS_Handle
@@ -1049,13 +1104,37 @@ os_semaphore_close(OS_Handle semaphore)
internal B32
os_semaphore_take(OS_Handle semaphore, U64 endt_us)
{
NotImplemented;
AssertAlways(endt_us == max_U64);
for (;;) {
int err = sem_wait((sem_t*)semaphore.u64[0]);
if (err == 0) {
break;
} else {
if (errno == EAGAIN) {
continue;
}
}
InvalidPath;
break;
}
return 1;
}
internal void
os_semaphore_drop(OS_Handle semaphore)
{
NotImplemented;
for (;;) {
int err = sem_post((sem_t*)semaphore.u64[0]);
if (err == 0) {
break;
} else {
if (errno == EAGAIN) {
continue;
}
}
InvalidPath;
break;
}
}
////////////////////////////////
@@ -1066,7 +1145,7 @@ os_library_open(String8 path)
{
Temp scratch = scratch_begin(0, 0);
char *path_cstr = (char *)push_str8_copy(scratch.arena, path).str;
void *so = dlopen(path_cstr, RTLD_LAZY);
void *so = dlopen(path_cstr, RTLD_LAZY|RTLD_LOCAL);
OS_Handle lib = { (U64)so };
scratch_end(scratch);
return lib;
@@ -1130,14 +1209,11 @@ os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, v
////////////////////////////////
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
internal OS_Guid
internal Guid
os_make_guid(void)
{
U8 random_bytes[16] = {0};
StaticAssert(sizeof(random_bytes) == sizeof(OS_Guid), os_lnx_guid_size_check);
getrandom(random_bytes, sizeof(random_bytes), 0);
OS_Guid guid = {0};
MemoryCopy(&guid, random_bytes, sizeof(random_bytes));
Guid guid = {0};
getrandom(guid.v, sizeof(guid.v), 0);
guid.data3 &= 0x0fff;
guid.data3 |= (4 << 12);
guid.data4[0] &= 0x3f;
@@ -1256,5 +1332,5 @@ main(int argc, char **argv)
}
//- rjf: call into "real" entry point
main_thread_base_entry_point(entry_point, argv, (U64)argc);
main_thread_base_entry_point(argc, argv);
}
@@ -8,24 +8,27 @@
//~ rjf: Includes
#define _GNU_SOURCE
#include <dirent.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <features.h>
#include <linux/limits.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <time.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <signal.h>
#include <errno.h>
#include <dlfcn.h>
#include <sys/sysinfo.h>
#include <sys/random.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
pid_t gettid(void);
int pthread_setname_np(pthread_t thread, const char *name);
int pthread_getname_np(pthread_t thread, char *name, size_t size);
+82 -15
View File
@@ -152,22 +152,89 @@ os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
}
////////////////////////////////
//~ rjf: GUID Helpers (Helpers, Implemented Once)
//~ rjf: Process Launcher Helpers
internal String8
os_string_from_guid(Arena *arena, OS_Guid guid)
internal OS_Handle
os_cmd_line_launch(String8 string)
{
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.data1,
guid.data2,
guid.data3,
guid.data4[0],
guid.data4[1],
guid.data4[2],
guid.data4[3],
guid.data4[4],
guid.data4[5],
guid.data4[6],
guid.data4[7]);
Temp scratch = scratch_begin(0, 0);
U8 split_chars[] = {' '};
String8List parts = str8_split(scratch.arena, string, split_chars, ArrayCount(split_chars), 0);
OS_Handle handle = {0};
if(parts.node_count != 0)
{
// rjf: unpack exe part
String8 exe = parts.first->string;
String8 exe_folder = str8_chop_last_slash(exe);
if(exe_folder.size == 0)
{
exe_folder = os_get_current_path(scratch.arena);
}
// rjf: find stdout delimiter
String8Node *stdout_delimiter_n = 0;
for(String8Node *n = parts.first; n != 0; n = n->next)
{
if(str8_match(n->string, str8_lit(">"), 0))
{
stdout_delimiter_n = n;
break;
}
}
// rjf: read stdout path
String8 stdout_path = {0};
if(stdout_delimiter_n && stdout_delimiter_n->next)
{
stdout_path = stdout_delimiter_n->next->string;
}
// rjf: open stdout handle
OS_Handle stdout_handle = {0};
if(stdout_path.size != 0)
{
OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Read, stdout_path);
os_file_close(file);
stdout_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, stdout_path);
}
// rjf: form command line
String8List cmdline = {0};
for(String8Node *n = parts.first; n != stdout_delimiter_n && n != 0; n = n->next)
{
str8_list_push(scratch.arena, &cmdline, n->string);
}
// rjf: launch
OS_ProcessLaunchParams params = {0};
params.cmd_line = cmdline;
params.path = exe_folder;
params.inherit_env = 1;
params.stdout_file = stdout_handle;
handle = os_process_launch(&params);
// rjf: close stdout handle
{
if(stdout_path.size != 0)
{
os_file_close(stdout_handle);
}
}
}
scratch_end(scratch);
return handle;
}
internal OS_Handle
os_cmd_line_launchf(char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
OS_Handle result = os_cmd_line_launch(string);
va_end(args);
scratch_end(scratch);
return result;
}
+31 -32
View File
@@ -24,6 +24,7 @@ typedef struct OS_ProcessInfo OS_ProcessInfo;
struct OS_ProcessInfo
{
U32 pid;
B32 large_pages_allowed;
String8 binary_path;
String8 initial_path;
String8 user_program_data_path;
@@ -37,12 +38,13 @@ struct OS_ProcessInfo
typedef U32 OS_AccessFlags;
enum
{
OS_AccessFlag_Read = (1<<0),
OS_AccessFlag_Write = (1<<1),
OS_AccessFlag_Execute = (1<<2),
OS_AccessFlag_Append = (1<<3),
OS_AccessFlag_ShareRead = (1<<4),
OS_AccessFlag_ShareWrite = (1<<5),
OS_AccessFlag_Read = (1<<0),
OS_AccessFlag_Write = (1<<1),
OS_AccessFlag_Execute = (1<<2),
OS_AccessFlag_Append = (1<<3),
OS_AccessFlag_ShareRead = (1<<4),
OS_AccessFlag_ShareWrite = (1<<5),
OS_AccessFlag_Inherited = (1<<6),
};
////////////////////////////////
@@ -78,19 +80,6 @@ struct OS_FileID
U64 v[3];
};
////////////////////////////////
//~ rjf: Process Launch Parameters
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
struct OS_ProcessLaunchParams
{
String8List cmd_line;
String8 path;
String8List env;
B32 inherit_env;
B32 consoleless;
};
////////////////////////////////
//~ rjf: Handle Type
@@ -123,17 +112,21 @@ struct OS_HandleArray
};
////////////////////////////////
//~ rjf: Globally Unique IDs
//~ rjf: Process Launch Parameters
typedef struct OS_Guid OS_Guid;
struct OS_Guid
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
struct OS_ProcessLaunchParams
{
U32 data1;
U16 data2;
U16 data3;
U8 data4[8];
String8List cmd_line;
String8 path;
String8List env;
B32 inherit_env;
B32 debug_subprocesses;
B32 consoleless;
OS_Handle stdout_file;
OS_Handle stderr_file;
OS_Handle stdin_file;
};
StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
////////////////////////////////
//~ rjf: Thread Types
@@ -165,16 +158,18 @@ internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
////////////////////////////////
//~ rjf: GUID Helpers (Helpers, Implemented Once)
//~ rjf: Process Launcher Helpers
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
internal OS_Handle os_cmd_line_launch(String8 string);
internal OS_Handle os_cmd_line_launchf(char *fmt, ...);
////////////////////////////////
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
internal OS_SystemInfo *os_get_system_info(void);
internal OS_SystemInfo *os_get_system_info(void);
internal OS_ProcessInfo *os_get_process_info(void);
internal String8 os_get_current_path(Arena *arena);
internal String8 os_get_current_path(Arena *arena);
internal U32 os_get_process_start_time_unix(void);
////////////////////////////////
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
@@ -207,14 +202,18 @@ internal void os_abort(S32 exit_code);
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
internal void os_file_close(OS_Handle file);
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
#define os_file_read_struct(f, off, ptr) os_file_read((f), r1u64((off), (off)+sizeof(*(ptr))), (ptr))
internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
internal B32 os_file_set_times(OS_Handle file, DateTime time);
internal FileProperties os_properties_from_file(OS_Handle file);
internal OS_FileID os_id_from_file(OS_Handle file);
internal B32 os_file_reserve_size(OS_Handle file, U64 size);
internal B32 os_delete_file_at_path(String8 path);
internal B32 os_copy_file_path(String8 dst, String8 src);
internal B32 os_move_file_path(String8 dst, String8 src);
internal String8 os_full_path_from_path(Arena *arena, String8 path);
internal B32 os_file_path_exists(String8 path);
internal B32 os_folder_path_exists(String8 path);
internal FileProperties os_properties_from_file_path(String8 path);
//- rjf: file maps
@@ -320,7 +319,7 @@ internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *f
////////////////////////////////
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
internal OS_Guid os_make_guid(void);
internal Guid os_make_guid(void);
////////////////////////////////
//~ rjf: @os_hooks Entry Points (Implemented Per-OS)
@@ -90,6 +90,18 @@ os_w32_sleep_ms_from_endt_us(U64 endt_us)
return sleep_ms;
}
internal U32
os_w32_unix_time_from_file_time(FILETIME file_time)
{
U64 win32_time = ((U64)file_time.dwHighDateTime << 32) | file_time.dwLowDateTime;
U64 unix_time64 = ((win32_time - 0x19DB1DED53E8000ULL) / 10000000);
Assert(unix_time64 <= max_U32);
U32 unix_time32 = (U32)unix_time64;
return unix_time32;
}
////////////////////////////////
//~ rjf: Entity Functions
@@ -167,6 +179,21 @@ os_get_current_path(Arena *arena)
return name;
}
internal U32
os_get_process_start_time_unix(void)
{
HANDLE handle = GetCurrentProcess();
FILETIME start_time = {0};
FILETIME exit_time;
FILETIME kernel_time;
FILETIME user_time;
if(GetProcessTimes(handle, &start_time, &exit_time, &kernel_time, &user_time))
{
return os_w32_unix_time_from_file_time(start_time);
}
return 0;
}
////////////////////////////////
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
@@ -293,14 +320,19 @@ os_file_open(OS_AccessFlags flags, String8 path)
DWORD access_flags = 0;
DWORD share_mode = 0;
DWORD creation_disposition = OPEN_EXISTING;
if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;}
if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;}
if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;}
if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;}
if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;}
if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;}
if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS;}
HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, 0, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0);
SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0};
if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;}
if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;}
if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;}
if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;}
if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;}
if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;}
if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS; access_flags |= FILE_APPEND_DATA; }
if(flags & OS_AccessFlag_Inherited)
{
security_attributes.bInheritHandle = 1;
}
HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, &security_attributes, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0);
if(file != INVALID_HANDLE_VALUE)
{
result.u64[0] = (U64)file;
@@ -361,27 +393,29 @@ os_file_write(OS_Handle file, Rng1U64 rng, void *data)
HANDLE win_handle = (HANDLE)file.u64[0];
U64 src_off = 0;
U64 dst_off = rng.min;
U64 bytes_to_write_total = rng.max-rng.min;
U64 total_bytes_written = 0;
for(;src_off < bytes_to_write_total;)
U64 total_write_size = dim_1u64(rng);
for(;;)
{
void *bytes_src = (void *)((U8 *)data + src_off);
U64 bytes_to_write_64 = (bytes_to_write_total-src_off);
U32 bytes_to_write_32 = u32_from_u64_saturate(bytes_to_write_64);
U32 bytes_written = 0;
void *bytes_src = (U8 *)data + src_off;
U64 bytes_left = total_write_size - src_off;
DWORD write_size = Min(MB(1), bytes_left);
DWORD bytes_written = 0;
OVERLAPPED overlapped = {0};
overlapped.Offset = (dst_off&0x00000000ffffffffull);
overlapped.Offset = (dst_off&0x00000000ffffffffull);
overlapped.OffsetHigh = (dst_off&0xffffffff00000000ull) >> 32;
BOOL success = WriteFile(win_handle, bytes_src, bytes_to_write_32, (DWORD *)&bytes_written, &overlapped);
BOOL success = WriteFile(win_handle, bytes_src, write_size, &bytes_written, &overlapped);
if(success == 0)
{
break;
}
src_off += bytes_written;
dst_off += bytes_written;
total_bytes_written += bytes_written;
if(bytes_left == 0)
{
break;
}
}
return total_bytes_written;
return src_off;
}
internal B32
@@ -435,6 +469,19 @@ os_id_from_file(OS_Handle file)
return result;
}
internal B32
os_file_reserve_size(OS_Handle file, U64 size)
{
HANDLE handle = (HANDLE)file.u64[0];
FILE_ALLOCATION_INFO alloc_info = {0};
alloc_info.AllocationSize.LowPart = size & max_U32;
alloc_info.AllocationSize.HighPart = (size >> 32) & max_U32;
BOOL is_reserved = SetFileInformationByHandle(handle, FileAllocationInfo, &alloc_info, sizeof(alloc_info));
return is_reserved;
}
internal B32
os_delete_file_at_path(String8 path)
{
@@ -456,15 +503,33 @@ os_copy_file_path(String8 dst, String8 src)
return result;
}
internal B32
os_move_file_path(String8 dst, String8 src)
{
Temp scratch = scratch_begin(0, 0);
String16 dst16 = str16_from_8(scratch.arena, dst);
String16 src16 = str16_from_8(scratch.arena, src);
B32 result = MoveFileW((WCHAR*)src16.str, (WCHAR*)dst16.str);
scratch_end(scratch);
return result;
}
internal String8
os_full_path_from_path(Arena *arena, String8 path)
{
Temp scratch = scratch_begin(&arena, 1);
DWORD buffer_size = MAX_PATH + 1;
U16 *buffer = push_array_no_zero(scratch.arena, U16, buffer_size);
String16 path16 = str16_from_8(scratch.arena, path);
DWORD path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, (WCHAR*)buffer, NULL);
String8 full_path = str8_from_16(arena, str16(buffer, path16_size));
DWORD buffer_size = Max(MAX_PATH, path.size * 2) + 1;
String16 path16 = str16_from_8(scratch.arena, path);
WCHAR *buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size);
DWORD path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL);
if(path16_size > buffer_size)
{
arena_pop(scratch.arena, buffer_size);
buffer_size = path16_size + 1;
buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size);
path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL);
}
String8 full_path = str8_from_16(arena, str16((U16*)buffer, path16_size));
scratch_end(scratch);
return full_path;
}
@@ -480,6 +545,17 @@ os_file_path_exists(String8 path)
return exists;
}
internal B32
os_folder_path_exists(String8 path)
{
Temp scratch = scratch_begin(0,0);
String16 path16 = str16_from_8(scratch.arena, path);
DWORD attributes = GetFileAttributesW((WCHAR *)path16.str);
B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY);
scratch_end(scratch);
return exists;
}
internal FileProperties
os_properties_from_file_path(String8 path)
{
@@ -495,6 +571,28 @@ os_properties_from_file_path(String8 path)
os_w32_dense_time_from_file_time(&props.modified, &find_data.ftLastWriteTime);
props.flags = os_w32_file_property_flags_from_dwFileAttributes(find_data.dwFileAttributes);
}
else
{
Temp scratch = scratch_begin(0, 0);
WCHAR buffer[512] = {0};
DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer);
U64 last_slash_pos = 0;
for(;last_slash_pos < path.size; last_slash_pos = str8_find_needle(path, last_slash_pos+1, str8_lit("/"), StringMatchFlag_SlashInsensitive));
String8 path_trimmed = str8_prefix(path, last_slash_pos);
for(U64 off = 0; off < (U64)length;)
{
String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off);
off += next_drive_string_16.size+1;
String8 next_drive_string = str8_from_16(scratch.arena, next_drive_string_16);
next_drive_string = str8_chop_last_slash(next_drive_string);
if(str8_match(path_trimmed, next_drive_string, StringMatchFlag_CaseInsensitive))
{
props.flags |= FilePropertyFlag_IsFolder;
break;
}
}
scratch_end(scratch);
}
FindClose(handle);
scratch_end(scratch);
return props;
@@ -704,7 +802,12 @@ internal void
os_file_iter_end(OS_FileIter *iter)
{
OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory;
FindClose(w32_iter->handle);
HANDLE zero_handle;
MemoryZeroStruct(&zero_handle);
if(!MemoryMatchStruct(&zero_handle, &w32_iter->handle))
{
FindClose(w32_iter->handle);
}
}
//- rjf: directory creation
@@ -805,10 +908,8 @@ os_now_unix(void)
{
FILETIME file_time;
GetSystemTimeAsFileTime(&file_time);
U64 win32_time = ((U64)file_time.dwHighDateTime << 32) | file_time.dwLowDateTime;
U64 unix_time64 = ((win32_time - 0x19DB1DED53E8000ULL) / 10000000);
U32 unix_time32 = (U32)unix_time64;
return unix_time32;
U32 unix_time = os_w32_unix_time_from_file_time(file_time);
return unix_time;
}
internal DateTime
@@ -926,9 +1027,31 @@ os_process_launch(OS_ProcessLaunchParams *params)
}
//- rjf: launch
BOOL inherit_handles = 0;
STARTUPINFOW startup_info = {sizeof(startup_info)};
if(!os_handle_match(params->stdout_file, os_handle_zero()))
{
HANDLE stdout_handle = (HANDLE)params->stdout_file.u64[0];
startup_info.hStdOutput = stdout_handle;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
inherit_handles = 1;
}
if(!os_handle_match(params->stderr_file, os_handle_zero()))
{
HANDLE stderr_handle = (HANDLE)params->stderr_file.u64[0];
startup_info.hStdError = stderr_handle;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
inherit_handles = 1;
}
if(!os_handle_match(params->stdin_file, os_handle_zero()))
{
HANDLE stdin_handle = (HANDLE)params->stdin_file.u64[0];
startup_info.hStdInput = stdin_handle;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
inherit_handles = 1;
}
PROCESS_INFORMATION process_info = {0};
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 0, creation_flags, use_null_env_arg ? 0 : (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, inherit_handles, creation_flags, use_null_env_arg ? 0 : (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
{
result.u64[0] = (U64)process_info.hProcess;
CloseHandle(process_info.hThread);
@@ -977,8 +1100,9 @@ os_thread_join(OS_Handle handle, U64 endt_us)
if(entity != 0)
{
wait_result = WaitForSingleObject(entity->thread.handle, sleep_ms);
CloseHandle(entity->thread.handle);
os_w32_entity_release(entity);
}
os_w32_entity_release(entity);
return (wait_result == WAIT_OBJECT_0);
}
@@ -986,7 +1110,11 @@ internal void
os_thread_detach(OS_Handle thread)
{
OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(thread.u64[0]);
os_w32_entity_release(entity);
if(entity != 0)
{
CloseHandle(entity->thread.handle);
os_w32_entity_release(entity);
}
}
////////////////////////////////
@@ -1255,10 +1383,10 @@ os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, v
////////////////////////////////
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
internal OS_Guid
internal Guid
os_make_guid(void)
{
OS_Guid result; MemoryZeroStruct(&result);
Guid result; MemoryZeroStruct(&result);
UUID uuid;
RPC_STATUS rpc_status = UuidCreate(&uuid);
if(rpc_status == RPC_S_OK)
@@ -1344,8 +1472,12 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
HANDLE thread = GetCurrentThread();
CONTEXT* context = exception_ptrs->ContextRecord;
WCHAR module_path[MAX_PATH];
GetModuleFileNameW(NULL, module_path, ArrayCount(module_path));
PathRemoveFileSpecW(module_path);
dbg_SymSetOptions(SYMOPT_EXACT_SYMBOLS | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
if(dbg_SymInitializeW(process, L"", TRUE))
if(dbg_SymInitializeW(process, module_path, TRUE))
{
// check that raddbg.pdb file is good
B32 raddbg_pdb_valid = 0;
@@ -1384,7 +1516,7 @@ win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs)
frame.AddrStack.Offset = context->Sp;
frame.AddrStack.Mode = AddrModeFlat;
#else
# error Architecture not supported!
# error Arch not supported!
#endif
for(U32 idx=0; ;idx++)
@@ -1488,129 +1620,60 @@ w32_entry_point_caller(int argc, WCHAR **wargv)
{
SetUnhandledExceptionFilter(&win32_exception_filter);
//- rjf: do OS layer initialization
//- rjf: dynamically load windows functions which are not guaranteed
// in all SDKs
{
// rjf: dynamically load windows functions which are not guaranteed
// in all SDKs
HMODULE module = LoadLibraryA("kernel32.dll");
w32_SetThreadDescription_func = (W32_SetThreadDescription_Type *)GetProcAddress(module, "SetThreadDescription");
FreeLibrary(module);
}
//- rjf: try to allow large pages if we can
B32 large_pages_allowed = 0;
{
HANDLE token;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
{
HMODULE module = LoadLibraryA("kernel32.dll");
w32_SetThreadDescription_func = (W32_SetThreadDescription_Type *)GetProcAddress(module, "SetThreadDescription");
FreeLibrary(module);
}
// rjf: try to enable large pages if we can
{
HANDLE token;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
LUID luid;
if(LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid))
{
LUID luid;
if(LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid))
{
TOKEN_PRIVILEGES priv;
priv.PrivilegeCount = 1;
priv.Privileges[0].Luid = luid;
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(token, 0, &priv, sizeof(priv), 0, 0);
}
CloseHandle(token);
TOKEN_PRIVILEGES priv;
priv.PrivilegeCount = 1;
priv.Privileges[0].Luid = luid;
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
large_pages_allowed = !!AdjustTokenPrivileges(token, 0, &priv, sizeof(priv), 0, 0);
}
CloseHandle(token);
}
// rjf: get system info
SYSTEM_INFO sysinfo = {0};
GetSystemInfo(&sysinfo);
// rjf: set up non-dynamically-alloc'd state
//
// (we need to set up some basics before this layer can supply
// memory allocation primitives)
}
//- rjf: get system info
SYSTEM_INFO sysinfo = {0};
GetSystemInfo(&sysinfo);
//- rjf: set up non-dynamically-alloc'd state
//
// (we need to set up some basics before this layer can supply
// memory allocation primitives)
{
os_w32_state.microsecond_resolution = 1;
LARGE_INTEGER large_int_resolution;
if(QueryPerformanceFrequency(&large_int_resolution))
{
os_w32_state.microsecond_resolution = 1;
LARGE_INTEGER large_int_resolution;
if(QueryPerformanceFrequency(&large_int_resolution))
{
os_w32_state.microsecond_resolution = large_int_resolution.QuadPart;
}
os_w32_state.microsecond_resolution = large_int_resolution.QuadPart;
}
{
OS_SystemInfo *info = &os_w32_state.system_info;
info->logical_processor_count = (U64)sysinfo.dwNumberOfProcessors;
info->page_size = sysinfo.dwPageSize;
info->large_page_size = GetLargePageMinimum();
info->allocation_granularity = sysinfo.dwAllocationGranularity;
}
{
OS_ProcessInfo *info = &os_w32_state.process_info;
info->pid = GetCurrentProcessId();
}
// rjf: set up thread context
local_persist TCTX tctx;
tctx_init_and_equip(&tctx);
// rjf: set up dynamically-alloc'd state
Arena *arena = arena_alloc();
{
os_w32_state.arena = arena;
{
OS_SystemInfo *info = &os_w32_state.system_info;
U8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0};
DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
if(GetComputerNameA((char*)buffer, &size))
{
info->machine_name = push_str8_copy(arena, str8(buffer, size));
}
}
}
{
OS_ProcessInfo *info = &os_w32_state.process_info;
{
Temp scratch = scratch_begin(0, 0);
DWORD size = KB(32);
U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size);
String8 name8 = str8_from_16(scratch.arena, str16(buffer, length));
String8 name_chopped = str8_chop_last_slash(name8);
info->binary_path = push_str8_copy(arena, name_chopped);
scratch_end(scratch);
}
info->initial_path = os_get_current_path(arena);
{
Temp scratch = scratch_begin(0, 0);
U64 size = KB(32);
U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer)))
{
info->user_program_data_path = str8_from_16(arena, str16_cstring(buffer));
}
scratch_end(scratch);
}
{
WCHAR *this_proc_env = GetEnvironmentStringsW();
U64 start_idx = 0;
for(U64 idx = 0;; idx += 1)
{
if(this_proc_env[idx] == 0)
{
if(start_idx == idx)
{
break;
}
else
{
String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx);
String8 string = str8_from_16(arena, string16);
str8_list_push(arena, &info->environment, string);
start_idx = idx+1;
}
}
}
}
}
// rjf: set up entity storage
InitializeCriticalSection(&os_w32_state.entity_mutex);
os_w32_state.entity_arena = arena_alloc();
}
{
OS_SystemInfo *info = &os_w32_state.system_info;
info->logical_processor_count = (U64)sysinfo.dwNumberOfProcessors;
info->page_size = sysinfo.dwPageSize;
info->large_page_size = GetLargePageMinimum();
info->allocation_granularity = sysinfo.dwAllocationGranularity;
}
{
OS_ProcessInfo *info = &os_w32_state.process_info;
info->large_pages_allowed = large_pages_allowed;
info->pid = GetCurrentProcessId();
}
//- rjf: extract arguments
@@ -1620,13 +1683,89 @@ w32_entry_point_caller(int argc, WCHAR **wargv)
{
String16 arg16 = str16_cstring((U16 *)wargv[i]);
String8 arg8 = str8_from_16(args_arena, arg16);
if(str8_match(arg8, str8_lit("--quiet"), StringMatchFlag_CaseInsensitive))
if(str8_match(arg8, str8_lit("--quiet"), StringMatchFlag_CaseInsensitive) ||
str8_match(arg8, str8_lit("-quiet"), StringMatchFlag_CaseInsensitive))
{
win32_g_is_quiet = 1;
}
if(str8_match(arg8, str8_lit("--large_pages"), StringMatchFlag_CaseInsensitive) ||
str8_match(arg8, str8_lit("-large_pages"), StringMatchFlag_CaseInsensitive))
{
arena_default_flags = ArenaFlag_LargePages;
arena_default_reserve_size = Max(MB(64), os_w32_state.system_info.large_page_size);
arena_default_commit_size = arena_default_reserve_size;
}
argv[i] = (char *)arg8.str;
}
//- rjf: set up thread context
local_persist TCTX tctx;
tctx_init_and_equip(&tctx);
//- rjf: set up dynamically-alloc'd state
Arena *arena = arena_alloc();
{
os_w32_state.arena = arena;
{
OS_SystemInfo *info = &os_w32_state.system_info;
U8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0};
DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
if(GetComputerNameA((char*)buffer, &size))
{
info->machine_name = push_str8_copy(arena, str8(buffer, size));
}
}
}
{
OS_ProcessInfo *info = &os_w32_state.process_info;
{
Temp scratch = scratch_begin(0, 0);
DWORD size = KB(32);
U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size);
String8 name8 = str8_from_16(scratch.arena, str16(buffer, length));
String8 name_chopped = str8_chop_last_slash(name8);
info->binary_path = push_str8_copy(arena, name_chopped);
scratch_end(scratch);
}
info->initial_path = os_get_current_path(arena);
{
Temp scratch = scratch_begin(0, 0);
U64 size = KB(32);
U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer)))
{
info->user_program_data_path = str8_from_16(arena, str16_cstring(buffer));
}
scratch_end(scratch);
}
{
WCHAR *this_proc_env = GetEnvironmentStringsW();
U64 start_idx = 0;
for(U64 idx = 0;; idx += 1)
{
if(this_proc_env[idx] == 0)
{
if(start_idx == idx)
{
break;
}
else
{
String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx);
String8 string = str8_from_16(arena, string16);
str8_list_push(arena, &info->environment, string);
start_idx = idx+1;
}
}
}
}
}
//- rjf: set up entity storage
InitializeCriticalSection(&os_w32_state.entity_mutex);
os_w32_state.entity_arena = arena_alloc();
//- rjf: call into "real" entry point
main_thread_base_entry_point(argc, argv);
}
@@ -7,7 +7,6 @@
////////////////////////////////
//~ rjf: Includes / Libraries
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <timeapi.h>
-4
View File
@@ -8,10 +8,6 @@
# define OS_FEATURE_GRAPHICAL 0
#endif
#if !defined(OS_GFX_STUB)
# define OS_GFX_STUB 0
#endif
#include "metagen/metagen_os/core/metagen_os_core.h"
#if OS_WINDOWS
+2 -2
View File
@@ -473,11 +473,11 @@ internal B32
os_file_reserve_size(OS_Handle file, U64 size)
{
HANDLE handle = (HANDLE)file.u64[0];
FILE_ALLOCATION_INFO alloc_info = {0};
alloc_info.AllocationSize.LowPart = size & max_U32;
alloc_info.AllocationSize.HighPart = (size >> 32) & max_U32;
BOOL is_reserved = SetFileInformationByHandle(handle, FileAllocationInfo, &alloc_info, sizeof(alloc_info));
return is_reserved;
}
+4 -1
View File
@@ -4335,6 +4335,9 @@ rd_view_ui(Rng2F32 rect)
// rjf: commit edited cell string
switch(cell->kind)
{
case RD_WatchCellKind_ViewUI:
case RD_WatchCellKind_CallStackFrame:
{}break;
case RD_WatchCellKind_Expr:
{
RD_Cfg *cfg = row_info.group_cfg_child;
@@ -10269,7 +10272,7 @@ rd_window_frame(void)
}
// rjf: draw sides
if(b->flags & UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideRight)
if(b->flags & (UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideRight))
{
Vec4F32 border_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("border"));
Rng2F32 r = b->rect;