2022-08-21 23:34:15 +00:00
|
|
|
/* date = August 13th 2022 1:57 pm */
|
|
|
|
|
|
|
|
#ifndef LUMENARIUM_OSX_THREAD_H
|
|
|
|
#define LUMENARIUM_OSX_THREAD_H
|
|
|
|
|
|
|
|
typedef struct Os_Osx_Thread Os_Osx_Thread;
|
|
|
|
struct Os_Osx_Thread
|
|
|
|
{
|
|
|
|
pthread_t thread;
|
|
|
|
Thread_Proc* proc;
|
|
|
|
u8* user_data;
|
|
|
|
Thread_Result result;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define OSX_THREAD_CAP 8
|
|
|
|
global Os_Osx_Thread osx_threads_[OSX_THREAD_CAP];
|
|
|
|
global u32 osx_threads_len_;
|
|
|
|
|
|
|
|
void*
|
|
|
|
os_thread_proc_wrapper(void* arg)
|
|
|
|
{
|
|
|
|
// Call the actual thread function
|
|
|
|
// This is essentially a blocking call for the rest of this function
|
|
|
|
Os_Osx_Thread* thread_data = (Os_Osx_Thread*)arg;
|
|
|
|
thread_data->result = thread_data->proc(thread_data->user_data);
|
|
|
|
|
|
|
|
// Clean up this threads thread slot so other threads
|
|
|
|
// can use it
|
|
|
|
thread_data->proc = 0;
|
|
|
|
thread_data->user_data = 0;
|
|
|
|
|
|
|
|
pthread_exit(&thread_data->result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread_Handle
|
|
|
|
os_thread_begin(Thread_Proc* proc, u8* user_data)
|
|
|
|
{
|
|
|
|
// Find an unused thread slot
|
|
|
|
Thread_Handle result = { .value = 0 };
|
|
|
|
if (osx_threads_len_ < OSX_THREAD_CAP)
|
|
|
|
{
|
|
|
|
result = (Thread_Handle){ .value = osx_threads_len_++ };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (u32 i = 0; i < OSX_THREAD_CAP; i++)
|
|
|
|
{
|
|
|
|
if (osx_threads_[i].proc == 0)
|
|
|
|
{
|
|
|
|
result.value = i;
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
printf("ERROR: Unable to create thread.\n");
|
|
|
|
invalid_code_path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize Thread Slot
|
|
|
|
Os_Osx_Thread* t = osx_threads_ + result.value;
|
|
|
|
*t = (Os_Osx_Thread){
|
|
|
|
.proc = proc,
|
|
|
|
.user_data = user_data
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create PThread
|
|
|
|
s32 create_error = pthread_create(
|
|
|
|
&t->thread,
|
|
|
|
NULL, // use default attrs
|
|
|
|
(void * _Nullable (* _Nonnull)(void * _Nullable))proc,
|
|
|
|
user_data
|
|
|
|
);
|
|
|
|
|
|
|
|
if (create_error)
|
|
|
|
{
|
|
|
|
switch (create_error) {
|
|
|
|
case EAGAIN: {
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case EINVAL: {
|
|
|
|
} break;
|
|
|
|
|
|
|
|
// case ELEMULTITHREADFORK: {
|
|
|
|
// } break;
|
|
|
|
|
|
|
|
case ENOMEM: {
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
os_thread_end(Thread_Handle thread_handle)
|
|
|
|
{
|
|
|
|
Os_Osx_Thread* t = osx_threads_ + thread_handle.value;
|
2022-08-28 14:55:15 +00:00
|
|
|
//pthread_kill(t->thread, 0);
|
2022-08-21 23:34:15 +00:00
|
|
|
}
|
|
|
|
|
2022-08-28 14:55:15 +00:00
|
|
|
#if defined(PLATFORM_osx)
|
|
|
|
|
2022-08-21 23:34:15 +00:00
|
|
|
u32
|
|
|
|
os_interlocked_increment(volatile u32* value)
|
|
|
|
{
|
|
|
|
assert(*value <= s32_max);
|
|
|
|
u32 result = OSAtomicIncrement32((volatile s32*)value);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
os_interlocked_cmp_exchg(volatile u32* dest, u32 old_value, u32 new_value)
|
|
|
|
{
|
|
|
|
assert(*dest <= s32_max);
|
|
|
|
bool result = OSAtomicCompareAndSwapInt((s32)old_value, (s32)new_value, (volatile s32*)dest);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-08-28 14:55:15 +00:00
|
|
|
#else
|
|
|
|
u32
|
|
|
|
os_interlocked_increment(volatile u32* value)
|
|
|
|
{
|
|
|
|
*value += 1;
|
|
|
|
return *value;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
os_interlocked_cmp_exchg(volatile u32* dest, u32 old_value, u32 new_value)
|
|
|
|
{
|
|
|
|
assert(*dest <= s32_max);
|
|
|
|
if (*dest == old_value) {
|
|
|
|
*dest = new_value;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-08-21 23:34:15 +00:00
|
|
|
#endif //LUMENARIUM_OSX_THREAD_H
|