1
0
Fork 0
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:
Steffen Vogel 2015-06-02 21:59:31 +02:00
parent 08e08e6711
commit 5aa1530baf
8 changed files with 182 additions and 61 deletions

55
server/include/timing.h Normal file
View 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

View file

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

View file

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

View file

@ -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 }
};

View file

@ -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 }
};

View file

@ -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
View 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);
}

View file

@ -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, ...)
{