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

Add a periodic real-time thread

parent 126b0141
...@@ -9,11 +9,13 @@ SRCS += send_packet.c ...@@ -9,11 +9,13 @@ SRCS += send_packet.c
OBJS = $(SRCS:%.c=%.o) OBJS = $(SRCS:%.c=%.o)
CFLAGS = -O1 -g -Wall -Werror -Wextra CFLAGS = -Og -g -Wall -Werror -Wextra
CFLAGS += -MD -MP CFLAGS += -MD -MP
CFLAGS += -I $(SRCDIR) CFLAGS += -I $(SRCDIR)
CFLAGS += -std=gnu99 CFLAGS += -std=gnu99
LDFLAGS = -pthread
vpath %.c $(SRCDIR) vpath %.c $(SRCDIR)
......
#include <errno.h>
#include <error.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "getip.h" #include "getip.h"
#include "send_packet.h" #include "send_packet.h"
int main(int argc, char * argv[]) { #define CLOCK_ID CLOCK_MONOTONIC
if( argc != 2) { typedef struct thread_stat {
int nb_cycles;
} thread_stat_t;
typedef struct thread_param {
int interval;
int priority;
int max_cycles;
const char *ip_address;
thread_stat_t stats;
} thread_param_t;
// Real-time thread
// Sends packets at a regular intervall
static void *packet_sending_thread(void *p) {
struct timespec next;
struct sched_param priority;
thread_param_t *param = (thread_param_t *)p;
priority.sched_priority = param->priority;
int err = sched_setscheduler(0, SCHED_FIFO, &priority);
if (err)
error(EXIT_FAILURE, errno, "Couldn't set priority");
for(param->stats.nb_cycles = 0;; param->stats.nb_cycles++) {
if(param->max_cycles)
if(param->stats.nb_cycles >= param->max_cycles)
break;
clock_gettime(CLOCK_ID, &next);
next.tv_sec += param->interval;
send_udp_packet(param->ip_address);
clock_nanosleep(CLOCK_ID, TIMER_ABSTIME, &next, NULL);
}
return NULL;
}
static void process_options(int argc, char *argv[], thread_param_t * param) {
for(;;) {
int c = getopt(argc, argv, "l:p:i:");
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;
default:
exit(EXIT_FAILURE);
break;
}
}
if (argc != optind + 1) {
printf("Usage: %s server_ip\n", argv[0]); printf("Usage: %s server_ip\n", argv[0]);
return -1; exit(EXIT_FAILURE);
} }
param->ip_address = argv[optind];
}
// 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;
for(int i = 0; i < 100; i++) // Default values
send_udp_packet(argv[1]); param.interval = 1;
param.max_cycles = -1;
param.priority = 80;
process_options(argc, argv, &param);
int err =
pthread_create(&thread, NULL, packet_sending_thread, (void *)&param);
if(err)
error(EXIT_FAILURE, errno, "Couldn't create thread");
for (;;) {
usleep(100000);
printf("Nb cycles: %d\n", param.stats.nb_cycles);
if( param.max_cycles == param.stats.nb_cycles )
break;
}
return 0; exit(EXIT_SUCCESS);
} }
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <sys/types.h>
#include <arpa/inet.h> #include <unistd.h>
#include <netdb.h>
#define SERVER_PORT "50000" #define SERVER_PORT "50000"
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
static void *get_in_addr(struct sockaddr *sa) { static void *get_in_addr(struct sockaddr *sa) {
if(sa->sa_family == AF_INET) if (sa->sa_family == AF_INET) return &(((struct sockaddr_in *)sa)->sin_addr);
return &(((struct sockaddr_in*) sa)->sin_addr); return &(((struct sockaddr_in6 *)sa)->sin6_addr);
return &(((struct sockaddr_in6*) sa)->sin6_addr);
} }
int main() { int main() {
int status;
int status; int sockfd = 0;
int sockfd = 0; struct addrinfo hints, *servinfo, *servinfo_it;
struct addrinfo hints, *servinfo, *servinfo_it;
int bytes_received = 0;
int bytes_received = 0;
struct sockaddr_storage client_addr;
struct sockaddr_storage client_addr; socklen_t addr_len;
socklen_t addr_len; char client_addr_str[INET6_ADDRSTRLEN];
char client_addr_str[INET6_ADDRSTRLEN];
char buf[BUFFER_SIZE];
char buf[BUFFER_SIZE];
memset(&hints, 0, sizeof hints);
memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM;
hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE;
hints.ai_flags = AI_PASSIVE;
status = getaddrinfo(NULL, SERVER_PORT, &hints, &servinfo);
status = getaddrinfo(NULL, SERVER_PORT, &hints, &servinfo); if (status != 0) {
if( status != 0 ) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); printf("getaddrinfo: %s\n", gai_strerror(status));
printf("getaddrinfo: %s\n", gai_strerror(status)); return 1;
return 1; }
}
for (servinfo_it = servinfo; servinfo_it;
for(servinfo_it = servinfo; servinfo_it; servinfo_it = servinfo_it->ai_next) { servinfo_it = servinfo_it->ai_next) {
sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); sockfd = socket(servinfo->ai_family, servinfo->ai_socktype,
if( sockfd == -1 ) { servinfo->ai_protocol);
printf("Socket error, continuing...\n"); if (sockfd == -1) {
continue; printf("Socket error, continuing...\n");
} continue;
}
if( bind(sockfd, servinfo_it->ai_addr, servinfo_it->ai_addrlen) == -1 ) {
close(sockfd); if (bind(sockfd, servinfo_it->ai_addr, servinfo_it->ai_addrlen) == -1) {
printf("Bind error, continuing...\n"); close(sockfd);
continue; printf("Bind error, continuing...\n");
} continue;
break; }
} break;
}
freeaddrinfo(servinfo);
freeaddrinfo(servinfo);
addr_len = sizeof client_addr;
addr_len = sizeof client_addr;
printf("waiting to recvfrom...\n");
printf("waiting to recvfrom...\n");
while(1) {
while (1) {
if( (bytes_received = recvfrom(sockfd, buf, BUFFER_SIZE-1, 0, if ((bytes_received =
(struct sockaddr *)&client_addr, &addr_len)) == -1) { recvfrom(sockfd, buf, BUFFER_SIZE - 1, 0,
printf("recvfrom error\n"); (struct sockaddr *)&client_addr, &addr_len)) == -1) {
return 2; printf("recvfrom error\n");
} return 2;
}
inet_ntop(client_addr.ss_family,
get_in_addr((struct sockaddr *)&client_addr), inet_ntop(client_addr.ss_family,
client_addr_str, sizeof(client_addr_str)); get_in_addr((struct sockaddr *)&client_addr), client_addr_str,
buf[bytes_received] = '\0'; sizeof(client_addr_str));
buf[bytes_received] = '\0';
printf("got packet from %s: %s (%d long)\n", client_addr_str, buf, bytes_received);
} printf("got packet from %s: %s (%d long)\n", client_addr_str, buf,
bytes_received);
close(sockfd); }
return 0; close(sockfd);
return 0;
} }
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