rtmlib
task_compat.h
Go to the documentation of this file.
1 /*
2  * rtmlib is a Real-Time Monitoring Library.
3  *
4  * Copyright (C) 2018-2020 AndrĂ© Pedro
5  *
6  * This file is part of rtmlib.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef _TASK_COMPAT_H_
23 #define _TASK_COMPAT_H_
24 
25 #include <errno.h>
26 #include <pthread.h>
27 #include <sys/types.h>
28 
29 #include "debug_compat.h"
30 #include "time_compat.h"
31 
32 #ifdef __NUTTX__
33 #define STACK_SIZE 6000
34 #elif defined(__x86__) || defined(__x86_64__)
35 #define STACK_SIZE 1000000
36 #endif
37 
38 #define P_OK 0
39 
40 #define pcheck(val) \
41  if (val != P_OK) { \
42  ::printf("Error: %d\n", val); \
43  return val; \
44  }
45 
46 #define pcheck_print(val, checkval, extra_action) \
47  if (val != checkval) { \
48  ::printf("Error: %d\n", val); \
49  extra_action \
50  }
51 
52 #define pcheck_attr(val, attr) \
53  if (val != P_OK) { \
54  ::printf("Destroying ERROR:%d\n", val); \
55  pthread_attr_destroy(attr); \
56  return val; \
57  }
58 
60 
61 struct task {
62 
63  pthread_t thread;
64 
65  pthread_mutex_t fmtx;
66 
67  pthread_cond_t cond;
68 
69  char const *tid;
70 
71  const useconds_t period;
72 
73  const int sched_policy;
74 
75  const int priority;
76 
77  bool running;
78 
80 
81  void *(*run)(void *);
82 
83  int create_task(void *(*loop)(void *), const int pri, const int s_policy,
84  int stack_size = STACK_SIZE) {
85  pthread_attr_t attribute = {0};
86  struct sched_param parameter;
87 
88  DEBUGV("Task %s started!\n", tid);
89 
90  pcheck(pthread_attr_init(&attribute));
91 
92  pcheck_attr(pthread_attr_setschedpolicy(&attribute, sched_policy),
93  &attribute);
94 
95  pcheck_attr(pthread_attr_setstacksize(&attribute, stack_size), &attribute);
96  DEBUGV("Stack:%d\n", stack_size);
97 
98  DEBUGV("Priority:%d\n", priority);
99  parameter.sched_priority = priority;
100 
101  pcheck_attr(pthread_attr_setschedparam(&attribute, &parameter), &attribute);
102 
103  pcheck_attr(pthread_create(&thread, &attribute, loop, this), &attribute);
104 
105  pcheck(pthread_attr_destroy(&attribute));
106 
107  running = true;
108 
109  return 0;
110  }
111 
112  task(char const *id, void *(*loop)(void *), const int prio,
113  const int sch_policy, const useconds_t p)
114  : tid(id), period(p), sched_policy(sch_policy), priority(prio),
115  run(loop) {
116  create_task(
117  [](void *tsk) -> void * {
118  struct task *ttask = (struct task *)tsk;
119  struct timespec now = {0}, next = {0}, tmp = {0};
120 
121  // Mutex and conditional variables for pthread_cond_timedwait
122  pcheck_print(pthread_mutex_init(&ttask->fmtx, NULL), P_OK,
123  return NULL;);
124  pcheck_print(pthread_cond_init(&ttask->cond, NULL), P_OK,
125  return NULL;);
126 
127  clock_gettime(CLOCK_REALTIME, &next);
128 
129  for (;;) {
130 
131  DEBUGV3("#loop+_%s\n", ttask->tid);
132 
133  clock_gettime(CLOCK_REALTIME, &now);
134 
135  // convert useconds_t to struct timespec
136  struct timespec spec_p;
137 
138  DEBUGV3("useconds: %lu\n", ttask->period);
139 
140  useconds_t2timespec(&ttask->period, &spec_p);
141 
142  DEBUGV3("timespecp: %lu,%lu\n", spec_p.tv_sec, spec_p.tv_nsec);
143  DEBUGV3("timespec: %lu,%lu\n", next.tv_sec, next.tv_nsec);
144 
145  timespecadd(&next, &spec_p, &next);
146 
147  DEBUGV3("timespec2: %lu,%lu\n", next.tv_sec, next.tv_nsec);
148  DEBUGV3("timespecnow: %lu,%lu\n", now.tv_sec, now.tv_nsec);
149 
150  if (timespeccmp(&now, &next, >)) {
151 
152  timespecsub(&next, &now, &tmp);
153  DEBUGV_ERROR("Task is missing their deadline for %lu s.%lu ns\n",
154  tmp.tv_sec, tmp.tv_nsec);
155  }
156 
157  pthread_mutex_lock(&ttask->fmtx);
158  pcheck_print(
159  pthread_cond_timedwait(&ttask->cond, &ttask->fmtx, &next),
160  ETIMEDOUT, break;);
161  pthread_mutex_unlock(&ttask->fmtx);
162 
163  ttask->run(NULL);
164 
165  if (ttask->st == ABORT) {
166  ttask->running = false;
167  return NULL;
168  }
169  }
170 
171  return NULL;
172  },
173  prio, sch_policy);
174  }
175 };
176 
177 typedef struct task __task;
178 
179 #endif //_TASK_COMPAT_H_
pthread_t thread
Definition: task_compat.h:63
#define pcheck_print(val, checkval, extra_action)
Definition: task_compat.h:46
pthread_mutex_t fmtx
Definition: task_compat.h:65
#define pcheck(val)
Definition: task_compat.h:40
const useconds_t period
Definition: task_compat.h:71
#define P_OK
Definition: task_compat.h:38
Definition: task_compat.h:59
#define DEBUGV_ERROR(...)
Definition: debug_compat.h:85
void *(* run)(void *)
Definition: task_compat.h:81
status
Definition: task_compat.h:59
Definition: task_compat.h:59
pthread_cond_t cond
Definition: task_compat.h:67
#define DEBUGV3(...)
Definition: debug_compat.h:84
char const * tid
Definition: task_compat.h:69
#define DEBUGV(...)
Definition: debug_compat.h:83
Definition: task_compat.h:59
#define pcheck_attr(val, attr)
Definition: task_compat.h:52
#define timespecadd(tsp, usp, vsp)
Definition: time_compat.h:105
Definition: task_compat.h:59
Definition: task_compat.h:61
task(char const *id, void *(*loop)(void *), const int prio, const int sch_policy, const useconds_t p)
Definition: task_compat.h:112
int create_task(void *(*loop)(void *), const int pri, const int s_policy, int stack_size=STACK_SIZE)
Definition: task_compat.h:83
Definition: task_compat.h:59
status st
Definition: task_compat.h:79
#define useconds_t2timespec(tsp, vsp)
Definition: time_compat.h:125
const int sched_policy
Definition: task_compat.h:73
Definition: task_compat.h:59
bool running
Definition: task_compat.h:77
#define timespeccmp(tsp, usp, cmp)
Definition: time_compat.h:101
#define timespecsub(tsp, usp, vsp)
Definition: time_compat.h:115
const int priority
Definition: task_compat.h:75