New upstream version 8.1.0

This commit is contained in:
geos_one
2025-08-10 01:34:16 +02:00
commit c891bb7105
4398 changed files with 838833 additions and 0 deletions

View 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_ */

View 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_ */

View 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_*/

View 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_*/

View 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_ */

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

View 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_*/