merged the fucking shit

This commit is contained in:
Allen Webster 2017-07-18 15:55:20 -04:00
commit 39bd02e79c
8 changed files with 193 additions and 169 deletions

View File

@ -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)

View File

@ -9,7 +9,7 @@
// TOP
#define FM_PRINT_COMMANDS
//#define FM_PRINT_COMMANDS
#include "../4ed_defines.h"

View File

@ -9,6 +9,10 @@
// TOP
#if !defined(CORE_COUNT)
#define CORE_COUNT 8
#endif
enum CV_ID{
CANCEL_CV0,
CANCEL_CV1,
@ -21,6 +25,25 @@ enum CV_ID{
CV_COUNT
};
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;
@ -45,6 +68,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];
@ -116,7 +140,7 @@ PLAT_THREAD_SIG(job_thread_proc){
}
}
else{
system_wait_on(queue->semaphore);
system_wait_on_semaphore(&queue->semaphore);
}
}
}
@ -212,7 +236,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);
@ -348,5 +372,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

View File

@ -115,8 +115,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);
@ -183,12 +181,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;
////////////////////////////////
@ -215,6 +211,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;
};
@ -227,6 +249,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);
@ -237,6 +273,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);
@ -247,24 +288,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
@ -1078,27 +1116,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
//
@ -1154,6 +1171,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)
@ -1888,7 +1906,7 @@ LinuxHandleX11Events(void)
}
if (should_step){
LinuxScheduleStep();
system_schedule_step();
}
}
@ -2029,7 +2047,7 @@ main(int argc, char **argv){
#endif
//
// Coroutine / Thread / Semaphore / Mutex init
// Coroutines
//
linuxvars.coroutine_free = linuxvars.coroutine_data;
@ -2043,40 +2061,11 @@ 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;
//
// Threads
//
system_init_threaded_work_system();
Thread_Memory thread_memory[ArrayCount(background)];
threadvars.thread_memory = thread_memory;
sem_init(&linuxvars.thread_semaphore, 0, 0);
threadvars.queues[BACKGROUND_THREADS].semaphore = handle_sem(&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);
}
//
// X11 init
@ -2217,7 +2206,7 @@ main(int argc, char **argv){
system_acquire_lock(FRAME_LOCK);
LinuxScheduleStep();
system_schedule_step();
linuxvars.keep_running = 1;
linuxvars.input.first_step = 1;
@ -2276,7 +2265,7 @@ main(int argc, char **argv){
} break;
case LINUX_4ED_EVENT_CLI: {
LinuxScheduleStep();
system_schedule_step();
} break;
}
}
@ -2310,7 +2299,7 @@ main(int argc, char **argv){
}
if (result.animating){
LinuxScheduleStep();
system_schedule_step();
}
LinuxRedrawTarget();

View File

@ -165,8 +165,10 @@ struct Win32_Vars{
};
global System_Functions sysfunc;
////////////////////////////////
global Win32_Vars win32vars;
global System_Functions sysfunc;
global Application_Memory memory_vars;
////////////////////////////////
@ -187,6 +189,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;
};
@ -199,6 +211,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);
@ -209,6 +235,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);
@ -220,22 +251,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)
////////////////////////////////
//
@ -282,7 +311,7 @@ Sys_Log_Sig(system_log){
}
//
// Memory (not exposed to application, but needed in system_shared.cpp)
// Memory
//
internal
@ -297,24 +326,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);
@ -326,6 +346,10 @@ Sys_Memory_Free_Sig(system_memory_free){
VirtualFree(ptr, 0, MEM_RELEASE);
}
//
// Threads
//
#include "4ed_work_queues.cpp"
//
@ -1601,51 +1625,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];
}
//
@ -2122,7 +2111,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);

View File

@ -1,5 +1,5 @@
1
0
103
104

View File

@ -1,4 +1,4 @@
// 4ed_standard_preamble.h
// 4tech_standard_preamble.h
#if !defined(FTECH_INTEGERS)
#define FTECH_INTEGERS
#include <stdint.h>

View File

@ -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