Success running on linux

This commit is contained in:
Karol Krzosa
2025-05-17 08:22:27 +02:00
parent 76d52d9e1c
commit 720fdd9f34
16 changed files with 408 additions and 122 deletions

View File

@@ -6,12 +6,9 @@
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#define Assert(x) \
if (!(x)) { \
__debugbreak(); \
}
#define InvalidCodepath() Assert(!"invalid codepath")
#define ElseInvalidCodepath() else {InvalidCodepath()}
#include <signal.h>
#include <stddef.h>
#if defined(__APPLE__) && defined(__MACH__)
#define OS_MAC 1
@@ -62,6 +59,19 @@
#define COMPILER_GCC 0
#endif
#if OS_WINDOWS
#define DebugBreak() __debugbreak()
#elif OS_LINUX
#define DebugBreak() raise(SIGTRAP)
#endif
#define Assert(x) \
if (!(x)) { \
DebugBreak(); \
}
#define InvalidCodepath() Assert(!"invalid codepath")
#define ElseInvalidCodepath() else {InvalidCodepath()}
#define KiB(x) ((x##ull) * 1024ull)
#define MiB(x) (KiB(x) * 1024ull)
#define GiB(x) (MiB(x) * 1024ull)
@@ -710,48 +720,6 @@ ReverseIter<T> IterateInReverse(Slice<T> *slice) {
return {slice->end() - 1, slice};
}
template <class T>
struct CircularArray {
Allocator allocator;
T *data;
int16_t cap;
int16_t write;
};
template <class T>
CircularArray<T> MakeCircularArray(Allocator allocator, int size) {
CircularArray<T> arr = {allocator};
arr.data = AllocArray(allocator, T, size);
arr.cap = size;
return arr;
}
template <class T>
void Add(CircularArray<T> *arr, T item) {
if (arr->cap == 0) {
arr->allocator = GetSystemAllocator();
arr->cap = 128;
arr->data = AllocArray(arr->allocator, T, arr->cap);
}
int16_t i = arr->write;
arr->write = (arr->write + 1) % arr->cap;
arr->data[i] = item;
}
static int GetCircularIndex(int cap, int idx) {
int result = idx % cap;
if (result < 0) result = cap + result;
return result;
}
template <class T>
T Get(CircularArray<T> *arr, int idx, T default_value) {
int idx = circ->write - 1 - i;
idx = GetCircularIndex(circ->size, idx);
int result = circ->data[idx];
return result;
}
struct UTF32Result {
uint32_t out_str;
int64_t advance;
@@ -1063,7 +1031,7 @@ inline void Clear(Arena *arena) { SetLen(arena, 0); }
void *VReserve(size_t size);
bool VCommit(void *p, size_t size);
bool VRelease(void *p);
bool VRelease(void *p, size_t size);
bool VDecommit(void *p, size_t size);
void InitArena(Arena *arena, size_t reserve = GiB(4));
@@ -1662,7 +1630,7 @@ Arena *AllocArena(size_t reserve) {
bool success = VCommit(data, PAGE_SIZE);
if (!success) {
VRelease(data);
VRelease(data, reserve);
return result;
}
@@ -1711,7 +1679,7 @@ void *PushSize(Arena *arena, size_t size) {
void Release(Arena *arena) {
if (arena == NULL || arena->data == NULL) return;
bool zero_memory = (uint8_t *)arena != arena->data;
VRelease(arena->data);
VRelease(arena->data, arena->reserve);
if (zero_memory) MemoryZero(arena, sizeof(Arena));
}

View File

@@ -24,6 +24,7 @@ void Advance(FileIter *it);
FileIter IterateFiles(Allocator allocator, String path);
void InitOS(void (*error_proc)(const char *, ...));
bool DeleteFile(String path);
String GetExePath(Allocator allocator);
String GetExeDir(Allocator allocator);
bool FileExists(String path);

View File

@@ -295,7 +295,7 @@ Int SkipNumber(String16 *string) {
String16 SkipUntil(String16 *string, String16 str) {
String16 begin = *string;
begin.len = 0;
for (Int i = 0; string->len; begin.len += 1) {
for (; string->len; begin.len += 1) {
String16 match = GetPrefix(*string, str.len);
if (StartsWith(match, str)) break;
*string = Skip(*string, 1);

239
src/basic/unix.cpp Normal file
View File

@@ -0,0 +1,239 @@
#include "filesystem.h"
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <linux/limits.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
void (*Error)(const char *, ...);
void *VReserve(size_t size) {
void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t)0);
return result == (void *)-1 ? 0 : result;
}
bool VCommit(void *p, size_t size) {
int result = mprotect(p, size, PROT_READ | PROT_WRITE);
return result == 0;
}
bool VRelease(void *p, size_t size) {
int result = munmap(p, size);
return result == 0;
}
bool VDecommit(void *p, size_t size) {
mprotect(p, size, PROT_NONE);
madvise(p, size, MADV_DONTNEED);
return true;
}
void InitOS(void (*error_proc)(const char *, ...)) {
Error = error_proc;
}
String ReadFile(Allocator al, String path) {
Scratch scratch(al);
String null_term = Copy(scratch, path);
String result = {};
FILE *f = fopen(null_term.data, "rb");
if (f) {
fseek(f, 0, SEEK_END);
result.len = ftell(f);
fseek(f, 0, SEEK_SET);
result.data = (char *)AllocSize(al, result.len + 1);
fread(result.data, result.len, 1, f);
result.data[result.len] = 0;
fclose(f);
}
return result;
}
bool WriteFile(String path, String data) {
Scratch scratch;
String null_term = Copy(scratch, path);
bool result = false;
FILE *f = fopen((const char *)null_term.data, "w");
if (f) {
size_t written = fwrite(data.data, 1, data.len, f);
if (written == data.len) {
result = true;
}
fclose(f);
}
return result;
}
bool DeleteFile(String path) {
Scratch scratch;
String null_term = Copy(scratch, path);
int result = unlink(null_term.data);
return result == 0;
}
MakeDirResult MakeDir(String path) {
Scratch scratch;
String null_term = Copy(scratch, path);
int error = mkdir(null_term.data, 0755);
MakeDirResult result = MakeDirResult_Success;
if (error != 0) {
result = MakeDirResult_ErrorOther;
if (errno == EEXIST) result = MakeDirResult_Exists;
}
return result;
}
int64_t GetFileModTime(String path) {
Scratch scratch;
String null_term = Copy(scratch, path);
struct stat attrib = {};
stat(null_term.data, &attrib);
struct timespec ts = attrib.st_mtim;
int64_t result = (((int64_t)ts.tv_sec) * 1000000ll) + ((int64_t)ts.tv_nsec) / 1000ll;
return result;
}
String GetAbsolutePath(Allocator al, String path) {
Scratch scratch(al);
String null_term = Copy(scratch, path);
char *buffer = AllocArray(al, char, PATH_MAX);
realpath(null_term.data, buffer);
String result = buffer;
return buffer;
}
bool FileExists(String path) {
Scratch scratch;
String null_term = Copy(scratch, path);
bool result = false;
if (access((char *)null_term.data, F_OK) == 0) {
result = true;
}
return result;
}
bool IsDir(String path) {
Scratch scratch;
String null_term = Copy(scratch, path);
struct stat s;
if (stat(null_term.data, &s) != 0)
return false;
return S_ISDIR(s.st_mode);
}
bool IsFile(String path) {
Scratch scratch;
String null_term = Copy(scratch, path);
struct stat s;
if (stat(null_term.data, &s) != 0)
return false;
return S_ISREG(s.st_mode);
}
bool IsAbsolute(String path) {
bool result = path.len && path.data[0] == '/';
return result;
}
String GetWorkingDir(Allocator al) {
char *buffer = AllocArray(al, char, PATH_MAX);
char *cwd = getcwd(buffer, PATH_MAX);
return cwd;
}
String GetExePath(Allocator al) {
char *buffer = AllocArray(al, char, PATH_MAX);
readlink("/proc/self/exe", buffer, PATH_MAX);
return buffer;
}
String GetExeDir(Allocator al) {
Scratch scratch(al);
String exe_path = GetExePath(scratch);
String dir = ChopLastSlash(exe_path);
String result = Copy(al, dir);
return result;
}
double get_time_in_micros(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
return (((double)spec.tv_sec) * 1000000) + (((double)spec.tv_nsec) / 1000);
}
bool IsValid(const FileIter &it) {
return it.is_valid;
}
void Advance(FileIter *it) {
struct dirent *file = NULL;
while ((file = readdir((DIR *)it->dir)) != NULL) {
if (file->d_name[0] == '.' && file->d_name[1] == '.' && file->d_name[2] == 0) {
continue;
}
if (file->d_name[0] == '.' && file->d_name[1] == 0) {
continue;
}
it->is_directory = file->d_type == DT_DIR;
it->filename = Copy(it->allocator, file->d_name);
const char *dir_char_ending = it->is_directory ? "/" : "";
const char *separator = it->path.data[it->path.len - 1] == '/' ? "" : "/";
it->relative_path = Format(it->allocator, "%.*s%s%s%s", FmtString(it->path), separator, file->d_name, dir_char_ending);
it->absolute_path = GetAbsolutePath(it->allocator, it->relative_path);
if (it->is_directory) it->absolute_path = Format(it->allocator, "%.*s/", FmtString(it->absolute_path));
it->is_valid = true;
return;
}
it->is_valid = false;
closedir((DIR *)it->dir);
}
FileIter IterateFiles(Allocator alo, String path) {
FileIter it = {};
it.allocator = alo;
it.path = path;
Scratch scratch(alo);
String null_term = Copy(scratch, path);
it.dir = (void *)opendir((char *)null_term.data);
if (it.dir) {
Advance(&it);
}
return it;
}
struct UnixProcess {
pid_t pid;
};
Process SpawnProcess(String command_line, String working_dir, String write_stdin, Array<String> enviroment) {
return {};
}
bool IsValid(Process *process) {
return false;
}
void KillProcess(Process *process) {
}
String PollStdout(Allocator allocator, Process *process) {
return "";
}
void WriteStdin(Process *process, String string) {
}
void CloseStdin(Process *process) {
}

View File

@@ -15,7 +15,6 @@
void (*Error)(const char *, ...);
// Basic begin
void *VReserve(size_t size) {
void *result = (uint8_t *)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
return result;
@@ -26,7 +25,7 @@ bool VCommit(void *p, size_t size) {
return result ? true : false;
}
bool VRelease(void *p) {
bool VRelease(void *p, size_t size) {
BOOL result = VirtualFree(p, 0, MEM_RELEASE);
return result ? true : false;
}
@@ -35,7 +34,6 @@ bool VDecommit(void *p, size_t size) {
BOOL result = VirtualFree(p, size, MEM_DECOMMIT);
return result ? true : false;
}
// Basic end
void InitOS(void (*error_proc)(const char *, ...)) {
Error = error_proc;
@@ -146,8 +144,6 @@ FileIter IterateFiles(Allocator alo, String path) {
return it;
}
#if _WIN32
#include <Windows.h>
double get_time_in_micros(void) {
static double invfreq;
if (!invfreq) {
@@ -159,14 +155,6 @@ double get_time_in_micros(void) {
QueryPerformanceCounter(&counter);
return counter.QuadPart * invfreq;
}
#else
#include <unistd.h>
double get_time_in_micros(void) {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
return (((double)spec.tv_sec) * 1000000) + (((double)spec.tv_nsec) / 1000);
}
#endif
bool WriteFile(String path, String data) {
bool result = false;

View File

@@ -14,7 +14,11 @@ void PushWork(WorkQueue *wq, void *data, WorkQueueCallback *callback) {
entry->data = data;
entry->callback = callback;
wq->completion_goal += 1;
wq->completion_goal += 1;dex_to_read + 1) % Lengthof(wq->entries);
if (original_index_to_read != wq->index_to_write) {
int64_t index = AtomicCompareAndSwap(&wq->index_to_read, new_index_to_read, original_index_to_read);
if (index == original_index_to_read) {
WorkQueueEntry *entry = wq->entries +
_WriteBarrier();
wq->index_to_write = new_index;
ReleaseSemaphore(wq->semaphore, 1, 0);
@@ -23,11 +27,7 @@ void PushWork(WorkQueue *wq, void *data, WorkQueueCallback *callback) {
bool TryDoingWork(WorkQueue *wq) {
bool should_sleep = false;
int64_t original_index_to_read = wq->index_to_read;
int64_t new_index_to_read = (original_index_to_read + 1) % Lengthof(wq->entries);
if (original_index_to_read != wq->index_to_write) {
int64_t index = AtomicCompareAndSwap(&wq->index_to_read, new_index_to_read, original_index_to_read);
if (index == original_index_to_read) {
WorkQueueEntry *entry = wq->entries + index;
int64_t new_index_to_read = (original_inindex;
entry->callback(entry->data);
AtomicIncrement(&wq->completion_index);
}