83 SFthread(
const unsigned long PeriodTime,
const std::function<
bool(
double,
double,
double)>& FuncObject,
const int CPUno)
84 : SyncMutex(PTHREAD_MUTEX_INITIALIZER),
85 SyncCond(PTHREAD_COND_INITIALIZER),
95 MinMemo(PeriodTime*1e-9)
99 if constexpr(SFA == SFalgorithm::INSERT_ZEROSLEEP){
102 EventLog(
"WITHOUT_ZEROSLEEP MODE.");
104 SetKernelParameters();
105 pthread_mutex_init(&SyncMutex,
nullptr);
106 pthread_cond_init(&SyncCond,
nullptr);
107 pthread_create(&ThreadID, NULL, (
void*(*)(
void*))RealTimeThread,
this);
115 SFthread(
const unsigned long PeriodTime,
const int CPUno)
116 : SyncMutex(PTHREAD_MUTEX_INITIALIZER),
117 SyncCond(PTHREAD_COND_INITIALIZER),
127 MinMemo(PeriodTime*1e-9)
131 if constexpr(SFA == SFalgorithm::INSERT_ZEROSLEEP){
134 EventLog(
"WITHOUT_ZEROSLEEP MODE.");
136 SetKernelParameters();
137 pthread_mutex_init(&SyncMutex,
nullptr);
138 pthread_cond_init(&SyncCond,
nullptr);
139 pthread_create(&ThreadID, NULL, (
void*(*)(
void*))RealTimeThread,
this);
147 : SyncMutex(r.SyncMutex),
148 SyncCond(r.SyncCond),
149 StateFlag(r.StateFlag),
153 ActPeriodicTime(r.ActPeriodicTime),
154 ComputationTime(r.ComputationTime),
155 ThreadID(r.ThreadID),
156 ThreadParam(r.ThreadParam),
166 pthread_mutex_lock(&SyncMutex);
168 pthread_cond_broadcast(&SyncCond);
169 pthread_mutex_unlock(&SyncMutex);
170 pthread_join(ThreadID,
nullptr);
171 ResetKernelParameters();
178 FuncObj = FuncObject;
183 pthread_mutex_lock(&SyncMutex);
185 pthread_cond_broadcast(&SyncCond);
186 pthread_mutex_unlock(&SyncMutex);
192 EventLog(
"Waiting for SFID_RUN...");
193 pthread_mutex_lock(&SyncMutex);
195 pthread_cond_wait(&SyncCond, &SyncMutex);
197 pthread_mutex_unlock(&SyncMutex);
198 EventLog(
"Waiting for SFID_RUN...Done");
203 pthread_mutex_lock(&SyncMutex);
205 pthread_cond_broadcast(&SyncCond);
206 pthread_mutex_unlock(&SyncMutex);
212 EventLog(
"Waiting for SFID_EXCMPL...");
213 pthread_mutex_lock(&SyncMutex);
215 pthread_cond_wait(&SyncCond, &SyncMutex);
217 pthread_mutex_unlock(&SyncMutex);
218 EventLog(
"Waiting for SFID_EXCMPL...Done");
223 timespec_clear(Time);
224 timespec_clear(ActPeriodicTime);
225 timespec_clear(ComputationTime);
232 pthread_cancel(ThreadID);
233 pthread_join(ThreadID,
nullptr);
239 return timespec_to_sec(Time);
245 return timespec_to_sec(ActPeriodicTime);
251 return timespec_to_sec(ComputationTime);
268 if(TsZ0 < MinMemo && 1e-6 < TsZ0){
278 static const long ONE_SEC_IN_NANO = 1000000000;
279 static const long SKEW_IN_NANO = 40;
280 pthread_mutex_t SyncMutex;
281 pthread_cond_t SyncCond;
283 const unsigned long Ts;
284 std::function<bool(
double,
double,
double)> FuncObj;
286 timespec ActPeriodicTime;
287 timespec ComputationTime;
289 struct sched_param ThreadParam;
295 void RealTimeLoop(
void){
296 timespec InitTime = {0};
297 timespec NextTime = {0};
298 timespec TimeInWait = {0};
299 timespec PeriodTime = nsec_to_timespec(Ts - SKEW_IN_NANO);
300 timespec StartTime = {0};
301 timespec StartTimePrev = {0};
302 timespec EndTime = {0};
303 timespec PreventStuck = {0};
304 bool ClockOverride =
false;
306 EventLog(
"Starting Realtime Loop.");
308 clock_gettime(CLOCK_MONOTONIC, &InitTime);
309 StartTimePrev = timespec_sub(InitTime, PeriodTime);
314 clock_gettime(CLOCK_MONOTONIC, &StartTime);
315 Time = timespec_sub(StartTime, InitTime);
316 ActPeriodicTime = timespec_sub(StartTime, StartTimePrev);
318 std::feclearexcept(FE_ALL_EXCEPT);
320 arcs_assert(std::fetestexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) ==
false);
321 StartTimePrev = StartTime;
322 NextTime = timespec_add(StartTime, PeriodTime);
324 if constexpr(SFA == SFalgorithm::INSERT_ZEROSLEEP){
325 clock_nanosleep(CLOCK_MONOTONIC, 0, &PreventStuck,
nullptr);
327 clock_gettime(CLOCK_MONOTONIC, &EndTime);
328 ComputationTime = timespec_sub(EndTime, StartTime);
332 clock_gettime(CLOCK_MONOTONIC, &TimeInWait);
333 if(timespec_lessthaneq(NextTime, TimeInWait) ==
true || ClockOverride ==
true){
347 static void RealTimeThread(
SFthread *p){
351 EventLog(
"Waiting for SFID_START,SFID_DSTRCT...");
352 pthread_mutex_lock(&(p->SyncMutex));
354 pthread_cond_wait(&(p->SyncCond), &(p->SyncMutex));
356 pthread_mutex_unlock(&(p->SyncMutex));
357 EventLog(
"Waiting for SFID_START,SFID_DSTRCT...Done");
361 pthread_mutex_lock(&(p->SyncMutex));
363 pthread_cond_broadcast(&(p->SyncCond));
364 pthread_mutex_unlock(&(p->SyncMutex));
366 mlockall(MCL_CURRENT);
370 pthread_mutex_lock(&(p->SyncMutex));
372 pthread_cond_broadcast(&(p->SyncCond));
373 pthread_mutex_unlock(&(p->SyncMutex));
375 EventLog(
"RealTimeThread Destructed.");
382 static timespec timespec_add(
const timespec& a,
const timespec& b){
384 ret.tv_sec = a.tv_sec + b.tv_sec;
385 ret.tv_nsec = a.tv_nsec + b.tv_nsec;
386 if(ONE_SEC_IN_NANO <= ret.tv_nsec){
388 ret.tv_nsec -= ONE_SEC_IN_NANO;
398 static timespec timespec_sub(
const timespec& a,
const timespec& b){
400 ret.tv_sec = a.tv_sec - b.tv_sec;
401 ret.tv_nsec = a.tv_nsec - b.tv_nsec;
404 ret.tv_nsec += ONE_SEC_IN_NANO;
414 static bool timespec_lessthaneq(
const timespec& a,
const timespec& b){
415 if(a.tv_sec != b.tv_sec){
416 if(a.tv_sec < b.tv_sec){
422 if(a.tv_nsec <= b.tv_nsec){
432 static void timespec_clear(timespec& a){
440 static timespec nsec_to_timespec(
const unsigned long time){
442 ret.tv_sec = time/ONE_SEC_IN_NANO;
443 ret.tv_nsec = time - ret.tv_sec*ONE_SEC_IN_NANO;
450 static double timespec_to_sec(
const timespec& time){
451 return (
double)time.tv_sec + (double)time.tv_nsec*1e-9;
455 void SetKernelParameters(
void){
457 if(IsInWSL() ==
true){
458 EventLog(
"Setting kernel parameters for WSL");
464 EventLog(
"Setting kernel parameters for x86_64");
468 if constexpr(
static_cast<uint8_t
>(SFK) &
static_cast<uint8_t
>(SFkernelparam::CFS_DISABLED) ){
472 EventLog(
"Kernel param: CFS Disabled");
476 if constexpr(
static_cast<uint8_t
>(SFK) &
static_cast<uint8_t
>(SFkernelparam::PREEMPT_DYNFULL) ){
478 EventLog(
"Kernel param: Set to \"full\" mode on PREEMPT_DYNAMIC");
482 if constexpr(SFA == SFalgorithm::WITHOUT_ZEROSLEEP){
484 EventLog(
"Kernel param: Watchdog Disabled");
490 EventLog(
"Setting kernel parameters for ARM");
500 void ResetKernelParameters(
void){
502 if(IsInWSL() ==
true){
509 if constexpr(
static_cast<uint8_t
>(SFK) &
static_cast<uint8_t
>(SFkernelparam::CFS_DISABLED) ){
513 EventLog(
"Kernel param: CFS Enabled");
517 if constexpr(
static_cast<uint8_t
>(SFK) &
static_cast<uint8_t
>(SFkernelparam::PREEMPT_DYNFULL) ){
519 EventLog(
"Kernel param: Set to \"voluntary\" mode on PREEMPT_DYNAMIC");
523 EventLog(
"Kernel param: Returned to default settings.");
539 static bool IsInWSL(
void){
540 const std::string WSLpath =
"/proc/sys/fs/binfmt_misc/WSLInterop";
541 std::ifstream ifs(WSLpath);
542 return ifs.is_open();