Browse Source

Migrate and remove more from gb.h

gingerBill 4 years ago
parent
commit
df372dbd5b
8 changed files with 386 additions and 1208 deletions
  1. 15 15
      src/checker.cpp
  2. 2 128
      src/common.cpp
  3. 2 1042
      src/gb/gb.h
  4. 2 4
      src/llvm_backend.hpp
  5. 1 1
      src/llvm_backend_const.cpp
  6. 3 5
      src/llvm_backend_general.cpp
  7. 13 13
      src/thread_pool.cpp
  8. 348 0
      src/threading.cpp

+ 15 - 15
src/checker.cpp

@@ -4129,7 +4129,7 @@ struct ThreadProcCheckerSection {
 };
 };
 
 
 
 
-void check_with_workers(Checker *c, gbThreadProc *proc, isize total_count) {
+void check_with_workers(Checker *c, ThreadProc *proc, isize total_count) {
 	isize thread_count = gb_max(build_context.thread_count, 1);
 	isize thread_count = gb_max(build_context.thread_count, 1);
 	isize worker_count = thread_count-1; // NOTE(bill): The main thread will also be used for work
 	isize worker_count = thread_count-1; // NOTE(bill): The main thread will also be used for work
 	if (!build_context.threaded_checker) {
 	if (!build_context.threaded_checker) {
@@ -4143,7 +4143,7 @@ void check_with_workers(Checker *c, gbThreadProc *proc, isize total_count) {
 		section_all.checker = c;
 		section_all.checker = c;
 		section_all.offset = 0;
 		section_all.offset = 0;
 		section_all.count = total_count;
 		section_all.count = total_count;
-		gbThread dummy_main_thread = {};
+		Thread dummy_main_thread = {};
 		dummy_main_thread.user_data = &section_all;
 		dummy_main_thread.user_data = &section_all;
 		proc(&dummy_main_thread);
 		proc(&dummy_main_thread);
 		return;
 		return;
@@ -4162,27 +4162,27 @@ void check_with_workers(Checker *c, gbThreadProc *proc, isize total_count) {
 	}
 	}
 	GB_ASSERT(remaining_count <= 0);
 	GB_ASSERT(remaining_count <= 0);
 
 
-	gbThread *threads = gb_alloc_array(permanent_allocator(), gbThread, worker_count);
+	Thread *threads = gb_alloc_array(permanent_allocator(), Thread, worker_count);
 	for (isize i = 0; i < worker_count; i++) {
 	for (isize i = 0; i < worker_count; i++) {
-		gb_thread_init(threads+i);
+		thread_init(threads+i);
 	}
 	}
 
 
 	for (isize i = 0; i < worker_count; i++) {
 	for (isize i = 0; i < worker_count; i++) {
-		gb_thread_start(threads+i, proc, thread_data+i);
+		thread_start(threads+i, proc, thread_data+i);
 	}
 	}
-	gbThread dummy_main_thread = {};
+	Thread dummy_main_thread = {};
 	dummy_main_thread.user_data = thread_data+worker_count;
 	dummy_main_thread.user_data = thread_data+worker_count;
 	proc(&dummy_main_thread);
 	proc(&dummy_main_thread);
 
 
 	semaphore_wait(&c->info.collect_semaphore);
 	semaphore_wait(&c->info.collect_semaphore);
 
 
 	for (isize i = 0; i < worker_count; i++) {
 	for (isize i = 0; i < worker_count; i++) {
-		gb_thread_destroy(threads+i);
+		thread_destroy(threads+i);
 	}
 	}
 }
 }
 
 
 
 
-GB_THREAD_PROC(thread_proc_collect_entities) {
+THREAD_PROC(thread_proc_collect_entities) {
 	auto *data = cast(ThreadProcCheckerSection *)thread->user_data;
 	auto *data = cast(ThreadProcCheckerSection *)thread->user_data;
 	Checker *c = data->checker;
 	Checker *c = data->checker;
 	CheckerContext collect_entity_ctx = make_checker_context(c);
 	CheckerContext collect_entity_ctx = make_checker_context(c);
@@ -4231,7 +4231,7 @@ void check_export_entities_in_pkg(CheckerContext *ctx, AstPackage *pkg, UntypedE
 	}
 	}
 }
 }
 
 
-GB_THREAD_PROC(thread_proc_check_export_entities) {
+THREAD_PROC(thread_proc_check_export_entities) {
 	auto data = cast(ThreadProcCheckerSection *)thread->user_data;
 	auto data = cast(ThreadProcCheckerSection *)thread->user_data;
 	Checker *c = data->checker;
 	Checker *c = data->checker;
 
 
@@ -4720,7 +4720,7 @@ struct ThreadProcBodyData {
 	ThreadProcBodyData *all_data;
 	ThreadProcBodyData *all_data;
 };
 };
 
 
-GB_THREAD_PROC(thread_proc_body) {
+THREAD_PROC(thread_proc_body) {
 	ThreadProcBodyData *data = cast(ThreadProcBodyData *)thread->user_data;
 	ThreadProcBodyData *data = cast(ThreadProcBodyData *)thread->user_data;
 	Checker *c = data->checker;
 	Checker *c = data->checker;
 	GB_ASSERT(c != nullptr);
 	GB_ASSERT(c != nullptr);
@@ -4797,22 +4797,22 @@ void check_procedure_bodies(Checker *c) {
 
 
 	semaphore_post(&c->procs_to_check_semaphore, cast(i32)thread_count);
 	semaphore_post(&c->procs_to_check_semaphore, cast(i32)thread_count);
 
 
-	gbThread *threads = gb_alloc_array(permanent_allocator(), gbThread, worker_count);
+	Thread *threads = gb_alloc_array(permanent_allocator(), Thread, worker_count);
 	for (isize i = 0; i < worker_count; i++) {
 	for (isize i = 0; i < worker_count; i++) {
-		gb_thread_init(threads+i);
+		thread_init(threads+i);
 	}
 	}
 
 
 	for (isize i = 0; i < worker_count; i++) {
 	for (isize i = 0; i < worker_count; i++) {
-		gb_thread_start(threads+i, thread_proc_body, thread_data+i);
+		thread_start(threads+i, thread_proc_body, thread_data+i);
 	}
 	}
-	gbThread dummy_main_thread = {};
+	Thread dummy_main_thread = {};
 	dummy_main_thread.user_data = thread_data+worker_count;
 	dummy_main_thread.user_data = thread_data+worker_count;
 	thread_proc_body(&dummy_main_thread);
 	thread_proc_body(&dummy_main_thread);
 
 
 	semaphore_wait(&c->procs_to_check_semaphore);
 	semaphore_wait(&c->procs_to_check_semaphore);
 
 
 	for (isize i = 0; i < worker_count; i++) {
 	for (isize i = 0; i < worker_count; i++) {
-		gb_thread_destroy(threads+i);
+		thread_destroy(threads+i);
 	}
 	}
 
 
 	isize global_remaining = c->procs_to_check_queue.count.load(std::memory_order_relaxed);
 	isize global_remaining = c->procs_to_check_queue.count.load(std::memory_order_relaxed);

+ 2 - 128
src/common.cpp

@@ -29,135 +29,9 @@
 #include <string.h>
 #include <string.h>
 #include <atomic> // Because I wanted the C++11 memory order semantics, of which gb.h does not offer (because it was a C89 library)
 #include <atomic> // Because I wanted the C++11 memory order semantics, of which gb.h does not offer (because it was a C89 library)
 
 
+gbAllocator heap_allocator(void);
 
 
-#if defined(GB_SYSTEM_WINDOWS)
-	struct BlockingMutex {
-		SRWLOCK srwlock;
-	};
-	void mutex_init(BlockingMutex *m) {
-	}
-	void mutex_destroy(BlockingMutex *m) {
-	}
-	void mutex_lock(BlockingMutex *m) {
-		AcquireSRWLockExclusive(&m->srwlock);
-	}
-	bool mutex_try_lock(BlockingMutex *m) {
-		return !!TryAcquireSRWLockExclusive(&m->srwlock);
-	}
-	void mutex_unlock(BlockingMutex *m) {
-		ReleaseSRWLockExclusive(&m->srwlock);
-	}
-
-	struct RecursiveMutex {
-		CRITICAL_SECTION win32_critical_section;
-	};
-	void mutex_init(RecursiveMutex *m) {
-		InitializeCriticalSection(&m->win32_critical_section);
-	}
-	void mutex_destroy(RecursiveMutex *m) {
-		DeleteCriticalSection(&m->win32_critical_section);
-	}
-	void mutex_lock(RecursiveMutex *m) {
-		EnterCriticalSection(&m->win32_critical_section);
-	}
-	bool mutex_try_lock(RecursiveMutex *m) {
-		return TryEnterCriticalSection(&m->win32_critical_section) != 0;
-	}
-	void mutex_unlock(RecursiveMutex *m) {
-		LeaveCriticalSection(&m->win32_critical_section);
-	}
-
-	struct Semaphore {
-		void *win32_handle;
-	};
-
-	gb_inline void semaphore_init(Semaphore *s) {
-		s->win32_handle = CreateSemaphoreA(NULL, 0, I32_MAX, NULL);
-	}
-	gb_inline void semaphore_destroy(Semaphore *s) {
-		CloseHandle(s->win32_handle);
-	}
-	gb_inline void semaphore_post(Semaphore *s, i32 count) {
-		ReleaseSemaphore(s->win32_handle, count, NULL);
-	}
-	gb_inline void semaphore_wait(Semaphore *s) {
-		WaitForSingleObjectEx(s->win32_handle, INFINITE, FALSE);
-	}
-
-	gb_inline void semaphore_release(Semaphore *s) {
-		semaphore_post(s, 1);
-	}
-
-#else
-	struct BlockingMutex {
-		pthread_mutex_t pthread_mutex;
-	};
-	void mutex_init(BlockingMutex *m) {
-		pthread_mutex_init(&m->pthread_mutex, nullptr);
-	}
-	void mutex_destroy(BlockingMutex *m) {
-		pthread_mutex_destroy(&m->pthread_mutex);
-	}
-	void mutex_lock(BlockingMutex *m) {
-		pthread_mutex_lock(&m->pthread_mutex);
-	}
-	bool mutex_try_lock(BlockingMutex *m) {
-		return pthread_mutex_trylock(&m->pthread_mutex) == 0;
-	}
-	void mutex_unlock(BlockingMutex *m) {
-		pthread_mutex_unlock(&m->pthread_mutex);
-	}
-
-	struct RecursiveMutex {
-		pthread_mutex_t pthread_mutex;
-		pthread_mutexattr_t pthread_mutexattr;
-	};
-	void mutex_init(RecursiveMutex *m) {
-		pthread_mutexattr_init(&m->pthread_mutexattr);
-		pthread_mutexattr_settype(&m->pthread_mutexattr, PTHREAD_MUTEX_RECURSIVE);
-		pthread_mutex_init(&m->pthread_mutex, &m->pthread_mutexattr);
-	}
-	void mutex_destroy(RecursiveMutex *m) {
-		pthread_mutex_destroy(&m->pthread_mutex);
-	}
-	void mutex_lock(RecursiveMutex *m) {
-		pthread_mutex_lock(&m->pthread_mutex);
-	}
-	bool mutex_try_lock(RecursiveMutex *m) {
-		return pthread_mutex_trylock(&m->pthread_mutex) == 0;
-	}
-	void mutex_unlock(RecursiveMutex *m) {
-		pthread_mutex_unlock(&m->pthread_mutex);
-	}
-
-	#if defined(GB_SYSTEM_OSX)
-		struct Semaphore {
-			semaphore_t osx_handle;
-		};
-
-		gb_inline void semaphore_init   (Semaphore *s)            { semaphore_create(mach_task_self(), &s->osx_handle, SYNC_POLICY_FIFO, 0); }
-		gb_inline void semaphore_destroy(Semaphore *s)            { semaphore_destroy(mach_task_self(), s->osx_handle); }
-		gb_inline void semaphore_post   (Semaphore *s, i32 count) { while (count --> 0) semaphore_signal(s->osx_handle); }
-		gb_inline void semaphore_wait   (Semaphore *s)            { semaphore_wait(s->osx_handle); }
-	#elif defined(GB_SYSTEM_UNIX)
-		struct Semaphore {
-			sem_t unix_handle;
-		};
-
-		gb_inline void semaphore_init   (Semaphore *s)            { sem_init(&s->unix_handle, 0, 0); }
-		gb_inline void semaphore_destroy(Semaphore *s)            { sem_destroy(&s->unix_handle); }
-		gb_inline void semaphore_post   (Semaphore *s, i32 count) { while (count --> 0) sem_post(&s->unix_handle); }
-		gb_inline void semaphore_wait   (Semaphore *s)            { int i; do { i = sem_wait(&s->unix_handle); } while (i == -1 && errno == EINTR); }
-	#else
-	#error
-	#endif
-
-	gb_inline void semaphore_release(Semaphore *s) {
-		semaphore_post(s, 1);
-	}
-#endif
-
-
+#include "threading.cpp"
 
 
 gb_inline void zero_size(void *ptr, isize len) {
 gb_inline void zero_size(void *ptr, isize len) {
 	memset(ptr, 0, len);
 	memset(ptr, 0, len);

File diff suppressed because it is too large
+ 2 - 1042
src/gb/gb.h


+ 2 - 4
src/llvm_backend.hpp

@@ -136,8 +136,6 @@ struct lbModule {
 struct lbGenerator {
 struct lbGenerator {
 	CheckerInfo *info;
 	CheckerInfo *info;
 
 
-	gbMutex mutex;
-
 	Array<String> output_object_paths;
 	Array<String> output_object_paths;
 	Array<String> output_temp_paths;
 	Array<String> output_temp_paths;
 	String   output_base;
 	String   output_base;
@@ -148,8 +146,8 @@ struct lbGenerator {
 
 
 	Map<lbProcedure *> anonymous_proc_lits; // Key: Ast *
 	Map<lbProcedure *> anonymous_proc_lits; // Key: Ast *
 
 
-	gbAtomic32 global_array_index;
-	gbAtomic32 global_generated_index;
+	std::atomic<u32> global_array_index;
+	std::atomic<u32> global_generated_index;
 };
 };
 
 
 
 

+ 1 - 1
src/llvm_backend_const.cpp

@@ -400,7 +400,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 			} else {
 			} else {
 				isize max_len = 7+8+1;
 				isize max_len = 7+8+1;
 				char *str = gb_alloc_array(permanent_allocator(), char, max_len);
 				char *str = gb_alloc_array(permanent_allocator(), char, max_len);
-				u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_array_index, 1);
+				u32 id = m->gen->global_array_index.fetch_add(1);
 				isize len = gb_snprintf(str, max_len, "csba$%x", id);
 				isize len = gb_snprintf(str, max_len, "csba$%x", id);
 
 
 				String name = make_string(cast(u8 *)str, len-1);
 				String name = make_string(cast(u8 *)str, len-1);

+ 3 - 5
src/llvm_backend_general.cpp

@@ -127,8 +127,6 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) {
 	map_init(&gen->modules_through_ctx, permanent_allocator(), gen->info->packages.entries.count*2);
 	map_init(&gen->modules_through_ctx, permanent_allocator(), gen->info->packages.entries.count*2);
 	map_init(&gen->anonymous_proc_lits, heap_allocator(), 1024);
 	map_init(&gen->anonymous_proc_lits, heap_allocator(), 1024);
 
 
-	gb_mutex_init(&gen->mutex);
-
 	if (USE_SEPARATE_MODULES) {
 	if (USE_SEPARATE_MODULES) {
 		for_array(i, gen->info->packages.entries) {
 		for_array(i, gen->info->packages.entries) {
 			AstPackage *pkg = gen->info->packages.entries[i].value;
 			AstPackage *pkg = gen->info->packages.entries[i].value;
@@ -2163,7 +2161,7 @@ LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String const &str) {
 		isize max_len = 7+8+1;
 		isize max_len = 7+8+1;
 		char *name = gb_alloc_array(permanent_allocator(), char, max_len);
 		char *name = gb_alloc_array(permanent_allocator(), char, max_len);
 
 
-		u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_array_index, 1);
+		u32 id = m->gen->global_array_index.fetch_add(1);
 		isize len = gb_snprintf(name, max_len, "csbs$%x", id);
 		isize len = gb_snprintf(name, max_len, "csbs$%x", id);
 		len -= 1;
 		len -= 1;
 
 
@@ -2205,7 +2203,7 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str)
 	{
 	{
 		isize max_len = 7+8+1;
 		isize max_len = 7+8+1;
 		name = gb_alloc_array(permanent_allocator(), char, max_len);
 		name = gb_alloc_array(permanent_allocator(), char, max_len);
-		u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_array_index, 1);
+		u32 id = m->gen->global_array_index.fetch_add(1);
 		isize len = gb_snprintf(name, max_len, "csbs$%x", id);
 		isize len = gb_snprintf(name, max_len, "csbs$%x", id);
 		len -= 1;
 		len -= 1;
 	}
 	}
@@ -2317,7 +2315,7 @@ lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) {
 	isize max_len = 7+8+1;
 	isize max_len = 7+8+1;
 	u8 *str = cast(u8 *)gb_alloc_array(permanent_allocator(), u8, max_len);
 	u8 *str = cast(u8 *)gb_alloc_array(permanent_allocator(), u8, max_len);
 
 
-	u32 id = cast(u32)gb_atomic32_fetch_add(&m->gen->global_generated_index, 1);
+	u32 id = m->gen->global_generated_index.fetch_add(1);
 
 
 	isize len = gb_snprintf(cast(char *)str, max_len, "ggv$%x", id);
 	isize len = gb_snprintf(cast(char *)str, max_len, "ggv$%x", id);
 	String name = make_string(str, len-1);
 	String name = make_string(str, len-1);

+ 13 - 13
src/thread_pool.cpp

@@ -20,7 +20,7 @@ struct ThreadPool {
 
 
 	MPMCQueue<WorkerTask> tasks;
 	MPMCQueue<WorkerTask> tasks;
 
 
-	gbThread *threads;
+	Thread *threads;
 	isize thread_count;
 	isize thread_count;
 
 
 	char worker_prefix[10];
 	char worker_prefix[10];
@@ -32,13 +32,13 @@ void thread_pool_destroy(ThreadPool *pool);
 void thread_pool_start(ThreadPool *pool);
 void thread_pool_start(ThreadPool *pool);
 void thread_pool_join(ThreadPool *pool);
 void thread_pool_join(ThreadPool *pool);
 void thread_pool_add_task(ThreadPool *pool, WorkerTaskProc *proc, void *data);
 void thread_pool_add_task(ThreadPool *pool, WorkerTaskProc *proc, void *data);
-GB_THREAD_PROC(worker_thread_internal);
+THREAD_PROC(worker_thread_internal);
 
 
 void thread_pool_init(ThreadPool *pool, gbAllocator const &a, isize thread_count, char const *worker_prefix) {
 void thread_pool_init(ThreadPool *pool, gbAllocator const &a, isize thread_count, char const *worker_prefix) {
 	pool->allocator = a;
 	pool->allocator = a;
 	mpmc_init(&pool->tasks, a, 1024);
 	mpmc_init(&pool->tasks, a, 1024);
 	pool->thread_count = gb_max(thread_count, 0);
 	pool->thread_count = gb_max(thread_count, 0);
-	pool->threads = gb_alloc_array(a, gbThread, pool->thread_count);
+	pool->threads = gb_alloc_array(a, Thread, pool->thread_count);
 	mutex_init(&pool->mutex);
 	mutex_init(&pool->mutex);
 	semaphore_init(&pool->sem_available);
 	semaphore_init(&pool->sem_available);
 	pool->is_running = true;
 	pool->is_running = true;
@@ -52,15 +52,15 @@ void thread_pool_init(ThreadPool *pool, gbAllocator const &a, isize thread_count
 	}
 	}
 
 
 	for (isize i = 0; i < pool->thread_count; i++) {
 	for (isize i = 0; i < pool->thread_count; i++) {
-		gbThread *t = &pool->threads[i];
-		gb_thread_init(t);
+		Thread *t = &pool->threads[i];
+		thread_init(t);
 		t->user_index = i;
 		t->user_index = i;
 		#if 0
 		#if 0
 		// TODO(bill): Fix this on Linux as it causes a seg-fault
 		// TODO(bill): Fix this on Linux as it causes a seg-fault
 		if (pool->worker_prefix_len > 0) {
 		if (pool->worker_prefix_len > 0) {
 			char worker_name[16] = {};
 			char worker_name[16] = {};
 			gb_snprintf(worker_name, gb_size_of(worker_name), "%.*s%u", pool->worker_prefix_len, pool->worker_prefix, cast(u16)i);
 			gb_snprintf(worker_name, gb_size_of(worker_name), "%.*s%u", pool->worker_prefix_len, pool->worker_prefix, cast(u16)i);
-			gb_thread_set_name(t, worker_name);
+			thread_set_name(t, worker_name);
 		}
 		}
 		#endif
 		#endif
 	}
 	}
@@ -68,8 +68,8 @@ void thread_pool_init(ThreadPool *pool, gbAllocator const &a, isize thread_count
 
 
 void thread_pool_start(ThreadPool *pool) {
 void thread_pool_start(ThreadPool *pool) {
 	for (isize i = 0; i < pool->thread_count; i++) {
 	for (isize i = 0; i < pool->thread_count; i++) {
-		gbThread *t = &pool->threads[i];
-		gb_thread_start(t, worker_thread_internal, pool);
+		Thread *t = &pool->threads[i];
+		thread_start(t, worker_thread_internal, pool);
 	}
 	}
 }
 }
 
 
@@ -78,11 +78,11 @@ void thread_pool_join(ThreadPool *pool) {
 
 
 	semaphore_post(&pool->sem_available, cast(i32)pool->thread_count);
 	semaphore_post(&pool->sem_available, cast(i32)pool->thread_count);
 
 
-	gb_yield();
+	yield();
 
 
 	for (isize i = 0; i < pool->thread_count; i++) {
 	for (isize i = 0; i < pool->thread_count; i++) {
-		gbThread *t = &pool->threads[i];
-		gb_thread_join(t);
+		Thread *t = &pool->threads[i];
+		thread_join(t);
 	}
 	}
 }
 }
 
 
@@ -144,14 +144,14 @@ void thread_pool_wait_to_process(ThreadPool *pool) {
 			mutex_unlock(&pool->mutex);
 			mutex_unlock(&pool->mutex);
 		}
 		}
 
 
-		gb_yield();
+		yield();
 	}
 	}
 
 
 	thread_pool_join(pool);
 	thread_pool_join(pool);
 }
 }
 
 
 
 
-GB_THREAD_PROC(worker_thread_internal) {
+THREAD_PROC(worker_thread_internal) {
 	ThreadPool *pool = cast(ThreadPool *)thread->user_data;
 	ThreadPool *pool = cast(ThreadPool *)thread->user_data;
 	while (pool->is_running) {
 	while (pool->is_running) {
 		semaphore_wait(&pool->sem_available);
 		semaphore_wait(&pool->sem_available);

+ 348 - 0
src/threading.cpp

@@ -0,0 +1,348 @@
+struct BlockingMutex;
+struct RecursiveMutex;
+struct Semaphore;
+struct Thread;
+
+#define THREAD_PROC(name) isize name(struct Thread *thread)
+typedef THREAD_PROC(ThreadProc);
+
+struct Thread {
+#if defined(GB_SYSTEM_WINDOWS)
+	void *        win32_handle;
+#else
+	pthread_t     posix_handle;
+#endif
+
+	ThreadProc * proc;
+	void *         user_data;
+	isize          user_index;
+	isize volatile return_value;
+
+	Semaphore     *semaphore;
+	isize          stack_size;
+	b32 volatile   is_running;
+};
+
+
+void mutex_init    (BlockingMutex *m);
+void mutex_destroy (BlockingMutex *m);
+void mutex_lock    (BlockingMutex *m);
+bool mutex_try_lock(BlockingMutex *m);
+void mutex_unlock  (BlockingMutex *m);
+void mutex_init    (RecursiveMutex *m);
+void mutex_destroy (RecursiveMutex *m);
+void mutex_lock    (RecursiveMutex *m);
+bool mutex_try_lock(RecursiveMutex *m);
+void mutex_unlock  (RecursiveMutex *m);
+
+void semaphore_init   (Semaphore *s);
+void semaphore_destroy(Semaphore *s);
+void semaphore_post   (Semaphore *s, i32 count);
+void semaphore_wait   (Semaphore *s);
+void semaphore_release(Semaphore *s) { semaphore_post(s, 1); }
+
+u32  thread_current_id(void);
+
+void thread_init            (Thread *t);
+void thread_destroy         (Thread *t);
+void thread_start           (Thread *t, ThreadProc *proc, void *data);
+void thread_start_with_stack(Thread *t, ThreadProc *proc, void *data, isize stack_size);
+void thread_join            (Thread *t);
+bool thread_is_running      (Thread const *t);
+void thread_set_name        (Thread *t, char const *name);
+
+void yield_thread(void);
+void yield_process(void);
+
+
+#if defined(GB_SYSTEM_WINDOWS)
+	struct BlockingMutex {
+		SRWLOCK srwlock;
+	};
+	void mutex_init(BlockingMutex *m) {
+	}
+	void mutex_destroy(BlockingMutex *m) {
+	}
+	void mutex_lock(BlockingMutex *m) {
+		AcquireSRWLockExclusive(&m->srwlock);
+	}
+	bool mutex_try_lock(BlockingMutex *m) {
+		return !!TryAcquireSRWLockExclusive(&m->srwlock);
+	}
+	void mutex_unlock(BlockingMutex *m) {
+		ReleaseSRWLockExclusive(&m->srwlock);
+	}
+
+	struct RecursiveMutex {
+		CRITICAL_SECTION win32_critical_section;
+	};
+	void mutex_init(RecursiveMutex *m) {
+		InitializeCriticalSection(&m->win32_critical_section);
+	}
+	void mutex_destroy(RecursiveMutex *m) {
+		DeleteCriticalSection(&m->win32_critical_section);
+	}
+	void mutex_lock(RecursiveMutex *m) {
+		EnterCriticalSection(&m->win32_critical_section);
+	}
+	bool mutex_try_lock(RecursiveMutex *m) {
+		return TryEnterCriticalSection(&m->win32_critical_section) != 0;
+	}
+	void mutex_unlock(RecursiveMutex *m) {
+		LeaveCriticalSection(&m->win32_critical_section);
+	}
+
+	struct Semaphore {
+		void *win32_handle;
+	};
+
+	void semaphore_init(Semaphore *s) {
+		s->win32_handle = CreateSemaphoreA(NULL, 0, I32_MAX, NULL);
+	}
+	void semaphore_destroy(Semaphore *s) {
+		CloseHandle(s->win32_handle);
+	}
+	void semaphore_post(Semaphore *s, i32 count) {
+		ReleaseSemaphore(s->win32_handle, count, NULL);
+	}
+	void semaphore_wait(Semaphore *s) {
+		WaitForSingleObjectEx(s->win32_handle, INFINITE, FALSE);
+	}
+
+#else
+	struct BlockingMutex {
+		pthread_mutex_t pthread_mutex;
+	};
+	void mutex_init(BlockingMutex *m) {
+		pthread_mutex_init(&m->pthread_mutex, nullptr);
+	}
+	void mutex_destroy(BlockingMutex *m) {
+		pthread_mutex_destroy(&m->pthread_mutex);
+	}
+	void mutex_lock(BlockingMutex *m) {
+		pthread_mutex_lock(&m->pthread_mutex);
+	}
+	bool mutex_try_lock(BlockingMutex *m) {
+		return pthread_mutex_trylock(&m->pthread_mutex) == 0;
+	}
+	void mutex_unlock(BlockingMutex *m) {
+		pthread_mutex_unlock(&m->pthread_mutex);
+	}
+
+	struct RecursiveMutex {
+		pthread_mutex_t pthread_mutex;
+		pthread_mutexattr_t pthread_mutexattr;
+	};
+	void mutex_init(RecursiveMutex *m) {
+		pthread_mutexattr_init(&m->pthread_mutexattr);
+		pthread_mutexattr_settype(&m->pthread_mutexattr, PTHREAD_MUTEX_RECURSIVE);
+		pthread_mutex_init(&m->pthread_mutex, &m->pthread_mutexattr);
+	}
+	void mutex_destroy(RecursiveMutex *m) {
+		pthread_mutex_destroy(&m->pthread_mutex);
+	}
+	void mutex_lock(RecursiveMutex *m) {
+		pthread_mutex_lock(&m->pthread_mutex);
+	}
+	bool mutex_try_lock(RecursiveMutex *m) {
+		return pthread_mutex_trylock(&m->pthread_mutex) == 0;
+	}
+	void mutex_unlock(RecursiveMutex *m) {
+		pthread_mutex_unlock(&m->pthread_mutex);
+	}
+
+	#if defined(GB_SYSTEM_OSX)
+		struct Semaphore {
+			semaphore_t osx_handle;
+		};
+
+		void semaphore_init   (Semaphore *s)            { semaphore_create(mach_task_self(), &s->osx_handle, SYNC_POLICY_FIFO, 0); }
+		void semaphore_destroy(Semaphore *s)            { semaphore_destroy(mach_task_self(), s->osx_handle); }
+		void semaphore_post   (Semaphore *s, i32 count) { while (count --> 0) semaphore_signal(s->osx_handle); }
+		void semaphore_wait   (Semaphore *s)            { semaphore_wait(s->osx_handle); }
+	#elif defined(GB_SYSTEM_UNIX)
+		struct Semaphore {
+			sem_t unix_handle;
+		};
+
+		void semaphore_init   (Semaphore *s)            { sem_init(&s->unix_handle, 0, 0); }
+		void semaphore_destroy(Semaphore *s)            { sem_destroy(&s->unix_handle); }
+		void semaphore_post   (Semaphore *s, i32 count) { while (count --> 0) sem_post(&s->unix_handle); }
+		void semaphore_wait   (Semaphore *s)            { int i; do { i = sem_wait(&s->unix_handle); } while (i == -1 && errno == EINTR); }
+	#else
+	#error
+	#endif
+#endif
+
+
+
+
+u32 thread_current_id(void) {
+	u32 thread_id;
+#if defined(GB_SYSTEM_WINDOWS)
+	#if defined(GB_ARCH_32_BIT) && defined(GB_CPU_X86)
+		thread_id = (cast(u32 *)__readfsdword(24))[9];
+	#elif defined(GB_ARCH_64_BIT) && defined(GB_CPU_X86)
+		thread_id = (cast(u32 *)__readgsqword(48))[18];
+	#else
+		thread_id = GetCurrentThreadId();
+	#endif
+
+#elif defined(GB_SYSTEM_OSX) && defined(GB_ARCH_64_BIT)
+	thread_id = pthread_mach_thread_np(pthread_self());
+#elif defined(GB_ARCH_32_BIT) && defined(GB_CPU_X86)
+	__asm__("mov %%gs:0x08,%0" : "=r"(thread_id));
+#elif defined(GB_ARCH_64_BIT) && defined(GB_CPU_X86)
+	__asm__("mov %%fs:0x10,%0" : "=r"(thread_id));
+#else
+	#error Unsupported architecture for thread_current_id()
+#endif
+
+	return thread_id;
+}
+
+
+gb_inline void yield_thread(void) {
+#if defined(GB_SYSTEM_WINDOWS)
+	_mm_pause();
+#elif defined(GB_SYSTEM_OSX)
+	#if defined(GB_CPU_X86)
+	__asm__ volatile ("" : : : "memory");
+	#elif defined(GB_CPU_ARM)
+	__asm__ volatile ("yield" : : : "memory");
+	#endif
+#elif defined(GB_CPU_X86)
+	_mm_pause();
+#else
+#error Unknown architecture
+#endif
+}
+
+gb_inline void yield(void) {
+#if defined(GB_SYSTEM_WINDOWS)
+	YieldProcessor();
+#else
+	sched_yield();
+#endif
+}
+
+
+void thread_init(Thread *t) {
+	gb_zero_item(t);
+#if defined(GB_SYSTEM_WINDOWS)
+	t->win32_handle = INVALID_HANDLE_VALUE;
+#else
+	t->posix_handle = 0;
+#endif
+	t->semaphore = gb_alloc_item(heap_allocator(), Semaphore);
+	semaphore_init(t->semaphore);
+}
+
+void thread_destroy(Thread *t) {
+	if (t->is_running) thread_join(t);
+	semaphore_destroy(t->semaphore);
+	gb_free(heap_allocator(), t->semaphore);
+}
+
+
+void gb__thread_run(Thread *t) {
+	semaphore_release(t->semaphore);
+	t->return_value = t->proc(t);
+}
+
+#if defined(GB_SYSTEM_WINDOWS)
+	DWORD __stdcall internal_thread_proc(void *arg) {
+		Thread *t = cast(Thread *)arg;
+		gb__thread_run(t);
+		t->is_running = false;
+		return 0;
+	}
+#else
+	void *          internal_thread_proc(void *arg) {
+		Thread *t = cast(Thread *)arg;
+		gb__thread_run(t);
+		t->is_running = false;
+		return NULL;
+	}
+#endif
+
+void thread_start(Thread *t, ThreadProc *proc, void *user_data) { thread_start_with_stack(t, proc, user_data, 0); }
+
+void thread_start_with_stack(Thread *t, ThreadProc *proc, void *user_data, isize stack_size) {
+	GB_ASSERT(!t->is_running);
+	GB_ASSERT(proc != NULL);
+	t->proc = proc;
+	t->user_data = user_data;
+	t->stack_size = stack_size;
+	t->is_running = true;
+
+#if defined(GB_SYSTEM_WINDOWS)
+	t->win32_handle = CreateThread(NULL, stack_size, internal_thread_proc, t, 0, NULL);
+	GB_ASSERT_MSG(t->win32_handle != NULL, "CreateThread: GetLastError");
+#else
+	{
+		pthread_attr_t attr;
+		pthread_attr_init(&attr);
+		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+		if (stack_size != 0) {
+			pthread_attr_setstacksize(&attr, stack_size);
+		}
+		pthread_create(&t->posix_handle, &attr, internal_thread_proc, t);
+		pthread_attr_destroy(&attr);
+	}
+#endif
+
+	semaphore_wait(t->semaphore);
+}
+
+void thread_join(Thread *t) {
+	if (!t->is_running) return;
+
+#if defined(GB_SYSTEM_WINDOWS)
+	WaitForSingleObject(t->win32_handle, INFINITE);
+	CloseHandle(t->win32_handle);
+	t->win32_handle = INVALID_HANDLE_VALUE;
+#else
+	pthread_join(t->posix_handle, NULL);
+	t->posix_handle = 0;
+#endif
+	t->is_running = false;
+}
+
+bool thread_is_running(Thread const *t) { return t->is_running != 0; }
+
+void thread_set_name(Thread *t, char const *name) {
+#if defined(GB_COMPILER_MSVC)
+	#pragma pack(push, 8)
+		typedef struct {
+			DWORD       type;
+			char const *name;
+			DWORD       id;
+			DWORD       flags;
+		} gbprivThreadName;
+	#pragma pack(pop)
+		gbprivThreadName tn;
+		tn.type  = 0x1000;
+		tn.name  = name;
+		tn.id    = GetThreadId(cast(HANDLE)t->win32_handle);
+		tn.flags = 0;
+
+		__try {
+			RaiseException(0x406d1388, 0, gb_size_of(tn)/4, cast(ULONG_PTR *)&tn);
+		} __except(1 /*EXCEPTION_EXECUTE_HANDLER*/) {
+		}
+
+#elif defined(GB_SYSTEM_WINDOWS) && !defined(GB_COMPILER_MSVC)
+	// IMPORTANT TODO(bill): Set thread name for GCC/Clang on windows
+	return;
+#elif defined(GB_SYSTEM_OSX)
+	// TODO(bill): Test if this works
+	pthread_setname_np(name);
+#elif defined(GB_SYSTEM_FREEBSD)
+	pthread_set_name_np(t->posix_handle, name);
+#else
+	// TODO(bill): Test if this works
+	pthread_setname_np(t->posix_handle, name);
+#endif
+}
+

Some files were not shown because too many files changed in this diff