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();