I am writting a wrapper function sleep_new()
for clock_nanosleep()
which would make thread suspension easier for me.
// POSIX.1-2017 is what compiler is confined to.
#define _XOPEN_SOURCE 700
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
// POSIX headers.
// Other headers
#include "sleep_new.h"
void sleep_new(long value, const char unit[3]){
// Create a timespec structure and set it's members.
// Members are added together!!! So to set time "1.5 s" we set "t.tv_sec = 1" and "t.tv_sec = 500000000".
// Members ".tv_sec" and ".tv_nsec" represent unit and not value!
struct timespec sleep_time;
// Set flags i.e. TIMER_ABSTIME to 0 to use relative instead of absolute time.
int flags = 0;
// Choose the clock i.e. CLOCK_MONOTONIC is a "clock_id" for the clock started at system start.
int clock_id = CLOCK_MONOTONIC;
// Set timespec structure's members according to the chosen unit.
if (!strcmp(unit, "s")) {
sleep_time.tv_sec = value;
sleep_time.tv_nsec = 0;
}
else if (!strcmp(unit, "ns")){
sleep_time.tv_sec = 0;
sleep_time.tv_nsec = value;
}
else if (!strcmp(unit, "us")){
sleep_time.tv_sec = 0;
sleep_time.tv_nsec = value * 1000;
}
else if (!strcmp(unit, "ms")){
sleep_time.tv_sec = 0;
sleep_time.tv_nsec = value * 1000000;
}
else{
puts("Unit not supported - choose between: s, ms, us, ns\n");
}
// Because last argument is NULL in case of error, remaining time is not stored in "t".
clock_nanosleep(clock_id, flags, &sleep_time, NULL);
}
int main(int argc, char *argv[])
{
// Counter.
uint8_t i;
for(i = 0; i < 256; i++){
// Stdout is newline buffered. This is why we either have to include `\n` at the end or flush() it manually.
// So uncomment one example A or B.
// A
//printf("%d\n", i);
// B
printf("%d, ", i);
fflush(stdout);
// Because last argument is NULL in case of error, remaining time is not stored in "t".
sleep_new(1000, "ms");
}
return 0;
}
If I call this function with sleep_new(1, "s")
or sleep_new(2, "s")
it works fine, because it sets the sleep_time.tv_nsec = 0;
and sleep_time.tv_sec = value;
.
In any other scenarios i.e. sleep_new(1000, "ms")
something is wrong and sleep is not applied. I debugged application and values are applied to the timespec
members just fine but clock_nanosec()
just ignores them.
I am using type long
for the value
because I read in the POSIX here where header time.h
defines timespec
structure's members tv_nsec
who needs long
and member tv_sec
who uses time_t
which is in turn defined in header sys/types.h
like this:
time_t
shall be an integer type.
So because long
can also hold int
values I expected this to work, but it doesn't. Does anyone have any suggestion?
The tv_nsec
is the number of nanoseconds in a second - 1000 * 1000000
nanoseconds is too much. That's 1 second! tv_nsec
should range from 0
to 999999999
. The proper calculation could look like:
sleep_time.tv_sec = value / 1000;
sleep_time.tv_nsec = (value % 1000) * 1000000;