diff --git a/code2/host/host.odin b/code2/host/host.odin index 6b73072..da77958 100644 --- a/code2/host/host.odin +++ b/code2/host/host.odin @@ -22,10 +22,11 @@ main :: proc() context.allocator = arena_allocator(& host_scratch) context.temp_allocator = context.allocator - thread_memory.index = .Master_Prepper + thread_memory.id = .Master_Prepper thread_id := thread_current_id() { using thread_memory + system_ctx = & host_memory.threads[WorkerID.Master_Prepper] system_ctx.creation_allocator = {} system_ctx.procedure = master_prepper_proc when ODIN_OS == .Windows { @@ -50,31 +51,45 @@ main :: proc() panic( "Failed to load the sectr module." ) } - startup := cast( type_of( host_memory.client_api.startup )) os_lib_get_proc(lib, "startup") - hot_reload := cast( type_of( host_memory.client_api.hot_reload)) os_lib_get_proc(lib, "hot_reload") - if startup == nil do panic("Failed to load sectr.startup symbol" ) - if hot_reload == nil do panic("Failed to load sectr.reload symbol" ) + startup := cast( type_of( host_memory.client_api.startup)) os_lib_get_proc(lib, "startup") + hot_reload := cast( type_of( host_memory.client_api.hot_reload)) os_lib_get_proc(lib, "hot_reload") + tick_lane_startup := cast( type_of( host_memory.client_api.tick_lane_startup)) os_lib_get_proc(lib, "tick_lane_startup") + if startup == nil do panic("Failed to load sectr.startup symbol" ) + if hot_reload == nil do panic("Failed to load sectr.hot_reload symbol" ) + if tick_lane_startup == nil do panic("Failed to load sectr.tick_lane_startup symbol" ) - host_memory.client_api.lib = lib - host_memory.client_api.startup = startup - host_memory.client_api.hot_reload = hot_reload + host_memory.client_api.lib = lib + host_memory.client_api.startup = startup + host_memory.client_api.hot_reload = hot_reload + host_memory.client_api.tick_lane_startup = tick_lane_startup } - host_memory.host_api.sync_client_module = sync_client_api - host_memory.host_api.launch_live_thread = launch_live_thread + host_memory.host_api.sync_client_module = sync_client_api + host_memory.host_api.launch_tick_lane_thread = launch_tick_lane_thread host_memory.client_api.startup(& host_memory, & thread_memory) } @export -sync_client_api :: proc() -{ +sync_client_api :: proc() { + assert_contextless(thread_memory.id == .Master_Prepper) // Fill out detection and reloading of client api. // Needs to flag and atomic to spin-lock live helepr threads when reloading } +import "core:thread" + + @export -launch_live_thread :: proc() -{ - // TODO(Ed): Prep the thread - host_memory.client_api.live_thread_startup(& thread_memory) +launch_tick_lane_thread :: proc(id : WorkerID) { + assert_contextless(thread_memory.id == .Master_Prepper) + // TODO(Ed): We need to make our own version of this that doesn't allocate memory. + lane_thread := thread.create(host_tick_lane_startup, .High) + lane_thread.user_index = int(id) + thread.start(lane_thread) +} + +host_tick_lane_startup :: proc(lane_thread: ^SysThread) { + thread_memory.system_ctx = lane_thread + thread_memory.id = cast(WorkerID) lane_thread.user_index + host_memory.client_api.tick_lane_startup(& thread_memory) } diff --git a/code2/host/pkg_mappings.odin b/code2/host/pkg_mappings.odin index 7e51812..2275d94 100644 --- a/code2/host/pkg_mappings.odin +++ b/code2/host/pkg_mappings.odin @@ -45,9 +45,11 @@ import grime "codebase:grime" file_copy_sync :: grime.file_copy_sync import "codebase:sectr" + MAX_THREADS :: sectr.MAX_THREADS Client_API :: sectr.ModuleAPI HostMemory :: sectr.HostMemory ThreadMemory :: sectr.ThreadMemory + WorkerID :: sectr.WorkerID Kilo :: 1024 Mega :: Kilo * 1024 diff --git a/code2/sectr/engine/client_api.odin b/code2/sectr/engine/client_api.odin index c0f5622..88aa3d0 100644 --- a/code2/sectr/engine/client_api.odin +++ b/code2/sectr/engine/client_api.odin @@ -28,29 +28,23 @@ startup :: proc(host_mem: ^HostMemory, thread_mem: ^ThreadMemory) memory = host_mem - thread_wide_startup() + thread_wide_startup(thread_mem) } -thread_wide_startup :: proc() +thread_wide_startup :: proc(thread_mem: ^ThreadMemory) { - if thread_memory.id == .Master_Prepper - { - thread_memory.live_lanes = - - tick_lane_startup() // + if thread_mem.id == .Master_Prepper { + sync.barrier_init(& memory.client_api_sync_lock, THREAD_TICK_LANES) } - - // TODO(Ed): Spawn helper thraed, then prepp both live threads - memory.state.live_threads += 1; // Atomic_Accountant - memory.host_api.launch_live_thread() + memory.host_api.launch_tick_lane_thread(.Atomic_Accountant) + tick_lane_startup(thread_mem) } @export tick_lane_startup :: proc(thread_mem: ^ThreadMemory) { - memory.state.live_threads += 1 - - + thread_memory = thread_mem + thread_memory.live_lanes = THREAD_TICK_LANES tick_lane() } @@ -60,11 +54,11 @@ tick_lane :: proc() for ;; { dummy += 1 - if thread_memory.index == .Master_Prepper + if thread_memory.id == .Master_Prepper { - memory.host_api.sync_client_api() + memory.host_api.sync_client_module() } - + leader := sync.barrier_wait(& memory.client_api_sync_lock) } } diff --git a/code2/sectr/engine/host_api.odin b/code2/sectr/engine/host_api.odin index 5bdb952..8106f3f 100644 --- a/code2/sectr/engine/host_api.odin +++ b/code2/sectr/engine/host_api.odin @@ -5,15 +5,17 @@ import "core:sync" HostMemory :: struct { host_scratch: [256 * Kilo]byte, - client_api_sync_lock: sync.Benaphore, + threads: [MAX_THREADS](SysThread), - client_api: ModuleAPI, - client_memory: ^State, - host_api: Host_API, + client_api_sync_lock: sync.Barrier, + + client_api: ModuleAPI, + client_memory: State, + host_api: Host_API, } Host_API :: struct { - launch_live_thread: #type proc(), + launch_tick_lane_thread: #type proc(WorkerID), request_virtual_memory: #type proc(), request_virtual_mapped_io: #type proc(), diff --git a/code2/sectr/engine/job_system.odin b/code2/sectr/engine/job_system.odin index 4fdc28c..e32b950 100644 --- a/code2/sectr/engine/job_system.odin +++ b/code2/sectr/engine/job_system.odin @@ -41,7 +41,7 @@ JobSystemContext :: struct { } ThreadWorkerContext :: struct { - system_ctx: Thread, + system_ctx: ^SysThread, id: WorkerID, } @@ -189,7 +189,7 @@ WorkerID :: enum int { } // Hard constraint for Windows -JOB_SYSTEM_MAX_WORKER_THREADS :: 64 +MAX_THREADS :: 64 /* Threads are setup upfront during the client API's startup. diff --git a/code2/sectr/pkg_mappings.odin b/code2/sectr/pkg_mappings.odin index 4625837..478112c 100644 --- a/code2/sectr/pkg_mappings.odin +++ b/code2/sectr/pkg_mappings.odin @@ -4,7 +4,7 @@ import "core:sync" AtomicMutex :: sync.Atomic_Mutex import "core:thread" - Thread :: thread.Thread + SysThread :: thread.Thread Kilo :: 1024 Mega :: Kilo * 1024 diff --git a/code2/sectr/state.odin b/code2/sectr/state.odin index e3ab347..3f34d4a 100644 --- a/code2/sectr/state.odin +++ b/code2/sectr/state.odin @@ -9,6 +9,5 @@ thread_memory: ^ThreadMemory THREAD_TICK_LANES :: 2 State :: struct { - live_threads: int, job_system: JobSystemContext, }