00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*- 00002 00003 // -- BEGIN LICENSE BLOCK ---------------------------------------------- 00004 // This file is part of FZIs ic_workspace. 00005 // 00006 // This program is free software licensed under the LGPL 00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3). 00008 // You can find a copy of this license in LICENSE folder in the top 00009 // directory of the source code. 00010 // 00011 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany 00012 // 00013 // -- END LICENSE BLOCK ------------------------------------------------ 00014 00015 //---------------------------------------------------------------------- 00021 //---------------------------------------------------------------------- 00022 00023 #if defined _SYSTEM_POSIX_ 00024 # include <linux/version.h> 00025 # if (!(LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))) 00026 00027 #include "PeriodicThreadImplTimerfd.h" 00028 #include "Logging.h" 00029 00030 #include <sys/timerfd.h> 00031 00032 namespace icl_core { 00033 namespace thread { 00034 00035 PeriodicThreadImplTimerfd::PeriodicThreadImplTimerfd(const icl_core::TimeSpan& period) 00036 : m_period(period), 00037 timer_created(false) 00038 { 00039 m_info = new struct periodic_info; 00040 } 00041 00042 PeriodicThreadImplTimerfd::~PeriodicThreadImplTimerfd() 00043 { 00044 delete m_info; 00045 } 00046 00047 void PeriodicThreadImplTimerfd::makePeriodic() 00048 { 00049 /* Create the timer */ 00050 int fd = timerfd_create(CLOCK_MONOTONIC, 0); 00051 m_info->wakeups_missed = 0; 00052 m_info->timer_fd = fd; 00053 if (fd != -1) 00054 { 00055 timer_created = true; 00056 } 00057 00058 setPeriod(m_period); 00059 } 00060 00061 bool PeriodicThreadImplTimerfd::setPeriod(const icl_core::TimeSpan& period) 00062 { 00063 m_period = period; 00064 00065 int ret = -1; 00066 if (timer_created) 00067 { 00068 /* Make the timer periodic */ 00069 unsigned int ns; 00070 unsigned int sec; 00071 struct itimerspec itval; 00072 00073 sec = period.tsSec(); 00074 ns = period.tsNSec(); 00075 itval.it_interval.tv_sec = sec; 00076 itval.it_interval.tv_nsec = ns; 00077 itval.it_value.tv_sec = sec; 00078 itval.it_value.tv_nsec = ns; 00079 ret = timerfd_settime(m_info->timer_fd, 0, &itval, NULL); 00080 } 00081 if (ret == -1) 00082 { 00083 return false; 00084 } 00085 else 00086 { 00087 return true; 00088 } 00089 } 00090 00091 void PeriodicThreadImplTimerfd::waitPeriod() 00092 { 00093 unsigned long long missed; 00094 int ret; 00095 00096 /* Wait for the next timer event. If we have missed any the 00097 number is written to "missed" */ 00098 ret = read(m_info->timer_fd, &missed, sizeof(missed)); 00099 if (ret == -1) 00100 { 00101 perror ("read timer"); 00102 return; 00103 } 00104 00105 m_info->wakeups_missed += missed; 00106 } 00107 00108 } 00109 } 00110 00111 # endif 00112 #endif