diff --git a/Makefile b/Makefile index 5d5680f6..482ca7da 100755 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ CPP_FILES := $(wildcard *.cpp) $(wildcard **/*.cpp) +C_FILES := $(wildcard *.c) $(wildcard **/*.c) H_FILES := $(wildcard *.h) $(wildcard **/*.h) WARNINGS := -Wno-write-strings 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: ../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 $@ -../4ed: $(CPP_FILES) $(H_FILES) +../4ed: $(CPP_FILES) $(C_FILES) $(H_FILES) g++ $(WARNINGS) $(FLAGS) linux_4ed.cpp -iquoteforeign $(PLAT_LINKS) -o $@ clean: diff --git a/filetrack/4tech_file_track_linux.c b/filetrack/4tech_file_track_linux.c index f4a36e35..e8b7251f 100644 --- a/filetrack/4tech_file_track_linux.c +++ b/filetrack/4tech_file_track_linux.c @@ -1,10 +1,10 @@ /* -The OS agnostic file tracking API for applications -that want to interact with potentially many files on -the disk that could be changed by other applications. + The OS agnostic file tracking API for applications + that want to interact with potentially many files on + 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 // only ever add memory and never free it. If freeing becomes necessary // 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; +//static_assert(sizeof(Linux_File_Track_Vars) <= sizeof(File_Track_System)); + typedef struct { File_Index hash; // NOTE(allen): @@ -54,8 +62,11 @@ typedef struct { // 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 // entry because it is used as the key for the table. + char* filename; } 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_tables(v) ((File_Track_Tables*)(v->tables)) @@ -65,24 +76,29 @@ init_track_system(File_Track_System *system, void *listener_memory, int32_t listener_memory_size){ File_Track_Result result = FileTrack_MemoryTooSmall; Linux_File_Track_Vars *vars = to_vars(system); - + Assert(sizeof(Linux_File_Track_Entry) <= sizeof(File_Track_Entry)); - + if (enough_memory_to_init_table(table_memory_size) && /*if listener memory is important check it's size here*/ 1){ - + // NOTE(allen): Initialize main data tables - vars->tables = table_memory; + vars->tables = (File_Track_Tables*) table_memory; File_Track_Tables *tables = to_tables(vars); init_table_memory(tables, table_memory_size); - - // NOTE(allen): - // Here prepare the data structure and synchronization primatives - // in the vars struct. - + + vars->inotify = inotify_init1(IN_NONBLOCK); + + 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; } - + + LINUX_FN_DEBUG("result: %d", result); + return(result); } @@ -90,9 +106,10 @@ FILE_TRACK_LINK File_Track_Result add_listener(File_Track_System *system, char *filename){ File_Track_Result result = FileTrack_Good; Linux_File_Track_Vars *vars = to_vars(system); - - // ACQUIRE LOCK (only keep this if either of the data structures is kept) - + File_Track_Tables *tables = to_tables(vars); + + pthread_mutex_lock(&vars->lock); + // NOTE(allen): // Here do something to begin listening to changes to the file named filename. // On Windows it listens to the parent directory if no other file in that @@ -101,9 +118,43 @@ add_listener(File_Track_System *system, char *filename){ // different names that both refer to the same file. In this case we should // treat them as two separate files so that if one of the listeners is removed // 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); } @@ -111,16 +162,35 @@ FILE_TRACK_LINK File_Track_Result remove_listener(File_Track_System *system, char *filename){ File_Track_Result result = FileTrack_Good; Linux_File_Track_Vars *vars = to_vars(system); - - // ACQUIRE LOCK - + File_Track_Tables *tables = to_tables(vars); + File_Track_Entry *entries = (File_Track_Entry*) to_ptr(tables, tables->file_table); + + pthread_mutex_lock(&vars->lock); + // NOTE(allen): // 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 // 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); } @@ -128,9 +198,9 @@ FILE_TRACK_LINK File_Track_Result move_track_system(File_Track_System *system, void *mem, int32_t size){ File_Track_Result result = FileTrack_Good; Linux_File_Track_Vars *vars = to_vars(system); - - // ACQUIRE LOCK - + + pthread_mutex_lock(&vars->lock); + { File_Track_Tables *original_tables = to_tables(vars); result = move_table_memory(original_tables, mem, size); @@ -138,9 +208,11 @@ move_track_system(File_Track_System *system, void *mem, int32_t size){ vars->tables = mem; } } - - // RELEASE LOCK - + + pthread_mutex_unlock(&vars->lock); + + LINUX_FN_DEBUG("size: %d, %d", size, result); + return(result); } @@ -148,16 +220,30 @@ FILE_TRACK_LINK File_Track_Result expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size){ File_Track_Result result = FileTrack_Good; 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 // this call adds more memory to that system. If this system // wants to free old memory the API does not currently support // 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); } @@ -165,9 +251,10 @@ FILE_TRACK_LINK File_Track_Result get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *size){ File_Track_Result result = FileTrack_NoMoreEvents; Linux_File_Track_Vars *vars = to_vars(system); - - // ACQUIRE LOCK - + File_Track_Tables *tables = to_tables(vars); + + pthread_mutex_lock(&vars->lock); + // NOTE(allen): If there are any new file changes report them // by copying the name of the file to the buffer and returning // FileTrack_Good. It is allowed for this system to report @@ -175,9 +262,36 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t * // is up to the user to check the filename and see if it cares // about that file. If there are no new changes the return // 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); } @@ -185,27 +299,16 @@ FILE_TRACK_LINK File_Track_Result shut_down_track_system(File_Track_System *system){ File_Track_Result result = FileTrack_Good; 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. - + if(close(vars->inotify) == -1){ + result = FileTrack_FileSystemError; + } + + pthread_mutex_destroy(&vars->lock); + + LINUX_FN_DEBUG("result: %d", result); + return(result); } diff --git a/linux_4ed.cpp b/linux_4ed.cpp index a938fa00..dd72d139 100644 --- a/linux_4ed.cpp +++ b/linux_4ed.cpp @@ -69,8 +69,6 @@ #include #include -#include "filetrack/4tech_file_track_linux.c" -#include "system_shared.h" // // Linux macros @@ -105,6 +103,9 @@ #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 // @@ -120,11 +121,10 @@ struct Sys_Bubble : public Bubble{ enum { LINUX_4ED_EVENT_X11 = (UINT64_C(1) << 32), - LINUX_4ED_EVENT_X11_INTERNAL = (UINT64_C(1) << 33), - LINUX_4ED_EVENT_FILE = (UINT64_C(1) << 34), - LINUX_4ED_EVENT_STEP = (UINT64_C(1) << 35), - LINUX_4ED_EVENT_STEP_TIMER = (UINT64_C(1) << 36), - LINUX_4ED_EVENT_CLI = (UINT64_C(1) << 37), + LINUX_4ED_EVENT_X11_INTERNAL = (UINT64_C(2) << 32), + LINUX_4ED_EVENT_STEP = (UINT64_C(3) << 32), + LINUX_4ED_EVENT_STEP_TIMER = (UINT64_C(4) << 32), + LINUX_4ED_EVENT_CLI = (UINT64_C(5) << 32), }; 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"); // -// Linux shared/system functions -// - -// -// Memory +// Shared system functions (system_shared.h) // internal void* @@ -341,9 +337,6 @@ Sys_Free_Memory_Sig(system_free_memory){ LinuxFreeMemory(block); } -// -// File -// internal 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 Sys_Set_File_List_Sig(system_set_file_list){ DIR *d; @@ -503,105 +460,88 @@ Sys_Set_File_List_Sig(system_set_file_list){ } internal -Sys_File_Unique_Hash_Sig(system_file_unique_hash){ - Unique_Hash result = {}; - struct stat st = {}; - *success = 0; +Sys_Get_Canonical_Sig(system_get_canonical){ + int32_t result = 0; - if(stat(filename.str, &st) == 0){ - memcpy(&result, &st.st_dev, sizeof(st.st_dev)); - memcpy((char*)&result + sizeof(st.st_dev), &st.st_ino, sizeof(st.st_ino)); - *success = 1; + char* path = realpath(strndupa(filename, len), NULL); + if(!path){ + perror("realpath"); + } 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; } internal -Sys_File_Track_Sig(system_file_track){ - if(filename.size <= 0 || !filename.str) return; - - 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); +Sys_Load_Handle_Sig(system_load_handle){ + b32 result = 0; int fd = open(filename, O_RDONLY); - if(fd < 0){ - fprintf(stderr, "sys_open_file: open '%s': %s\n", filename, strerror(errno)); - goto out; - } - if(fstat(fd, &info) < 0){ - 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; + if(fd == -1){ + perror("open"); + } else { + *(int*)handle_out = fd; + result = 1; } - loading.handle = LinuxFDToHandle(fd); - loading.size = info.st_size; - loading.exists = 1; - -out: - if(fd != -1 && !loading.exists) close(fd); - return(loading); + return result; } internal -Sys_File_Load_End_Sig(system_file_load_end){ - int fd = LinuxHandleToFD(loading.handle); - char* ptr = buffer; - size_t size = loading.size; +Sys_Load_Size_Sig(system_load_size){ + u32 result = 0; - if(!loading.exists || fd == -1) return 0; + int fd = *(int*)&handle; + struct stat st; + if(fstat(fd, &st) == -1){ + perror("fstat"); + } else { + result = st.st_size; + } + + return result; +} + +internal +Sys_Load_File_Sig(system_load_file){ + + int fd = *(int*)&handle; do { - ssize_t read_result = read(fd, buffer, size); - if(read_result == -1){ - if(errno != EINTR){ - perror("system_file_load_end"); - break; - } + ssize_t n = read(fd, buffer, size); + if(n == -1 && errno != EAGAIN){ + perror("read"); + break; } else { - size -= read_result; - ptr += read_result; + size -= n; + buffer += n; } } while(size); - close(fd); - - LINUX_FN_DEBUG("success == %d", (size == 0)); - - return (size == 0); + return size == 0; } 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; 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 @@ -692,10 +649,6 @@ MEMORY_FREE_SIG(system_memory_free){ munmap(mem, size); } -// -// Filesystem navigation -// - internal FILE_EXISTS_SIG(system_file_exists){ int result = 0; @@ -983,175 +936,26 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ // Threads // -//#define OLD_JOB_QUEUE - -#ifdef OLD_JOB_QUEUE -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 +Sys_Acquire_Lock_Sig(system_acquire_lock){ + pthread_mutex_lock(linuxvars.locks + id); } internal -Sys_Post_Job_Sig(system_post_job){ - Work_Queue *queue = linuxvars.queues + group_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; +Sys_Release_Lock_Sig(system_release_lock){ + pthread_mutex_unlock(linuxvars.locks + id); } -internal -Sys_Cancel_Job_Sig(system_cancel_job){ - Work_Queue *queue = linuxvars.queues + group_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 void +system_wait_cv(i32 lock_id, i32 cv_id){ + pthread_cond_wait(linuxvars.conds + cv_id, linuxvars.locks + lock_id); } -internal -Sys_Check_Cancel_Sig(system_check_cancel){ - b32 result = 0; - - 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 void +system_signal_cv(i32 lock_id, i32 cv_id){ + pthread_cond_signal(linuxvars.conds + cv_id); } -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* JobThreadProc(void* 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); } -#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 // @@ -1607,17 +1389,23 @@ LinuxLoadAppCode(String* base_dir){ internal void LinuxLoadSystemCode(){ - - linuxvars.system.file_time_stamp = system_file_time_stamp; - linuxvars.system.now_time_stamp = system_now_time_stamp; + + // files linuxvars.system.set_file_list = system_set_file_list; - linuxvars.system.file_unique_hash = system_file_unique_hash; - linuxvars.system.file_track = system_file_track; - linuxvars.system.file_untrack = system_file_untrack; - linuxvars.system.file_load_begin = system_file_load_begin; - linuxvars.system.file_load_end = system_file_load_end; - linuxvars.system.file_save = system_file_save; + linuxvars.system.get_canonical = system_get_canonical; + linuxvars.system.add_listener = system_add_listener; + linuxvars.system.remove_listener = system_remove_listener; + linuxvars.system.get_file_change = system_get_file_change; + linuxvars.system.load_handle = system_load_handle; + 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_set_protection = system_memory_set_protection; linuxvars.system.memory_free = system_memory_free; @@ -1626,18 +1414,22 @@ LinuxLoadSystemCode(){ linuxvars.system.get_4ed_path = system_get_4ed_path; linuxvars.system.show_mouse_cursor = system_show_mouse_cursor; + // clipboard linuxvars.system.post_clipboard = system_post_clipboard; + // coroutine linuxvars.system.create_coroutine = system_create_coroutine; linuxvars.system.launch_coroutine = system_launch_coroutine; linuxvars.system.resume_coroutine = system_resume_coroutine; linuxvars.system.yield_coroutine = system_yield_coroutine; + // cli linuxvars.system.cli_call = system_cli_call; linuxvars.system.cli_begin_update = system_cli_begin_update; linuxvars.system.cli_update_step = system_cli_update_step; linuxvars.system.cli_end_update = system_cli_end_update; + // threads linuxvars.system.post_job = system_post_job; linuxvars.system.cancel_job = system_cancel_job; linuxvars.system.check_cancel = system_check_cancel; @@ -1645,12 +1437,14 @@ LinuxLoadSystemCode(){ linuxvars.system.acquire_lock = system_acquire_lock; linuxvars.system.release_lock = system_release_lock; + // debug #if FRED_INTERNAL linuxvars.system.internal_sentinel = internal_sentinel; linuxvars.system.internal_get_thread_states = internal_get_thread_states; linuxvars.system.internal_debug_message = internal_debug_message; #endif + // non-function details linuxvars.system.slash = '/'; } @@ -2226,7 +2020,7 @@ LinuxStringDup(String* str, void* data, size_t size){ internal void LinuxScheduleStep(void) { - u64 now = system_now_time_stamp(); + u64 now = system_now_time(); u64 diff = (now - linuxvars.last_step); 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 // @@ -2979,7 +2756,9 @@ main(int argc, char **argv) memory_vars.user_memory = system_get_memory(memory_vars.user_memory_size); 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 @@ -3248,9 +3027,6 @@ main(int argc, char **argv) e.data.u64 = LINUX_4ED_EVENT_X11; 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; 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); } break; - case LINUX_4ED_EVENT_FILE: { - LinuxHandleFileEvents(); - } break; - case LINUX_4ED_EVENT_STEP: { u64 ev; int ret; @@ -3350,7 +3122,7 @@ main(int argc, char **argv) } if(do_step){ - linuxvars.last_step = system_now_time_stamp(); + linuxvars.last_step = system_now_time(); if(linuxvars.input.first_step || !linuxvars.has_xfixes){ XConvertSelection(