CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
Threading

Thread creation, lifecycle control and per-thread CPU statistics. More...

Detailed Description

Thread creation, lifecycle control and per-thread CPU statistics.

Why a threading layer of its own
CMSDK predates a usable std::thread and, more importantly, needs more than thread creation: every thread in a Psyclone node is registered centrally so diagnostic tools can enumerate them, sample their CPU load and pause/interrupt/terminate them by id. Writing this against pthreads on Linux/macOS and the Win32 thread API on Windows directly would mean two divergent code paths in every caller; instead ThreadManager exposes one portable, id-based API (backed by the utils:: wrappers - utils::CreateThread, utils::TerminateThread, CRITICAL_SECTION- or pthread_mutex-backed cmlabs::utils::Mutex, and semaphores) and keeps all bookkeeping in one contiguous ThreadStats block that is cheap to snapshot.
Pool threads vs owned threads
Higher Psyclone layers use threads in two ways: a continuous crank owns a dedicated thread for its whole lifetime, while a one-shot crank borrows a pool thread for each trigger firing - so the same function may run on several threads at once. ThreadManager itself only provides the raw threads and statistics; pooling/queueing policy lives in the higher-level scheduling code.
Starting a worker and guarding shared state
static utils::Mutex statsMutex; // protects sharedCounter
static uint64 sharedCounter = 0;
THREAD_RET THREAD_FUNCTION_CALL Worker(void* arg) {
ThreadManager::AddLocalThreadStats(); // self-report on pthreads
while (running) {
// ... do a unit of work ...
if (statsMutex.enter(1000, __FUNCTION__)) { // 1 s timeout
sharedCounter++; // critical section
statsMutex.leave();
}
}
return 0;
}
uint32 tid;
ThreadManager::CreateThread((THREAD_FUNCTION)Worker, NULL, tid);
// ... later ...
ThreadStats st = ThreadManager::GetThreadStats(tid); // CPU usage etc.
ThreadManager::TerminateThread(tid); // last resort only
#define THREAD_RET
Definition Utils.h:127
#define THREAD_FUNCTION_CALL
Definition Utils.h:129
THREAD_RET(* THREAD_FUNCTION)(void *)
Definition Utils.h:128
Warning
Concurrency rules: any state reachable from more than one thread must be independently synchronised (utils::Mutex / utils::Semaphore or a shared-memory named mutex); one-shot crank functions in particular must assume they run concurrently with themselves. TerminateThread() kills a thread without unwinding - locks it holds stay held and resources leak - so prefer cooperative shutdown flags and use termination only for hung threads.
Note
On pthreads there is no portable way to read another thread's CPU usage, so worker threads should call AddLocalThreadStats() once at startup (THREAD_STATS_ADHOC policy); on Windows the built-in monitoring thread samples every registered thread centrally.
See also
ThreadManager, ThreadStats, utils::Mutex, utils::Semaphore, Shared-Memory Subsystem

Classes

struct  cmlabs::ThreadStats
 Bookkeeping record for a single managed thread. More...
struct  cmlabs::ThreadDataHeader
 Header at the start of the ThreadManager's contiguous storage block. More...
class  cmlabs::Runnable
 Minimal cooperative-shutdown base class for objects that run a worker thread. More...
class  cmlabs::ThreadManager
 Singleton registry that creates, controls and profiles all CMSDK threads. More...

Macros

#define GETTHREADSTATS(data, id)
 Compute the address of thread slot id inside storage block data.

Functions

static THREAD_RET THREAD_FUNCTION_CALL cmlabs::ThreadMonitoring (void *arg)
 Entry function of the monitoring thread; delegates to ThreadManager::threadMonitoring().

Macro Definition Documentation

◆ GETTHREADSTATS

#define GETTHREADSTATS ( data,
id )
Value:
(ThreadStats*)(data + sizeof(ThreadDataHeader) + ((ThreadDataHeader*)data)->bitFieldSize + id*sizeof(ThreadStats))

Compute the address of thread slot id inside storage block data.

Resolves the block layout header + bitfield + stats[] described in ThreadDataHeader. Must only be used while holding the manager mutex, since a concurrent resizeThreadStorage() may free the block.

Definition at line 190 of file ThreadManager.h.

Referenced by cmlabs::ThreadManager::addLocalThreadStats(), cmlabs::ThreadManager::continueThread(), cmlabs::ThreadManager::createThread(), cmlabs::ThreadManager::getAllThreadStats(), cmlabs::ThreadManager::getLocalThreadID(), cmlabs::ThreadManager::getThreadStats(), cmlabs::ThreadManager::interruptThread(), cmlabs::ThreadManager::isThreadRunning(), cmlabs::ThreadManager::pauseThread(), cmlabs::ThreadManager::resizeThreadStorage(), cmlabs::ThreadManager::shutdown(), cmlabs::ThreadManager::terminateThread(), and cmlabs::ThreadManager::threadMonitoring().

Function Documentation

◆ ThreadMonitoring()

THREAD_RET THREAD_FUNCTION_CALL cmlabs::ThreadMonitoring ( void * arg)
static

Entry function of the monitoring thread; delegates to ThreadManager::threadMonitoring().

On POSIX (non-Darwin) it first unblocks SIGQUIT so the thread can be cancelled; on Windows no signal setup is needed.

Definition at line 528 of file ThreadManager.cpp.

References cmlabs::ThreadManager::Singleton, THREAD_FUNCTION_CALL, THREAD_RET, and thread_ret_val.

Referenced by cmlabs::ThreadManager::init().