linux file track stuff working afaict
parent
0378546dd8
commit
a0f3996e73
5
Makefile
5
Makefile
|
@ -1,4 +1,5 @@
|
||||||
CPP_FILES := $(wildcard *.cpp) $(wildcard **/*.cpp)
|
CPP_FILES := $(wildcard *.cpp) $(wildcard **/*.cpp)
|
||||||
|
C_FILES := $(wildcard *.c) $(wildcard **/*.c)
|
||||||
H_FILES := $(wildcard *.h) $(wildcard **/*.h)
|
H_FILES := $(wildcard *.h) $(wildcard **/*.h)
|
||||||
WARNINGS := -Wno-write-strings
|
WARNINGS := -Wno-write-strings
|
||||||
PLAT_LINKS := -L/usr/local/lib -lX11 -lpthread -lm -lrt -lGL -ldl -lXfixes -lfreetype -lfontconfig
|
PLAT_LINKS := -L/usr/local/lib -lX11 -lpthread -lm -lrt -lGL -ldl -lXfixes -lfreetype -lfontconfig
|
||||||
|
@ -9,10 +10,10 @@ FLAGS := -fPIC -fno-threadsafe-statics -pthread -I../foreign $(shell pkg-co
|
||||||
debug: FLAGS += -DFRED_INTERNAL=1 -DFRED_SUPER=1 -g -O0
|
debug: FLAGS += -DFRED_INTERNAL=1 -DFRED_SUPER=1 -g -O0
|
||||||
debug: ../4ed_app.so ../4ed
|
debug: ../4ed_app.so ../4ed
|
||||||
|
|
||||||
../4ed_app.so: $(CPP_FILES) $(H_FILES)
|
../4ed_app.so: $(CPP_FILES) $(C_FILES) $(H_FILES)
|
||||||
g++ $(WARNINGS) $(FLAGS) -shared 4ed_app_target.cpp -iquoteforeign -o $@
|
g++ $(WARNINGS) $(FLAGS) -shared 4ed_app_target.cpp -iquoteforeign -o $@
|
||||||
|
|
||||||
../4ed: $(CPP_FILES) $(H_FILES)
|
../4ed: $(CPP_FILES) $(C_FILES) $(H_FILES)
|
||||||
g++ $(WARNINGS) $(FLAGS) linux_4ed.cpp -iquoteforeign $(PLAT_LINKS) -o $@
|
g++ $(WARNINGS) $(FLAGS) linux_4ed.cpp -iquoteforeign $(PLAT_LINKS) -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
The OS agnostic file tracking API for applications
|
The OS agnostic file tracking API for applications
|
||||||
that want to interact with potentially many files on
|
that want to interact with potentially many files on
|
||||||
the disk that could be changed by other applications.
|
the disk that could be changed by other applications.
|
||||||
|
|
||||||
Created on: 29.08.2016
|
Created on: 29.08.2016
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -43,8 +43,16 @@ typedef struct {
|
||||||
// Right now the way the API works, it assumes that the user will
|
// Right now the way the API works, it assumes that the user will
|
||||||
// only ever add memory and never free it. If freeing becomes necessary
|
// only ever add memory and never free it. If freeing becomes necessary
|
||||||
// on Linux the API can be extended to support that.
|
// on Linux the API can be extended to support that.
|
||||||
|
|
||||||
|
int inotify;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
char *string_mem_begin;
|
||||||
|
char *string_mem_end;
|
||||||
|
|
||||||
} Linux_File_Track_Vars;
|
} Linux_File_Track_Vars;
|
||||||
|
|
||||||
|
//static_assert(sizeof(Linux_File_Track_Vars) <= sizeof(File_Track_System));
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
File_Index hash;
|
File_Index hash;
|
||||||
// NOTE(allen):
|
// NOTE(allen):
|
||||||
|
@ -54,8 +62,11 @@ typedef struct {
|
||||||
// would be fine. If it is used hash should be the first element
|
// would be fine. If it is used hash should be the first element
|
||||||
// of this struct and it should be used to uniquely identify each
|
// of this struct and it should be used to uniquely identify each
|
||||||
// entry because it is used as the key for the table.
|
// entry because it is used as the key for the table.
|
||||||
|
char* filename;
|
||||||
} Linux_File_Track_Entry;
|
} Linux_File_Track_Entry;
|
||||||
|
|
||||||
|
//static_assert(sizeof(Linux_File_Track_Entry) <= sizeof(File_Track_Entry));
|
||||||
|
|
||||||
#define to_vars(s) ((Linux_File_Track_Vars*)(s))
|
#define to_vars(s) ((Linux_File_Track_Vars*)(s))
|
||||||
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
||||||
|
|
||||||
|
@ -72,17 +83,22 @@ init_track_system(File_Track_System *system,
|
||||||
/*if listener memory is important check it's size here*/ 1){
|
/*if listener memory is important check it's size here*/ 1){
|
||||||
|
|
||||||
// NOTE(allen): Initialize main data tables
|
// NOTE(allen): Initialize main data tables
|
||||||
vars->tables = table_memory;
|
vars->tables = (File_Track_Tables*) table_memory;
|
||||||
File_Track_Tables *tables = to_tables(vars);
|
File_Track_Tables *tables = to_tables(vars);
|
||||||
init_table_memory(tables, table_memory_size);
|
init_table_memory(tables, table_memory_size);
|
||||||
|
|
||||||
// NOTE(allen):
|
vars->inotify = inotify_init1(IN_NONBLOCK);
|
||||||
// Here prepare the data structure and synchronization primatives
|
|
||||||
// in the vars struct.
|
pthread_mutex_init(&vars->lock, NULL);
|
||||||
|
|
||||||
|
vars->string_mem_begin = (char*)listener_memory;
|
||||||
|
vars->string_mem_end = (char*)listener_memory + listener_memory_size;
|
||||||
|
|
||||||
result = FileTrack_Good;
|
result = FileTrack_Good;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LINUX_FN_DEBUG("result: %d", result);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +106,9 @@ FILE_TRACK_LINK File_Track_Result
|
||||||
add_listener(File_Track_System *system, char *filename){
|
add_listener(File_Track_System *system, char *filename){
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
Linux_File_Track_Vars *vars = to_vars(system);
|
Linux_File_Track_Vars *vars = to_vars(system);
|
||||||
|
File_Track_Tables *tables = to_tables(vars);
|
||||||
|
|
||||||
// ACQUIRE LOCK (only keep this if either of the data structures is kept)
|
pthread_mutex_lock(&vars->lock);
|
||||||
|
|
||||||
// NOTE(allen):
|
// NOTE(allen):
|
||||||
// Here do something to begin listening to changes to the file named filename.
|
// Here do something to begin listening to changes to the file named filename.
|
||||||
|
@ -102,7 +119,41 @@ add_listener(File_Track_System *system, char *filename){
|
||||||
// treat them as two separate files so that if one of the listeners is removed
|
// treat them as two separate files so that if one of the listeners is removed
|
||||||
// the other on the same file keeps working.
|
// the other on the same file keeps working.
|
||||||
|
|
||||||
// RELEASE LOCK
|
if(tracking_system_has_space(tables, 1)){
|
||||||
|
size_t filename_len = strlen(filename) + 1;
|
||||||
|
if(vars->string_mem_end - vars->string_mem_begin >= filename_len){
|
||||||
|
|
||||||
|
// TODO(inso): which events do we want?
|
||||||
|
int wd = inotify_add_watch(vars->inotify, filename, IN_ALL_EVENTS);
|
||||||
|
if(wd != -1){
|
||||||
|
File_Index key = { wd, 1 };
|
||||||
|
File_Track_Entry *entry = tracking_system_lookup_entry(tables, key);
|
||||||
|
Linux_File_Track_Entry *linux_entry = (Linux_File_Track_Entry*) entry;
|
||||||
|
|
||||||
|
LINUX_FN_DEBUG("map %s to wd %d", filename, wd);
|
||||||
|
|
||||||
|
Assert(entry_is_available(entry));
|
||||||
|
|
||||||
|
linux_entry->hash = key;
|
||||||
|
linux_entry->filename = vars->string_mem_begin;
|
||||||
|
|
||||||
|
memcpy(vars->string_mem_begin, filename, filename_len);
|
||||||
|
vars->string_mem_begin += filename_len;
|
||||||
|
|
||||||
|
++tables->tracked_count;
|
||||||
|
} else {
|
||||||
|
result = FileTrack_FileSystemError;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = FileTrack_OutOfListenerMemory;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = FileTrack_OutOfTableMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&vars->lock);
|
||||||
|
|
||||||
|
LINUX_FN_DEBUG("result: %d", result);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
@ -111,15 +162,34 @@ FILE_TRACK_LINK File_Track_Result
|
||||||
remove_listener(File_Track_System *system, char *filename){
|
remove_listener(File_Track_System *system, char *filename){
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
Linux_File_Track_Vars *vars = to_vars(system);
|
Linux_File_Track_Vars *vars = to_vars(system);
|
||||||
|
File_Track_Tables *tables = to_tables(vars);
|
||||||
|
File_Track_Entry *entries = (File_Track_Entry*) to_ptr(tables, tables->file_table);
|
||||||
|
|
||||||
// ACQUIRE LOCK
|
pthread_mutex_lock(&vars->lock);
|
||||||
|
|
||||||
// NOTE(allen):
|
// NOTE(allen):
|
||||||
// Here do something to stop listening to changes to the file named filename.
|
// Here do something to stop listening to changes to the file named filename.
|
||||||
// We assume this filename has been passed into add_listener already and that
|
// We assume this filename has been passed into add_listener already and that
|
||||||
// if it has not it is a bug in the user's code not in this code.
|
// if it has not it is a bug in the user's code not in this code.
|
||||||
|
|
||||||
// RELEASE LOCK
|
for(uint32_t i = 0; i < tables->max; ++i){
|
||||||
|
Linux_File_Track_Entry *e = (Linux_File_Track_Entry*)(entries + i);
|
||||||
|
if(e->hash.id[1] != 1) continue;
|
||||||
|
if(strcmp(e->filename, filename) == 0){
|
||||||
|
LINUX_FN_DEBUG("%s found as wd %d", filename, e->hash.id[0]);
|
||||||
|
if(inotify_rm_watch(vars->inotify, e->hash.id[0]) == -1){
|
||||||
|
perror("inotify_rm_watch");
|
||||||
|
result = FileTrack_FileSystemError;
|
||||||
|
}
|
||||||
|
internal_free_slot(tables, (File_Track_Entry*)e);
|
||||||
|
// NOTE(inso): associated string memory in listeners would be freed here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&vars->lock);
|
||||||
|
|
||||||
|
LINUX_FN_DEBUG("result: %d", result);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
@ -129,7 +199,7 @@ move_track_system(File_Track_System *system, void *mem, int32_t size){
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
Linux_File_Track_Vars *vars = to_vars(system);
|
Linux_File_Track_Vars *vars = to_vars(system);
|
||||||
|
|
||||||
// ACQUIRE LOCK
|
pthread_mutex_lock(&vars->lock);
|
||||||
|
|
||||||
{
|
{
|
||||||
File_Track_Tables *original_tables = to_tables(vars);
|
File_Track_Tables *original_tables = to_tables(vars);
|
||||||
|
@ -139,7 +209,9 @@ move_track_system(File_Track_System *system, void *mem, int32_t size){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RELEASE LOCK
|
pthread_mutex_unlock(&vars->lock);
|
||||||
|
|
||||||
|
LINUX_FN_DEBUG("size: %d, %d", size, result);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
@ -149,14 +221,28 @@ expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
Linux_File_Track_Vars *vars = to_vars(system);
|
Linux_File_Track_Vars *vars = to_vars(system);
|
||||||
|
|
||||||
// ACQUIRE LOCK
|
pthread_mutex_lock(&vars->lock);
|
||||||
|
|
||||||
// NOTE(allen): If there is a data structure for the listeners
|
// NOTE(allen): If there is a data structure for the listeners
|
||||||
// this call adds more memory to that system. If this system
|
// this call adds more memory to that system. If this system
|
||||||
// wants to free old memory the API does not currently support
|
// wants to free old memory the API does not currently support
|
||||||
// that but it can.
|
// that but it can.
|
||||||
|
|
||||||
// RELEASE LOCK
|
// NOTE(inso): pointer to old string mem is lost here.
|
||||||
|
// would need to keep it around if we want to free in the future
|
||||||
|
|
||||||
|
// NOTE(inso): assuming PATH_MAX is a reasonable lower bound of extra memory to get
|
||||||
|
|
||||||
|
if(size < PATH_MAX){
|
||||||
|
result = FileTrack_MemoryTooSmall;
|
||||||
|
} else {
|
||||||
|
vars->string_mem_begin = (char*) mem;
|
||||||
|
vars->string_mem_end = (char*) mem + size;;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&vars->lock);
|
||||||
|
|
||||||
|
LINUX_FN_DEBUG("size: %d, result: %d", size, result);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
@ -165,8 +251,9 @@ FILE_TRACK_LINK File_Track_Result
|
||||||
get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *size){
|
get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *size){
|
||||||
File_Track_Result result = FileTrack_NoMoreEvents;
|
File_Track_Result result = FileTrack_NoMoreEvents;
|
||||||
Linux_File_Track_Vars *vars = to_vars(system);
|
Linux_File_Track_Vars *vars = to_vars(system);
|
||||||
|
File_Track_Tables *tables = to_tables(vars);
|
||||||
|
|
||||||
// ACQUIRE LOCK
|
pthread_mutex_lock(&vars->lock);
|
||||||
|
|
||||||
// NOTE(allen): If there are any new file changes report them
|
// NOTE(allen): If there are any new file changes report them
|
||||||
// by copying the name of the file to the buffer and returning
|
// by copying the name of the file to the buffer and returning
|
||||||
|
@ -176,7 +263,34 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *
|
||||||
// about that file. If there are no new changes the return
|
// about that file. If there are no new changes the return
|
||||||
// FileTrack_NoMoreEvents.
|
// FileTrack_NoMoreEvents.
|
||||||
|
|
||||||
// RELEASE LOCK
|
struct inotify_event ev;
|
||||||
|
|
||||||
|
ssize_t n = read(vars->inotify, &ev, sizeof(ev));
|
||||||
|
if(n == -1 && errno != EAGAIN){
|
||||||
|
perror("inotify read");
|
||||||
|
} else if(n > 0){
|
||||||
|
File_Index key = { ev.wd, 1 };
|
||||||
|
File_Track_Entry *entry = tracking_system_lookup_entry(tables, key);
|
||||||
|
Linux_File_Track_Entry *linux_entry = (Linux_File_Track_Entry*) entry;
|
||||||
|
|
||||||
|
if(!entry_is_available(entry)){
|
||||||
|
LINUX_FN_DEBUG("event from wd %d (%s)", ev.wd, linux_entry->filename);
|
||||||
|
size_t filename_size = strlen(linux_entry->filename);
|
||||||
|
if(max < filename_size){
|
||||||
|
result = FileTrack_MemoryTooSmall;
|
||||||
|
// NOTE(inso): this event will be dropped, needs to be stashed.
|
||||||
|
LINUX_FN_DEBUG("max too small, event dropped");
|
||||||
|
} else {
|
||||||
|
memcpy(buffer, linux_entry->filename, filename_size);
|
||||||
|
*size = filename_size;
|
||||||
|
result = FileTrack_Good;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LINUX_FN_DEBUG("dead event from wd %d", ev.wd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&vars->lock);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
@ -186,25 +300,14 @@ shut_down_track_system(File_Track_System *system){
|
||||||
File_Track_Result result = FileTrack_Good;
|
File_Track_Result result = FileTrack_Good;
|
||||||
Linux_File_Track_Vars *vars = to_vars(system);
|
Linux_File_Track_Vars *vars = to_vars(system);
|
||||||
|
|
||||||
|
|
||||||
// NOTE(allen): Close all the handles stored in the table.
|
|
||||||
{
|
|
||||||
File_Track_Tables *tables = to_tables(vars);
|
|
||||||
|
|
||||||
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
|
||||||
uint32_t max = tables->max;
|
|
||||||
|
|
||||||
for (uint32_t index = 0; index < max; ++index){
|
|
||||||
File_Track_Entry *entry = entries + index;
|
|
||||||
|
|
||||||
if (!entry_is_available(entry)){
|
|
||||||
// NOTE(allen): If table entries contain anything
|
|
||||||
// that need cleanup, that cleanup should happen here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(allen): Close all the global track system resources.
|
// NOTE(allen): Close all the global track system resources.
|
||||||
|
if(close(vars->inotify) == -1){
|
||||||
|
result = FileTrack_FileSystemError;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&vars->lock);
|
||||||
|
|
||||||
|
LINUX_FN_DEBUG("result: %d", result);
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
474
linux_4ed.cpp
474
linux_4ed.cpp
|
@ -69,8 +69,6 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
#include "filetrack/4tech_file_track_linux.c"
|
|
||||||
#include "system_shared.h"
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Linux macros
|
// Linux macros
|
||||||
|
@ -105,6 +103,9 @@
|
||||||
|
|
||||||
#define InterlockedCompareExchange(dest, ex, comp) __sync_val_compare_and_swap((dest), (comp), (ex))
|
#define InterlockedCompareExchange(dest, ex, comp) __sync_val_compare_and_swap((dest), (comp), (ex))
|
||||||
|
|
||||||
|
#include "filetrack/4tech_file_track_linux.c"
|
||||||
|
#include "system_shared.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Linux structs / enums
|
// Linux structs / enums
|
||||||
//
|
//
|
||||||
|
@ -120,11 +121,10 @@ struct Sys_Bubble : public Bubble{
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
LINUX_4ED_EVENT_X11 = (UINT64_C(1) << 32),
|
LINUX_4ED_EVENT_X11 = (UINT64_C(1) << 32),
|
||||||
LINUX_4ED_EVENT_X11_INTERNAL = (UINT64_C(1) << 33),
|
LINUX_4ED_EVENT_X11_INTERNAL = (UINT64_C(2) << 32),
|
||||||
LINUX_4ED_EVENT_FILE = (UINT64_C(1) << 34),
|
LINUX_4ED_EVENT_STEP = (UINT64_C(3) << 32),
|
||||||
LINUX_4ED_EVENT_STEP = (UINT64_C(1) << 35),
|
LINUX_4ED_EVENT_STEP_TIMER = (UINT64_C(4) << 32),
|
||||||
LINUX_4ED_EVENT_STEP_TIMER = (UINT64_C(1) << 36),
|
LINUX_4ED_EVENT_CLI = (UINT64_C(5) << 32),
|
||||||
LINUX_4ED_EVENT_CLI = (UINT64_C(1) << 37),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Linux_Coroutine {
|
struct Linux_Coroutine {
|
||||||
|
@ -268,11 +268,7 @@ static_assert(sizeof(Plat_Handle) >= sizeof(sem_t*), "Plat_Handle not big e
|
||||||
static_assert(sizeof(Plat_Handle) >= sizeof(int), "Plat_Handle not big enough");
|
static_assert(sizeof(Plat_Handle) >= sizeof(int), "Plat_Handle not big enough");
|
||||||
|
|
||||||
//
|
//
|
||||||
// Linux shared/system functions
|
// Shared system functions (system_shared.h)
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Memory
|
|
||||||
//
|
//
|
||||||
|
|
||||||
internal void*
|
internal void*
|
||||||
|
@ -341,9 +337,6 @@ Sys_Free_Memory_Sig(system_free_memory){
|
||||||
LinuxFreeMemory(block);
|
LinuxFreeMemory(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// File
|
|
||||||
//
|
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Sys_File_Can_Be_Made_Sig(system_file_can_be_made){
|
Sys_File_Can_Be_Made_Sig(system_file_can_be_made){
|
||||||
|
@ -368,49 +361,13 @@ Sys_Get_Binary_Path_Sig(system_get_binary_path){
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Linux application/system functions
|
// System Functions (4ed_system.h)
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// File
|
// Files
|
||||||
//
|
//
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_File_Time_Stamp_Sig(system_file_time_stamp){
|
|
||||||
struct stat info = {};
|
|
||||||
u64 microsecond_timestamp = 0;
|
|
||||||
|
|
||||||
if(stat(filename, &info) == 0){
|
|
||||||
#if OLD_STAT_NANO_TIME
|
|
||||||
microsecond_timestamp =
|
|
||||||
(info.st_mtime * UINT64_C(1000000)) +
|
|
||||||
(info.st_mtimensec / UINT64_C(1000));
|
|
||||||
#else
|
|
||||||
microsecond_timestamp =
|
|
||||||
(info.st_mtim.tv_sec * UINT64_C(1000000)) +
|
|
||||||
(info.st_mtim.tv_nsec / UINT64_C(1000));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//LINUX_FN_DEBUG("%s = %" PRIu64, filename, microsecond_timestamp);
|
|
||||||
|
|
||||||
return(microsecond_timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Now_Time_Stamp_Sig(system_now_time_stamp){
|
|
||||||
struct timespec spec;
|
|
||||||
u64 result;
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &spec);
|
|
||||||
result = (spec.tv_sec * UINT64_C(1000000)) + (spec.tv_nsec / UINT64_C(1000));
|
|
||||||
|
|
||||||
//LINUX_FN_DEBUG("ts: %" PRIu64, result);
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Sys_Set_File_List_Sig(system_set_file_list){
|
Sys_Set_File_List_Sig(system_set_file_list){
|
||||||
DIR *d;
|
DIR *d;
|
||||||
|
@ -503,105 +460,88 @@ Sys_Set_File_List_Sig(system_set_file_list){
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Sys_File_Unique_Hash_Sig(system_file_unique_hash){
|
Sys_Get_Canonical_Sig(system_get_canonical){
|
||||||
Unique_Hash result = {};
|
int32_t result = 0;
|
||||||
struct stat st = {};
|
|
||||||
*success = 0;
|
|
||||||
|
|
||||||
if(stat(filename.str, &st) == 0){
|
char* path = realpath(strndupa(filename, len), NULL);
|
||||||
memcpy(&result, &st.st_dev, sizeof(st.st_dev));
|
if(!path){
|
||||||
memcpy((char*)&result + sizeof(st.st_dev), &st.st_ino, sizeof(st.st_ino));
|
perror("realpath");
|
||||||
*success = 1;
|
} else {
|
||||||
|
size_t path_len = strlen(path);
|
||||||
|
if(max >= path_len){
|
||||||
|
memcpy(buffer, path, path_len);
|
||||||
|
result = path_len;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LINUX_FN_DEBUG("%s = %ld:%ld", filename.str, (long)st.st_dev, (long)st.st_ino);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Sys_File_Track_Sig(system_file_track){
|
Sys_Load_Handle_Sig(system_load_handle){
|
||||||
if(filename.size <= 0 || !filename.str) return;
|
b32 result = 0;
|
||||||
|
|
||||||
char* fname = (char*) alloca(filename.size+1);
|
|
||||||
memcpy(fname, filename.str, filename.size);
|
|
||||||
fname[filename.size] = 0;
|
|
||||||
|
|
||||||
int wd = inotify_add_watch(linuxvars.inotify_fd, fname, IN_ALL_EVENTS);
|
|
||||||
if(wd == -1){
|
|
||||||
perror("inotify_add_watch");
|
|
||||||
} else {
|
|
||||||
printf("watch %s\n", fname);
|
|
||||||
// TODO: store the wd somewhere so Untrack can use it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_File_Untrack_Sig(system_file_untrack){
|
|
||||||
//TODO
|
|
||||||
// inotify_rm_watch(...)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_File_Load_Begin_Sig(system_file_load_begin){
|
|
||||||
File_Loading loading = {};
|
|
||||||
struct stat info = {};
|
|
||||||
|
|
||||||
LINUX_FN_DEBUG("%s", filename);
|
|
||||||
|
|
||||||
int fd = open(filename, O_RDONLY);
|
int fd = open(filename, O_RDONLY);
|
||||||
if(fd < 0){
|
if(fd == -1){
|
||||||
fprintf(stderr, "sys_open_file: open '%s': %s\n", filename, strerror(errno));
|
perror("open");
|
||||||
goto out;
|
} else {
|
||||||
}
|
*(int*)handle_out = fd;
|
||||||
if(fstat(fd, &info) < 0){
|
result = 1;
|
||||||
fprintf(stderr, "sys_open_file: stat '%s': %s\n", filename, strerror(errno));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if(info.st_size < 0){
|
|
||||||
fprintf(stderr, "sys_open_file: st_size < 0: %ld\n", info.st_size);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.handle = LinuxFDToHandle(fd);
|
return result;
|
||||||
loading.size = info.st_size;
|
|
||||||
loading.exists = 1;
|
|
||||||
|
|
||||||
out:
|
|
||||||
if(fd != -1 && !loading.exists) close(fd);
|
|
||||||
return(loading);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Sys_File_Load_End_Sig(system_file_load_end){
|
Sys_Load_Size_Sig(system_load_size){
|
||||||
int fd = LinuxHandleToFD(loading.handle);
|
u32 result = 0;
|
||||||
char* ptr = buffer;
|
|
||||||
size_t size = loading.size;
|
|
||||||
|
|
||||||
if(!loading.exists || fd == -1) return 0;
|
int fd = *(int*)&handle;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
do {
|
if(fstat(fd, &st) == -1){
|
||||||
ssize_t read_result = read(fd, buffer, size);
|
perror("fstat");
|
||||||
if(read_result == -1){
|
|
||||||
if(errno != EINTR){
|
|
||||||
perror("system_file_load_end");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
size -= read_result;
|
result = st.st_size;
|
||||||
ptr += read_result;
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Load_File_Sig(system_load_file){
|
||||||
|
|
||||||
|
int fd = *(int*)&handle;
|
||||||
|
do {
|
||||||
|
ssize_t n = read(fd, buffer, size);
|
||||||
|
if(n == -1 && errno != EAGAIN){
|
||||||
|
perror("read");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
size -= n;
|
||||||
|
buffer += n;
|
||||||
}
|
}
|
||||||
} while(size);
|
} while(size);
|
||||||
|
|
||||||
close(fd);
|
return size == 0;
|
||||||
|
|
||||||
LINUX_FN_DEBUG("success == %d", (size == 0));
|
|
||||||
|
|
||||||
return (size == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Sys_File_Save_Sig(system_file_save){
|
Sys_Load_Close_Sig(system_load_close){
|
||||||
|
b32 result = 1;
|
||||||
|
|
||||||
|
int fd = *(int*)&handle;
|
||||||
|
if(close(fd) == -1){
|
||||||
|
perror("close");
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Save_File_Sig(system_save_file){
|
||||||
b32 result = 0;
|
b32 result = 0;
|
||||||
int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 00640);
|
int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 00640);
|
||||||
|
|
||||||
|
@ -630,7 +570,24 @@ Sys_File_Save_Sig(system_file_save){
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Custom access to OS pages
|
// Time
|
||||||
|
//
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Now_Time_Sig(system_now_time){
|
||||||
|
struct timespec spec;
|
||||||
|
u64 result;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_REALTIME, &spec);
|
||||||
|
result = (spec.tv_sec * UINT64_C(1000000)) + (spec.tv_nsec / UINT64_C(1000));
|
||||||
|
|
||||||
|
//LINUX_FN_DEBUG("ts: %" PRIu64, result);
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 4coder_custom.h
|
||||||
//
|
//
|
||||||
|
|
||||||
internal
|
internal
|
||||||
|
@ -692,10 +649,6 @@ MEMORY_FREE_SIG(system_memory_free){
|
||||||
munmap(mem, size);
|
munmap(mem, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Filesystem navigation
|
|
||||||
//
|
|
||||||
|
|
||||||
internal
|
internal
|
||||||
FILE_EXISTS_SIG(system_file_exists){
|
FILE_EXISTS_SIG(system_file_exists){
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
@ -983,175 +936,26 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
|
||||||
// Threads
|
// Threads
|
||||||
//
|
//
|
||||||
|
|
||||||
//#define OLD_JOB_QUEUE
|
internal
|
||||||
|
Sys_Acquire_Lock_Sig(system_acquire_lock){
|
||||||
#ifdef OLD_JOB_QUEUE
|
pthread_mutex_lock(linuxvars.locks + id);
|
||||||
internal void*
|
|
||||||
JobThreadProc(void* arg){
|
|
||||||
Thread_Context *thread = (Thread_Context*)arg;
|
|
||||||
Work_Queue *queue = linuxvars.queues + thread->group_id;
|
|
||||||
Thread_Group *group = linuxvars.groups + thread->group_id;
|
|
||||||
|
|
||||||
i32 thread_index = thread->id - 1;
|
|
||||||
|
|
||||||
i32 cancel_lock = group->cancel_lock0 + thread_index;
|
|
||||||
i32 cancel_cv = group->cancel_cv0 + thread_index;
|
|
||||||
|
|
||||||
Thread_Memory *thread_memory = linuxvars.thread_memory + thread_index;
|
|
||||||
|
|
||||||
if (thread_memory->size == 0){
|
|
||||||
i32 new_size = Kbytes(64);
|
|
||||||
thread_memory->data = LinuxGetMemory(new_size);
|
|
||||||
thread_memory->size = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;){
|
|
||||||
u32 read_index = queue->read_position;
|
|
||||||
u32 write_index = queue->write_position;
|
|
||||||
|
|
||||||
if (read_index != write_index){
|
|
||||||
u32 next_read_index = (read_index + 1) % QUEUE_WRAP;
|
|
||||||
u32 safe_read_index =
|
|
||||||
__sync_val_compare_and_swap(&queue->read_position,
|
|
||||||
read_index, next_read_index);
|
|
||||||
|
|
||||||
if (safe_read_index == read_index){
|
|
||||||
Full_Job_Data *full_job = queue->jobs + safe_read_index;
|
|
||||||
// NOTE(allen): This is interlocked so that it plays nice
|
|
||||||
// with the cancel job routine, which may try to cancel this job
|
|
||||||
// at the same time that we try to run it
|
|
||||||
|
|
||||||
i32 safe_running_thread =
|
|
||||||
__sync_val_compare_and_swap(&full_job->running_thread,
|
|
||||||
THREAD_NOT_ASSIGNED, thread->id);
|
|
||||||
|
|
||||||
if (safe_running_thread == THREAD_NOT_ASSIGNED){
|
|
||||||
thread->job_id = full_job->id;
|
|
||||||
thread->running = 1;
|
|
||||||
|
|
||||||
full_job->job.callback(&linuxvars.system, thread, thread_memory, full_job->job.data);
|
|
||||||
full_job->running_thread = 0;
|
|
||||||
thread->running = 0;
|
|
||||||
|
|
||||||
system_acquire_lock(cancel_lock);
|
|
||||||
if(thread->cancel){
|
|
||||||
thread->cancel = 0;
|
|
||||||
pthread_cond_signal(linuxvars.conds + cancel_cv);
|
|
||||||
}
|
|
||||||
system_release_lock(cancel_lock);
|
|
||||||
|
|
||||||
LinuxScheduleStep();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
sem_wait(LinuxHandleToSem(queue->semaphore));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
Sys_Post_Job_Sig(system_post_job){
|
Sys_Release_Lock_Sig(system_release_lock){
|
||||||
Work_Queue *queue = linuxvars.queues + group_id;
|
pthread_mutex_unlock(linuxvars.locks + id);
|
||||||
|
|
||||||
Assert((queue->write_position + 1) % QUEUE_WRAP != queue->read_position % QUEUE_WRAP);
|
|
||||||
|
|
||||||
b32 success = 0;
|
|
||||||
u32 result = 0;
|
|
||||||
while (!success){
|
|
||||||
u32 write_index = queue->write_position;
|
|
||||||
u32 next_write_index = (write_index + 1) % QUEUE_WRAP;
|
|
||||||
u32 safe_write_index =
|
|
||||||
__sync_val_compare_and_swap(&queue->write_position,
|
|
||||||
write_index, next_write_index);
|
|
||||||
if (safe_write_index == write_index){
|
|
||||||
result = write_index;
|
|
||||||
write_index = write_index % QUEUE_WRAP;
|
|
||||||
queue->jobs[write_index].job = job;
|
|
||||||
queue->jobs[write_index].running_thread = THREAD_NOT_ASSIGNED;
|
|
||||||
queue->jobs[write_index].id = result;
|
|
||||||
success = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sem_post(LinuxHandleToSem(queue->semaphore));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal void
|
||||||
Sys_Cancel_Job_Sig(system_cancel_job){
|
system_wait_cv(i32 lock_id, i32 cv_id){
|
||||||
Work_Queue *queue = linuxvars.queues + group_id;
|
pthread_cond_wait(linuxvars.conds + cv_id, linuxvars.locks + lock_id);
|
||||||
Thread_Group *group = linuxvars.groups + group_id;
|
|
||||||
|
|
||||||
u32 job_index = job_id % QUEUE_WRAP;
|
|
||||||
Full_Job_Data *full_job = queue->jobs + job_index;
|
|
||||||
|
|
||||||
Assert(full_job->id == job_id);
|
|
||||||
u32 thread_id =
|
|
||||||
__sync_val_compare_and_swap(&full_job->running_thread,
|
|
||||||
THREAD_NOT_ASSIGNED, 0);
|
|
||||||
|
|
||||||
if (thread_id != THREAD_NOT_ASSIGNED && thread_id != 0){
|
|
||||||
i32 thread_index = thread_id - 1;
|
|
||||||
|
|
||||||
i32 cancel_lock = group->cancel_lock0 + thread_index;
|
|
||||||
i32 cancel_cv = group->cancel_cv0 + thread_index;
|
|
||||||
Thread_Context *thread = group->threads + thread_index;
|
|
||||||
|
|
||||||
system_acquire_lock(cancel_lock);
|
|
||||||
thread->cancel = 1;
|
|
||||||
|
|
||||||
system_release_lock(FRAME_LOCK);
|
|
||||||
do {
|
|
||||||
pthread_cond_wait(linuxvars.conds + cancel_cv, linuxvars.locks + cancel_lock);
|
|
||||||
} while(thread->cancel == 1);
|
|
||||||
system_acquire_lock(FRAME_LOCK);
|
|
||||||
|
|
||||||
system_release_lock(cancel_lock);
|
|
||||||
|
|
||||||
LinuxScheduleStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal void
|
||||||
Sys_Check_Cancel_Sig(system_check_cancel){
|
system_signal_cv(i32 lock_id, i32 cv_id){
|
||||||
b32 result = 0;
|
pthread_cond_signal(linuxvars.conds + cv_id);
|
||||||
|
|
||||||
Thread_Group* group = linuxvars.groups + thread->group_id;
|
|
||||||
i32 thread_index = thread->id - 1;
|
|
||||||
i32 cancel_lock = group->cancel_lock0 + thread_index;
|
|
||||||
|
|
||||||
system_acquire_lock(cancel_lock);
|
|
||||||
if (thread->cancel){
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
system_release_lock(cancel_lock);
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
|
|
||||||
void *old_data;
|
|
||||||
i32 old_size, new_size;
|
|
||||||
|
|
||||||
system_acquire_lock(CANCEL_LOCK0 + memory->id - 1);
|
|
||||||
old_data = memory->data;
|
|
||||||
old_size = memory->size;
|
|
||||||
new_size = LargeRoundUp(memory->size*2, Kbytes(4));
|
|
||||||
memory->data = system_get_memory(new_size);
|
|
||||||
memory->size = new_size;
|
|
||||||
if (old_data){
|
|
||||||
memcpy(memory->data, old_data, old_size);
|
|
||||||
system_free_memory(old_data);
|
|
||||||
}
|
|
||||||
system_release_lock(CANCEL_LOCK0 + memory->id - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // new job queue
|
|
||||||
|
|
||||||
internal void*
|
internal void*
|
||||||
JobThreadProc(void* lpParameter){
|
JobThreadProc(void* lpParameter){
|
||||||
Thread_Context *thread = (Thread_Context*)lpParameter;
|
Thread_Context *thread = (Thread_Context*)lpParameter;
|
||||||
|
@ -1441,28 +1245,6 @@ Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
|
||||||
system_release_lock(CANCEL_LOCK0 + memory->id - 1);
|
system_release_lock(CANCEL_LOCK0 + memory->id - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // OLD_JOB_QUEUE
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Acquire_Lock_Sig(system_acquire_lock){
|
|
||||||
pthread_mutex_lock(linuxvars.locks + id);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Release_Lock_Sig(system_release_lock){
|
|
||||||
pthread_mutex_unlock(linuxvars.locks + id);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
system_wait_cv(i32 lock_id, i32 cv_id){
|
|
||||||
pthread_cond_wait(linuxvars.conds + cv_id, linuxvars.locks + lock_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
system_signal_cv(i32 lock_id, i32 cv_id){
|
|
||||||
pthread_cond_signal(linuxvars.conds + cv_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Debug
|
// Debug
|
||||||
//
|
//
|
||||||
|
@ -1608,16 +1390,22 @@ LinuxLoadAppCode(String* base_dir){
|
||||||
internal void
|
internal void
|
||||||
LinuxLoadSystemCode(){
|
LinuxLoadSystemCode(){
|
||||||
|
|
||||||
linuxvars.system.file_time_stamp = system_file_time_stamp;
|
// files
|
||||||
linuxvars.system.now_time_stamp = system_now_time_stamp;
|
|
||||||
linuxvars.system.set_file_list = system_set_file_list;
|
linuxvars.system.set_file_list = system_set_file_list;
|
||||||
linuxvars.system.file_unique_hash = system_file_unique_hash;
|
linuxvars.system.get_canonical = system_get_canonical;
|
||||||
linuxvars.system.file_track = system_file_track;
|
linuxvars.system.add_listener = system_add_listener;
|
||||||
linuxvars.system.file_untrack = system_file_untrack;
|
linuxvars.system.remove_listener = system_remove_listener;
|
||||||
linuxvars.system.file_load_begin = system_file_load_begin;
|
linuxvars.system.get_file_change = system_get_file_change;
|
||||||
linuxvars.system.file_load_end = system_file_load_end;
|
linuxvars.system.load_handle = system_load_handle;
|
||||||
linuxvars.system.file_save = system_file_save;
|
linuxvars.system.load_size = system_load_size;
|
||||||
|
linuxvars.system.load_file = system_load_file;
|
||||||
|
linuxvars.system.load_close = system_load_close;
|
||||||
|
linuxvars.system.save_file = system_save_file;
|
||||||
|
|
||||||
|
// time
|
||||||
|
linuxvars.system.now_time = system_now_time;
|
||||||
|
|
||||||
|
// 4coder_custom.h
|
||||||
linuxvars.system.memory_allocate = system_memory_allocate;
|
linuxvars.system.memory_allocate = system_memory_allocate;
|
||||||
linuxvars.system.memory_set_protection = system_memory_set_protection;
|
linuxvars.system.memory_set_protection = system_memory_set_protection;
|
||||||
linuxvars.system.memory_free = system_memory_free;
|
linuxvars.system.memory_free = system_memory_free;
|
||||||
|
@ -1626,18 +1414,22 @@ LinuxLoadSystemCode(){
|
||||||
linuxvars.system.get_4ed_path = system_get_4ed_path;
|
linuxvars.system.get_4ed_path = system_get_4ed_path;
|
||||||
linuxvars.system.show_mouse_cursor = system_show_mouse_cursor;
|
linuxvars.system.show_mouse_cursor = system_show_mouse_cursor;
|
||||||
|
|
||||||
|
// clipboard
|
||||||
linuxvars.system.post_clipboard = system_post_clipboard;
|
linuxvars.system.post_clipboard = system_post_clipboard;
|
||||||
|
|
||||||
|
// coroutine
|
||||||
linuxvars.system.create_coroutine = system_create_coroutine;
|
linuxvars.system.create_coroutine = system_create_coroutine;
|
||||||
linuxvars.system.launch_coroutine = system_launch_coroutine;
|
linuxvars.system.launch_coroutine = system_launch_coroutine;
|
||||||
linuxvars.system.resume_coroutine = system_resume_coroutine;
|
linuxvars.system.resume_coroutine = system_resume_coroutine;
|
||||||
linuxvars.system.yield_coroutine = system_yield_coroutine;
|
linuxvars.system.yield_coroutine = system_yield_coroutine;
|
||||||
|
|
||||||
|
// cli
|
||||||
linuxvars.system.cli_call = system_cli_call;
|
linuxvars.system.cli_call = system_cli_call;
|
||||||
linuxvars.system.cli_begin_update = system_cli_begin_update;
|
linuxvars.system.cli_begin_update = system_cli_begin_update;
|
||||||
linuxvars.system.cli_update_step = system_cli_update_step;
|
linuxvars.system.cli_update_step = system_cli_update_step;
|
||||||
linuxvars.system.cli_end_update = system_cli_end_update;
|
linuxvars.system.cli_end_update = system_cli_end_update;
|
||||||
|
|
||||||
|
// threads
|
||||||
linuxvars.system.post_job = system_post_job;
|
linuxvars.system.post_job = system_post_job;
|
||||||
linuxvars.system.cancel_job = system_cancel_job;
|
linuxvars.system.cancel_job = system_cancel_job;
|
||||||
linuxvars.system.check_cancel = system_check_cancel;
|
linuxvars.system.check_cancel = system_check_cancel;
|
||||||
|
@ -1645,12 +1437,14 @@ LinuxLoadSystemCode(){
|
||||||
linuxvars.system.acquire_lock = system_acquire_lock;
|
linuxvars.system.acquire_lock = system_acquire_lock;
|
||||||
linuxvars.system.release_lock = system_release_lock;
|
linuxvars.system.release_lock = system_release_lock;
|
||||||
|
|
||||||
|
// debug
|
||||||
#if FRED_INTERNAL
|
#if FRED_INTERNAL
|
||||||
linuxvars.system.internal_sentinel = internal_sentinel;
|
linuxvars.system.internal_sentinel = internal_sentinel;
|
||||||
linuxvars.system.internal_get_thread_states = internal_get_thread_states;
|
linuxvars.system.internal_get_thread_states = internal_get_thread_states;
|
||||||
linuxvars.system.internal_debug_message = internal_debug_message;
|
linuxvars.system.internal_debug_message = internal_debug_message;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// non-function details
|
||||||
linuxvars.system.slash = '/';
|
linuxvars.system.slash = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2226,7 +2020,7 @@ LinuxStringDup(String* str, void* data, size_t size){
|
||||||
internal void
|
internal void
|
||||||
LinuxScheduleStep(void)
|
LinuxScheduleStep(void)
|
||||||
{
|
{
|
||||||
u64 now = system_now_time_stamp();
|
u64 now = system_now_time();
|
||||||
u64 diff = (now - linuxvars.last_step);
|
u64 diff = (now - linuxvars.last_step);
|
||||||
|
|
||||||
if(diff > (u64)frame_useconds){
|
if(diff > (u64)frame_useconds){
|
||||||
|
@ -2924,23 +2718,6 @@ LinuxHandleX11Events(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// inotify utility func
|
|
||||||
//
|
|
||||||
|
|
||||||
internal void
|
|
||||||
LinuxHandleFileEvents()
|
|
||||||
{
|
|
||||||
struct inotify_event* e;
|
|
||||||
char buff[sizeof(*e) + NAME_MAX + 1];
|
|
||||||
|
|
||||||
ssize_t num_bytes = read(linuxvars.inotify_fd, buff, sizeof(buff));
|
|
||||||
for(char* p = buff; (p - buff) < num_bytes; p += (sizeof(*e) + e->len)){
|
|
||||||
e = (struct inotify_event*)p;
|
|
||||||
// TODO: do something with the e->wd / e->name & report that in app.step?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Entry point
|
// Entry point
|
||||||
//
|
//
|
||||||
|
@ -2979,7 +2756,9 @@ main(int argc, char **argv)
|
||||||
memory_vars.user_memory = system_get_memory(memory_vars.user_memory_size);
|
memory_vars.user_memory = system_get_memory(memory_vars.user_memory_size);
|
||||||
|
|
||||||
linuxvars.target.max = Mbytes(1);
|
linuxvars.target.max = Mbytes(1);
|
||||||
linuxvars.target.push_buffer = (byte*)system_get_memory(linuxvars.target.max);
|
linuxvars.target.push_buffer = (char*)system_get_memory(linuxvars.target.max);
|
||||||
|
|
||||||
|
init_shared_vars();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Read command line
|
// Read command line
|
||||||
|
@ -3248,9 +3027,6 @@ main(int argc, char **argv)
|
||||||
e.data.u64 = LINUX_4ED_EVENT_X11;
|
e.data.u64 = LINUX_4ED_EVENT_X11;
|
||||||
epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, linuxvars.x11_fd, &e);
|
epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, linuxvars.x11_fd, &e);
|
||||||
|
|
||||||
e.data.u64 = LINUX_4ED_EVENT_FILE;
|
|
||||||
epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, linuxvars.inotify_fd, &e);
|
|
||||||
|
|
||||||
e.data.u64 = LINUX_4ED_EVENT_STEP;
|
e.data.u64 = LINUX_4ED_EVENT_STEP;
|
||||||
epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, linuxvars.step_event_fd, &e);
|
epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, linuxvars.step_event_fd, &e);
|
||||||
|
|
||||||
|
@ -3321,10 +3097,6 @@ main(int argc, char **argv)
|
||||||
XProcessInternalConnection(linuxvars.XDisplay, fd);
|
XProcessInternalConnection(linuxvars.XDisplay, fd);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case LINUX_4ED_EVENT_FILE: {
|
|
||||||
LinuxHandleFileEvents();
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case LINUX_4ED_EVENT_STEP: {
|
case LINUX_4ED_EVENT_STEP: {
|
||||||
u64 ev;
|
u64 ev;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -3350,7 +3122,7 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(do_step){
|
if(do_step){
|
||||||
linuxvars.last_step = system_now_time_stamp();
|
linuxvars.last_step = system_now_time();
|
||||||
|
|
||||||
if(linuxvars.input.first_step || !linuxvars.has_xfixes){
|
if(linuxvars.input.first_step || !linuxvars.has_xfixes){
|
||||||
XConvertSelection(
|
XConvertSelection(
|
||||||
|
|
Loading…
Reference in New Issue