Xenomai 3.** have the following contexts
1 Creating a task & Starting a task
The exercises are based onXenomai 3using theAlchemy API.The example program below creates and starts a task, see also the task management services of the Alchemy API. The codes are
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <alchemy/task.h>
RT_TASK hello_task;
// function to be executed by task
void helloWorld(void *arg)
{
RT_TASK_INFO curtaskinfo;
printf("Hello World!\n");
// inquire current task
rt_task_inquire(NULL,&curtaskinfo);
// print task name
printf("Task name : %s \n", curtaskinfo.name);
}
int main(int argc, char* argv[])
{
char str[10];
printf("start task\n");
sprintf(str,"hello");
/* Create task
* Arguments: &task,
* name,
* stack size (0=default),
* priority,
* mode (FPU, start suspended, ...)
*/
rt_task_create(&hello_task, str, 0, 50, 0);
/* Start task
* Arguments: &task,
* task function,
* function argument
*/
rt_task_start(&hello_task, &helloWorld, 0);
}
To compile the program ex01.c we use the following Makefile
XENO_CONFIG := /usr/xenomai/bin/xeno-config
CFLAGS := $(shell $(XENO_CONFIG) --posix --alchemy --cflags)
LDFLAGS := $(shell $(XENO_CONFIG) --posix --alchemy --ldflags)
CC := gcc
EXECUTABLE := ex01a
all: $(EXECUTABLE)
%: %.c
$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)
clean:
rm -f $(EXECUTABLE)
Note that by adding the “posix” flag in the Makefile,printf
is mapped tort_printf
which puts text to be printed in a buffer. The actual printing is done by a non-real-time periodic thread.
2 Changing a global variable by two tasks
In the example below, two tasks (taskOne and taskTwo), are competing to update the value of a global variable, called “global.” The objective of the program is to toggle the value of the global variable (1s and 0s). TaskOne increments the value of “global” and taskTwo decrements the value.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <alchemy/sem.h>
#define ITER 10
static RT_TASK t1;
static RT_TASK t2;
int global = 0;
void taskOne(void *arg)
{
int i;
for (i=0; i < ITER; i++) {
printf("I am taskOne and global = %d................\n", ++global);
}
}
void taskTwo(void *arg)
{
int i;
for (i=0; i < ITER; i++) {
printf("I am taskTwo and global = %d----------------\n", --global);
}
}
int main(int argc, char* argv[]) {
rt_task_create(&t1, "task1", 0, 1, 0);
rt_task_create(&t2, "task2", 0, 1, 0);
rt_task_start(&t1, &taskOne, 0);
rt_task_start(&t2, &taskTwo, 0);
return 0;
}
3 Priority-Based Scheduling
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <alchemy/task.h>
#include <alchemy/sem.h>
#include <alchemy/timer.h>
#define NTASKS 3
#define HIGH 52 /* high priority */
#define MID 51 /* medium priority */
#define LOW 50 /* low priority */
RT_TASK demo_task[NTASKS];
RT_SEM mysync;
#define EXECTIME 2e8 // execution time in ns
#define SPINTIME 1e7 // spin time in ns
void demo(void *arg)
{
RTIME starttime, runtime;
RT_TASK_INFO taskinfo;
int num=*(int *)arg;
printf("Task : %d\n",num);
rt_sem_p(&mysync,TM_INFINITE);
runtime = 0;
while(runtime < EXECTIME) {
rt_timer_spin(SPINTIME); // spin cpu doing nothing
runtime = runtime + SPINTIME;
printf("Running Task : %d at ms : %d\n",num, runtime/1000000);
}
printf("End Task : %d\n",num);
}
//startup code
void startup()
{
int i;
char str[20] ;
// semaphore to sync task startup on
rt_sem_create(&mysync,"MySemaphore",0,S_FIFO);
for(i=0; i < NTASKS; i++) {
printf("start task : %d\n",i);
sprintf(str,"task%d",i);
rt_task_create(&demo_task[i], str, 0, 50, 0);
rt_task_start(&demo_task[i], &demo, &i);
}
// assign priorities to tasks
rt_task_set_priority(&demo_task[0],LOW);
rt_task_set_priority(&demo_task[1],MID);
rt_task_set_priority(&demo_task[2],HIGH);
printf("wake up all tasks\n");
rt_sem_broadcast(&mysync);
}
int main(int argc, char* argv[])
{
startup();
printf("\nType CTRL-C to end this program\n\n" );
pause();
}
4 Round-robin Scheduling
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <alchemy/task.h>
#include <alchemy/sem.h>
#include <alchemy/timer.h>
#define NTASKS 3
RT_TASK demo_task[NTASKS];
RT_SEM mysync;
#define EXECTIME 2e8 // execution time in ns
#define SPINTIME 1e7 // spin time in ns
void demo(void *arg) {
RTIME starttime, runtime;
int num=*(int *)arg;
printf("Task : %d\n",num);
rt_sem_p(&mysync,TM_INFINITE);
// let the task run RUNTIME ns in steps of SPINTIME ns
runtime = 0;
while(runtime < EXECTIME) {
rt_timer_spin(SPINTIME); // spin cpu doing nothing
runtime = runtime + SPINTIME;
printf("Running Task : %d at time : %d\n",num,runtime);
}
printf("End Task : %d\n",num);
}
//startup code
void startup() {
int i;
char str[20] ;
// semaphore to sync task startup on
rt_sem_create(&mysync,"MySemaphore",0,S_FIFO);
for(i=0; i < NTASKS; i++) {
printf("start task : %d\n",i);
sprintf(str,"task%d",i);
rt_task_create(&demo_task[i], str, 0, 50, 0);
rt_task_start(&demo_task[i], &demo, &i);
}
printf("wake up all tasks\n");
rt_sem_broadcast(&mysync);
}
int main(int argc, char* argv[])
{
startup();
printf("\nType CTRL-C to end this program\n\n" );
pause();
}