zipped all of the threading code together
							parent
							
								
									122cecb6ff
								
							
						
					
					
						commit
						bfc6fc689d
					
				| 
						 | 
					@ -9,11 +9,37 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TOP
 | 
					// TOP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Threading_Vars{
 | 
				
			||||||
 | 
					    Thread_Memory *thread_memory;
 | 
				
			||||||
 | 
					    Work_Queue queues[THREAD_GROUP_COUNT];
 | 
				
			||||||
 | 
					    Thread_Group groups[THREAD_GROUP_COUNT];
 | 
				
			||||||
 | 
					    Mutex locks[LOCK_COUNT];
 | 
				
			||||||
 | 
					    Condition_Variable conds[CV_COUNT];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					global Threading_Vars threadvars;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal
 | 
				
			||||||
 | 
					Sys_Acquire_Lock_Sig(system_acquire_lock){
 | 
				
			||||||
 | 
					    system_acquire_lock(&threadvars.locks[id]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal
 | 
				
			||||||
 | 
					Sys_Release_Lock_Sig(system_release_lock){
 | 
				
			||||||
 | 
					    system_release_lock(&threadvars.locks[id]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
job_proc(System_Functions *system, Thread_Context *thread, Work_Queue *queue, Thread_Group *group, Thread_Memory *thread_memory){
 | 
					job_thread_proc(System_Functions *system, Thread_Context *thread){
 | 
				
			||||||
 | 
					    Work_Queue *queue = threadvars.queues + thread->group_id;
 | 
				
			||||||
 | 
					    Thread_Group *group = threadvars.groups + thread->group_id;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    i32 thread_index = thread->id - 1;
 | 
					    i32 thread_index = thread->id - 1;
 | 
				
			||||||
    i32 cancel_lock = group->cancel_lock0 + thread_index;
 | 
					    Thread_Memory *thread_memory = threadvars.thread_memory + thread_index;
 | 
				
			||||||
    i32 cancel_cv = group->cancel_cv0 + thread_index;
 | 
					    
 | 
				
			||||||
 | 
					    i32 cancel_lock_id = group->cancel_lock0 + thread_index;
 | 
				
			||||||
 | 
					    i32 cancel_cv_id = group->cancel_cv0 + thread_index;
 | 
				
			||||||
 | 
					    Mutex *cancel_lock = &threadvars.locks[cancel_lock_id];
 | 
				
			||||||
 | 
					    Condition_Variable *cancel_cv = &threadvars.conds[cancel_cv_id];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (thread_memory->size == 0){
 | 
					    if (thread_memory->size == 0){
 | 
				
			||||||
        i32 new_size = KB(64);
 | 
					        i32 new_size = KB(64);
 | 
				
			||||||
| 
						 | 
					@ -47,7 +73,7 @@ job_proc(System_Functions *system, Thread_Context *thread, Work_Queue *queue, Th
 | 
				
			||||||
                    system_acquire_lock(cancel_lock);
 | 
					                    system_acquire_lock(cancel_lock);
 | 
				
			||||||
                    if (thread->cancel){
 | 
					                    if (thread->cancel){
 | 
				
			||||||
                        thread->cancel = 0;
 | 
					                        thread->cancel = 0;
 | 
				
			||||||
                        system_signal_cv(cancel_lock, cancel_cv);
 | 
					                        system_signal_cv(cancel_cv, cancel_lock);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    system_release_lock(cancel_lock);
 | 
					                    system_release_lock(cancel_lock);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -92,7 +118,12 @@ get_work_queue_available_space(i32 write, i32 read){
 | 
				
			||||||
#define UNBOUNDED_SKIP_MAX 128
 | 
					#define UNBOUNDED_SKIP_MAX 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal i32
 | 
					internal i32
 | 
				
			||||||
flush_to_direct_queue(Unbounded_Work_Queue *source_queue, Work_Queue *queue, i32 thread_count){
 | 
					flush_thread_group(Thread_Group_ID group_id){
 | 
				
			||||||
 | 
					    Thread_Group *group = threadvars.groups + group_id;
 | 
				
			||||||
 | 
					    Work_Queue *queue = threadvars.queues + group_id;
 | 
				
			||||||
 | 
					    Unbounded_Work_Queue *source_queue = &group->queue;
 | 
				
			||||||
 | 
					    i32 thread_count = group->count;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // NOTE(allen): It is understood that read_position may be changed by other
 | 
					    // NOTE(allen): It is understood that read_position may be changed by other
 | 
				
			||||||
    // threads but it will only make more space in the queue if it is changed.
 | 
					    // threads but it will only make more space in the queue if it is changed.
 | 
				
			||||||
    // Meanwhile write_position should not ever be changed by anything but the
 | 
					    // Meanwhile write_position should not ever be changed by anything but the
 | 
				
			||||||
| 
						 | 
					@ -155,8 +186,9 @@ flush_to_direct_queue(Unbounded_Work_Queue *source_queue, Work_Queue *queue, i32
 | 
				
			||||||
// The unbounded queue is entirely managed by the main thread.
 | 
					// The unbounded queue is entirely managed by the main thread.
 | 
				
			||||||
// The thread safe queue is bounded in size so the unbounded
 | 
					// The thread safe queue is bounded in size so the unbounded
 | 
				
			||||||
// queue is periodically flushed into the direct work queue.
 | 
					// queue is periodically flushed into the direct work queue.
 | 
				
			||||||
internal u32
 | 
					internal
 | 
				
			||||||
post_job(Thread_Group *group, Work_Queue *direct_queue, Job_Data job){
 | 
					Sys_Post_Job_Sig(system_post_job){
 | 
				
			||||||
 | 
					    Thread_Group *group = threadvars.groups + group_id;
 | 
				
			||||||
    Unbounded_Work_Queue *queue = &group->queue;
 | 
					    Unbounded_Work_Queue *queue = &group->queue;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    u32 result = queue->next_job_id++;
 | 
					    u32 result = queue->next_job_id++;
 | 
				
			||||||
| 
						 | 
					@ -176,13 +208,16 @@ post_job(Thread_Group *group, Work_Queue *direct_queue, Job_Data job){
 | 
				
			||||||
    full_job.id = result;
 | 
					    full_job.id = result;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    queue->jobs[queue->count++] = full_job;
 | 
					    queue->jobs[queue->count++] = full_job;
 | 
				
			||||||
    flush_to_direct_queue(queue, direct_queue, group->count);
 | 
					    flush_thread_group(group_id);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal
 | 
				
			||||||
cancel_job(Thread_Group *group, Work_Queue *queue, u32 job_id){
 | 
					Sys_Cancel_Job_Sig(system_cancel_job){
 | 
				
			||||||
 | 
					    Thread_Group *group = threadvars.groups + group_id;
 | 
				
			||||||
 | 
					    Work_Queue *queue = threadvars.queues + group_id;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    Unbounded_Work_Queue *source_queue = &group->queue;
 | 
					    Unbounded_Work_Queue *source_queue = &group->queue;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    b32 handled_in_unbounded = false;
 | 
					    b32 handled_in_unbounded = false;
 | 
				
			||||||
| 
						 | 
					@ -205,29 +240,36 @@ cancel_job(Thread_Group *group, Work_Queue *queue, u32 job_id){
 | 
				
			||||||
        if (thread_id != THREAD_NOT_ASSIGNED && thread_id != 0){
 | 
					        if (thread_id != THREAD_NOT_ASSIGNED && thread_id != 0){
 | 
				
			||||||
            i32 thread_index = thread_id - 1;
 | 
					            i32 thread_index = thread_id - 1;
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            i32 cancel_lock = group->cancel_lock0 + thread_index;
 | 
					            i32 cancel_lock_id = group->cancel_lock0 + thread_index;
 | 
				
			||||||
            i32 cancel_cv = group->cancel_cv0 + thread_index;
 | 
					            i32 cancel_cv_id = group->cancel_cv0 + thread_index;
 | 
				
			||||||
 | 
					            Mutex *cancel_lock = &threadvars.locks[cancel_lock_id];
 | 
				
			||||||
 | 
					            Condition_Variable *cancel_cv = &threadvars.conds[cancel_cv_id];
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            Thread_Context *thread = group->threads + thread_index;
 | 
					            Thread_Context *thread = group->threads + thread_index;
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            system_acquire_lock(cancel_lock);
 | 
					            system_acquire_lock(cancel_lock);
 | 
				
			||||||
            thread->cancel = true;
 | 
					            thread->cancel = true;
 | 
				
			||||||
            system_release_lock(FRAME_LOCK);
 | 
					            system_release_lock(&threadvars.locks[FRAME_LOCK]);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            do{
 | 
					            do{
 | 
				
			||||||
                system_wait_cv(cancel_lock, cancel_cv);
 | 
					                system_wait_cv(cancel_cv, cancel_lock);
 | 
				
			||||||
            }while (thread->cancel);
 | 
					            }while (thread->cancel);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            system_acquire_lock(FRAME_LOCK);
 | 
					            system_acquire_lock(&threadvars.locks[FRAME_LOCK]);
 | 
				
			||||||
            system_release_lock(cancel_lock);
 | 
					            system_release_lock(cancel_lock);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal b32
 | 
					internal
 | 
				
			||||||
check_cancel_status(Thread_Group *group, Thread_Context *thread){
 | 
					Sys_Check_Cancel_Sig(system_check_cancel){
 | 
				
			||||||
 | 
					    Thread_Group *group = threadvars.groups + thread->group_id;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    b32 result = false;
 | 
					    b32 result = false;
 | 
				
			||||||
    i32 thread_index = thread->id - 1;
 | 
					    i32 thread_index = thread->id - 1;
 | 
				
			||||||
    i32 cancel_lock = group->cancel_lock0 + thread_index;
 | 
					    i32 cancel_lock_id = group->cancel_lock0 + thread_index;
 | 
				
			||||||
 | 
					    Mutex *cancel_lock = &threadvars.locks[cancel_lock_id];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    system_acquire_lock(cancel_lock);
 | 
					    system_acquire_lock(cancel_lock);
 | 
				
			||||||
    if (thread->cancel){
 | 
					    if (thread->cancel){
 | 
				
			||||||
        result = true;
 | 
					        result = true;
 | 
				
			||||||
| 
						 | 
					@ -236,9 +278,11 @@ check_cancel_status(Thread_Group *group, Thread_Context *thread){
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal
 | 
				
			||||||
grow_thread_memory(Thread_Memory *memory){
 | 
					Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
 | 
				
			||||||
    system_acquire_lock(CANCEL_LOCK0 + memory->id - 1);
 | 
					    Mutex *cancel_lock = &threadvars.locks[CANCEL_LOCK0 + memory->id - 1];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    system_acquire_lock(cancel_lock);
 | 
				
			||||||
    void *old_data = memory->data;
 | 
					    void *old_data = memory->data;
 | 
				
			||||||
    i32 old_size = memory->size;
 | 
					    i32 old_size = memory->size;
 | 
				
			||||||
    i32 new_size = l_round_up_i32(memory->size*2, KB(4));
 | 
					    i32 new_size = l_round_up_i32(memory->size*2, KB(4));
 | 
				
			||||||
| 
						 | 
					@ -248,11 +292,13 @@ grow_thread_memory(Thread_Memory *memory){
 | 
				
			||||||
        memcpy(memory->data, old_data, old_size);
 | 
					        memcpy(memory->data, old_data, old_size);
 | 
				
			||||||
        system_memory_free(old_data, old_size);
 | 
					        system_memory_free(old_data, old_size);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    system_release_lock(CANCEL_LOCK0 + memory->id - 1);
 | 
					    system_release_lock(cancel_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal
 | 
				
			||||||
dbg_get_thread_states(Thread_Group *group, Work_Queue *queue, b8 *running, i32 *pending){
 | 
					INTERNAL_Sys_Get_Thread_States_Sig(system_internal_get_thread_states){
 | 
				
			||||||
 | 
					    Thread_Group *group = threadvars.groups + id;
 | 
				
			||||||
 | 
					    Work_Queue *queue = threadvars.queues + id;
 | 
				
			||||||
    Unbounded_Work_Queue *source_queue = &group->queue;
 | 
					    Unbounded_Work_Queue *source_queue = &group->queue;
 | 
				
			||||||
    u32 write = queue->write_position;
 | 
					    u32 write = queue->write_position;
 | 
				
			||||||
    u32 read = queue->read_position;
 | 
					    u32 read = queue->read_position;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,11 +190,6 @@ struct Linux_Vars{
 | 
				
			||||||
    void *app_code;
 | 
					    void *app_code;
 | 
				
			||||||
    void *custom;
 | 
					    void *custom;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Thread_Memory *thread_memory;
 | 
					 | 
				
			||||||
    Thread_Group groups[THREAD_GROUP_COUNT];
 | 
					 | 
				
			||||||
    Work_Queue queues[THREAD_GROUP_COUNT];
 | 
					 | 
				
			||||||
    Mutex locks[LOCK_COUNT];
 | 
					 | 
				
			||||||
    Condition_Variable conds[8];
 | 
					 | 
				
			||||||
    sem_t thread_semaphore;
 | 
					    sem_t thread_semaphore;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    i32 dpi_x, dpi_y;
 | 
					    i32 dpi_x, dpi_y;
 | 
				
			||||||
| 
						 | 
					@ -488,37 +483,27 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Threads
 | 
					// Multithreading
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
system_internal_acquire_lock(Mutex *m){
 | 
					system_acquire_lock(Mutex *m){
 | 
				
			||||||
    pthread_mutex_lock(m->crit);
 | 
					    pthread_mutex_lock(m->crit);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
system_internal_release_lock(Mutex *m){
 | 
					system_release_lock(Mutex *m){
 | 
				
			||||||
    pthread_mutex_unlock(m->crit);
 | 
					    pthread_mutex_unlock(m->crit);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal
 | 
					internal void
 | 
				
			||||||
Sys_Acquire_Lock_Sig(system_acquire_lock){
 | 
					system_wait_cv(Condition_Variable *cv, Mutex *m){
 | 
				
			||||||
    system_internal_acquire_lock(&linuxvars.locks[id]);
 | 
					    pthread_cond_wait(cv->cv, m->crit);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Release_Lock_Sig(system_release_lock){
 | 
					 | 
				
			||||||
    system_internal_release_lock(&linuxvars.locks[id]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
system_wait_cv(i32 lock_id, i32 cv_id){
 | 
					system_signal_cv(Condition_Variable *cv, Mutex *m){
 | 
				
			||||||
    pthread_cond_wait(linuxvars.conds + cv_id, linuxvars.locks + lock_id);
 | 
					    pthread_cond_signal(cv->cv);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal void
 | 
					 | 
				
			||||||
system_signal_cv(i32 lock_id, i32 cv_id){
 | 
					 | 
				
			||||||
    pthread_cond_signal(linuxvars.conds + cv_id);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HACK(allen): Reduce this down to just one layer of call.
 | 
					// HACK(allen): Reduce this down to just one layer of call.
 | 
				
			||||||
| 
						 | 
					@ -542,53 +527,11 @@ system_release_semaphore(Plat_Handle handle){
 | 
				
			||||||
internal void*
 | 
					internal void*
 | 
				
			||||||
JobThreadProc(void* lpParameter){
 | 
					JobThreadProc(void* lpParameter){
 | 
				
			||||||
    Thread_Context *thread = (Thread_Context*)lpParameter;
 | 
					    Thread_Context *thread = (Thread_Context*)lpParameter;
 | 
				
			||||||
    Work_Queue *queue = linuxvars.queues + thread->group_id;
 | 
					    job_thread_proc(&linuxvars.system, thread);
 | 
				
			||||||
    Thread_Group *group = linuxvars.groups + thread->group_id;
 | 
					 | 
				
			||||||
    i32 thread_index = thread->id - 1;
 | 
					 | 
				
			||||||
    Thread_Memory *memory = linuxvars.thread_memory + thread_index;
 | 
					 | 
				
			||||||
    job_proc(&linuxvars.system, thread, queue, group, memory);
 | 
					 | 
				
			||||||
    InvalidCodePath;
 | 
					    InvalidCodePath;
 | 
				
			||||||
    return(0);
 | 
					    return(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Note(allen): post_job puts the job on the unbounded queue.
 | 
					 | 
				
			||||||
// The unbounded queue is entirely managed by the main thread.
 | 
					 | 
				
			||||||
// The thread safe queue is bounded in size so the unbounded
 | 
					 | 
				
			||||||
// queue is periodically flushed into the direct work queue.
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Post_Job_Sig(system_post_job){
 | 
					 | 
				
			||||||
    Thread_Group *group = linuxvars.groups + group_id;
 | 
					 | 
				
			||||||
    Work_Queue *direct_queue = linuxvars.queues + group_id;
 | 
					 | 
				
			||||||
    u32 result = post_job(group, direct_queue, job);
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Cancel_Job_Sig(system_cancel_job){
 | 
					 | 
				
			||||||
    Thread_Group *group = linuxvars.groups + group_id;
 | 
					 | 
				
			||||||
    Work_Queue *queue = linuxvars.queues + group_id;
 | 
					 | 
				
			||||||
    cancel_job(group, queue, job_id);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Check_Cancel_Sig(system_check_cancel){
 | 
					 | 
				
			||||||
    Thread_Group *group = linuxvars.groups + thread->group_id;
 | 
					 | 
				
			||||||
    b32 result = check_cancel_status(group, thread);
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
 | 
					 | 
				
			||||||
    grow_thread_memory(memory);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
INTERNAL_Sys_Get_Thread_States_Sig(system_internal_get_thread_states){
 | 
					 | 
				
			||||||
    Thread_Group *group = linuxvars.groups + id;
 | 
					 | 
				
			||||||
    Work_Queue *queue = linuxvars.queues + id;
 | 
					 | 
				
			||||||
    dbg_get_thread_states(group, queue, running, pending);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Linux rendering/font system functions
 | 
					// Linux rendering/font system functions
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
| 
						 | 
					@ -629,13 +572,6 @@ LinuxLoadAppCode(String* base_dir){
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "4ed_link_system_functions.cpp"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal void
 | 
					 | 
				
			||||||
LinuxLoadSystemCode(){
 | 
					 | 
				
			||||||
    link_system_code(&linuxvars.system);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
LinuxLoadRenderCode(){
 | 
					LinuxLoadRenderCode(){
 | 
				
			||||||
    linuxvars.target.push_clip = draw_push_clip;
 | 
					    linuxvars.target.push_clip = draw_push_clip;
 | 
				
			||||||
| 
						 | 
					@ -1994,6 +1930,8 @@ LinuxHandleX11Events(void)
 | 
				
			||||||
// Entry point
 | 
					// Entry point
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "4ed_link_system_functions.cpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char **argv){
 | 
					main(int argc, char **argv){
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
| 
						 | 
					@ -2008,7 +1946,7 @@ main(int argc, char **argv){
 | 
				
			||||||
        return 99;
 | 
					        return 99;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    LinuxLoadSystemCode();
 | 
					    link_system_code(&linuxvars.system);
 | 
				
			||||||
    LinuxLoadRenderCode();
 | 
					    LinuxLoadRenderCode();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    memory_vars.vars_memory_size   = MB(2);
 | 
					    memory_vars.vars_memory_size   = MB(2);
 | 
				
			||||||
| 
						 | 
					@ -2140,31 +2078,31 @@ main(int argc, char **argv){
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Thread_Context background[4] = {};
 | 
					    Thread_Context background[4] = {};
 | 
				
			||||||
    linuxvars.groups[BACKGROUND_THREADS].threads = background;
 | 
					    threadvars.groups[BACKGROUND_THREADS].threads = background;
 | 
				
			||||||
    linuxvars.groups[BACKGROUND_THREADS].count = ArrayCount(background);
 | 
					    threadvars.groups[BACKGROUND_THREADS].count = ArrayCount(background);
 | 
				
			||||||
    linuxvars.groups[BACKGROUND_THREADS].cancel_lock0 = CANCEL_LOCK0;
 | 
					    threadvars.groups[BACKGROUND_THREADS].cancel_lock0 = CANCEL_LOCK0;
 | 
				
			||||||
    linuxvars.groups[BACKGROUND_THREADS].cancel_cv0 = 0;
 | 
					    threadvars.groups[BACKGROUND_THREADS].cancel_cv0 = 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Thread_Memory thread_memory[ArrayCount(background)];
 | 
					    Thread_Memory thread_memory[ArrayCount(background)];
 | 
				
			||||||
    linuxvars.thread_memory = thread_memory;
 | 
					    threadvars.thread_memory = thread_memory;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    sem_init(&linuxvars.thread_semaphore, 0, 0);
 | 
					    sem_init(&linuxvars.thread_semaphore, 0, 0);
 | 
				
			||||||
    linuxvars.queues[BACKGROUND_THREADS].semaphore = LinuxSemToHandle(&linuxvars.thread_semaphore);
 | 
					    threadvars.queues[BACKGROUND_THREADS].semaphore = LinuxSemToHandle(&linuxvars.thread_semaphore);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for(i32 i = 0; i < linuxvars.groups[BACKGROUND_THREADS].count; ++i){
 | 
					    for(i32 i = 0; i < threadvars.groups[BACKGROUND_THREADS].count; ++i){
 | 
				
			||||||
        Thread_Context *thread = linuxvars.groups[BACKGROUND_THREADS].threads + i;
 | 
					        Thread_Context *thread = threadvars.groups[BACKGROUND_THREADS].threads + i;
 | 
				
			||||||
        thread->id = i + 1;
 | 
					        thread->id = i + 1;
 | 
				
			||||||
        thread->group_id = BACKGROUND_THREADS;
 | 
					        thread->group_id = BACKGROUND_THREADS;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Thread_Memory *memory = linuxvars.thread_memory + i;
 | 
					        Thread_Memory *memory = threadvars.thread_memory + i;
 | 
				
			||||||
        *memory = null_thread_memory;
 | 
					        *memory = null_thread_memory;
 | 
				
			||||||
        memory->id = thread->id;
 | 
					        memory->id = thread->id;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        thread->queue = &linuxvars.queues[BACKGROUND_THREADS];
 | 
					        thread->queue = &threadvars.queues[BACKGROUND_THREADS];
 | 
				
			||||||
        pthread_create(&thread->handle, NULL, &JobThreadProc, thread);
 | 
					        pthread_create(&thread->handle, NULL, &JobThreadProc, thread);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    initialize_unbounded_queue(&linuxvars.groups[BACKGROUND_THREADS].queue);
 | 
					    initialize_unbounded_queue(&threadvars.groups[BACKGROUND_THREADS].queue);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for(i32 i = 0; i < LOCK_COUNT; ++i){
 | 
					    for(i32 i = 0; i < LOCK_COUNT; ++i){
 | 
				
			||||||
        pthread_mutex_init(linuxvars.locks + i, NULL);
 | 
					        pthread_mutex_init(linuxvars.locks + i, NULL);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,12 +173,6 @@ struct Win32_Vars{
 | 
				
			||||||
    HMODULE custom;
 | 
					    HMODULE custom;
 | 
				
			||||||
    Plat_Settings settings;
 | 
					    Plat_Settings settings;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Thread_Memory *thread_memory;
 | 
					 | 
				
			||||||
    Work_Queue queues[THREAD_GROUP_COUNT];
 | 
					 | 
				
			||||||
    Thread_Group groups[THREAD_GROUP_COUNT];
 | 
					 | 
				
			||||||
    Mutex locks[LOCK_COUNT];
 | 
					 | 
				
			||||||
    Condition_Variable condition_vars[CV_COUNT];
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    Win32_Coroutine coroutine_data[18];
 | 
					    Win32_Coroutine coroutine_data[18];
 | 
				
			||||||
    Win32_Coroutine *coroutine_free;
 | 
					    Win32_Coroutine *coroutine_free;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -344,33 +338,23 @@ Sys_Memory_Free_Sig(system_memory_free){
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
system_internal_acquire_lock(Mutex *m){
 | 
					system_acquire_lock(Mutex *m){
 | 
				
			||||||
    EnterCriticalSection(&m->crit);
 | 
					    EnterCriticalSection(&m->crit);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
system_internal_release_lock(Mutex *m){
 | 
					system_release_lock(Mutex *m){
 | 
				
			||||||
    LeaveCriticalSection(&m->crit);
 | 
					    LeaveCriticalSection(&m->crit);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal
 | 
					internal void
 | 
				
			||||||
Sys_Acquire_Lock_Sig(system_acquire_lock){
 | 
					system_wait_cv(Condition_Variable *cv, Mutex *lock){
 | 
				
			||||||
    system_internal_acquire_lock(&win32vars.locks[id]);
 | 
					    SleepConditionVariableCS(&cv->cv, &lock->crit, INFINITE);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Release_Lock_Sig(system_release_lock){
 | 
					 | 
				
			||||||
    system_internal_release_lock(&win32vars.locks[id]);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
system_wait_cv(i32 crit_id, i32 cv_id){
 | 
					system_signal_cv(Condition_Variable *cv, Mutex *lock){
 | 
				
			||||||
    SleepConditionVariableCS(&win32vars.condition_vars[cv_id].cv, &win32vars.locks[crit_id].crit, INFINITE);
 | 
					    WakeConditionVariable(&cv->cv);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal void
 | 
					 | 
				
			||||||
system_signal_cv(i32 crit_id, i32 cv_id){
 | 
					 | 
				
			||||||
    WakeConditionVariable(&win32vars.condition_vars[cv_id].cv);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
| 
						 | 
					@ -393,57 +377,11 @@ system_release_semaphore(Plat_Handle handle){
 | 
				
			||||||
internal DWORD CALL_CONVENTION
 | 
					internal DWORD CALL_CONVENTION
 | 
				
			||||||
JobThreadProc(LPVOID lpParameter){
 | 
					JobThreadProc(LPVOID lpParameter){
 | 
				
			||||||
    Thread_Context *thread = (Thread_Context*)lpParameter;
 | 
					    Thread_Context *thread = (Thread_Context*)lpParameter;
 | 
				
			||||||
    Work_Queue *queue = win32vars.queues + thread->group_id;
 | 
					    job_thread_proc(&win32vars.system, thread);
 | 
				
			||||||
    Thread_Group *group = win32vars.groups + thread->group_id;
 | 
					 | 
				
			||||||
    i32 thread_index = thread->id - 1;
 | 
					 | 
				
			||||||
    Thread_Memory *memory = win32vars.thread_memory + thread_index;
 | 
					 | 
				
			||||||
    job_proc(&win32vars.system, thread, queue, group, memory);
 | 
					 | 
				
			||||||
    InvalidCodePath;
 | 
					    InvalidCodePath;
 | 
				
			||||||
    return(0);
 | 
					    return(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					 | 
				
			||||||
flush_thread_group(i32 group_id){
 | 
					 | 
				
			||||||
    Thread_Group *group = win32vars.groups + group_id;
 | 
					 | 
				
			||||||
    Work_Queue *queue = win32vars.queues + group_id;
 | 
					 | 
				
			||||||
    Unbounded_Work_Queue *source_queue = &group->queue;
 | 
					 | 
				
			||||||
    flush_to_direct_queue(source_queue, queue, group->count);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Post_Job_Sig(system_post_job){
 | 
					 | 
				
			||||||
    Thread_Group *group = win32vars.groups + group_id;
 | 
					 | 
				
			||||||
    Work_Queue *direct_queue = win32vars.queues + group_id;
 | 
					 | 
				
			||||||
    u32 result = post_job(group, direct_queue, job);
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Cancel_Job_Sig(system_cancel_job){
 | 
					 | 
				
			||||||
    Thread_Group *group = win32vars.groups + group_id;
 | 
					 | 
				
			||||||
    Work_Queue *queue = win32vars.queues + group_id;
 | 
					 | 
				
			||||||
    cancel_job(group, queue, job_id);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Check_Cancel_Sig(system_check_cancel){
 | 
					 | 
				
			||||||
    Thread_Group *group = win32vars.groups + thread->group_id;
 | 
					 | 
				
			||||||
    b32 result = check_cancel_status(group, thread);
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
 | 
					 | 
				
			||||||
    grow_thread_memory(memory);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal
 | 
					 | 
				
			||||||
INTERNAL_Sys_Get_Thread_States_Sig(system_internal_get_thread_states){
 | 
					 | 
				
			||||||
    Thread_Group *group = win32vars.groups + id;
 | 
					 | 
				
			||||||
    Work_Queue *queue = win32vars.queues + id;
 | 
					 | 
				
			||||||
    dbg_get_thread_states(group, queue, running, pending);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Coroutines
 | 
					// Coroutines
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
| 
						 | 
					@ -1220,13 +1158,6 @@ Win32LoadAppCode(){
 | 
				
			||||||
#include "4ed_font_data.h"
 | 
					#include "4ed_font_data.h"
 | 
				
			||||||
#include "4ed_system_shared.cpp"
 | 
					#include "4ed_system_shared.cpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "4ed_link_system_functions.cpp"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal void
 | 
					 | 
				
			||||||
Win32LoadSystemCode(){
 | 
					 | 
				
			||||||
    link_system_code(&win32vars.system);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
Win32LoadRenderCode(){
 | 
					Win32LoadRenderCode(){
 | 
				
			||||||
    win32vars.target.push_clip = draw_push_clip;
 | 
					    win32vars.target.push_clip = draw_push_clip;
 | 
				
			||||||
| 
						 | 
					@ -1713,6 +1644,8 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "4ed_link_system_functions.cpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int CALL_CONVENTION
 | 
					int CALL_CONVENTION
 | 
				
			||||||
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
 | 
					WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
 | 
				
			||||||
    i32 argc = __argc;
 | 
					    i32 argc = __argc;
 | 
				
			||||||
| 
						 | 
					@ -1727,41 +1660,41 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for (i32 i = 0; i < LOCK_COUNT; ++i){
 | 
					    for (i32 i = 0; i < LOCK_COUNT; ++i){
 | 
				
			||||||
        InitializeCriticalSection(&win32vars.locks[i].crit);
 | 
					        InitializeCriticalSection(&threadvars.locks[i].crit);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for (i32 i = 0; i < CV_COUNT; ++i){
 | 
					    for (i32 i = 0; i < CV_COUNT; ++i){
 | 
				
			||||||
        InitializeConditionVariable(&win32vars.condition_vars[i].cv);
 | 
					        InitializeConditionVariable(&threadvars.conds[i].cv);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Thread_Context background[4];
 | 
					    Thread_Context background[4];
 | 
				
			||||||
    memset(background, 0, sizeof(background));
 | 
					    memset(background, 0, sizeof(background));
 | 
				
			||||||
    win32vars.groups[BACKGROUND_THREADS].threads = background;
 | 
					    threadvars.groups[BACKGROUND_THREADS].threads = background;
 | 
				
			||||||
    win32vars.groups[BACKGROUND_THREADS].count = ArrayCount(background);
 | 
					    threadvars.groups[BACKGROUND_THREADS].count = ArrayCount(background);
 | 
				
			||||||
    win32vars.groups[BACKGROUND_THREADS].cancel_lock0 = CANCEL_LOCK0;
 | 
					    threadvars.groups[BACKGROUND_THREADS].cancel_lock0 = CANCEL_LOCK0;
 | 
				
			||||||
    win32vars.groups[BACKGROUND_THREADS].cancel_cv0 = CANCEL_CV0;
 | 
					    threadvars.groups[BACKGROUND_THREADS].cancel_cv0 = CANCEL_CV0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Thread_Memory thread_memory[ArrayCount(background)];
 | 
					    Thread_Memory thread_memory[ArrayCount(background)];
 | 
				
			||||||
    win32vars.thread_memory = thread_memory;
 | 
					    threadvars.thread_memory = thread_memory;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    win32vars.queues[BACKGROUND_THREADS].semaphore =Win32Handle(CreateSemaphore(0, 0, win32vars.groups[BACKGROUND_THREADS].count, 0));
 | 
					    threadvars.queues[BACKGROUND_THREADS].semaphore =Win32Handle(CreateSemaphore(0, 0, threadvars.groups[BACKGROUND_THREADS].count, 0));
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    u32 creation_flag = 0;
 | 
					    u32 creation_flag = 0;
 | 
				
			||||||
    for (i32 i = 0; i < win32vars.groups[BACKGROUND_THREADS].count; ++i){
 | 
					    for (i32 i = 0; i < threadvars.groups[BACKGROUND_THREADS].count; ++i){
 | 
				
			||||||
        Thread_Context *thread = win32vars.groups[BACKGROUND_THREADS].threads + i;
 | 
					        Thread_Context *thread = threadvars.groups[BACKGROUND_THREADS].threads + i;
 | 
				
			||||||
        thread->id = i + 1;
 | 
					        thread->id = i + 1;
 | 
				
			||||||
        thread->group_id = BACKGROUND_THREADS;
 | 
					        thread->group_id = BACKGROUND_THREADS;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Thread_Memory *memory = win32vars.thread_memory + i;
 | 
					        Thread_Memory *memory = threadvars.thread_memory + i;
 | 
				
			||||||
        *memory = null_thread_memory;
 | 
					        *memory = null_thread_memory;
 | 
				
			||||||
        memory->id = thread->id;
 | 
					        memory->id = thread->id;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        thread->queue = &win32vars.queues[BACKGROUND_THREADS];
 | 
					        thread->queue = &threadvars.queues[BACKGROUND_THREADS];
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        thread->handle = CreateThread(0, 0, JobThreadProc, thread, creation_flag, (LPDWORD)&thread->windows_id);
 | 
					        thread->handle = CreateThread(0, 0, JobThreadProc, thread, creation_flag, (LPDWORD)&thread->windows_id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    initialize_unbounded_queue(&win32vars.groups[BACKGROUND_THREADS].queue);
 | 
					    initialize_unbounded_queue(&threadvars.groups[BACKGROUND_THREADS].queue);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    ConvertThreadToFiber(0);
 | 
					    ConvertThreadToFiber(0);
 | 
				
			||||||
    win32vars.coroutine_free = win32vars.coroutine_data;
 | 
					    win32vars.coroutine_free = win32vars.coroutine_data;
 | 
				
			||||||
| 
						 | 
					@ -1821,7 +1754,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Win32LoadSystemCode();
 | 
					    link_system_code(&win32vars.system);
 | 
				
			||||||
    Win32LoadRenderCode();
 | 
					    Win32LoadRenderCode();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    System_Functions *system = &win32vars.system;
 | 
					    System_Functions *system = &win32vars.system;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue