what does timer expiration value for periodic linux timer signify? - c

I have already gone through the man page to create, and start the timer.
http://man7.org/linux/man-pages/man2/timerfd_create.2.html
However, i am not sure the use of the field "it_value" of struct itimerspec other than arm(start) and disarm(stop).
Question: what happens when a non-zero value is specified for this field.The man page documents that non-zero will start the timer and documents as timer expiration period? what does a timer expiration mean? what is the effect of timer expiration?
To start(arm) a timer, one can give value ranging from 1 ns to value equal to timer interval(non-zero). what would be the difference and the expected behavior in these two cases
Method1: Make the timer expiration equal to interval
int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
int milliseconds = 50;// 50 ms for example
struct itimerspec timspec;
timspec.it_interval.tv_sec = 0;
timspec.it_interval.tv_nsec = milliseconds * 1000000;
timspec.it_value.tv_sec = timspec.it_interval.tv_sec;
timspec.it_value.tv_nsec = timspec.it_interval.tv_nsec;
int res = timerfd_settime(timerfd, 0, &timspec, 0);
Method 2: Timer expiration less then timer interval
int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
int milliseconds = 50;// 50 ms for example
struct itimerspec timspec;
timspec.it_interval.tv_sec = 0;
timspec.it_interval.tv_nsec = milliseconds * 1000000;
timspec.it_value.tv_sec = 0;
timspec.it_value.tv_nsec = 1;
int res = timerfd_settime(timerfd, 0, &timspec, 0);

However, i am not sure the use of the field "it_value" of struct itimerspec other than arm(start) and disarm(stop).
Apparently your interest is in the use of this field with the second argument to timerfd_settime(), as opposed to the interpretation of values set in the struct, if any, pointed to by the third argument, or filled in by timerfd_gettime(). It's all pretty much the same, though.
You seem to have focused on the wrong thing in keying in on arming and disarming the timer. As the manpage you linked puts it,
The new_value argument specifies the initial expiration and interval for the timer.
(emphasis added). That is, the it_value of a struct itimerspec conveys the amount of time until the next timer expiration (or the absolute time of that expiration, depending on the flags), except that both fields zero indicates that the timer will never expire -- it is disarmed -- rather than that it will expire immediately. The value conveyed by this member does not have any particular correlation to the value conveyed by the it_interval member.
It follows that timerfd_settime() can be used to arm a disarmed timer or disarm an armed one, depending on the it_value passed to it, but those are special outcomes of more general behavior. The general case is that it is used to change the amount of time before a timer next expires, and the time increment between subsequent expirations.
To start(arm) a timer, one can give value ranging from 1 ns to value equal to timer interval(non-zero).
... or more. The delay before the next expiration is not limited to the length of the interval. As an extreme case, the interval can be zero, so that the timer is disarmed after expiring once.
what would be the difference and the expected behavior in these two cases
Method1: Make the timer expiration equal to [nonzero] interval
The timer will first expire after the specified amount of time (which is equal to the interval). Each time it expires, it will be reset to the time given by the interval.
Method 2: [nonzero] Timer expiration less then [nonzero] timer interval
The timer will first expire after the specified amount of time (which is less than the interval). Each time it expires, it will be reset to the time given by the interval.

Related

Protecting against overflow in a delay function

I have in a project of mine a small delay function that I have written myself by making use of a timer peripheral of my MCU:
static void delay100Us(void)
{
uint_64 ctr = TIMER_read(0); //10ns resolution
uint_64 ctr2 = ctr + 10000;
while(ctr <= ctr2) //wait 100 microseconds(10000)
{
ctr = TIMER_read(0);
}
}
The counter is a freerunning hw counter with 10ns resolution so I wrote that function as to give approximately 100us delay.
I think this should work in principle however there could be the situation where the timer is less than 10000 from overflowing and so ctr2 will get assigned a value which is more than ctr can actually reach and therefore I would end up getting stuck into an infinite loop.
I need to generate a delay using this timer in my project so I need to somehow make sure that I always get the same delay(100us) while at the same time protect myself from getting stuck there.
Is there any way I can do this or is this just a limitation that I can't get passed?
Thank you!
Edit:
ctr_start = TimerRead(); //get initial value for the counter
interval = TimerRead() - ctr_start;
while(interval <= 10000)
{
interval = ( TimerRead() - ctr_start + countersize ) % countersize;
}
Where countersize = 0xFFFFFFFFFFFFFFFF;
It can be dangerous to wait for a specific timer value in case an interrupt happens at just that moment and you miss the required count. So it is better to wait until the counter has reached at least the target value. But as noticed, comparing the timer with a target value creates a problem when the target is lower than the initial value.
One way to avoid this problem is to consider the interval that has elapsed with unsigned variables and arithmetic. Their behaviour is well defined when values wrap.
A hardware counter is almost invariably of size 8, 16, 32 or 64 bits, so choose a variable type to suit. Suppose the counter is 32-bit:
void delay(uint32_t period)
{
uint32_t mark = TIMER_read(0);
uint32_t interval;
do {
interval = TIMER_read(0) - mark; // underflow is well defined
} while(interval < period);
}
Obviously, the required period must be less than the counter's period. If not, either scale the timer's clock, or use another method (such as a counter maintained by interrupt).
Sometimes a one-shot timer is used to count down the required period, but using a free-run counter is easy, and using a one-shot timer means it can't be used by another process at the same time.

How to use hrtimer if the processing time of the callback function is dynamic?

I am writing a kernel module in which I need to trigger a function on a periodic basis. The function will access a queue and process its elements. The number of elements in the queue is dynamic and so the processing time.
In the following code, I have added 1ms sleep to represent the processing time. I am getting this error : [116588.117966] BUG: scheduling while atomic: systemd-journal/408/0x00010000. If my understanding is correct, this happens since I try to sleep 1ms when the expiry time of the hr_timer is just 1us. I can increase this expiry time but the processing time of the queue can be sometimes more than seconds, sometimes in hours even. Please help me to achieve this.
unsigned long timer_interval_ns = 1e3;
static struct hrtimer hr_timer;
enum hrtimer_restart timer_callback( struct hrtimer *timer_for_restart )
{
uint64_t rawtime;
struct timespec curtime;
ktime_t currtime , interval;
/ * My Operations would take ~ 1ms, so adding 1ms for simplicity* /
msleep(1);
currtime = ktime_get();
interval = ktime_set(0,timer_interval_ns);
hrtimer_forward(timer_for_restart, currtime, interval);
return HRTIMER_RESTART;
}
static int __init timer_init(void) {
ktime_t ktime = ktime_set( 0, timer_interval_ns );
hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
hr_timer.function = &timer_callback;
hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL );
return 0;
}
BUG: scheduling while atomic
This message means that while you are in an atomic context you tried to schedule some other task.
To make it easy (so, not perfect and orthodox explanation): if a function is running in an atomic context, this function cannot stop its execution and call the scheduler (a.k.a. sleeping).
When you call msleep(1) you are actually asking the kernel to schedule some other task because for 1 millisecond you do not have anything to do and you ask the kernel to use this time to do something useful. But this is not allowed in an atomic context. Functions running in an atomic context must finish their execution without any interruption.
Another example of function that will sleep and you may have the temptation to use is kmalloc. If you need it in an atomic context then use the GFP_ATOMIC flag in order to have an atomic allocation that does not sleep (schedule).
Another example of atomic context is the interrupt handler function.
Another problem that you may have with msleep(1) is that is not guaranteed that it will sleep 1 millisecond. It it too short to be guaranteed. Indeed, it is suggested to use a sleeping time greater or equal than 20 milliseconds. If you need a shorter sleeping time, then use delay functions.
Read The following links:
https://en.wikipedia.org/wiki/Linearizability
https://lwn.net/Articles/274695/
https://www.kernel.org/doc/Documentation/timers/timers-howto.txt

How to know if a timer has ended in C

I need to be able to start multiple timers simultaneously and know specifically if a timer has stopped or is still going.
#define RESEND_TIMEOUT 5
void timerCreate();
void timer_start(timer_t * timer, uint32 timeout);
bool timer_complete(timer_t * timer);
int main() {
timer_t resend_timer = timerCreate();
timer_start(&resend_timer, RESEND_TIMEOUT);
while(1) {
if (timer_complete(&resend_timer))
break;
}
}
void timer_start(timer_t * timer, uint32_t timeout)
{
printf("timer starting\n");
struct itimerspec it_val;
it_val.it_value.tv_sec = timeout;
it_val.it_value.tv_nsec = 0;
// timer expires once
it_val.it_interval.tv_sec = 0;
it_val.it_interval.tv_nsec = 0;
if (timer_settime(*timer, 0, &it_val, NULL) == -1) {
errExit("Could not set timeout");
}
}
// return true if timer ended
bool timer_complete(timer_t * timer)
{
if(timer_getoverrun(*timer) == 0)
return false;
else
return true;
}
I never break out of the loop. Why can't I get the overrun of the timer (it always returns 0, which means the timer has not passed its expiration)? Yet when I add a signal handler, I know that the timer expires.
I want to try timer_gettime(timer_t timerid, struct itimerspec *curr_value) inside of my timer_complete function to see if the remaining time is 0, but how can I pass the curr_value argument without having a global variable?
Last but not least, I have tried with the TIMER_ABSTIME flag when arming the timer with timer_settime. From the manpage of int timer_settime(timer_t timerid, int flags,
const struct itimerspec *new_value,
struct itimerspec * old_value):
By default, the initial expiration time specified in
new_value->it_value is interpreted relative to the current time on
the timer's clock at the time of the call. This can be modified by
specifying TIMER_ABSTIME in flags, in which case new_value->it_value
is interpreted as an absolute value as measured on the timer's clock;
that is, the timer will expire when the clock value reaches the value
specified by new_value->it_value. If the specified absolute time has
already passed, then the timer expires immediately, and the overrun
count (see timer_getoverrun(2)) will be set correctly.
I never break out of the loop. Why can't I get the overrun of the timer (it always returns 0, which means the timer has not passed its expiration)?
No, it means you had no overruns.
The OS is not going to queue timer signals even if you specify realtime signals. Overun tells you how many signals would have been queued if the wood chuck didn't chuck signals.
So consider you set a timer to go off once every second. But for some reason you didn't handle the signal. Say you had it blocked for 5 seconds. The overrun count is going to be 4 - the signal you will/are processing and the 4 you missed.
In your case you set a one-time timer to go off after "timeout" seconds. The signal was delivered. There will be no more signals hence overrun is always going to be 0, as it should be.

Windows Driver Timestamp function

