mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
moved time related functions to timing.{c,h}
This commit is contained in:
parent
08e08e6711
commit
5aa1530baf
8 changed files with 182 additions and 61 deletions
55
server/include/timing.h
Normal file
55
server/include/timing.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/** Time related functions.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC
|
||||
* This file is part of S2SS. All Rights Reserved. Proprietary and confidential.
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
*********************************************************************************/
|
||||
|
||||
#ifndef _TIME_H_
|
||||
#define _TIME_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** Wait until timer elapsed
|
||||
*
|
||||
* @param fd A file descriptor which was created by timerfd_create(3).
|
||||
* @retval 0 An error occured. Maybe the timer was stopped.
|
||||
* @retval >0 The nummer of runs this timer already fired.
|
||||
*/
|
||||
uint64_t timerfd_wait(int fd);
|
||||
|
||||
/** Wait until a fixed time in the future is reached
|
||||
*
|
||||
* @param fd A file descriptor which was created by timerfd_create(3).
|
||||
* @param until A pointer to a time in the future.
|
||||
* @retval 0 An error occured. Maybe the timer was stopped.
|
||||
* @retval >0 The nummer of runs this timer already fired.
|
||||
*/
|
||||
uint64_t timerfd_wait_until(int fd, struct timespec *until);
|
||||
|
||||
/** Get delta between two timespec structs */
|
||||
struct timespec time_diff(struct timespec *start, struct timespec *end);
|
||||
|
||||
/** Get sum of two timespec structs */
|
||||
struct timespec time_add(struct timespec *start, struct timespec *end);
|
||||
|
||||
/** Return the diffrence off two timestamps as double value in seconds. */
|
||||
double time_delta(struct timespec *start, struct timespec *end);
|
||||
|
||||
/** Convert timespec to double value representing seconds */
|
||||
double time_to_double(struct timespec *ts);
|
||||
|
||||
/** Convert double containing seconds after 1970 to timespec. */
|
||||
struct timespec time_from_double(double secs);
|
||||
|
||||
/** Read a timestamp from a file with the format: "secs.nanosecs\t" */
|
||||
int time_fscan(FILE *f, struct timespec *ts);
|
||||
|
||||
/** Write a timestamp to a file with the format: "secs.nanosecs\t" */
|
||||
int time_fprint(FILE *f, struct timespec *ts);
|
||||
|
||||
#endif
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "file.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "timing.h"
|
||||
|
||||
int file_init(int argc, char *argv[], struct settings *set)
|
||||
{ INDENT
|
||||
|
@ -53,10 +53,7 @@ int file_parse(config_setting_t *cfg, struct node *n)
|
|||
f->mode = "w+";
|
||||
|
||||
if (!config_setting_lookup_float(cfg, "rate", &f->rate))
|
||||
f->rate = 1;
|
||||
|
||||
if (!config_setting_lookup_bool(cfg, "timestamp", &f->timestamp))
|
||||
f->timestamp = 0;
|
||||
f->rate = 0;
|
||||
|
||||
n->file = f;
|
||||
|
||||
|
@ -76,10 +73,19 @@ int file_open(struct node *n)
|
|||
if (f->tfd < 0)
|
||||
serror("Failed to create timer");
|
||||
|
||||
struct itimerspec its = {
|
||||
.it_interval = timespec_rate(f->rate),
|
||||
.it_value = { 1, 0 }
|
||||
};
|
||||
/* Arm the timer */
|
||||
struct itimerspec its;
|
||||
if (f->rate) {
|
||||
/* Send with fixed rate */
|
||||
its.it_interval = time_from_double(1 / f->rate);
|
||||
its.it_value = (struct timespec) { 1, 0 };
|
||||
}
|
||||
else {
|
||||
/* Read timestamp from first line to get an epoch offset */
|
||||
time_fscan(f->in, &f->offset);
|
||||
rewind(f->in);
|
||||
}
|
||||
|
||||
int ret = timerfd_settime(f->tfd, 0, &its, NULL);
|
||||
if (ret)
|
||||
serror("Failed to start timer");
|
||||
|
@ -116,14 +122,16 @@ int file_read(struct node *n, struct msg *pool, int poolsize, int first, int cnt
|
|||
struct file *f = n->file;
|
||||
|
||||
if (f->in) {
|
||||
/* Blocking for 1/f->rate seconds */
|
||||
if (timerfd_wait(f->tfd)) {
|
||||
for (i = 0; i < cnt; i++) {
|
||||
struct msg *m = &pool[(first+i) % poolsize];
|
||||
struct timespec ts;
|
||||
|
||||
msg_fscan(f->in, m);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < cnt; i++)
|
||||
msg_fscan(f->in, &pool[(first+i) % poolsize]);
|
||||
|
||||
if (f->rate)
|
||||
timerfd_wait(f->tfd);
|
||||
else
|
||||
timerfd_wait_until(f->tfd, &ts);
|
||||
|
||||
}
|
||||
else
|
||||
warn("Can not read from node '%s'", n->name);
|
||||
|
@ -136,18 +144,12 @@ int file_write(struct node *n, struct msg *pool, int poolsize, int first, int cn
|
|||
int i = 0;
|
||||
struct file *f = n->file;
|
||||
|
||||
if (f->out) {
|
||||
for (i = 0; i < cnt; i++) {
|
||||
struct msg *m = &pool[(first+i) % poolsize];
|
||||
if (f->out) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
if (f->timestamp) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
fprintf(f->out, "%lu.%06lu\t", ts.tv_sec, (long) (ts.tv_nsec / 1e3));
|
||||
}
|
||||
|
||||
msg_fprint(f->out, m);
|
||||
}
|
||||
for (i = 0; i < cnt; i++)
|
||||
msg_fprint(f->out, &pool[(first+i) % poolsize]);
|
||||
}
|
||||
else
|
||||
warn("Can not write to node '%s", n->name);
|
||||
|
|
|
@ -211,7 +211,7 @@ int gtfpga_open(struct node *n)
|
|||
serror("Failed to create timer");
|
||||
|
||||
struct itimerspec its = {
|
||||
.it_interval = timespec_rate(g->rate),
|
||||
.it_interval = time_from_double(1 / g->rate),
|
||||
.it_value = { 1, 0 }
|
||||
};
|
||||
ret = timerfd_settime(g->fd_irq, 0, &its, NULL);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "utils.h"
|
||||
#include "path.h"
|
||||
#include "socket.h"
|
||||
#include "timing.h"
|
||||
|
||||
#ifndef sigev_notify_thread_id
|
||||
#define sigev_notify_thread_id _sigev_un._tid
|
||||
|
@ -46,7 +47,7 @@ static void * path_run_async(void *arg)
|
|||
{
|
||||
struct path *p = arg;
|
||||
struct itimerspec its = {
|
||||
.it_interval = timespec_rate(p->rate),
|
||||
.it_interval = time_from_double(1 / p->rate),
|
||||
.it_value = { 1, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* Setup timer */
|
||||
struct itimerspec its = {
|
||||
.it_interval = timespec_rate(rate),
|
||||
.it_interval = time_from_double(1 / rate),
|
||||
.it_value = { 1, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ void test_rtt() {
|
|||
node_read_single(node, &m); /* Pong */
|
||||
clock_gettime(CLOCK_ID, ts2);
|
||||
|
||||
rtt = timespec_delta(ts1, ts2);
|
||||
rtt = time_delta(ts1, ts2);
|
||||
|
||||
if (rtt < 0) continue;
|
||||
if (rtt > rtt_max) rtt_max = rtt;
|
||||
|
|
93
server/src/timing.c
Normal file
93
server/src/timing.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
/** Time related functions.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC
|
||||
* This file is part of S2SS. All Rights Reserved. Proprietary and confidential.
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
#include "timing.h"
|
||||
|
||||
uint64_t timerfd_wait(int fd)
|
||||
{
|
||||
uint64_t runs;
|
||||
|
||||
return read(fd, &runs, sizeof(runs)) < 0 ? 0 : runs;
|
||||
}
|
||||
|
||||
uint64_t timerfd_wait_until(int fd, struct timespec *until)
|
||||
{
|
||||
struct itimerspec its = {
|
||||
.it_value = *until
|
||||
};
|
||||
|
||||
if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL))
|
||||
return 0;
|
||||
else
|
||||
return timerfd_wait(fd);
|
||||
}
|
||||
|
||||
struct timespec time_add(struct timespec *start, struct timespec *end)
|
||||
{
|
||||
struct timespec sum = {
|
||||
.tv_sec = end->tv_sec + start->tv_sec,
|
||||
.tv_nsec = end->tv_nsec + start->tv_nsec
|
||||
};
|
||||
|
||||
if (sum.tv_nsec > 1000000000) {
|
||||
sum.tv_sec += 1;
|
||||
sum.tv_nsec -= 1000000000;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
struct timespec time_diff(struct timespec *start, struct timespec *end)
|
||||
{
|
||||
struct timespec diff = {
|
||||
.tv_sec = end->tv_sec - start->tv_sec,
|
||||
.tv_nsec = end->tv_nsec - start->tv_nsec
|
||||
};
|
||||
|
||||
if (diff.tv_nsec < 0) {
|
||||
diff.tv_sec -= 1;
|
||||
diff.tv_nsec += 1000000000;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
struct timespec time_from_double(double secs)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = secs;
|
||||
ts.tv_nsec = 1.0e9 * (secs - ts.tv_sec);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
double time_to_double(struct timespec *ts)
|
||||
{
|
||||
return ts->tv_sec + ts->tv_nsec * 1e-9;
|
||||
}
|
||||
|
||||
double time_delta(struct timespec *start, struct timespec *end)
|
||||
{
|
||||
struct timespec diff = time_diff(start, end);
|
||||
|
||||
return time_to_double(&diff);
|
||||
}
|
||||
|
||||
int time_fscan(FILE *f, struct timespec *ts)
|
||||
{
|
||||
return fscanf(f, "%lu.%lu", &ts->tv_sec, &ts->tv_nsec);
|
||||
}
|
||||
|
||||
int time_fprint(FILE *f, struct timespec *ts)
|
||||
{
|
||||
return fprintf(f, "%lu.%09lu\t", ts->tv_sec, ts->tv_nsec);
|
||||
}
|
|
@ -113,36 +113,6 @@ void * alloc(size_t bytes)
|
|||
return p;
|
||||
}
|
||||
|
||||
uint64_t timerfd_wait(int fd)
|
||||
{
|
||||
uint64_t runs;
|
||||
|
||||
return read(fd, &runs, sizeof(runs)) < 0 ? 0 : runs;
|
||||
}
|
||||
|
||||
double timespec_delta(struct timespec *start, struct timespec *end)
|
||||
{
|
||||
double sec = end->tv_sec - start->tv_sec;
|
||||
double nsec = end->tv_nsec - start->tv_nsec;
|
||||
|
||||
if (nsec < 0) {
|
||||
sec -= 1;
|
||||
nsec += 1e9;
|
||||
}
|
||||
|
||||
return sec + nsec * 1e-9;
|
||||
}
|
||||
|
||||
struct timespec timespec_rate(double rate)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = 1 / rate;
|
||||
ts.tv_nsec = 1.0e9 * (1 / rate - ts.tv_sec);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
/** @todo: Proper way: create additional pipe for stderr in child process */
|
||||
int system2(const char *cmd, ...)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue