aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorRoy Spliet <rspliet@eclipso.eu>2013-11-18 17:34:59 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2013-11-27 05:57:55 -0500
commit33efb47a220a3edfcb80ddf7aa20d65c26ebf916 (patch)
treef76b6abdf3ae73f2d38e97c09fb997c19ae1938f /include
parent000d127ec760ac2ec0ecbe403c30c2f85745c5da (diff)
liblitmus: Add Doxygen documentation for public APIs
Diffstat (limited to 'include')
-rw-r--r--include/common.h10
-rw-r--r--include/litmus.h321
-rw-r--r--include/migration.h70
-rw-r--r--include/tests.h59
4 files changed, 414 insertions, 46 deletions
diff --git a/include/common.h b/include/common.h
index d1234ba..fec3721 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1,7 +1,15 @@
1/**
2 * @file common.h
3 * Common miscellaneous functions
4 */
5
1#ifndef COMMON_H 6#ifndef COMMON_H
2#define COMMON_H 7#define COMMON_H
3 8
4 9/**
10 * End the current task with a message
11 * @param msg Message to output before bailing
12 */
5void bail_out(const char* msg); 13void bail_out(const char* msg);
6 14
7#endif 15#endif
diff --git a/include/litmus.h b/include/litmus.h
index dde5469..5a79b7d 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -1,3 +1,25 @@
1/**
2 * @file litmus.h
3 * Public API for LITMUS^RT
4 */
5
6/**
7 * @mainpage
8 * The LITMUS^RT patch is a (soft) real-time extension of the Linux kernel with a
9 * focus on multiprocessor real-time scheduling and synchronization. The Linux
10 * kernel is modified to support the sporadic task model and modular scheduler
11 * plugins. Clustered, partitioned, and global scheduling are included, and
12 * semi-partitioned scheduling is supported as well.
13 *
14 * \b liblitmus is the userspace API for LITMUS^RT. It consists of functions to
15 * control scheduling protocols and parameters, mutexes as well as functionality
16 * to create test suites.
17 *
18 * Example test programs can be found in \b bin/base_task.c and
19 * \b bin/base_task_mt.c . Several test suites are given in the \b tests
20 * directory.
21 */
22
1#ifndef LITMUS_H 23#ifndef LITMUS_H
2#define LITMUS_H 24#define LITMUS_H
3 25
@@ -18,86 +40,237 @@ extern "C" {
18 40
19#include "migration.h" 41#include "migration.h"
20 42
43/**
44 * @private
45 * Number of semaphore protocol object types
46 */
21#define SCHED_LITMUS 6 47#define SCHED_LITMUS 6
22 48
49/**
50 * Initialise a real-time task param struct
51 * @param param Pointer to the struct to initialise
52 */
23void init_rt_task_param(struct rt_task* param); 53void init_rt_task_param(struct rt_task* param);
54/**
55 * Set real-time task parameters for given process
56 * @param pid PID of process
57 * @param param Real-time task parameter struct
58 * @return 0 on success
59 */
24int set_rt_task_param(pid_t pid, struct rt_task* param); 60int set_rt_task_param(pid_t pid, struct rt_task* param);
61/**
62 * Get real-time task parameters for given process
63 * @param pid PID of process
64 * @param param Real-time task parameter struct to fill
65 * @return 0 on success
66 */
25int get_rt_task_param(pid_t pid, struct rt_task* param); 67int get_rt_task_param(pid_t pid, struct rt_task* param);
26 68
27/* Release-master-aware functions for getting the first 69/**
70 * Convert a partition number to a CPU identifier
71 * @param partition Partition number
72 * @return CPU identifier for given partition
73 *
74 * Release-master-aware functions for getting the first
28 * CPU in a particular cluster or partition. Use these 75 * CPU in a particular cluster or partition. Use these
29 * to set rt_task::cpu for cluster/partitioned scheduling. 76 * to set rt_task::cpu for cluster/partitioned scheduling.
30 */ 77 */
31int partition_to_cpu(int partition); 78int partition_to_cpu(int partition);
79/**
80 * For given cluster, return the identifier for the first associated CPU
81 * @param cluster Identifier of the cluster
82 * @param cluster_size Size for this cluster
83 * @return Identifier for the first associated CPU
84 */
32int cluster_to_first_cpu(int cluster, int cluster_size); 85int cluster_to_first_cpu(int cluster, int cluster_size);
33 86
34/* Convenience functions for setting up real-time tasks. 87/* Convenience functions for setting up real-time tasks.
35 * Default behaviors set by init_rt_task_params() used. 88 * Default behaviors set by init_rt_task_params() used.
36 * Also sets affinity masks for clustered/partitions 89 * Also sets affinity masks for clustered/partitions
37 * functions. Time units in nanoseconds. */ 90 * functions. Time units in nanoseconds. */
91/**
92 * Set up a sporadic task with global scheduling
93 * @param e_ns Execution time in nanoseconds
94 * @param p_ns Period in nanoseconds
95 * @return 0 on success
96 */
38int sporadic_global(lt_t e_ns, lt_t p_ns); 97int sporadic_global(lt_t e_ns, lt_t p_ns);
98/**
99 * Set up a sporadic task with partitioned scheduling
100 * @param e_ns Execution time in nanoseconds
101 * @param p_ns Period in nanoseconds
102 * @param partition Identifier for partition to add this task to
103 * @return 0 on success
104 */
39int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition); 105int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition);
106/**
107 * Set up a sporadic task with clustered scheduling
108 * @param e_ns Execution time in nanoseconds
109 * @param p_ns Period in nanoseconds
110 * @param cluster Cluster to add this task to
111 * @param cluster_size Size of the cluster
112 * @return 0 on success
113 */
40int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size); 114int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size);
41 115
42/* simple time unit conversion macros */ 116/* simple time unit conversion macros */
117/** Convert seconds to nanoseconds
118 * @param s Time units in seconds */
43#define s2ns(s) ((s)*1000000000LL) 119#define s2ns(s) ((s)*1000000000LL)
120
121/** Convert seconds to microseconds
122 * @param s Time units in seconds */
44#define s2us(s) ((s)*1000000LL) 123#define s2us(s) ((s)*1000000LL)
124
125/** Convert seconds to milliseconds
126 * @param s Time units in seconds */
45#define s2ms(s) ((s)*1000LL) 127#define s2ms(s) ((s)*1000LL)
128
129/** Convert milliseconds to nanoseconds
130 * @param ms Time units in milliseconds */
46#define ms2ns(ms) ((ms)*1000000LL) 131#define ms2ns(ms) ((ms)*1000000LL)
132
133/** Convert milliseconds to microseconds
134 * @param ms Time units in milliseconds */
47#define ms2us(ms) ((ms)*1000LL) 135#define ms2us(ms) ((ms)*1000LL)
136
137/** Convert microseconds to nanoseconds
138 * @param us Time units in microseconds */
48#define us2ns(us) ((us)*1000LL) 139#define us2ns(us) ((us)*1000LL)
49 140
50/* file descriptor attached shared objects support */ 141/**
142 * Locking protocols for allocated shared objects
143 */
51typedef enum { 144typedef enum {
52 FMLP_SEM = 0, 145 FMLP_SEM = 0, /**< Fifo-based Multiprocessor Locking Protocol */
53 SRP_SEM = 1, 146 SRP_SEM = 1, /**< Stack Resource Protocol */
54 MPCP_SEM = 2, 147 MPCP_SEM = 2, /**< Multiprocessor Priority Ceiling Protocol */
55 MPCP_VS_SEM = 3, 148 MPCP_VS_SEM = 3, /**< Multiprocessor Priority Ceiling Protocol with
56 DPCP_SEM = 4, 149 Virtual Spinning */
57 PCP_SEM = 5, 150 DPCP_SEM = 4, /**< Distributed Priority Ceiling Protocol */
151 PCP_SEM = 5, /**< Priority Ceiling Protocol */
58} obj_type_t; 152} obj_type_t;
59 153
154/**
155 * For given protocol name, return semaphore object type id
156 * @param name String representation of protocol name
157 * @return Object type ID as integer
158 */
60int lock_protocol_for_name(const char* name); 159int lock_protocol_for_name(const char* name);
160/**
161 * For given semaphore object type id, return the name of the protocol
162 * @param id Semaphore object type ID
163 * @return Name of the locking protocol
164 */
61const char* name_for_lock_protocol(int id); 165const char* name_for_lock_protocol(int id);
62 166
167/**
168 * @private
169 * Do a syscall for opening a generic lock
170 */
63int od_openx(int fd, obj_type_t type, int obj_id, void* config); 171int od_openx(int fd, obj_type_t type, int obj_id, void* config);
172/**
173 * Close a lock, given its object descriptor
174 * @param od Object descriptor for lock to close
175 * @return 0 Iff the lock was successfully closed
176 */
64int od_close(int od); 177int od_close(int od);
65 178
179/**
180 * @private
181 * Generic lock opening method
182 */
66static inline int od_open(int fd, obj_type_t type, int obj_id) 183static inline int od_open(int fd, obj_type_t type, int obj_id)
67{ 184{
68 return od_openx(fd, type, obj_id, 0); 185 return od_openx(fd, type, obj_id, 0);
69} 186}
70 187
71int litmus_open_lock( 188/**
72 obj_type_t protocol, /* which locking protocol to use, e.g., FMLP_SEM */ 189 * public:
73 int lock_id, /* numerical id of the lock, user-specified */ 190 * Open a lock, mark it used by the invoking thread
74 const char* name_space, /* path to a shared file */ 191 * @param protocol Desired locking protocol
75 void *config_param); /* any extra info needed by the protocol (such 192 * @param lock_id Name of the lock, user-specified numerical id
76 * as CPU under SRP and PCP), may be NULL */ 193 * @param name_space Path to a shared file
194 * @param config_param Any extra info needed by the protocol (like CPU for SRP
195 * or PCP), may be NULL
196 * @return Object descriptor for this lock
197 */
198int litmus_open_lock(obj_type_t protocol, int lock_id, const char* name_space,
199 void *config_param);
77 200
78/* real-time locking protocol support */ 201/**
202 * Obtain lock
203 * @param od Object descriptor obtained by litmus_open_lock()
204 * @return 0 iff the lock was opened successfully
205 */
79int litmus_lock(int od); 206int litmus_lock(int od);
207/**
208 * Release lock
209 * @param od Object descriptor obtained by litmus_open_lock()
210 * @return 0 iff the lock was released successfully
211 */
80int litmus_unlock(int od); 212int litmus_unlock(int od);
81 213
82/* job control*/ 214/***** job control *****/
215/**
216 * @todo Doxygen
217 */
83int get_job_no(unsigned int* job_no); 218int get_job_no(unsigned int* job_no);
219/**
220 * @todo Doxygen
221 */
84int wait_for_job_release(unsigned int job_no); 222int wait_for_job_release(unsigned int job_no);
223/**
224 * Sleep until next period
225 * @return 0 on success
226 */
85int sleep_next_period(void); 227int sleep_next_period(void);
86 228
87/* library functions */ 229/**
230 * Initialises real-time properties for the entire program
231 * @return 0 on success
232 */
88int init_litmus(void); 233int init_litmus(void);
234/**
235 * Initialises real-time properties for current thread
236 * @return 0 on success
237 */
89int init_rt_thread(void); 238int init_rt_thread(void);
239/**
240 * Cleans up real-time properties for the entire program
241 */
90void exit_litmus(void); 242void exit_litmus(void);
91 243
92/* A real-time program. */ 244/* A real-time program. */
93typedef int (*rt_fn_t)(void*); 245typedef int (*rt_fn_t)(void*);
94 246
95/* These two functions configure the RT task to use enforced exe budgets. 247/**
96 * Partitioned scheduling: cluster = desired partition, cluster_size = 1 248 * Create a real-time task that enforces exectution budgets
97 * Global scheduling: cluster = 0, cluster_size = 0 249 * @param rt_prog Function pointer to real-time task body
250 * @param arg Pointer to arguments to pass to the pointer in rt_prog
251 * @param cluster Cluster to schedule this task on. For partitioned scheduling,
252 * set to the desired partition. For global scheduling, set to 0
253 * @param cluster_size Size of the cluster. For partitioned scheduling, set to
254 * 1, for global scheduling set to 0.
255 * @param wcet Worst-Case execution time for this task
256 * @param period Period at which this task should be launched
257 * @param prio Priority for this task
98 */ 258 */
99int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, 259int create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size,
100 lt_t wcet, lt_t period, unsigned int prio); 260 lt_t wcet, lt_t period, unsigned int prio);
261/**
262 * Create a real-time task
263 * @param rt_prog Function pointer to real-time task body
264 * @param arg Pointer to arguments to pass to the pointer in rt_prog
265 * @param cluster Cluster to schedule this task on. For partitioned scheduling,
266 * set to the desired partition. For global scheduling, set to 0
267 * @param cluster_size Size of the cluster. For partitioned scheduling, set to
268 * 1, for global scheduling set to 0.
269 * @param wcet Worst-Case execution time for this task
270 * @param period Period at which this task should be launched
271 * @param prio Priority for this task
272 * @param cls Task class (???)
273 */
101int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size, 274int __create_rt_task(rt_fn_t rt_prog, void *arg, int cluster, int cluster_size,
102 lt_t wcet, lt_t period, unsigned int prio, task_class_t cls); 275 lt_t wcet, lt_t period, unsigned int prio, task_class_t cls);
103 276
@@ -106,65 +279,149 @@ enum rt_task_mode_t {
106 BACKGROUND_TASK = 0, 279 BACKGROUND_TASK = 0,
107 LITMUS_RT_TASK = 1 280 LITMUS_RT_TASK = 1
108}; 281};
282/**
283 * Set the task mode for current thread
284 * @param target_mode Desired mode, see enum rt_task_mode_t for valid values
285 * @return 0 iff taskmode was set correctly
286 */
109int task_mode(int target_mode); 287int task_mode(int target_mode);
110 288
289/**
290 * @todo Document
291 */
111void show_rt_param(struct rt_task* tp); 292void show_rt_param(struct rt_task* tp);
293/**
294 * @todo Document
295 */
112task_class_t str2class(const char* str); 296task_class_t str2class(const char* str);
113 297
114/* non-preemptive section support */ 298/**
299 * Enter non-preemtpive section for current thread
300 */
115void enter_np(void); 301void enter_np(void);
302/**
303 * Exit non-preemtpive section for current thread
304 */
116void exit_np(void); 305void exit_np(void);
306/**
307 * Find out whether task should have preempted
308 * @return 1 iff the task was requested to preempt while running non-preemptive
309 */
117int requested_to_preempt(void); 310int requested_to_preempt(void);
118 311
119/* task system support */ 312/***** Task System support *****/
313/**
314 * Wait until task master releases all real-time tasks
315 * @return 0 Iff task was successfully released
316 */
120int wait_for_ts_release(void); 317int wait_for_ts_release(void);
318/**
319 * Release all tasks in the task system
320 * @param delay Time to wait
321 * @return Number of tasks released
322 *
323 * Used by a task master to release all threads after each of them has been
324 * set up.
325 */
121int release_ts(lt_t *delay); 326int release_ts(lt_t *delay);
327/**
328 * Obtain the number of currently waiting tasks
329 * @return The number of waiting tasks
330 */
122int get_nr_ts_release_waiters(void); 331int get_nr_ts_release_waiters(void);
332/**
333 * @todo Document
334 */
123int read_litmus_stats(int *ready, int *total); 335int read_litmus_stats(int *ready, int *total);
124 336
125/* sleep for some number of nanoseconds */ 337/**
338 * Sleep for given time
339 * @param timeout Sleep time in nanoseconds
340 * @return 0 on success
341 */
126int lt_sleep(lt_t timeout); 342int lt_sleep(lt_t timeout);
127 343
128/* CPU time consumed so far in seconds */ 344/**
345 * Obtain CPU time consumed so far
346 * @return CPU time in seconds
347 */
129double cputime(void); 348double cputime(void);
130 349
131/* wall-clock time in seconds */ 350/**
351 * Obtain wall-clock time
352 * @return Wall-clock time in seconds
353 */
132double wctime(void); 354double wctime(void);
133 355
134/* semaphore allocation */ 356/***** semaphore allocation ******/
135 357/**
358 * Allocate a semaphore following the FMLP protocol
359 * @param fd File descriptor to associate lock with
360 * @param name Name of the lock, user-chosen integer
361 * @return Object descriptor for given lock
362 */
136static inline int open_fmlp_sem(int fd, int name) 363static inline int open_fmlp_sem(int fd, int name)
137{ 364{
138 return od_open(fd, FMLP_SEM, name); 365 return od_open(fd, FMLP_SEM, name);
139} 366}
140 367
368/**
369 * Allocate a semaphore following the SRP protocol
370 * @param fd File descriptor to associate lock with
371 * @param name Name of the lock, user-chosen integer
372 * @return Object descriptor for given lock
373 */
141static inline int open_srp_sem(int fd, int name) 374static inline int open_srp_sem(int fd, int name)
142{ 375{
143 return od_open(fd, SRP_SEM, name); 376 return od_open(fd, SRP_SEM, name);
144} 377}
145 378
379/**
380 * Allocate a semaphore following the PCP protocol
381 * @param fd File descriptor to associate lock with
382 * @param name Name of the lock, user-chosen integer
383 * @param cpu CPU to associate this lock with
384 * @return Object descriptor for given lock
385 */
146static inline int open_pcp_sem(int fd, int name, int cpu) 386static inline int open_pcp_sem(int fd, int name, int cpu)
147{ 387{
148 return od_openx(fd, PCP_SEM, name, &cpu); 388 return od_openx(fd, PCP_SEM, name, &cpu);
149} 389}
150 390
391/**
392 * Allocate a semaphore following the MPCP protocol
393 * @param fd File descriptor to associate lock with
394 * @param name Name of the lock, user-chosen integer
395 * @return Object descriptor for given lock
396 */
151static inline int open_mpcp_sem(int fd, int name) 397static inline int open_mpcp_sem(int fd, int name)
152{ 398{
153 return od_open(fd, MPCP_SEM, name); 399 return od_open(fd, MPCP_SEM, name);
154} 400}
155 401
402/**
403 * Allocate a semaphore following the DPCP protocol
404 * @param fd File descriptor to associate lock with
405 * @param name Name of the lock, user-chosen integer
406 * @param cpu CPU to associate this lock with
407 * @return Object descriptor for given lock
408 */
156static inline int open_dpcp_sem(int fd, int name, int cpu) 409static inline int open_dpcp_sem(int fd, int name, int cpu)
157{ 410{
158 return od_openx(fd, DPCP_SEM, name, &cpu); 411 return od_openx(fd, DPCP_SEM, name, &cpu);
159} 412}
160 413
161 414/**
162/* syscall overhead measuring */ 415 * Do nothing as a syscall
416 * @param timestamp Cyclecount before calling
417 * Can be used for syscall overhead measuring */
163int null_call(cycles_t *timestamp); 418int null_call(cycles_t *timestamp);
164 419
165/* 420/**
166 * get control page: 421 * Get control page:
167 * atm it is used only by preemption migration overhead code 422 * @return Pointer to the current tasks control page
423 *
424 * Atm it is used only by preemption migration overhead code,
168 * but it is very general and can be used for different purposes 425 * but it is very general and can be used for different purposes
169 */ 426 */
170struct control_page* get_ctrl_page(void); 427struct control_page* get_ctrl_page(void);
diff --git a/include/migration.h b/include/migration.h
index 2413e7c..32d933b 100644
--- a/include/migration.h
+++ b/include/migration.h
@@ -1,24 +1,80 @@
1/**
2 * @file migration.h
3 * Functions to migrate tasks to different CPUs, partitions, clusters...
4 */
1 5
2typedef int pid_t; 6typedef int pid_t;
3 7
4/* obtain the PID of a thread */ 8/**
9 * obtain the PID of a thread (TID)
10 * @return The PID of a thread
11 */
5pid_t gettid(); 12pid_t gettid();
6 13
7/* Assign a task to a cpu/partition/cluster. 14/**
8 * PRECOND: tid is not yet in real-time mode (it's a best effort task). 15 * Migrate and assign a task to a given CPU
9 * Set tid == 0 to migrate the caller */ 16 * @param tid Process ID for migrated task, 0 for current task
17 * @param target_cpu ID for CPU to migrate to
18 * @pre tid is not yet in real-time mode (it's a best effort task)
19 * @return 0 if successful
20 */
10int be_migrate_thread_to_cpu(pid_t tid, int target_cpu); 21int be_migrate_thread_to_cpu(pid_t tid, int target_cpu);
22/**
23 * Migrate and assign a task to a given partition
24 * @param tid Process ID for migrated task, 0 for current task
25 * @param partition Partition ID to migrate the task to
26 * @pre tid is not yet in real-time mode (it's a best effort task)
27 * @return 0 if successful
28 */
11int be_migrate_thread_to_partition(pid_t tid, int partition); 29int be_migrate_thread_to_partition(pid_t tid, int partition);
12/* If using release master, set cluster_sz to size of largest cluster. tid 30/**
13 * will not be scheduled on release master. */ 31 * Migrate current task to a given cluster
32 * @param tid Process ID for migrated task, 0 for current task
33 * @param cluster Cluster ID to migrate the task to
34 * @param cluster_sz Size of the cluster to migrate to
35 * @pre tid is not yet in real-time mode (it's a best effort task)
36 * @return 0 if successful
37 *
38 * If using release master, set cluster_sz to size of largest cluster. tid
39 * will not be scheduled on release master
40 */
14int be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz); 41int be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz);
15 42
16/* set ignore_rm == 1 to include release master in tid's cpu affinity */ 43/**
44 * @private
45 * set ignore_rm == 1 to include release master in tid's cpu affinity
46 */
17int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, int ignore_rm); 47int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, int ignore_rm);
18 48
49/**
50 * Migrate current task to a given CPU
51 * @param target_cpu ID for CPU to migrate to
52 * @pre tid is not yet in real-time mode (it's a best effort task)
53 * @return 0 if successful
54 */
19int be_migrate_to_cpu(int target_cpu); 55int be_migrate_to_cpu(int target_cpu);
56/**
57 * Migrate current task to a given partition
58 * @param partition Partition ID to migrate the task to
59 * @pre tid is not yet in real-time mode (it's a best effort task)
60 * @return 0 if successful
61 */
20int be_migrate_to_partition(int partition); 62int be_migrate_to_partition(int partition);
63/**
64 * Migrate current task to a given cluster
65 * @param cluster Cluster ID to migrate the task to
66 * @param cluster_sz Size of the cluster to migrate to
67 * @pre tid is not yet in real-time mode (it's a best effort task)
68 * @return 0 if successful
69 */
21int be_migrate_to_cluster(int cluster, int cluster_sz); 70int be_migrate_to_cluster(int cluster, int cluster_sz);
22 71
72/**
73 * Return the number of CPUs currently online
74 * @return The number of online CPUs
75 */
23int num_online_cpus(); 76int num_online_cpus();
77/**
78 * @todo Document!
79 */
24int release_master(); 80int release_master();
diff --git a/include/tests.h b/include/tests.h
index 4ca21f8..0c3248e 100644
--- a/include/tests.h
+++ b/include/tests.h
@@ -1,3 +1,8 @@
1/**
2 * @file tests.h
3 * Structs and macro's for use in unit test cases
4 */
5
1#ifndef TESTS_H 6#ifndef TESTS_H
2#define TESTS_H 7#define TESTS_H
3 8
@@ -5,6 +10,12 @@
5#include <stdlib.h> 10#include <stdlib.h>
6#include <errno.h> 11#include <errno.h>
7 12
13/**
14 * @private
15 * Print a failure message and exit
16 * @param fmt Error string
17 * @param args... Parameters for error string
18 */
8#define fail(fmt, args...) \ 19#define fail(fmt, args...) \
9 do { \ 20 do { \
10 fprintf(stderr, "\n!! TEST FAILURE " fmt \ 21 fprintf(stderr, "\n!! TEST FAILURE " fmt \
@@ -16,12 +27,20 @@
16 exit(200); \ 27 exit(200); \
17 } while (0) 28 } while (0)
18 29
30/**
31 * Assert given predicate, print error if it doesn't hold
32 * @param predicate Predicate that must hold
33 */
19#define ASSERT(predicate) \ 34#define ASSERT(predicate) \
20 do { \ 35 do { \
21 if (!(predicate)) \ 36 if (!(predicate)) \
22 fail("%s", #predicate); \ 37 fail("%s", #predicate); \
23 } while (0) 38 } while (0)
24 39
40/**
41 * Do and trace a syscall
42 * @param call Syscall to execute
43 */
25#define SYSCALL(call) \ 44#define SYSCALL(call) \
26 do { \ 45 do { \
27 int __test_ret = (call); \ 46 int __test_ret = (call); \
@@ -29,6 +48,11 @@
29 fail("%s -> %d, %m", #call, __test_ret); \ 48 fail("%s -> %d, %m", #call, __test_ret); \
30 } while (0) 49 } while (0)
31 50
51/**
52 * Do and trace a syscall that is expected to fail
53 * @param expected Expected error code
54 * @param call Syscall to execute
55 */
32#define SYSCALL_FAILS(expected, call) \ 56#define SYSCALL_FAILS(expected, call) \
33 do { \ 57 do { \
34 int __test_ret = (call); \ 58 int __test_ret = (call); \
@@ -37,22 +61,45 @@
37 #call, __test_ret, #expected); \ 61 #call, __test_ret, #expected); \
38 } while (0) 62 } while (0)
39 63
40 64/**
65 * Function prototype for a single test case
66 */
41typedef void (*testfun_t)(void); 67typedef void (*testfun_t)(void);
42 68
69/**
70 * Test case
71 */
43struct testcase { 72struct testcase {
44 testfun_t function; 73 testfun_t function; /**< Function-pointer to test-case */
45 const char* description; 74 const char* description; /**< Description of test-case */
46}; 75};
47 76
77/**
78 * Suite containing several test cases
79 */
48struct testsuite { 80struct testsuite {
49 const char* plugin; 81 const char* plugin; /**< Lock scheduling plugin to use */
50 int* testcases; 82 int* testcases; /**< Pointer to array of test-cases
51 int num_cases; 83 @todo why not struct testcase?*/
84 int num_cases; /**< Number of test cases in this suite */
52}; 85};
53 86
87/**
88 * Function descriptor for test case
89 * @param function Test name
90 * @param plugins Set of lock scheduling plugins this test case is applicable
91 * for, separated by |
92 * @param description Textual description of the test case
93 *
94 * Testcases defined with this macro will get picked up by a python test suite
95 * generator
96 */
54#define TESTCASE(function, plugins, description) void test_ ## function (void) 97#define TESTCASE(function, plugins, description) void test_ ## function (void)
55 98
99/**
100 * Fork given function body as separate thread
101 * @param code Function body
102 */
56#define FORK_TASK(code) ({int __pid = fork(); if (__pid == 0) {code; exit(0);}; __pid;}) 103#define FORK_TASK(code) ({int __pid = fork(); if (__pid == 0) {code; exit(0);}; __pid;})
57 104
58#endif 105#endif