I am modifying an existing Windows Kernel device driver and in there I need to capture a timestamp. I was intending to use time.h library and call the clock() function to get that, however under windows visual studio, the linking is failing. So I took it as a means that I need to work within the driver's libraries.
I found the following function, KeInitializeTimer, and KeSetTimerEx but these are used if I plan to set up a timer and wake up on it. What I really need is something that will give me a timestamp.
Any ideas?
I am updating my question with an answer for others to benefit from my findings.
To get a timestamp, you can use KeQueryTickCount(). This routine will give you the count of interval interrupts that occurred since the system was booted. However, if you need to find out since the last timestamp you captured, an X amount of time has passed you need to also query your system to determine the time it takes for each interval clock interrupt.
ULONG KeQueryTimeIncrement() give you the number of 100-nanosecond units.
Example:
PLARGE_INTEGER timeStamp;
KeQueryTickCount(&timeStamp);
Please note that PLARGE_INTEGER is defined as such:
#if defined(MIDL_PASS)
typedef struct _LARGE_INTEGER {
#else // MIDL_PASS
typedef union _LARGE_INTEGER {
struct {
ULONG LowPart;
LONG HighPart;
} DUMMYSTRUCTNAME;
struct {
ULONG LowPart;
LONG HighPart;
} u;
#endif //MIDL_PASS
LONGLONG QuadPart;
} LARGE_INTEGER;
So lets say, you want to see if 30 seconds passed since you last took a timestamp, you can do the following:
ULONG tickIncrement, ticks;
LARGE_INTEGER waitTillTimeStamp;
tickIncrement = KeQueryTimeIncrement();
// 1sec is 1,000,000,000 nano sec, however, since KeQueryTimeIncrement is in
// 100ns increments, divide that and your constant is 10,000,000
ticks = ((30 * 10,000,000) / tickIncrement);
KeQueryTickCount(&waitTillTimeStamp);
waitTillTimeStamp.QuadPart += ticks;
<.....Some code and time passage....>
KeQueryTickCount(&currTimeStamp);
if (waitTillTimeStamp.QuadPart < currTimeStamp.QuadPart) {
<...Do whatever...>
}
Another example to help you understand this, what if you want to translate the timestamp you got into a time value such as milliseconds.
LARGE_INTEGER mSec, currTimeStamp;
ULONG timeIncrement;
timeIncrement = KeQueryTimeIncrement();
KeQueryTickCount(&currTimeStamp);
// 1 millisecond is 1,000,000 nano seconds, but remember divide by 100 to account for
// KeQueryTickCount granularity.
mSec.QuadPart = (currTimeStamp.QuadPart * timeIncrement) / 10000;
Remember this example is for demonstration purposes, mSec is not the current time in milliseconds. Based on the APIs used above, it is merely the number of milliseconds that have elapsed since the system was started.
You can also use GetTickCount(), but this returns a DWORD and thus will only be able to give you the number of milliseonds since the system was started for up to 49.7 days.
I know this is a 10 years old question but... better later than never. I disagree with the OP's answer.
Proper solution:
// The KeQuerySystemTime routine obtains the current system time.
LARGE_INTEGER SystemTime;
KeQuerySystemTime(&SystemTime);
// The ExSystemTimeToLocalTime routine converts a GMT system time value to the local system time for the current time zone.
LARGE_INTEGER LocalTime;
ExSystemTimeToLocalTime(&SystemTime, &LocalTime);
// The RtlTimeToTimeFields routine converts system time into a TIME_FIELDS structure.
TIME_FIELDS TimeFields;
RtlTimeToTimeFields(&LocalTime, &TimeFields);

UTC time stamp on Windows

I have a buffer with the UTC time stamp in C, I broadcast that buffer after every ten seconds. The problem is that the time difference between two packets is not consistent. After 5 to 10 iterations the time difference becomes 9, 11 and then again 10. Kindly help me to sort out this problem.
I am using <time.h> for UTC time.
If your time stamp has only 1 second resolution then there will always be +/- 1 uncertainty in the least significant digit (i.e. +/- 1 second in this case).
Clarification: if you only have a resolution of 1 second then your time values are quantized. The real time, t, represented by such a quantized value has a range of t..t+0.9999. If you take the difference of two such times, t0 and t1, then the maximum error in t1-t0 is -0.999..+0.999, which when quantized is +/-1 second. So in your case you would expect to see difference values in the range 9..11 seconds.
A thread that sleeps for X milliseconds is not guaranteed to sleep for precisely that many milliseconds. I am assuming that you have a statement that goes something like:
while(1) {
...
sleep(10); // Sleep for 10 seconds.
// fetch timestamp and send
}
You will get a more accurate gauge of time if you sleep for shorter periods (say 20 milliseconds) in a loop checking until the time has expired. When you sleep for 10 seconds, your thread gets moved further out of the immediate scheduling priority of the underlying OS.
You might also take into account that the time taken to send the timestamps may vary, depending on network conditions, etc, if you do a sleep(10) -> send ->sleep(10) type of loop, the time taken to send will be added onto the next sleep(10) in real terms.
Try something like this (forgive me, my C is a little rusty):
bool expired = false;
double last, current;
double t1, t2;
double difference = 0;
while(1) {
...
last = (double)clock();
while(!expired) {
usleep(200); // sleep for 20 milliseconds
current = (double)clock();
if(((current - last) / (double)CLOCKS_PER_SEC) >= (10.0 - difference))
expired = true;
}
t1 = (double)clock();
// Set and send the timestamp.
t2 = (double)clock();
//
// Calculate how long it took to send the stamps.
// and take that away from the next sleep cycle.
//
difference = (t2 - t1) / (double)CLOCKS_PER_SEC;
expired = false;
}
If you are not bothered about using the standard C library, you could look at using the high resolution timer functionality of windows such as QueryPerformanceFrequency/QueryPerformanceCounter functions.
LONG_INTEGER freq;
LONG_INTEGER t2, t1;
//
// Get the resolution of the timer.
//
QueryPerformanceFrequency(&freq);
// Start Task.
QueryPerformanceCounter(&t1);
... Do something ....
QueryPerformanceCounter(&t2);
// Very accurate duration in seconds.
double duration = (double)(t2.QuadPart - t1.QuadPart) / (double)freq.QuadPart;

Resources