Commit d1170af3 authored by Joanne Hugé's avatar Joanne Hugé

Add clockres module

parent 1d9316bf
ARM_CC = arm-linux-gnueabihf-gcc
ARM_PROG = clockres_arm
PROG = clockres
SRCDIR = ../src
SRCS = clockres.c
OBJS = $(SRCS:%.c=%.o)
CFLAGS = -Og -g -Wall -Wextra
CFLAGS += -MD -MP
CFLAGS += -I $(SRCDIR)
CFLAGS += -std=gnu99
LDFLAGS = -pthread
vpath %.c $(SRCDIR)
$(ARM_PROG): FORCE
make clean
make -e CC:=arm-linux-gnueabihf-gcc $(PROG)
mv $(PROG) $(ARM_PROG)
FORCE:
$(PROG): $(OBJS)
$(CC) $(LDFLAGS) $^ -o $@
-include $(subst .c,.d,$(SRCS))
run: $(PROG)
./$^
clean:
$(RM) $(OBJS) $(PROG) $(subst .c,.d,$(SRCS))
.PHONY: clean FORCE
#include <errno.h>
#include <error.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdint.h>
#include <inttypes.h>
#define CLOCK_ID CLOCK_MONOTONIC
#define NSECS_PER_SECOND INT64_C(1000000000)
typedef struct thread_stat {
int nb_cycles;
int64_t max_res;
int64_t min_res;
} thread_stat_t;
typedef struct thread_param {
int priority;
int max_cycles;
int64_t interval;
thread_stat_t stat;
} thread_param_t;
typedef struct main_param {
int refresh_rate;
} main_param_t;
static inline int64_t diff_ns(struct timespec t1, struct timespec t2) {
int64_t diff;
diff = NSECS_PER_SECOND * (t1.tv_sec - t2.tv_sec);
diff += ((int64_t)t1.tv_nsec) - ((int64_t)t2.tv_nsec);
if( diff < 0 )
diff = -diff;
return diff;
}
static inline int64_t max(int64_t a, int64_t b) {
return a > b ? a : b;
}
static inline int64_t min(int64_t a, int64_t b) {
return a < b ? a : b;
}
// Real-time thread
// Sends packets at a regular intervall
static void *timerthread(void *p) {
struct timespec previous;
struct timespec current;
struct sched_param priority;
thread_param_t * param = (thread_param_t *)p;
thread_stat_t * stat = &param->stat;
priority.sched_priority = param->priority;
int err = sched_setscheduler(0, SCHED_FIFO, &priority);
if (err)
error(EXIT_FAILURE, errno, "Couldn't set priority");
stat->max_res = 0;
stat->min_res = 1000000;
for(stat->nb_cycles = 0;; stat->nb_cycles++) {
if(param->max_cycles)
if(stat->nb_cycles >= param->max_cycles)
break;
clock_gettime(CLOCK_ID, &previous);
clock_gettime(CLOCK_ID, &current);
int64_t res = diff_ns(previous, current);
stat->max_res = max(stat->max_res, res);
stat->min_res = min(stat->min_res, res);
usleep(param->interval);
}
printf("Done\n");
return NULL;
}
static void process_options(int argc, char *argv[], thread_param_t * param, main_param_t * main_param) {
for(;;) {
int c = getopt(argc, argv, "l:p:i:r:");
if(c == -1)
break;
switch(c) {
case 'p':
param->priority = atoi(optarg);
break;
case 'l':
param->max_cycles = atoi(optarg);
break;
case 'i':
param->interval = atoi(optarg);
break;
case 'r':
main_param->refresh_rate = atoi(optarg);
break;
default:
exit(EXIT_FAILURE);
break;
}
}
}
// Main thread, has non-real time priority
// Handles the IO and creates real time threads
int main(int argc, char *argv[]) {
pthread_t thread;
thread_param_t param;
main_param_t main_param;
int err;
// Default values
param.interval= 100;
param.max_cycles = 100000;
param.priority = 99;
main_param.refresh_rate = 10000;
process_options(argc, argv, &param, &main_param);
usleep(10000);
err = pthread_create(&thread, NULL, timerthread, (void *)&param);
if(err)
error(EXIT_FAILURE, errno, "Couldn't create thread");
for (;;) {
usleep(main_param.refresh_rate);
printf("Maximum res: %" PRIi64 "ns (%d)", (param.stat.max_res), param.stat.nb_cycles);
printf(", minimum res: %" PRIi64 "ns (%d)\n", (param.stat.min_res), param.stat.nb_cycles);
if( param.max_cycles == param.stat.nb_cycles )
break;
}
exit(EXIT_SUCCESS);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment