New upstream version 8.1.0
This commit is contained in:
129
client_module/source/common/threading/AtomicInt.h
Normal file
129
client_module/source/common/threading/AtomicInt.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#ifndef OPEN_ATOMICINT_H_
|
||||
#define OPEN_ATOMICINT_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
|
||||
|
||||
struct AtomicInt;
|
||||
typedef struct AtomicInt AtomicInt;
|
||||
|
||||
|
||||
static inline void AtomicInt_init(AtomicInt* this, int initialVal);
|
||||
static inline void AtomicInt_uninit(AtomicInt* this);
|
||||
|
||||
static inline int AtomicInt_incAndRead(AtomicInt* this);
|
||||
static inline void AtomicInt_inc(AtomicInt* this);
|
||||
static inline void AtomicInt_dec(AtomicInt* this);
|
||||
static inline int AtomicInt_read(AtomicInt* this);
|
||||
static inline void AtomicInt_set(AtomicInt* this, int newValue);
|
||||
static inline int AtomicInt_compareAndSwap(AtomicInt* this, int oldValue, int newValue);
|
||||
static inline void AtomicInt_max(AtomicInt* this, int minValue);
|
||||
static inline int AtomicInt_decAndTest(AtomicInt* this);
|
||||
|
||||
|
||||
struct AtomicInt
|
||||
{
|
||||
atomic_t kernelAtomic;
|
||||
};
|
||||
|
||||
|
||||
void AtomicInt_init(AtomicInt* this, int initialVal)
|
||||
{
|
||||
AtomicInt initializer =
|
||||
{
|
||||
.kernelAtomic = ATOMIC_INIT(initialVal),
|
||||
};
|
||||
|
||||
*this = initializer;
|
||||
}
|
||||
|
||||
void AtomicInt_uninit(AtomicInt* this)
|
||||
{
|
||||
// nothing to be done here
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase and return the new value
|
||||
*/
|
||||
int AtomicInt_incAndRead(AtomicInt* this)
|
||||
{
|
||||
return atomic_inc_return(&this->kernelAtomic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase by 1.
|
||||
*/
|
||||
void AtomicInt_inc(AtomicInt* this)
|
||||
{
|
||||
atomic_inc(&this->kernelAtomic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease by 1.
|
||||
*/
|
||||
void AtomicInt_dec(AtomicInt* this)
|
||||
{
|
||||
atomic_dec(&this->kernelAtomic);
|
||||
}
|
||||
|
||||
int AtomicInt_read(AtomicInt* this)
|
||||
{
|
||||
return atomic_read(&this->kernelAtomic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to "newValue".
|
||||
*/
|
||||
void AtomicInt_set(AtomicInt* this, int newValue)
|
||||
{
|
||||
atomic_set(&this->kernelAtomic, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether current value matches "oldValue" and only if it matches, update it to "newValue".
|
||||
*
|
||||
* @return the value *before* the swap, regardless if the swap was successful or not
|
||||
*/
|
||||
int AtomicInt_compareAndSwap(AtomicInt* this, int oldValue, int newValue)
|
||||
{
|
||||
return atomic_cmpxchg(&this->kernelAtomic, oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase current value to "minValue" if it is currently smaller, otherwise leave it as it was.
|
||||
*
|
||||
* Note: Use this carefully and only in special scenarios, because it could run endless if the
|
||||
* atomic value is not monotonically increasing.
|
||||
*/
|
||||
void AtomicInt_max(AtomicInt* this, int minValue)
|
||||
{
|
||||
int currentVal = AtomicInt_read(this);
|
||||
for( ; ; )
|
||||
{
|
||||
int swapRes;
|
||||
|
||||
if(currentVal >= minValue)
|
||||
return; // no need to update it at all
|
||||
|
||||
swapRes = AtomicInt_compareAndSwap(this, currentVal, minValue);
|
||||
if (swapRes == currentVal)
|
||||
return;
|
||||
|
||||
currentVal = swapRes; // swap was not successful, update currentVal
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease by one and test if the counter is 0
|
||||
*
|
||||
* @return 1 if the counter is zero, 0 in all other cases
|
||||
*/
|
||||
int AtomicInt_decAndTest(AtomicInt* this)
|
||||
{
|
||||
return atomic_dec_and_test(&this->kernelAtomic);
|
||||
}
|
||||
|
||||
|
||||
#endif /* OPEN_ATOMICINT_H_ */
|
||||
137
client_module/source/common/threading/AtomicInt64.h
Normal file
137
client_module/source/common/threading/AtomicInt64.h
Normal file
@@ -0,0 +1,137 @@
|
||||
#ifndef OPEN_AtomicInt64_H_
|
||||
#define OPEN_AtomicInt64_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
|
||||
#include <asm/atomic.h> // also adds ATOMIC64_INIT if available
|
||||
|
||||
|
||||
#ifndef ATOMIC64_INIT
|
||||
#include <os/atomic64.h>
|
||||
#endif
|
||||
|
||||
|
||||
struct AtomicInt64;
|
||||
typedef struct AtomicInt64 AtomicInt64;
|
||||
|
||||
|
||||
static inline void AtomicInt64_init(AtomicInt64* this, uint64_t initialVal);
|
||||
static inline void AtomicInt64_uninit(AtomicInt64* this);
|
||||
|
||||
static inline uint64_t AtomicInt64_incAndRead(AtomicInt64* this);
|
||||
static inline void AtomicInt64_inc(AtomicInt64* this);
|
||||
static inline void AtomicInt64_dec(AtomicInt64* this);
|
||||
static inline uint64_t AtomicInt64_read(AtomicInt64* this);
|
||||
static inline void AtomicInt64_set(AtomicInt64* this, uint64_t newValue);
|
||||
|
||||
#if 0 // not available in old kernels
|
||||
|
||||
static inline uint64_t AtomicInt64_compareAndSwap(
|
||||
AtomicInt64* this, uint64_t oldValue, uint64_t newValue);
|
||||
static inline void AtomicInt64_max(AtomicInt64* this, uint64_t minValue);
|
||||
|
||||
#endif // if 0 // not available in old kernels
|
||||
|
||||
|
||||
struct AtomicInt64
|
||||
{
|
||||
atomic64_t kernelAtomic64;
|
||||
};
|
||||
|
||||
|
||||
void AtomicInt64_init(AtomicInt64* this, uint64_t initialVal)
|
||||
{
|
||||
#ifdef ATOMIC64_INIT
|
||||
AtomicInt64 initializer =
|
||||
{
|
||||
.kernelAtomic64 = ATOMIC64_INIT(initialVal),
|
||||
};
|
||||
|
||||
*this = initializer;
|
||||
#else
|
||||
atomic_init(&this->kernelAtomic64, initialVal);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomicInt64_uninit(AtomicInt64* this)
|
||||
{
|
||||
// nothing to be done here
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase and return the new value
|
||||
*/
|
||||
uint64_t AtomicInt64_incAndRead(AtomicInt64* this)
|
||||
{
|
||||
return atomic64_inc_return(&this->kernelAtomic64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase by 1.
|
||||
*/
|
||||
void AtomicInt64_inc(AtomicInt64* this)
|
||||
{
|
||||
atomic64_inc(&this->kernelAtomic64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease by 1.
|
||||
*/
|
||||
void AtomicInt64_dec(AtomicInt64* this)
|
||||
{
|
||||
atomic64_dec(&this->kernelAtomic64);
|
||||
}
|
||||
|
||||
uint64_t AtomicInt64_read(AtomicInt64* this)
|
||||
{
|
||||
return atomic64_read(&this->kernelAtomic64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to "newValue".
|
||||
*/
|
||||
void AtomicInt64_set(AtomicInt64* this, uint64_t newValue)
|
||||
{
|
||||
atomic64_set(&this->kernelAtomic64, newValue);
|
||||
}
|
||||
|
||||
#if 0 // not available in old kernel version
|
||||
/**
|
||||
* Test whether current value matches "oldValue" and only if it matches, update it to "newValue".
|
||||
*
|
||||
* @return the value *before* the swap, regardless if the swap was successful or not
|
||||
*/
|
||||
uint64_t AtomicInt64_compareAndSwap(AtomicInt64* this, uint64_t oldValue, uint64_t newValue)
|
||||
{
|
||||
return atomic64_cmpxchg(&this->kernelAtomic64, oldValue, newValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increase current value to "minValue" if it is currently smaller, otherwise leave it as it was.
|
||||
*
|
||||
* Note: Use this carefully and only in special scenarios, because it could run endless if the
|
||||
* atomic value is not monotonically increasing.
|
||||
*/
|
||||
void AtomicInt64_max(AtomicInt64* this, uint64_t minValue)
|
||||
{
|
||||
uint64_t currentVal = AtomicInt64_read(this);
|
||||
for( ; ; )
|
||||
{
|
||||
uint64_t swapRes;
|
||||
|
||||
if(currentVal >= minValue)
|
||||
return; // no need to update it at all
|
||||
|
||||
swapRes = AtomicInt64_compareAndSwap(this, currentVal, minValue);
|
||||
if (swapRes == currentVal)
|
||||
return;
|
||||
|
||||
currentVal = swapRes; // swap was not successful, update currentVal
|
||||
}
|
||||
}
|
||||
|
||||
#endif // if 0 // not available in old kernel version
|
||||
|
||||
|
||||
#endif /* OPEN_AtomicInt64_H_ */
|
||||
185
client_module/source/common/threading/Condition.h
Normal file
185
client_module/source/common/threading/Condition.h
Normal file
@@ -0,0 +1,185 @@
|
||||
#ifndef OPEN_CONDITION_H_
|
||||
#define OPEN_CONDITION_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <common/toolkit/Time.h>
|
||||
#include <common/toolkit/TimeTk.h>
|
||||
#include "Mutex.h"
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
struct Condition;
|
||||
typedef struct Condition Condition;
|
||||
|
||||
enum cond_wait_res;
|
||||
typedef enum cond_wait_res cond_wait_res_t;
|
||||
|
||||
static inline void Condition_init(Condition* this);
|
||||
|
||||
static inline void Condition_wait(Condition* this, Mutex* mutex);
|
||||
static inline cond_wait_res_t Condition_timedwait(Condition* this, Mutex* mutex, int timeoutMS);
|
||||
static inline cond_wait_res_t Condition_timedwaitInterruptible(Condition* this, Mutex* mutex,
|
||||
int timeoutMS);
|
||||
static inline void Condition_broadcast(Condition* this);
|
||||
static inline void Condition_signal(Condition* this);
|
||||
|
||||
|
||||
struct Condition
|
||||
{
|
||||
wait_queue_head_t queue;
|
||||
};
|
||||
|
||||
|
||||
enum cond_wait_res
|
||||
{
|
||||
COND_WAIT_TIMEOUT = 0, // make sure that timeout is always 0
|
||||
COND_WAIT_SUCCESS = 1,
|
||||
COND_WAIT_SIGNAL = -1
|
||||
};
|
||||
|
||||
|
||||
void Condition_init(Condition* this)
|
||||
{
|
||||
init_waitqueue_head(&this->queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Waits uninterruptible.
|
||||
*
|
||||
* Uninterruptible waits are important in cases where we cannot continue until a certain external
|
||||
* condition becomes true. Otherwise we might go up to 100% cpu usage on ctrl+c because schedule()
|
||||
* will keep waking up immediately.
|
||||
*
|
||||
* The problem with uninterruptible waiting is that it will produce hung_task log msgs in the
|
||||
* kernel, so it is not appropriate for long sleeps like a worker waiting for new work.
|
||||
*/
|
||||
void Condition_wait(Condition* this, Mutex* mutex)
|
||||
{
|
||||
wait_queue_t wait;
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&this->queue, &wait);
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
|
||||
Mutex_unlock(mutex);
|
||||
|
||||
schedule();
|
||||
|
||||
Mutex_lock(mutex);
|
||||
|
||||
remove_wait_queue(&this->queue, &wait);
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
}
|
||||
|
||||
static inline enum cond_wait_res Condition_waitKillable(Condition* this, Mutex* mutex)
|
||||
{
|
||||
cond_wait_res_t retVal;
|
||||
wait_queue_t wait;
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&this->queue, &wait);
|
||||
|
||||
set_current_state(TASK_KILLABLE);
|
||||
|
||||
Mutex_unlock(mutex);
|
||||
|
||||
schedule();
|
||||
|
||||
retVal = fatal_signal_pending(current) ? COND_WAIT_SIGNAL : COND_WAIT_SUCCESS;
|
||||
|
||||
Mutex_lock(mutex);
|
||||
|
||||
remove_wait_queue(&this->queue, &wait);
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Waits uninterruptible. Read the _wait() comments.
|
||||
*
|
||||
* @return COND_WAIT_TIMEOUT if timeout occurred
|
||||
*/
|
||||
cond_wait_res_t Condition_timedwait(Condition* this, Mutex* mutex, int timeoutMS)
|
||||
{
|
||||
cond_wait_res_t retVal;
|
||||
long __timeout;
|
||||
|
||||
wait_queue_t wait;
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&this->queue, &wait);
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
|
||||
Mutex_unlock(mutex);
|
||||
|
||||
// timeval to jiffies
|
||||
__timeout = TimeTk_msToJiffiesSchedulable(timeoutMS);
|
||||
|
||||
// wait
|
||||
if( (__timeout = schedule_timeout(__timeout) ) )
|
||||
retVal = COND_WAIT_SUCCESS;
|
||||
else
|
||||
retVal = COND_WAIT_TIMEOUT;
|
||||
|
||||
Mutex_lock(mutex);
|
||||
|
||||
remove_wait_queue(&this->queue, &wait);
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Waits interruptible. Read the _waitInterruptible() comments.
|
||||
*
|
||||
* @return COND_WAIT_TIMEOUT if timeout occurred, COND_WAIT_SIGNAL on pending signal.
|
||||
*/
|
||||
cond_wait_res_t Condition_timedwaitInterruptible(Condition* this, Mutex* mutex, int timeoutMS)
|
||||
{
|
||||
cond_wait_res_t retVal;
|
||||
long __timeout;
|
||||
|
||||
wait_queue_t wait;
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&this->queue, &wait);
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
Mutex_unlock(mutex);
|
||||
|
||||
// timeval to jiffies
|
||||
__timeout = TimeTk_msToJiffiesSchedulable(timeoutMS);
|
||||
|
||||
// wait
|
||||
if( (__timeout = schedule_timeout(__timeout) ) )
|
||||
retVal = signal_pending(current) ? COND_WAIT_SIGNAL : COND_WAIT_SUCCESS;
|
||||
else
|
||||
retVal = COND_WAIT_TIMEOUT;
|
||||
|
||||
Mutex_lock(mutex);
|
||||
|
||||
remove_wait_queue(&this->queue, &wait);
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void Condition_broadcast(Condition* this)
|
||||
{
|
||||
wake_up_all(&this->queue);
|
||||
}
|
||||
|
||||
void Condition_signal(Condition* this)
|
||||
{
|
||||
wake_up(&this->queue);
|
||||
}
|
||||
|
||||
|
||||
#endif /*OPEN_CONDITION_H_*/
|
||||
47
client_module/source/common/threading/Mutex.h
Normal file
47
client_module/source/common/threading/Mutex.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef OPEN_MUTEX_H_
|
||||
#define OPEN_MUTEX_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
|
||||
#include <linux/mutex.h>
|
||||
|
||||
|
||||
struct Mutex;
|
||||
typedef struct Mutex Mutex;
|
||||
|
||||
static inline void Mutex_init(Mutex* this);
|
||||
static inline void Mutex_uninit(Mutex* this);
|
||||
static inline void Mutex_lock(Mutex* this);
|
||||
static inline void Mutex_unlock(Mutex* this);
|
||||
|
||||
|
||||
struct Mutex
|
||||
{
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
|
||||
void Mutex_init(Mutex* this)
|
||||
{
|
||||
mutex_init(&this->mutex);
|
||||
}
|
||||
|
||||
void Mutex_uninit(Mutex* this)
|
||||
{
|
||||
mutex_destroy(&this->mutex); /* optional call according to kernel api description, so we might
|
||||
just drop it if necessary (however, it has some functionality regarding to kernel mutex
|
||||
debugging) */
|
||||
}
|
||||
|
||||
void Mutex_lock(Mutex* this)
|
||||
{
|
||||
mutex_lock(&this->mutex);
|
||||
}
|
||||
|
||||
void Mutex_unlock(Mutex* this)
|
||||
{
|
||||
mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
|
||||
#endif /*OPEN_MUTEX_H_*/
|
||||
64
client_module/source/common/threading/RWLock.h
Normal file
64
client_module/source/common/threading/RWLock.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef OPEN_RWLOCK_H_
|
||||
#define OPEN_RWLOCK_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
|
||||
#include <linux/rwsem.h>
|
||||
|
||||
|
||||
struct RWLock;
|
||||
typedef struct RWLock RWLock;
|
||||
|
||||
|
||||
static inline void RWLock_init(RWLock* this);
|
||||
static inline void RWLock_writeLock(RWLock* this);
|
||||
static inline int RWLock_writeTryLock(RWLock* this);
|
||||
static inline void RWLock_readLock(RWLock* this);
|
||||
static inline void RWLock_writeUnlock(RWLock* this);
|
||||
static inline void RWLock_readUnlock(RWLock* this);
|
||||
|
||||
|
||||
struct RWLock
|
||||
{
|
||||
struct rw_semaphore rwSem;
|
||||
};
|
||||
|
||||
|
||||
void RWLock_init(RWLock* this)
|
||||
{
|
||||
init_rwsem(&this->rwSem);
|
||||
}
|
||||
|
||||
void RWLock_writeLock(RWLock* this)
|
||||
{
|
||||
down_write(&this->rwSem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try locking and return immediately even if lock cannot be aqcuired immediately.
|
||||
*
|
||||
* @return 1 if lock acquired, 0 if contention
|
||||
*/
|
||||
int RWLock_writeTryLock(RWLock* this)
|
||||
{
|
||||
return down_write_trylock(&this->rwSem);
|
||||
}
|
||||
|
||||
void RWLock_readLock(RWLock* this)
|
||||
{
|
||||
down_read(&this->rwSem);
|
||||
}
|
||||
|
||||
void RWLock_writeUnlock(RWLock* this)
|
||||
{
|
||||
up_write(&this->rwSem);
|
||||
}
|
||||
|
||||
void RWLock_readUnlock(RWLock* this)
|
||||
{
|
||||
up_read(&this->rwSem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* OPEN_RWLOCK_H_ */
|
||||
130
client_module/source/common/threading/Thread.c
Normal file
130
client_module/source/common/threading/Thread.c
Normal file
@@ -0,0 +1,130 @@
|
||||
#include <common/Common.h>
|
||||
#include <common/threading/Thread.h>
|
||||
#include <common/toolkit/TimeTk.h>
|
||||
#include <common/threading/Mutex.h>
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
void Thread_init(Thread* this, const char* threadName, ThreadRoutine threadRoutine)
|
||||
{
|
||||
Mutex_init(&this->selfTerminateMutex);
|
||||
Condition_init(&this->shallSelfTerminateCond);
|
||||
Condition_init(&this->isSelfTerminatedChangeCond);
|
||||
|
||||
this->shallSelfTerminate = false;
|
||||
this->isSelfTerminated = true; // start with true so that join(..) works with a nerver-ran thread
|
||||
|
||||
StringTk_strncpyTerminated(this->initialThreadName, threadName, BEEGFS_TASK_COMM_LEN);
|
||||
|
||||
this->threadRoutine = threadRoutine;
|
||||
}
|
||||
|
||||
void Thread_uninit(Thread* this)
|
||||
{
|
||||
Mutex_uninit(&this->selfTerminateMutex);
|
||||
}
|
||||
|
||||
bool Thread_start(Thread* this)
|
||||
{
|
||||
// set thread to not be selfTerminated
|
||||
Mutex_lock(&this->selfTerminateMutex);
|
||||
|
||||
this->isSelfTerminated = false;
|
||||
|
||||
Mutex_unlock(&this->selfTerminateMutex);
|
||||
|
||||
// actually run the thread
|
||||
this->threadData = kthread_run(__Thread_runStatic, this, "%s", this->initialThreadName);
|
||||
|
||||
return !IS_ERR(this->threadData);
|
||||
}
|
||||
|
||||
void Thread_join(Thread* this)
|
||||
{
|
||||
Mutex_lock(&this->selfTerminateMutex);
|
||||
|
||||
while(!this->isSelfTerminated)
|
||||
Condition_wait(&this->isSelfTerminatedChangeCond, &this->selfTerminateMutex);
|
||||
|
||||
Mutex_unlock(&this->selfTerminateMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if thread terminated before timeout expired
|
||||
*/
|
||||
bool Thread_timedjoin(Thread* this, int timeoutMS)
|
||||
{
|
||||
bool isTerminated;
|
||||
|
||||
Mutex_lock(&this->selfTerminateMutex);
|
||||
|
||||
if(!this->isSelfTerminated)
|
||||
Condition_timedwait(&this->isSelfTerminatedChangeCond, &this->selfTerminateMutex, timeoutMS);
|
||||
|
||||
isTerminated = this->isSelfTerminated;
|
||||
|
||||
Mutex_unlock(&this->selfTerminateMutex);
|
||||
|
||||
return isTerminated;
|
||||
}
|
||||
|
||||
void Thread_selfTerminate(Thread* this)
|
||||
{
|
||||
Mutex_lock(&this->selfTerminateMutex);
|
||||
|
||||
this->shallSelfTerminate = true;
|
||||
Condition_broadcast(&this->shallSelfTerminateCond);
|
||||
|
||||
Mutex_unlock(&this->selfTerminateMutex);
|
||||
}
|
||||
|
||||
void Thread_sleep(int timeoutMS)
|
||||
{
|
||||
long timeout = TimeTk_msToJiffiesSchedulable(timeoutMS);
|
||||
|
||||
/* wait INTERRUPTIBLE first to keep load down. callers of this function should ... not. */
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
timeout = schedule_timeout(timeout);
|
||||
if (timeout && !fatal_signal_pending(current))
|
||||
{
|
||||
set_current_state(TASK_KILLABLE);
|
||||
schedule_timeout(timeout);
|
||||
}
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data a this-pointer to the Thread struct
|
||||
*/
|
||||
int __Thread_runStatic(void* data)
|
||||
{
|
||||
Thread* this = (Thread*)data;
|
||||
|
||||
this->threadRoutine(this);
|
||||
|
||||
__Thread_setSelfTerminated(this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get (comm-)name of the given thread argument.
|
||||
*/
|
||||
const char* Thread_getName(Thread* this)
|
||||
{
|
||||
return this->initialThreadName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comm name of the thread calling this function.
|
||||
*
|
||||
* @param outBuf must be at least of length BEEGFS_TASK_COMM_LEN
|
||||
*/
|
||||
void Thread_getCurrentThreadName(char* outBuf)
|
||||
{
|
||||
StringTk_strncpyTerminated(outBuf, current->comm, BEEGFS_TASK_COMM_LEN);
|
||||
}
|
||||
106
client_module/source/common/threading/Thread.h
Normal file
106
client_module/source/common/threading/Thread.h
Normal file
@@ -0,0 +1,106 @@
|
||||
#ifndef OPEN_THREAD_H_
|
||||
#define OPEN_THREAD_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <common/threading/Mutex.h>
|
||||
#include <common/threading/Condition.h>
|
||||
#include <common/toolkit/StringTk.h>
|
||||
#include <common/toolkit/Time.h>
|
||||
|
||||
|
||||
#define BEEGFS_TASK_COMM_LEN 16 /* task command name length */
|
||||
|
||||
|
||||
struct task_struct; // forward declaration
|
||||
|
||||
|
||||
struct Thread;
|
||||
typedef struct Thread Thread;
|
||||
|
||||
|
||||
typedef void (*ThreadRoutine)(Thread* this);
|
||||
|
||||
|
||||
extern void Thread_init(Thread* this, const char* initialThreadName, ThreadRoutine threadRoutine);
|
||||
extern void Thread_uninit(Thread* this);
|
||||
|
||||
extern bool Thread_start(Thread* this);
|
||||
extern void Thread_join(Thread* this);
|
||||
extern bool Thread_timedjoin(Thread* this, int timeoutMS);
|
||||
extern void Thread_selfTerminate(Thread* this);
|
||||
extern void Thread_sleep(int timeoutMS);
|
||||
|
||||
extern int __Thread_runStatic(void* data);
|
||||
|
||||
// inliners
|
||||
static inline bool _Thread_waitForSelfTerminateOrder(Thread* this, int timeoutMS);
|
||||
|
||||
// getters & setters
|
||||
extern const char* Thread_getName(Thread* this);
|
||||
extern void Thread_getCurrentThreadName(char* outBuf);
|
||||
static inline bool Thread_getSelfTerminate(Thread* this);
|
||||
static inline void __Thread_setSelfTerminated(Thread* this);
|
||||
|
||||
|
||||
struct Thread
|
||||
{
|
||||
bool shallSelfTerminate;
|
||||
Mutex selfTerminateMutex;
|
||||
Condition shallSelfTerminateCond;
|
||||
|
||||
bool isSelfTerminated;
|
||||
Condition isSelfTerminatedChangeCond;
|
||||
|
||||
char initialThreadName[BEEGFS_TASK_COMM_LEN];
|
||||
|
||||
struct task_struct* threadData;
|
||||
|
||||
ThreadRoutine threadRoutine;
|
||||
};
|
||||
|
||||
|
||||
bool _Thread_waitForSelfTerminateOrder(Thread* this, int timeoutMS)
|
||||
{
|
||||
bool shallSelfTerminate;
|
||||
|
||||
Mutex_lock(&this->selfTerminateMutex);
|
||||
|
||||
if(!this->shallSelfTerminate)
|
||||
{
|
||||
Condition_timedwaitInterruptible(
|
||||
&this->shallSelfTerminateCond, &this->selfTerminateMutex, timeoutMS);
|
||||
}
|
||||
|
||||
shallSelfTerminate = this->shallSelfTerminate;
|
||||
|
||||
Mutex_unlock(&this->selfTerminateMutex);
|
||||
|
||||
return shallSelfTerminate;
|
||||
}
|
||||
|
||||
|
||||
bool Thread_getSelfTerminate(Thread* this)
|
||||
{
|
||||
bool shallSelfTerminate;
|
||||
|
||||
Mutex_lock(&this->selfTerminateMutex);
|
||||
|
||||
shallSelfTerminate = this->shallSelfTerminate;
|
||||
|
||||
Mutex_unlock(&this->selfTerminateMutex);
|
||||
|
||||
return shallSelfTerminate;
|
||||
}
|
||||
|
||||
void __Thread_setSelfTerminated(Thread* this)
|
||||
{
|
||||
Mutex_lock(&this->selfTerminateMutex);
|
||||
|
||||
this->isSelfTerminated = true;
|
||||
|
||||
Condition_broadcast(&this->isSelfTerminatedChangeCond);
|
||||
|
||||
Mutex_unlock(&this->selfTerminateMutex);
|
||||
}
|
||||
|
||||
#endif /*OPEN_THREAD_H_*/
|
||||
Reference in New Issue
Block a user