tlang-c/libtlang/src/threading.c

166 lines
4.0 KiB
C

#include "tlang.h"
#if defined(USE_THREADS)
bool thread_init=false;
#if defined(GEKKO)
#include <ogc/mutex.h>
#include <ogc/lwp.h>
#else
#include <pthread.h>
#endif
tmutex_t global_mutex;
tmutex_t Mutex_Create()
{
#if defined(GEKKO)
mutex_t mutex=LWP_MUTEX_NULL;
LWP_MutexInit(&mutex,true);
return (tmutex_t)mutex;
#else
pthread_mutex_t* mtx= (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
memset(mtx,0,sizeof(pthread_mutex_t));
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if defined(PTHREAD_MUTEX_RECURSIVE_NP)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
#else
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
#endif
pthread_mutex_init(mtx,&attr);
return (tmutex_t)mtx;
#endif
}
void Mutex_Free(tmutex_t mutex)
{
#if defined(GEKKO)
LWP_MutexDestroy((mutex_t)mutex);
#else
pthread_mutex_destroy((pthread_mutex_t*)mutex);
free(mutex);
#endif
}
int64_t Mutex_Lock(tmutex_t mutex)
{
#if defined(GEKKO)
return LWP_MutexLock((mutex_t)mutex);
#else
return pthread_mutex_lock((pthread_mutex_t*)mutex);
#endif
}
int64_t Mutex_Unlock(tmutex_t mutex)
{
#if defined(GEKKO)
LWP_MutexUnlock((mutex_t)mutex);
#else
return pthread_mutex_unlock((pthread_mutex_t*)mutex);
#endif
}
void Global_Mutex_Lock()
{
if(thread_init)
Mutex_Lock(global_mutex);
}
void Global_Mutex_Unlock()
{
if(thread_init)
Mutex_Unlock(global_mutex);
}
void Threading_Thread_Create(void*(*entry)(void*),void* arg)
{
#if defined(GEKKO)
lwp_t lwp=LWP_THREAD_NULL;
LWP_CreateThread(&lwp,entry,arg,NULL,0,64);
#else
pthread_t thrd;
pthread_create(&thrd,NULL,entry,arg);
pthread_detach(thrd);
#endif
}
typedef struct {
tobject_t* obj;
runtime_t* rt;
} __thread_arg_ctx;
static void* __create_thread_thread_func(void* data)
{
__thread_arg_ctx* ctx = (__thread_arg_ctx*)data;
list_tobject_t objs;
list_create(ctx->rt,&objs,0);
tobject_t* obj=tobject_call(ctx->rt->globals,ctx->obj,&objs);
tobject_freeifzero(obj);
tobject_rmref(ctx->obj);
free(data);
}
void __create_mutex_destroy(tobject_t* obj)
{
Mutex_Free((tmutex_t)obj->ptr_data);
}
tobject_t* __create_mutex_lock_external_method(runtime_t* rt,void* ptr,list_tobject_t* args)
{
Mutex_Lock((tmutex_t)ptr);
return tobject_basic(rt,tundef);
}
tobject_t* __create_mutex_unlock_external_method(runtime_t* rt,void* ptr,list_tobject_t* args)
{
Mutex_Unlock((tmutex_t)ptr);
return tobject_basic(rt,tundef);
}
tobject_t* __create_mutex_external_method(runtime_t* rt,void* ptr,list_tobject_t* args)
{
tobject_t* o = tobject_create(rt);
o->type = tdict;
o->data.dict = dict_create();
tmutex_t* mutex=Mutex_Create();
o->ptr_data = mutex;
runtime_create_method_on_dict(o->data.dict,"lock",rt,mutex,__create_mutex_lock_external_method,NULL);
runtime_create_method_on_dict(o->data.dict,"unlock",rt,mutex,__create_mutex_unlock_external_method,NULL);
o->free = __create_mutex_destroy;
return o;
}
tobject_t* __create_thread_external_method(runtime_t* rt,void* ptr,list_tobject_t* args)
{
if(args->length > 0)
{
tobject_t* data=args->items[0];
if(data->type == tinternalmethod || data->type == texternalmethod)
{
data->count++;
__thread_arg_ctx* ctx = (__thread_arg_ctx*)malloc(sizeof(__thread_arg_ctx));
ctx->obj = data;
ctx->rt = rt;
Threading_Thread_Create(__create_thread_thread_func,(void*)ctx);
}
}
return tobject_basic(rt,tundef);
}
void runtime_register_threads(runtime_t* rt,dict_t* create)
{
if(!thread_init)
{
global_mutex = Mutex_Create();
thread_init = true;
}
runtime_create_method_on_dict(create,"thread",rt,NULL,__create_thread_external_method,NULL);
runtime_create_method_on_dict(create,"mutex",rt,NULL,__create_mutex_external_method,NULL);
}
#else
void Global_Mutex_Lock()
{
}
void Global_Mutex_Unlock()
{
}
#endif