diff --git a/4ed_system.h b/4ed_system.h index c4d83767..2c5d410c 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -156,29 +156,8 @@ struct Job_Data{ void *data[4]; }; -struct Full_Job_Data{ - Job_Data job; - - u32 running_thread; - u32 id; -}; - -struct Unbounded_Work_Queue{ - Full_Job_Data *jobs; - i32 count, max, skip; - - u32 next_job_id; -}; - #define QUEUE_WRAP 256 -struct Work_Queue{ - Full_Job_Data jobs[QUEUE_WRAP]; - Plat_Handle semaphore; - volatile u32 write_position; - volatile u32 read_position; -}; - #define THREAD_NOT_ASSIGNED 0xFFFFFFFF #define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID group_id, Job_Data job) diff --git a/platform_all/4ed_work_queues.cpp b/platform_all/4ed_work_queues.cpp index bc584011..4e21498c 100644 --- a/platform_all/4ed_work_queues.cpp +++ b/platform_all/4ed_work_queues.cpp @@ -9,6 +9,29 @@ // TOP +#if !defined(CORE_COUNT) +#define CORE_COUNT 8 +#endif + +struct Full_Job_Data{ + Job_Data job; + u32 running_thread; + u32 id; +}; + +struct Unbounded_Work_Queue{ + Full_Job_Data *jobs; + i32 count, max, skip; + u32 next_job_id; +}; + +struct Work_Queue{ + Full_Job_Data jobs[QUEUE_WRAP]; + Semaphore semaphore; + volatile u32 write_position; + volatile u32 read_position; +}; + struct Thread_Context{ u32 job_id; b32 running; @@ -33,6 +56,7 @@ struct Thread_Group{ struct Threading_Vars{ Thread_Memory *thread_memory; + Work_Queue queues[THREAD_GROUP_COUNT]; Thread_Group groups[THREAD_GROUP_COUNT]; Mutex locks[LOCK_COUNT]; @@ -104,7 +128,7 @@ PLAT_THREAD_SIG(job_thread_proc){ } } else{ - system_wait_on(queue->semaphore); + system_wait_on_semaphore(&queue->semaphore); } } } @@ -200,7 +224,7 @@ flush_thread_group(Thread_Group_ID group_id){ } for (i32 i = 0; i < semaphore_release_count; ++i){ - system_release_semaphore(queue->semaphore); + system_release_semaphore(&queue->semaphore); } return(semaphore_release_count); @@ -336,5 +360,48 @@ INTERNAL_Sys_Get_Thread_States_Sig(system_internal_get_thread_states){ } } +internal void +system_init_threaded_work_system(){ + u32 core_count = CORE_COUNT; + i32 thread_system_memory_size = core_count*(sizeof(Thread_Context) + sizeof(Thread_Memory)); + void *thread_system_memory = system_memory_allocate(thread_system_memory_size); + Partition thread_part = make_part(thread_system_memory, thread_system_memory_size); + + for (i32 i = 0; i < LOCK_COUNT; ++i){ + system_init_lock(&threadvars.locks[i]); + } + + for (i32 i = 0; i < CV_COUNT; ++i){ + system_init_cv(&threadvars.conds[i]); + } + + threadvars.thread_memory = push_array(&thread_part, Thread_Memory, core_count); + + for (u32 group_i = 0; group_i < THREAD_GROUP_COUNT; ++group_i){ + Thread_Context *threads = push_array(&thread_part, Thread_Context, core_count); + threadvars.groups[group_i].threads = threads; + threadvars.groups[group_i].count = core_count; + threadvars.groups[group_i].cancel_lock0 = CANCEL_LOCK0; + threadvars.groups[group_i].cancel_cv0 = CANCEL_CV0; + + system_init_semaphore(&threadvars.queues[group_i].semaphore, core_count); + + for (u32 i = 0; i < core_count; ++i){ + Thread_Context *thread = threads + i; + thread->id = i + 1; + thread->group_id = group_i; + + Thread_Memory *memory = &threadvars.thread_memory[i]; + memset(memory, 0, sizeof(*memory)); + memory->id = thread->id; + + thread->queue = &threadvars.queues[group_i]; + system_init_and_launch_thread(&thread->thread, job_thread_proc, thread); + } + + initialize_unbounded_queue(&threadvars.groups[group_i].queue); + } +} + // BOTTOM diff --git a/platform_linux/linux_4ed.cpp b/platform_linux/linux_4ed.cpp index 98edba11..9608dfef 100644 --- a/platform_linux/linux_4ed.cpp +++ b/platform_linux/linux_4ed.cpp @@ -117,8 +117,6 @@ struct Linux_Coroutine { // Linux forward declarations // -internal void LinuxScheduleStep(void); - internal void LinuxStringDup(String*, void*, size_t); internal void LinuxToggleFullscreen(Display*, Window); internal void LinuxFatalErrorMsg(const char* msg); @@ -185,12 +183,10 @@ struct Linux_Vars{ Linux_Coroutine *coroutine_free; }; -// -// Linux globals -// +//////////////////////////////// -global System_Functions sysfunc; global Linux_Vars linuxvars; +global System_Functions sysfunc; global Application_Memory memory_vars; //////////////////////////////// @@ -217,6 +213,32 @@ handle_fd(Plat_Handle h){ //////////////////////////////// +internal void +system_schedule_step(){ + u64 now = system_now_time(); + u64 diff = (now - linuxvars.last_step); + + if (diff > (u64)frame_useconds){ + u64 ev = 1; + ssize_t size = write(linuxvars.step_event_fd, &ev, sizeof(ev)); + AllowLocal(size); + } + else{ + struct itimerspec its = {}; + timerfd_gettime(linuxvars.step_timer_fd, &its); + + if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0){ + its.it_value.tv_nsec = (frame_useconds - diff) * 1000UL; + timerfd_settime(linuxvars.step_timer_fd, 0, &its, NULL); + } + } +} + +//////////////////////////////// + +#define PLAT_THREAD_SIG(n) void* n(void *ptr) +typedef PLAT_THREAD_SIG(Thread_Function); + struct Thread{ pthread_t t; }; @@ -229,6 +251,20 @@ struct Condition_Variable{ pthread_cond_t cv; }; +struct Semaphore{ + sem_t s; +}; + +internal void +system_init_and_launch_thread(Thread *t, Thread_Function *proc, void *ptr){ + pthread_create(&t->t, 0, proc, ptr); +} + +internal void +system_init_lock(Mutex *m){ + pthread_mutex_init(&m->crit, NULL); +} + internal void system_acquire_lock(Mutex *m){ pthread_mutex_lock(m->crit); @@ -239,6 +275,11 @@ system_release_lock(Mutex *m){ pthread_mutex_unlock(m->crit); } +internal void +system_init_cv(Condition_Variable *cv){ + pthread_cond_init(&cv->cv, NULL); +} + internal void system_wait_cv(Condition_Variable *cv, Mutex *m){ pthread_cond_wait(cv->cv, m->crit); @@ -249,24 +290,21 @@ system_signal_cv(Condition_Variable *cv, Mutex *m){ pthread_cond_signal(cv->cv); } -// HACK(allen): Reduce this down to just one layer of call. internal void -system_schedule_step(){ - LinuxScheduleStep(); +system_init_semaphore(Semaphore *s, u32 count){ + sem_init(&s->s, 0, 0); } internal void -system_wait_on(Plat_Handle handle){ - sem_wait(handle_sem(handle)); +system_wait_on_semaphore(Semaphore *s){ + sem_wait(&s->s); } internal void -system_release_semaphore(Plat_Handle handle){ - sem_post(handle_sem(handle)); +system_release_semaphore(Semaphore *s){ + sem_post(&s->s); } -#define PLAT_THREAD_SIG(n) void* n(void *ptr) - //////////////////////////////// internal @@ -1080,27 +1118,6 @@ LinuxStringDup(String* str, void* data, size_t size){ memcpy(str->str, data, size); } -internal void -LinuxScheduleStep(void){ - u64 now = system_now_time(); - u64 diff = (now - linuxvars.last_step); - - if (diff > (u64)frame_useconds){ - u64 ev = 1; - ssize_t size = write(linuxvars.step_event_fd, &ev, sizeof(ev)); - (void)size; - } - else{ - struct itimerspec its = {}; - timerfd_gettime(linuxvars.step_timer_fd, &its); - - if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0){ - its.it_value.tv_nsec = (frame_useconds - diff) * 1000UL; - timerfd_settime(linuxvars.step_timer_fd, 0, &its, NULL); - } - } -} - // // X11 utility funcs // @@ -1156,6 +1173,7 @@ LinuxX11ConnectionWatch(Display* dpy, XPointer cdata, int fd, Bool opening, XPoi epoll_ctl(linuxvars.epoll, op, fd, &e); } +// HACK(allen): // NOTE(inso): this was a quick hack, might need some cleanup. internal void LinuxFatalErrorMsg(const char* msg) @@ -1890,7 +1908,7 @@ LinuxHandleX11Events(void) } if (should_step){ - LinuxScheduleStep(); + system_schedule_step(); } } @@ -2031,7 +2049,7 @@ main(int argc, char **argv){ #endif // - // Coroutine / Thread / Semaphore / Mutex init + // Coroutines // linuxvars.coroutine_free = linuxvars.coroutine_data; @@ -2045,40 +2063,10 @@ main(int argc, char **argv){ linuxvars.coroutine_data[i].stack.ss_sp = system_memory_allocate(stack_size); } - Thread_Context background[4] = {}; - threadvars.groups[BACKGROUND_THREADS].threads = background; - threadvars.groups[BACKGROUND_THREADS].count = ArrayCount(background); - threadvars.groups[BACKGROUND_THREADS].cancel_lock0 = CANCEL_LOCK0; - threadvars.groups[BACKGROUND_THREADS].cancel_cv0 = 0; - - Thread_Memory thread_memory[ArrayCount(background)]; - threadvars.thread_memory = thread_memory; - - sem_init(&linuxvars.thread_semaphore, 0, 0); - threadvars.queues[BACKGROUND_THREADS].semaphore = LinuxSemToHandle(&linuxvars.thread_semaphore); - - for(i32 i = 0; i < threadvars.groups[BACKGROUND_THREADS].count; ++i){ - Thread_Context *thread = threadvars.groups[BACKGROUND_THREADS].threads + i; - thread->id = i + 1; - thread->group_id = BACKGROUND_THREADS; - - Thread_Memory *memory = threadvars.thread_memory + i; - *memory = null_thread_memory; - memory->id = thread->id; - - thread->queue = &threadvars.queues[BACKGROUND_THREADS]; - pthread_create(&thread->handle, NULL, &job_thread_proc, thread); - } - - initialize_unbounded_queue(&threadvars.groups[BACKGROUND_THREADS].queue); - - for(i32 i = 0; i < LOCK_COUNT; ++i){ - pthread_mutex_init(linuxvars.locks + i, NULL); - } - - for(i32 i = 0; i < ArrayCount(linuxvars.conds); ++i){ - pthread_cond_init(linuxvars.conds + i, NULL); - } + // + // Threads + // + system_init_threaded_work_system(); // // X11 init @@ -2219,7 +2207,7 @@ main(int argc, char **argv){ system_acquire_lock(FRAME_LOCK); - LinuxScheduleStep(); + system_schedule_step(); linuxvars.keep_running = 1; linuxvars.input.first_step = 1; @@ -2278,7 +2266,7 @@ main(int argc, char **argv){ } break; case LINUX_4ED_EVENT_CLI: { - LinuxScheduleStep(); + system_schedule_step(); } break; } } @@ -2312,7 +2300,7 @@ main(int argc, char **argv){ } if (result.animating){ - LinuxScheduleStep(); + system_schedule_step(); } LinuxRedrawTarget(); diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index bdf7eb34..754492ef 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -177,8 +177,10 @@ struct Win32_Vars{ }; -global System_Functions sysfunc; +//////////////////////////////// + global Win32_Vars win32vars; +global System_Functions sysfunc; global Application_Memory memory_vars; //////////////////////////////// @@ -199,6 +201,16 @@ handle_type(HANDLE h){ //////////////////////////////// +internal void +system_schedule_step(){ + PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0); +} + +//////////////////////////////// + +#define PLAT_THREAD_SIG(n) DWORD CALL_CONVENTION n(LPVOID ptr) +typedef PLAT_THREAD_SIG(Thread_Function); + struct Thread{ HANDLE t; }; @@ -211,6 +223,20 @@ struct Condition_Variable{ CONDITION_VARIABLE cv; }; +struct Semaphore{ + HANDLE s; +}; + +internal void +system_init_and_launch_thread(Thread *t, Thread_Function *proc, void *ptr){ + t->t = CreateThread(0, 0, proc, ptr, 0, 0); +} + +internal void +system_init_lock(Mutex *m){ + InitializeCriticalSection(&m->crit); +} + internal void system_acquire_lock(Mutex *m){ EnterCriticalSection(&m->crit); @@ -221,6 +247,11 @@ system_release_lock(Mutex *m){ LeaveCriticalSection(&m->crit); } +internal void +system_init_cv(Condition_Variable *cv){ + InitializeConditionVariable(&cv->cv); +} + internal void system_wait_cv(Condition_Variable *cv, Mutex *lock){ SleepConditionVariableCS(&cv->cv, &lock->crit, INFINITE); @@ -232,22 +263,20 @@ system_signal_cv(Condition_Variable *cv, Mutex *lock){ } internal void -system_schedule_step(){ - PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0); +system_init_semaphore(Semaphore *s, u32 max){ + s->s = CreateSemaphore(0, 0, max, 0); } internal void -system_wait_on(Plat_Handle handle){ - WaitForSingleObject(handle_type(handle), INFINITE); +system_wait_on_semaphore(Semaphore *s){ + WaitForSingleObject(s->s, INFINITE); } internal void -system_release_semaphore(Plat_Handle handle){ - ReleaseSemaphore(handle_type(handle), 1, 0); +system_release_semaphore(Semaphore *s){ + ReleaseSemaphore(s->s, 1, 0); } -#define PLAT_THREAD_SIG(n) DWORD CALL_CONVENTION n(LPVOID ptr) - //////////////////////////////// // @@ -294,7 +323,7 @@ Sys_Log_Sig(system_log){ } // -// Memory (not exposed to application, but needed in system_shared.cpp) +// Memory // internal @@ -309,24 +338,15 @@ Sys_Memory_Set_Protection_Sig(system_memory_set_protection){ DWORD old_protect = 0; DWORD protect = 0; - flags = flags & 0x7; - - switch (flags){ - case 0: protect = PAGE_NOACCESS; break; - - case MemProtect_Read: protect = PAGE_READONLY; break; - - case MemProtect_Write: - case MemProtect_Read|MemProtect_Write: - protect = PAGE_READWRITE; break; - - case MemProtect_Execute: protect = PAGE_EXECUTE; break; - - case MemProtect_Execute|MemProtect_Read: protect = PAGE_EXECUTE_READ; break; - - case MemProtect_Execute|MemProtect_Write: - case MemProtect_Execute|MemProtect_Write|MemProtect_Read: - protect = PAGE_EXECUTE_READWRITE; break; + switch (flags & 0x7){ + case 0: protect = PAGE_NOACCESS; break; + case MemProtect_Read: protect = PAGE_READONLY; break; + case MemProtect_Write: /* below */ + case MemProtect_Write|MemProtect_Read: protect = PAGE_READWRITE; break; + case MemProtect_Execute: protect = PAGE_EXECUTE; break; + case MemProtect_Execute|MemProtect_Read: protect = PAGE_EXECUTE_READ; break; + case MemProtect_Execute|MemProtect_Write: /* below */ + case MemProtect_Execute|MemProtect_Write|MemProtect_Read: protect = PAGE_EXECUTE_READWRITE; break; } VirtualProtect(ptr, size, protect, &old_protect); @@ -338,6 +358,10 @@ Sys_Memory_Free_Sig(system_memory_free){ VirtualFree(ptr, 0, MEM_RELEASE); } +// +// Threads +// + #include "4ed_work_queues.cpp" // @@ -1613,51 +1637,16 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS win32vars.GlobalWindowPosition.length = sizeof(win32vars.GlobalWindowPosition); + system_init_threaded_work_system(); + // - // Threads and Coroutines + // Coroutines // - for (i32 i = 0; i < LOCK_COUNT; ++i){ - InitializeCriticalSection(&threadvars.locks[i].crit); - } - - for (i32 i = 0; i < CV_COUNT; ++i){ - InitializeConditionVariable(&threadvars.conds[i].cv); - } - - Thread_Context background[4]; - memset(background, 0, sizeof(background)); - threadvars.groups[BACKGROUND_THREADS].threads = background; - threadvars.groups[BACKGROUND_THREADS].count = ArrayCount(background); - threadvars.groups[BACKGROUND_THREADS].cancel_lock0 = CANCEL_LOCK0; - threadvars.groups[BACKGROUND_THREADS].cancel_cv0 = CANCEL_CV0; - - Thread_Memory thread_memory[ArrayCount(background)]; - threadvars.thread_memory = thread_memory; - - threadvars.queues[BACKGROUND_THREADS].semaphore =handle_type(CreateSemaphore(0, 0, threadvars.groups[BACKGROUND_THREADS].count, 0)); - - u32 creation_flag = 0; - for (i32 i = 0; i < threadvars.groups[BACKGROUND_THREADS].count; ++i){ - Thread_Context *thread = threadvars.groups[BACKGROUND_THREADS].threads + i; - thread->id = i + 1; - thread->group_id = BACKGROUND_THREADS; - - Thread_Memory *memory = threadvars.thread_memory + i; - *memory = null_thread_memory; - memory->id = thread->id; - - thread->queue = &threadvars.queues[BACKGROUND_THREADS]; - - thread->thread.t = CreateThread(0, 0, job_thread_proc, thread, creation_flag, (LPDWORD)&thread->windows_id); - } - - initialize_unbounded_queue(&threadvars.groups[BACKGROUND_THREADS].queue); - ConvertThreadToFiber(0); win32vars.coroutine_free = win32vars.coroutine_data; for (i32 i = 0; i+1 < ArrayCount(win32vars.coroutine_data); ++i){ - win32vars.coroutine_data[i].next = win32vars.coroutine_data + i + 1; + win32vars.coroutine_data[i].next = &win32vars.coroutine_data[i + 1]; } // @@ -2134,7 +2123,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS win32vars.first = 0; if (result.animating){ - PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0); + system_schedule_step(); } flush_thread_group(BACKGROUND_THREADS); diff --git a/string/4coder_string_build_num.txt b/string/4coder_string_build_num.txt index ae29c2fb..f67272eb 100644 --- a/string/4coder_string_build_num.txt +++ b/string/4coder_string_build_num.txt @@ -1,5 +1,5 @@ 1 0 -103 +104 diff --git a/string/4ed_standard_preamble.h b/string/4tech_standard_preamble.h similarity index 95% rename from string/4ed_standard_preamble.h rename to string/4tech_standard_preamble.h index 10790fe7..e5f56381 100644 --- a/string/4ed_standard_preamble.h +++ b/string/4tech_standard_preamble.h @@ -1,4 +1,4 @@ -// 4ed_standard_preamble.h +// 4tech_standard_preamble.h #if !defined(FTECH_INTEGERS) #define FTECH_INTEGERS #include diff --git a/string/internal_4coder_string.cpp b/string/internal_4coder_string.cpp index 27e0fd54..950438da 100644 --- a/string/internal_4coder_string.cpp +++ b/string/internal_4coder_string.cpp @@ -19,7 +19,7 @@ internal_4coder_string.cpp - Base file for generating 4coder_string.h FSTRING_BEGIN // TOP -#include "4ed_standard_preamble.h" +#include "4tech_standard_preamble.h" #if !defined(FSTRING_LINK) # define FSTRING_LINK static