2025-08-10 01:34:16 +02:00

131 lines
3.0 KiB
C

#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);
}