summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/console.c4
-rw-r--r--src/common/core.c5
-rw-r--r--src/common/spinlock.h72
-rw-r--r--src/common/thread.c27
-rw-r--r--src/common/thread.h204
-rw-r--r--src/plugins/HPMHooking.c1
-rw-r--r--src/test/test_spinlock.c4
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);