From 257b9e11ab6cf503d0b9582eb855ea0b50ec8877 Mon Sep 17 00:00:00 2001 From: hemagx Date: Tue, 1 Mar 2016 07:48:59 +0200 Subject: Interface thread.c --- src/common/console.c | 4 +- src/common/core.c | 5 +- src/common/spinlock.h | 72 +++++++++-------- src/common/thread.c | 27 ++++++- src/common/thread.h | 204 +++++++++++++++++++++++++---------------------- src/plugins/HPMHooking.c | 1 + src/test/test_spinlock.c | 4 +- 7 files changed, 176 insertions(+), 141 deletions(-) diff --git a/src/common/console.c b/src/common/console.c index bca9f36aa..4a12ba24b 100644 --- a/src/common/console.c +++ b/src/common/console.c @@ -499,7 +499,7 @@ void console_parse_final(void) { mutex->cond_signal(console->input->ptcond); /* wait for thread to close */ - rathread_wait(console->input->pthread, NULL); + thread->wait(console->input->pthread, NULL); mutex->cond_destroy(console->input->ptcond); mutex->destroy(console->input->ptmutex); @@ -515,7 +515,7 @@ void console_parse_init(void) { console->input->ptmutex = mutex->create(); console->input->ptcond = mutex->cond_create(); - if( (console->input->pthread = rathread_create(console->input->pthread_main, NULL)) == NULL ){ + if( (console->input->pthread = thread->create(console->input->pthread_main, NULL)) == NULL ){ ShowFatalError("console_parse_init: failed to spawn console_parse thread.\n"); exit(EXIT_FAILURE); } diff --git a/src/common/core.c b/src/common/core.c index f5860e992..508a728f0 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -266,6 +266,7 @@ void core_defaults(void) { socket_defaults(); rnd_defaults(); md5_defaults(); + thread_defaults(); #endif } /** @@ -505,7 +506,7 @@ int main (int argc, char **argv) { set_server_type(); Sql_Init(); - rathread_init(); + thread->init(); DB->init(); signals_init(); @@ -541,7 +542,7 @@ int main (int argc, char **argv) { timer->final(); sockt->final(); DB->final(); - rathread_final(); + thread->final(); ers_final(); rnd->final(); #endif diff --git a/src/common/spinlock.h b/src/common/spinlock.h index 4d9c4c668..f1df6ef34 100644 --- a/src/common/spinlock.h +++ b/src/common/spinlock.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) rAthena Project (www.rathena.org) * * Hercules is free software: you can redistribute it and/or modify @@ -54,57 +54,61 @@ typedef struct SPIN_LOCK{ #ifdef HERCULES_CORE -static forceinline void InitializeSpinLock(SPIN_LOCK *lck){ - lck->lock = 0; - lck->nest = 0; - lck->sync_lock = 0; +static forceinline void InitializeSpinLock(SPIN_LOCK *lck) +{ + lck->lock = 0; + lck->nest = 0; + lck->sync_lock = 0; } -static forceinline void FinalizeSpinLock(SPIN_LOCK *lck){ +static forceinline void FinalizeSpinLock(SPIN_LOCK *lck) +{ return; } -#define getsynclock(l) do { if(InterlockedCompareExchange((l), 1, 0) == 0) break; rathread_yield(); } while(/*always*/1) +#define getsynclock(l) do { if(InterlockedCompareExchange((l), 1, 0) == 0) break; thread->yield(); } while(/*always*/1) #define dropsynclock(l) do { InterlockedExchange((l), 0); } while(0) -static forceinline void EnterSpinLock(SPIN_LOCK *lck){ - int tid = rathread_get_tid(); +static forceinline void EnterSpinLock(SPIN_LOCK *lck) +{ + int tid = thread->get_tid(); - // Get Sync Lock && Check if the requester thread already owns the lock. - // if it owns, increase nesting level - getsynclock(&lck->sync_lock); - if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){ - InterlockedIncrement(&lck->nest); - dropsynclock(&lck->sync_lock); - return; // Got Lock - } - // drop sync lock + // Get Sync Lock && Check if the requester thread already owns the lock. + // if it owns, increase nesting level + getsynclock(&lck->sync_lock); + if (InterlockedCompareExchange(&lck->lock, tid, tid) == tid) { + InterlockedIncrement(&lck->nest); dropsynclock(&lck->sync_lock); - - // Spin until we've got it ! - while(1){ - if(InterlockedCompareExchange(&lck->lock, tid, 0) == 0){ - InterlockedIncrement(&lck->nest); - return; // Got Lock - } - rathread_yield(); // Force ctxswitch to another thread. + return; // Got Lock + } + // drop sync lock + dropsynclock(&lck->sync_lock); + + // Spin until we've got it ! + while (true) { + if (InterlockedCompareExchange(&lck->lock, tid, 0) == 0) { + InterlockedIncrement(&lck->nest); + return; // Got Lock } + thread->yield(); // Force ctxswitch to another thread. + } } -static forceinline void LeaveSpinLock(SPIN_LOCK *lck){ - int tid = rathread_get_tid(); +static forceinline void LeaveSpinLock(SPIN_LOCK *lck) +{ + int tid = thread->get_tid(); - getsynclock(&lck->sync_lock); + getsynclock(&lck->sync_lock); - if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){ // this thread owns the lock. - if(InterlockedDecrement(&lck->nest) == 0) - InterlockedExchange(&lck->lock, 0); // Unlock! - } + if (InterlockedCompareExchange(&lck->lock, tid, tid) == tid) { // this thread owns the lock. + if (InterlockedDecrement(&lck->nest) == 0) + InterlockedExchange(&lck->lock, 0); // Unlock! + } - dropsynclock(&lck->sync_lock); + dropsynclock(&lck->sync_lock); } #endif // HERCULES_CORE diff --git a/src/common/thread.c b/src/common/thread.c index b724344e6..7bcffaf86 100644 --- a/src/common/thread.c +++ b/src/common/thread.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) rAthena Project (www.rathena.org) * * Hercules is free software: you can redistribute it and/or modify @@ -68,6 +68,9 @@ struct rAthread { __thread int g_rathread_ID = -1; #endif +struct thread_interface thread_s; +struct thread_interface *thread; + /// /// Subystem Code /// @@ -100,7 +103,7 @@ void rathread_final(void) { for(i = 1; i < RA_THREADS_MAX; i++){ if(l_threads[i].proc != NULL){ ShowWarning("rAthread_final: unterminated Thread (tid %u entryPoint %p) - forcing to terminate (kill)\n", i, l_threads[i].proc); - rathread_destroy(&l_threads[i]); + thread->destroy(&l_threads[i]); } } @@ -159,7 +162,7 @@ static void *raThreadMainRedirector( void *p ){ /// API Level /// rAthread *rathread_create(rAthreadProc entryPoint, void *param) { - return rathread_createEx( entryPoint, param, (1<<23) /*8MB*/, RAT_PRIO_NORMAL ); + return thread->createEx(entryPoint, param, (1<<23) /*8MB*/, RAT_PRIO_NORMAL); }//end: rathread_create() rAthread *rathread_createEx(rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio) { @@ -205,7 +208,7 @@ rAthread *rathread_createEx(rAthreadProc entryPoint, void *param, size_t szStack pthread_attr_destroy(&attr); #endif - rathread_prio_set( handle, prio ); + thread->prio_set( handle, prio ); return handle; }//end: rathread_createEx @@ -301,3 +304,19 @@ void rathread_yield(void) { sched_yield(); #endif }//end: rathread_yield() + +void thread_defaults(void) +{ + thread = &thread_s; + thread->create = rathread_create; + thread->createEx = rathread_createEx; + thread->destroy = rathread_destroy; + thread->self = rathread_self; + thread->get_tid = rathread_get_tid; + thread->wait = rathread_wait; + thread->prio_set = rathread_prio_set; + thread->prio_get = rathread_prio_get; + thread->yield = rathread_yield; + thread->init = rathread_init; + thread->final = rathread_final; +} diff --git a/src/common/thread.h b/src/common/thread.h index 261735306..be34ea830 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) rAthena Project (www.rathena.org) * * Hercules is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ #ifndef COMMON_THREAD_H #define COMMON_THREAD_H -#include "common/cbasetypes.h" +#include "common/hercules.h" typedef struct rAthread rAthread; typedef void* (*rAthreadProc)(void*); @@ -32,103 +32,113 @@ typedef enum RATHREAD_PRIO { RAT_PRIO_HIGH } RATHREAD_PRIO; +struct thread_interface { + /** + * Creates a new Thread. + * + * @param entyPoint Thread's entry point. + * @param param General purpose parameter, would be given as + * parameter to the thread's entry point. + * + * @return The created thread object. + * @retval NULL in vase of failure. + */ + rAthread *(*create) (rAthreadProc entryPoint, void *param); + + /** + * Creates a new Thread (with more creation options). + * + * @param entyPoint Thread's entry point. + * @param param General purpose parameter, would be given as + * parameter to the thread's entry point. + * @param szStack Stack Size in bytes. + * @param prio Priority of the Thread in the OS scheduler. + * + * @return The created thread object. + * @retval NULL in case of failure. + */ + rAthread *(*createEx) (rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio); + + /** + * Destroys the given Thread immediately. + * + * @remark + * The Handle gets invalid after call! don't use it afterwards. + * + * @param handle The thread to destroy. + */ + void (*destroy) (rAthread *handle); + + /** + * Returns the thread handle of the thread calling this function. + * + * @remark + * This won't work in the program's main thread. + * + * @warning + * The underlying implementation might not perform very well, cache + * the value received! + * + * @return the thread handle. + * @retval NULL in case of failure. + */ + rAthread *(*self) (void); + + /** + * Returns own thread id (TID). + * + * @remark + * This is an unique identifier for the calling thread, and depends + * on platform/ compiler, and may not be the systems Thread ID! + * + * @return the thread ID. + * @retval -1 in case of failure. + */ + int (*get_tid) (void); + + /** + * Waits for the given thread to terminate. + * + * @param[in] handle The thread to wait (join) for. + * @param[out] out_Exitcode Pointer to return the exit code of the + * given thread after termination (optional). + * + * @retval true if the given thread has been terminated. + */ + bool (*wait) (rAthread *handle, void **out_exitCode); + + /** + * Sets the given priority in the OS scheduler. + * + * @param handle The thread to set the priority for. + * @param prio The priority to set (@see enum RATHREAD_PRIO). + */ + void (*prio_set) (rAthread *handle, RATHREAD_PRIO prio); + + /** + * Gets the current priority of the given thread. + * + * @param handle The thread to get the priority for. + */ + RATHREAD_PRIO (*prio_get) (rAthread *handle); + + /** + * Tells the OS scheduler to yield the execution of the calling thread. + * + * @remark + * This will not "pause" the thread, it just allows the OS to spend + * the remaining time of the slice to another thread. + */ + void (*yield) (void); + + void (*init) (void); + void (*final) (void); +}; #ifdef HERCULES_CORE -/** - * Creates a new Thread - * - * @param entyPoint - entryProc, - * @param param - general purpose parameter, would be given as parameter to the thread's entry point. - * - * @return not NULL if success - */ -rAthread *rathread_create(rAthreadProc entryPoint, void *param); - - -/** - * Creates a new Thread (with more creation options) - * - * @param entyPoint - entryProc, - * @param param - general purpose parameter, would be given as parameter to the thread's entry point - * @param szStack - stack Size in bytes - * @param prio - Priority of the Thread @ OS Scheduler.. - * - * @return not NULL if success - */ -rAthread *rathread_createEx(rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio); - - -/** - * Destroys the given Thread immediately - * - * @note The Handle gets invalid after call! don't use it afterwards. - * - * @param handle - thread to destroy. - */ -void rathread_destroy(rAthread *handle); - - -/** - * Returns the thread handle of the thread calling this function - * - * @note this wont work @ programs main thread - * @note the underlying implementation might not perform very well, cache the value received! - * - * @return not NULL if success - */ -rAthread *rathread_self(void); - - -/** - * Returns own thread id (TID) - * - * @note this is an unique identifier for the calling thread, and - * depends on platform/ compiler, and may not be the systems Thread ID! - * - * @return -1 when fails, otherwise >= 0 - */ -int rathread_get_tid(void); - - -/** - * Waits for the given thread to terminate - * - * @param handle - thread to wait (join) for - * @param out_Exitcode - [OPTIONAL] - if given => Exitcode (value) of the given thread - if it's terminated - * - * @return true - if the given thread has been terminated. - */ -bool rathread_wait(rAthread *handle, void **out_exitCode); - - -/** - * Sets the given PRIORITY @ OS Task Scheduler - * - * @param handle - thread to set prio for - * @param rio - the priority (RAT_PRIO_LOW ... ) - */ -void rathread_prio_set(rAthread *handle, RATHREAD_PRIO prio); - - -/** - * Gets the current Prio of the given thread - * - * @param handle - the thread to get the prio for. - */ -RATHREAD_PRIO rathread_prio_get(rAthread *handle); - - -/** - * Tells the OS scheduler to yield the execution of the calling thread - * - * @note: this will not "pause" the thread, - * it just allows the OS to spend the remaining time - * of the slice to another thread. - */ -void rathread_yield(void); - -void rathread_init(void); -void rathread_final(void); +void thread_defaults(void); #endif // HERCULES_CORE +HPShared struct thread_interface *thread; + #endif /* COMMON_THREAD_H */ diff --git a/src/plugins/HPMHooking.c b/src/plugins/HPMHooking.c index 1c0cec51d..97a36f4ce 100644 --- a/src/plugins/HPMHooking.c +++ b/src/plugins/HPMHooking.c @@ -120,6 +120,7 @@ #include "common/sql.h" #include "common/strlib.h" #include "common/sysinfo.h" +#include "common/thread.h" #include "common/timer.h" #include "common/utils.h" diff --git a/src/test/test_spinlock.c b/src/test/test_spinlock.c index 6ffc4eafc..a19887f8d 100644 --- a/src/test/test_spinlock.c +++ b/src/test/test_spinlock.c @@ -78,13 +78,13 @@ int do_init(int argc, char **argv){ InitializeSpinLock(&lock); for(i =0; i < THRC; i++){ - t[i] = rathread_createEx( worker, NULL, 1024*512, RAT_PRIO_NORMAL); + t[i] = thread->createEx(worker, NULL, 1024*512, RAT_PRIO_NORMAL); } while(1){ if(InterlockedCompareExchange(&done_threads, THRC, THRC) == THRC) break; - rathread_yield(); + thread->yield(); } FinalizeSpinLock(&lock); -- cgit v1.2.3-60-g2f50