+ SDL diagram

~ refactoring
This commit is contained in:
Johannes Theiner 2020-10-26 10:38:48 +01:00
parent ed75b5e575
commit d795038445
Signed by: joethei
GPG Key ID: 9D2B9A00FDA85BCD
32 changed files with 7834 additions and 97 deletions

View File

@ -3,6 +3,10 @@
#include <uint128.h> #include <uint128.h>
#include <sys/rtai_modbus.h> #include <sys/rtai_modbus.h>
#include "include/rtai_lxrt.h"
#include "include/rtai_modbus.h"
#include "include/rtai_sem.h"
#include "include/rtai_mbx.h"
#define SENSOR_PART_TURNTABLE 1<<0 #define SENSOR_PART_TURNTABLE 1<<0
#define SENSOR_PART_DRILL 1<<1 #define SENSOR_PART_DRILL 1<<1
@ -24,21 +28,40 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static RT_TASK turntable_task, drill_task, tester_task, output_task; static RT_TASK turntable_task, drill_task, tester_task, output_task;
static MBX drill_mbx, tester_mbx, output_mbx; static MBX tester_mbx, output_mbx;
static SEM semaphore; static SEM semaphore;
int connection;
char node[] = "modbus-node"; char node[] = "modbus-node";
void fail() {
rt_modbus_disconnect(connection);
rt_task_delete(&turntable_task);
rt_task_delete(&tester_task);
rt_task_delete(&drill_task);
rt_task_delete(&output_task);
rt_mbx_delete(&tester_mbx);
rt_mbx_delete(&output_mbx);
rt_sem_delete(&semaphore);
stop_rt_timer();
rt_printk("failed to read/send Modbus message.\n");
rt_printk("module needs to be restarted.\n");
}
/** /**
* read all bits of the specified type * readData all bits of the specified type
* this function is *not* thread safe. * this function is *not* thread safe.
* @param type (DIGITAL_IN, DIGITAL_OUT, ANALOG_IN, ANALOG_OUT) * @param type (DIGITAL_IN, DIGITAL_OUT, ANALOG_IN, ANALOG_OUT)
* @param connection modbus connection id * @param connection modbus connection id
* @param result value to write the result to * @param result value to write the result to
* @return status code(0: success, 1: failure) * @return status code(0: success, 1: failure)
*/ */
int readAll(int type, int connection, int *result) { int readAll(int type, int *result) {
return rt_modbus_get(fd_node, type, 0, (unsigned short *) &result)); return rt_modbus_get(connection, type, 0, (unsigned short *) &result));
} }
/** /**
@ -49,10 +72,10 @@ int readAll(int type, int connection, int *result) {
* @param result value to write the result to * @param result value to write the result to
* @return status code(0: success, 1: failure) * @return status code(0: success, 1: failure)
*/ */
int read(int connection, int part, int *result) { int readData(int part, int *result) {
rt_sem_wait(&semaphore); rt_sem_wait(&semaphore);
int value; int value;
int code = readAll(DIGITAL_IN, connection, &value); int code = readAll(DIGITAL_IN, &value);
*result = (value & part) != 0; *result = (value & part) != 0;
rt_sem_signal(&semaphore); rt_sem_signal(&semaphore);
return code; return code;
@ -63,16 +86,15 @@ int read(int connection, int part, int *result) {
* this function is thread safe. * this function is thread safe.
* @param connection modbus connection id * @param connection modbus connection id
* @param actor bitmask of the actor to disable * @param actor bitmask of the actor to disable
* @return status code(0: success, 1: failure)
*/ */
int disable(int connection, int actor) { void disable(int actor) {
rt_sem_wait(&semaphore); rt_sem_wait(&semaphore);
int value; int value;
int code = readAll(DIGITAL_OUT, connection, &value); int code = readAll(DIGITAL_OUT, &value);
if (code) return code; if(code) fail();
int result = rt_modbus_set(connection, DIGITAL_OUT, output &= ~actor) int result = rt_modbus_set(connection, DIGITAL_OUT, value &= ~actor)
rt_sem_signal(&semaphore); rt_sem_signal(&semaphore);
return result; if (result) fail();
} }
/** /**
@ -80,155 +102,99 @@ int disable(int connection, int actor) {
* this function is thread safe. * this function is thread safe.
* @param connection modbus connection id * @param connection modbus connection id
* @param actor bitmask of the actor to enable * @param actor bitmask of the actor to enable
* @return status code (0: success, 1: failure)
*/ */
int enable(int connection, int actor) { void enable(int actor) {
rt_sem_wait(&semaphore); rt_sem_wait(&semaphore);
int output; int output;
int code = readAll(DIGITAL_OUT, connection, &output); int code = readAll(DIGITAL_OUT, &output);
if (code) return code; if (code) fail();
int result = rt_modbus_set(connection, DIGITAL_OUT, output |= actor) int result = rt_modbus_set(connection, DIGITAL_OUT, output |= actor)
rt_sem_signal(&semaphore); rt_sem_signal(&semaphore);
return result; if(result) fail();
} }
void sleep() { void sleepStuff() {
rt_sleep(1000 * nano2count(1000000)); rt_sleep(1000 * nano2count(1000000));
} }
static void turntable(long x) { static void turntable(long x) {
int connection;
rt_printk("turntable: task started\n");
if ((connection = rt_modbus_connect(node)) == -1) {
rt_printk("turntable: could not connect to %s\n", node);
return;
}
rt_printk("turntable: MODBUS communication opened\n"); rt_printk("turntable: MODBUS communication opened\n");
disable(connection, ACTOR_TURNTABLE); disable(ACTOR_TURNTABLE);
while (1) { while (1) {
int partOnTable; int partOnTable;
if (read(connection, SENSOR_PART_TURNTABLE, &partOnTable)) goto fail; readData(SENSOR_PART_TURNTABLE, &partOnTable);
if (partOnTable) { if (partOnTable) {
if (enable(connection, ACTOR_TURNTABLE)) goto fail; enable(ACTOR_TURNTABLE);
} else { } else {
if (disable(connection, ACTOR_TURNTABLE)) goto fail; disable(ACTOR_TURNTABLE);
} }
rt_task_resume(&drill_task); rt_task_resume(&drill_task);
rt_task_resume(&tester_task); rt_task_resume(&tester_task);
rt_task_resume(&output_task); rt_task_resume(&output_task);
//rt_sleep(1000 * nano2count(1000000));
} }
/* Aufraeumen */
fail:
rt_modbus_disconnect(connection);
rt_printk("turntable: task exited with failure\n");
} }
static void drill(long x) { static void drill(long x) {
int connection;
rt_printk("drill: task started\n");
if ((connection = rt_modbus_connect(node)) == -1) {
rt_printk("drill: could not connect to %s\n", node);
return;
}
rt_printk("drill: MODBUS communication opened\n"); rt_printk("drill: MODBUS communication opened\n");
disable(connection, ACTOR_DRILL); disable(ACTOR_DRILL);
disable(connection, ACTOR_PART_HOLD); disable(ACTOR_PART_HOLD);
disable(connection, ACTOR_DRILL_DOWN); disable(ACTOR_DRILL_DOWN);
enable(connection, ACTOR_DRILL_UP); enable(ACTOR_DRILL_UP);
rt_sem_wait(&semaphore);
int drill_up = 0; int drill_up = 0;
if (read(connection, SENSOR_DRILL_UP, drill_up)) goto fail; readData(SENSOR_DRILL_UP, drill_up);
if (!drill_up) { if (!drill_up) {
do { do {
read(connection, SENSOR_DRILL_UP, drill_up); readData(SENSOR_DRILL_UP, drill_up);
} while (drill_up == 0); } while (drill_up == 0);
} }
disable(connection, ACTOR_DRILL_UP); rt_sem_signal(&semaphore);
disable(ACTOR_DRILL_UP);
while (1) { while (1) {
sleep(); sleepStuff();
} }
fail:
rt_modbus_disconnect(connection);
rt_printk("drill: task exited with failure\n");
} }
static void tester(long x) { static void tester(long x) {
int connection;
rt_printk("tester: task started\n");
if ((connection = rt_modbus_connect(node)) == -1) {
rt_printk("tester: could not connect to %s\n", node);
return;
}
while (1) { while (1) {
sleep(); sleepStuff();
} }
fail:
rt_modbus_disconnect(connection);
rt_printk("tester: task exited with failure\n");
} }
static void output(long x) { static void output(long x) {
int connection;
rt_printk("output: task started\n");
if ((connection = rt_modbus_connect(node)) == -1) {
rt_printk("output: could not connect to %s\n", node);
return;
}
while (1) { while (1) {
sleep(); sleepStuff();
} }
fail:
rt_modbus_disconnect(connection);
rt_printk("output: task exited with failure\n");
}
static void __exit
example_exit(void) {
rt_task_delete(&turntable_task);
rt_task_delete(&drill_task);
rt_task_delete(&tester_task);
rt_task_delete(&output_task);
stop_rt_timer();
rt_sem_delete(&semaphore);
printk("module Bearbeiten2 unloaded\n");
} }
static int __init static int __init
example_init(void) { example_init(void) {
rt_set_oneshot_mode(); rt_set_oneshot_mode();
start_rt_timer(0); start_rt_timer(0);
modbus_init(); modbus_init();
rt_printk("init: task started\n");
if ((connection = rt_modbus_connect(node)) == -1) {
rt_printk("init: could not connect to %s\n", node);
return;
}
rt_sem_init(&semaphore, 1); rt_sem_init(&semaphore, 1);
if (rt_task_init(&turntable_task, turntable, 0, 1024, 0, 0, NULL)) { if (rt_task_init(&turntable_task, turntable, 0, 1024, 10, 0, NULL)) {
printk("turntable: cannot initialize task\n"); printk("turntable: cannot initialize task\n");
goto fail; goto fail;
} }
@ -254,5 +220,16 @@ example_init(void) {
return (1); return (1);
} }
static void __exit
example_exit(void) {
rt_task_delete(&turntable_task);
rt_task_delete(&drill_task);
rt_task_delete(&tester_task);
rt_task_delete(&output_task);
stop_rt_timer();
rt_sem_delete(&semaphore);
printk("module Bearbeiten2 unloaded\n");
}
module_exit(example_exit) module_exit(example_exit)
module_init(example_init) module_init(example_init)

View File

@ -1,4 +1,7 @@
cmake_minimum_required(VERSION 3.3) cmake_minimum_required(VERSION 3.3)
project(Echtzeitdatenverarbeitung) project(Echtzeitdatenverarbeitung)
SET(CMAKE_C_STANDARD C99)
include_directories("include")
add_executable(Bearbeiten2 Bearbeiten2.c) add_executable(Bearbeiten2 Bearbeiten2.c)

1
README.md Normal file
View File

@ -0,0 +1 @@
![SDL Diagramm](https://files.joethei.space/documentation/diagram.png)

96
diagram.puml Normal file
View File

@ -0,0 +1,96 @@
@startuml
partition Drehteller {
start
:Drehteller ausschalten;
while(true) is (true)
if(Sensor aktiv ?) then (true)
:drehen an;
else (false)
:drehen aus;
endif
endwhile (false)
stop
}
partition Prüfer {
start
:Prüfer einfahren;
while(Dauerschleife) is (true)
if(Werkstück vorhanden ?) then (true)
:Prüfer ausfahren;
if(Werkstück Normallage ?) then (true)
:Bohrer(on)>
else (false)
:Bohrer(off)>
endif
:Prüfer einfahren;
else (false)
endif
endwhile (false)
stop
}
partition Bohrer {
start
:Bohrer ausschalten;
:Bohrer hochfahren;
:Werkstück loslassen;
while(Dauerschleife) is (true)
if(Werkstück vorhanden?) then(true)
:Bohrer<
:Auswerfer>
if(Normallage) then(true)
:Werkstück festhalten;
:Bohrer anschalten;
:Bohrer herunterfahren;
if(Bohrer unten) then (true)
:sleepStuff 500ms;
:Bohrer hochfahren;
endif
if(Bohrer oben) then (true)
:Bohrer ausschalten;
:Werkstück loslassen;
endif
else(false)
endif
else (false)
endif
endwhile(false)
stop
}
partition Auswerfer {
start
:Auswerfer einfahren;
while(Dauerschleife) is (true)
:Auswerfer<
note right
oder eher ne if hier ?
end note
:Auswerfen;
endwhile(false)
stop
}
@enduml

BIN
include/plantuml.jar Normal file

Binary file not shown.

62
include/rtai.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 1999-2015 Paolo Mantegazza <mantegazza@aero.polimi.it>
* Copyright (C) 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_RTAI_H
#define _RTAI_RTAI_H
#ifdef __KERNEL__
#include <linux/version.h>
#endif /* __KERNEL__ */
#include <asm/rtai.h>
#ifdef __KERNEL__
// see: Computing Practices, ACM, vol. 31, n. 10, 1988, pgs 1192-1201.
#define TWOPWR31M1 2147483647 // 2^31 - 1
static inline long next_rand(long rand)
{
const long a = 16807;
const long m = TWOPWR31M1;
const long q = 127773;
const long r = 2836;
long lo, hi;
hi = rand/q;
lo = rand - hi*q;
rand = a*lo - r*hi;
if (rand <= 0) {
rand += m;
}
return rand;
}
static inline long irandu(unsigned long range)
{
static long seed = 783637;
const long m = TWOPWR31M1;
seed = next_rand(seed);
return rtai_imuldiv(seed, range, m);
}
#endif /* __KERNEL__ */
#endif /* !_RTAI_RTAI_H */

26
include/rtai_defs.h.in Normal file
View File

@ -0,0 +1,26 @@
/*
* Re-written and fixed by Alec Ari
* Copyright (C) 1999-2016 Paolo Mantegazza <mantegazza@aero.polimi.it>
* Copyright (C) 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef RTAI_DEFS_H
#define RTAI_DEFS_H
#define RTAI_INSTALL_DIR "@prefix@"
#endif /* RTAI_DEFS_H */

797
include/rtai_fifos.h Normal file
View File

@ -0,0 +1,797 @@
/**
* @ingroup fifos
* @ingroup fifos_ipc
* @ingroup fifos_sem
* @file
*
* Interface of the @ref fifos "RTAI FIFO module".
*
* @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_FIFOS_H
#define _RTAI_FIFOS_H
#include <rtai_types.h>
#define MAX_FIFOS 64
#define RTAI_FIFOS_MAJOR 150
#define RESET 1
#define RESIZE 2
#define RTF_SUSPEND_TIMED 3
#define OPEN_SIZED 4
#define READ_ALL_AT_ONCE 5
#define READ_TIMED 6
#define WRITE_TIMED 7
#define RTF_SEM_INIT 8
#define RTF_SEM_WAIT 9
#define RTF_SEM_TRYWAIT 10
#define RTF_SEM_TIMED_WAIT 11
#define RTF_SEM_POST 12
#define RTF_SEM_DESTROY 13
#define SET_ASYNC_SIG 14
#define EAVESDROP 19
#define OVRWRITE 20
#define READ_IF 21
#define WRITE_IF 22
#define RTF_NAMED_CREATE 23
#define RTF_GET_N_FIFOS 15
#define RTF_GET_FIFO_INFO 16
#define RTF_CREATE_NAMED 17
#define RTF_NAME_LOOKUP 18
#define RTF_NAMELEN 15
struct rt_fifo_info_struct{
unsigned int fifo_number;
unsigned int size;
unsigned int opncnt;
int avbs, frbs;
char name[RTF_NAMELEN+1];
};
struct rt_fifo_get_info_struct{
unsigned int fifo;
unsigned int n;
struct rt_fifo_info_struct *ptr;
};
#define FUN_FIFOS_LXRT_INDX 10
#define _CREATE 0
#define _DESTROY 1
#define _PUT 2
#define _GET 3
#define _RESET 4
#define _RESIZE 5
#define _SEM_INIT 6
#define _SEM_DESTRY 7
#define _SEM_POST 8
#define _SEM_TRY 9
#define _CREATE_NAMED 10
#define _GETBY_NAME 11
#define _OVERWRITE 12
#define _PUT_IF 13
#define _GET_IF 14
#define _NAMED_CREATE 15
#define _AVBS 16
#define _FRBS 17
#ifdef __KERNEL__
#include <rtai.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int __rtai_fifos_init(void);
void __rtai_fifos_exit(void);
int rtf_init(void);
typedef int (*rtf_handler_t)(unsigned int fifo, int rw);
/* Attach a handler to an RT-FIFO.
*
* Allow function handler to be called when a user process reads or writes to
* the FIFO. When the function is called, it is passed the fifo number as the
* argument.
*/
int rtf_create_handler(unsigned int fifo, /* RT-FIFO */
void *handler /* function to be called */);
/**
* @ingroup fifos_ipc
* Extended fifo handler.
*
* The usage of X_FIFO_HANDLER(handler) allows to install an extended handler,
* i.e. one prototyped as:
* @code
* int (*handler)(unsigned int fifo, int rw);
* @endcode
* to allow the user to easily understand if the handler was called at fifo
* read (@a rw is 'r') or write (rw is 'w').
*/
#define X_FIFO_HANDLER(handler) ((int (*)(unsigned int, int rw))(handler))
/* Create an RT-FIFO.
*
* An RT-FIFO fifo is created with initial size of size.
* Return value: On success, 0 is returned. On error, -1 is returned.
*/
#undef rtf_create
RTAI_SYSCALL_MODE int rtf_create(unsigned int fifo, int size);
/* Create an RT-FIFO with a name and size.
*
* An RT-FIFO is created with a name of name, it will be allocated
* the first unused minor number and will have a user assigned size.
* Return value: On success, the allocated minor number is returned.
* On error, -errno is returned.
*/
int rtf_named_create(const char *name, int size);
/* Create an RT-FIFO with a name.
*
* An RT-FIFO is created with a name of name, it will be allocated
* the first unused minor number and will have a default size.
* Return value: On success, the allocated minor number is returned.
* On error, -errno is returned.
*/
RTAI_SYSCALL_MODE int rtf_create_named(const char *name);
/* Look up a named RT-FIFO.
*
* Find the RT-FIFO with the name name.
* Return value: On success, the minor number is returned.
* On error, -errno is returned.
*/
RTAI_SYSCALL_MODE int rtf_getfifobyname(const char *name);
/* Reset an RT-FIFO.
*
* An RT-FIFO fifo is reset by setting its buffer pointers to zero, so
* that any existing data is discarded and the fifo started anew like at its
* creation.
*/
RTAI_SYSCALL_MODE int rtf_reset(unsigned int fifo);
/* destroy an RT-FIFO.
*
* Return value: On success, 0 is returned.
*/
RTAI_SYSCALL_MODE int rtf_destroy(unsigned int fifo);
/* Resize an RT-FIFO.
*
* Return value: size is returned on success. On error, a negative value
* is returned.
*/
RTAI_SYSCALL_MODE int rtf_resize(unsigned int minor, int size);
/* Write to an RT-FIFO.
*
* Try to write count bytes to an FIFO. Returns the number of bytes written.
*/
RTAI_SYSCALL_MODE int rtf_put(unsigned int fifo, /* RT-FIFO */
void * buf, /* buffer address */
int count /* number of bytes to write */);
/* Write to an RT-FIFO, over writing if there is not enough space.
*
* Try to write count bytes to an FIFO. Returns 0.
*/
RTAI_SYSCALL_MODE int rtf_ovrwr_put(unsigned int fifo, /* RT-FIFO */
void * buf, /* buffer address */
int count /* number of bytes to write */);
/* Write atomically to an RT-FIFO.
*
* Try to write count bytes in block to an FIFO. Returns the number of bytes
* written.
*/
extern RTAI_SYSCALL_MODE int rtf_put_if (unsigned int fifo, /* RT-FIFO */
void * buf, /* buffer address */
int count /* number of bytes to write */);
/* Read from an RT-FIFO.
*
* Try to read count bytes from a FIFO. Returns the number of bytes read.
*/
RTAI_SYSCALL_MODE int rtf_get(unsigned int fifo, /* RT-FIFO */
void * buf, /* buffer address */
int count /* number of bytes to read */);
/* Atomically read from an RT-FIFO.
*
* Try to read count bytes in a block from an FIFO. Returns the number of bytes read.
*/
RTAI_SYSCALL_MODE int rtf_get_if(unsigned int fifo, /* RT-FIFO */
void * buf, /* buffer address */
int count /* number of bytes to read */);
/*
* Preview the an RT-FIFO content.
*/
int rtf_evdrp(unsigned int fifo, /* RT-FIFO */
void * buf, /* buffer address */
int count /* number of bytes to read */);
/* Open an RT-FIFO semaphore.
*
*/
RTAI_SYSCALL_MODE int rtf_sem_init(unsigned int fifo, /* RT-FIFO */
int value /* initial semaphore value */);
/* Post to an RT-FIFO semaphore.
*
*/
RTAI_SYSCALL_MODE int rtf_sem_post(unsigned int fifo /* RT-FIFO */);
/* Try to acquire an RT-FIFO semaphore.
*
*/
RTAI_SYSCALL_MODE int rtf_sem_trywait(unsigned int fifo /* RT-FIFO */);
/* Destroy an RT-FIFO semaphore.
*
*/
RTAI_SYSCALL_MODE int rtf_sem_destroy(unsigned int fifo /* RT-FIFO */);
#define rtf_sem_delete rtf_sem_destroy
/* Get an RT-FIFO free bytes in buffer.
*
*/
RTAI_SYSCALL_MODE int rtf_get_frbs(unsigned int fifo /* RT-FIFO */);
/* Just for compatibility with earlier rtai_fifos releases. No more bh and user
buffers. Fifos are now awakened immediately and buffers > 128K are vmalloced */
#define rtf_create_using_bh(fifo, size, bh_list) rtf_create(fifo, size)
#define rtf_create_using_bh_and_usr_buf(fifo, buf, size, bh_list) rtf_create(fifo, size)
#define rtf_destroy_using_usr_buf(fifo) rtf_destroy(fifo)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <rtai_lxrt.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
RTAI_PROTO(int, rtf_create,(unsigned int fifo, int size))
{
struct { unsigned long fifo, size; } arg = { fifo, size };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _CREATE, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_destroy,(unsigned int fifo))
{
struct { unsigned long fifo; } arg = { fifo };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _DESTROY, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_put,(unsigned int fifo, const void *buf, int count))
{
struct { unsigned long fifo; const void *buf; long count; } arg = { fifo, buf, count };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _PUT, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_put_if,(unsigned int fifo, const void *buf, int count))
{
struct { unsigned long fifo; const void *buf; long count; } arg = { fifo, buf, count };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _PUT_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_get,(unsigned int fifo, void *buf, int count))
{
struct { unsigned long fifo; void *buf; long count; } arg = { fifo, buf, count };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _GET, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_get_if,(unsigned int fifo, void *buf, int count))
{
struct { unsigned long fifo; void *buf; long count; } arg = { fifo, buf, count };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _GET_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_get_avbs, (unsigned int fifo))
{
struct { unsigned long fifo; } arg = { fifo };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _AVBS, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_get_frbs, (unsigned int fifo))
{
struct { unsigned long fifo; } arg = { fifo };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _FRBS, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_reset_lxrt,(unsigned int fifo))
{
struct { unsigned long fifo; } arg = { fifo };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _RESET, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_resize_lxrt,(unsigned int fifo, int size))
{
struct { unsigned long fifo, size; } arg = { fifo, size };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _RESIZE, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_sem_init_lxrt,(unsigned int fifo, int value))
{
struct { unsigned long fifo, value; } arg = { fifo, value };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _SEM_INIT, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_sem_post_lxrt,(unsigned int fifo))
{
struct { unsigned long fifo; } arg = { fifo };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _SEM_POST, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_sem_trywait_lxrt,(unsigned int fifo))
{
struct { unsigned long fifo; } arg = { fifo };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _SEM_TRY, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_sem_destroy_lxrt,(unsigned int fifo))
{
struct { unsigned long fifo; } arg = { fifo };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _SEM_DESTRY, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_named_create_lxrt,(const char *name, int size))
{
int len;
char lname[len = strlen(name)];
struct { char * name; long size; } arg = { lname, size };
strncpy(lname, name, len);
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _NAMED_CREATE, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_create_named_lxrt,(const char *name))
{
int len;
char lname[len = strlen(name)];
struct { char * name; } arg = { lname };
strncpy(lname, name, len);
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _CREATE_NAMED, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_getfifobyname_lxrt,(const char *name))
{
int len;
char lname[len = strlen(name)];
struct { char * name; } arg = { lname };
strncpy(lname, name, len);
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _GETBY_NAME, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_ovrwr_put,(unsigned int fifo, const void *buf, int count))
{
struct { unsigned long fifo; const void *buf; long count; } arg = { fifo, buf, count };
return rtai_lxrt(FUN_FIFOS_LXRT_INDX, SIZARG, _OVERWRITE, &arg).i[LOW];
}
RTAI_PROTO(int, rtf_reset,(int fd))
{
int ret = ioctl(fd, RESET);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_resize,(int fd, int size))
{
int ret = ioctl(fd, RESIZE, size);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_ipc
* Suspend a process for some time
*
* rtf_suspend_timed suspends a Linux process according to @a delay.
*
* @param fd is the file descriptor returned at fifo open, rtf_suspend_timed
* needs a fifo support.
* @param ms_delay is the timeout time in milliseconds.
*
* @note The standard, clumsy, way to achieve the same result is to use select
* with null file arguments, for long sleeps, with seconds resolution, sleep is
* also available.
*/
RTAI_PROTO(int, rtf_suspend_timed,(int fd, int ms_delay))
{
int ret = ioctl(fd, RTF_SUSPEND_TIMED, ms_delay);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_ipc
* Create a real-time FIFO
*
* rtf_open_sized is the equivalent of rtf_create() in user space; it creates a
* real-time fifo (RT-FIFO) of initial size @a size.
*
* @param size is the requested size for the fifo.
*
* The RT-FIFO is a character based mechanism to communicate among real-time
* tasks and ordinary Linux processes. The rtf_* functions are used by the
* real-time tasks; Linux processes use standard character device access
* functions such as read, write, and select.
*
* If this function finds an existing fifo of lower size it resizes it to the
* larger new size. Note that the same condition apply to the standard Linux
* device open, except that when it does not find any already existing fifo it
* creates it with a default size of 1K bytes.
*
* It must be remarked that practically any fifo size can be asked for. In
* fact if @a size is within the constraint allowed by kmalloc such a function
* is used, otherwise vmalloc is called, thus allowing any size that can fit
* into the available core memory.
*
* Multiple calls of this function are allowed, a counter is kept internally to
* track their number, and avoid destroying/closing a fifo that is still used.
*
* @return the usual Unix file descriptor on succes, to be used in standard reads
* and writes.
* @retval -ENOMEM if the necessary size could not be allocated for the RT-FIFO.
*
* @note In user space, the standard UNIX open acts like rtf_open_sized with a
* default 1K size.
*/
RTAI_PROTO(int, rtf_open_sized,(const char *dev, int perm, int size))
{
int fd;
if ((fd = open(dev, perm)) < 0) {
return -errno;
}
if (ioctl(fd, RESIZE, size) < 0) {
close(fd);
return -errno;
}
return fd;
}
RTAI_PROTO(int, rtf_evdrp,(int fd, void *buf, int count))
{
struct { void *buf; long count; } args = { buf, count };
int ret = ioctl(fd, EAVESDROP, &args);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_ipc
* Read data from FIFO in user space, waiting for all of them
*
* rtf_read_all_at_once reads a block of data from a real-time fifo identified
* by the file descriptor @a fd blocking till all waiting at most @a count
* bytes are available, whichever option was used at the related device
* opening.
*
* @param fd is the file descriptor returned at fifo open.
* @param buf points the block of data to be written.
* @param count is the size in bytes of the buffer.
*
* @return the number of bytes read on success.
* @retval -EINVAL if @a fd refers to a not opened fifo.
*/
RTAI_PROTO(int, rtf_read_all_at_once,(int fd, void *buf, int count))
{
struct { void *buf; long count; } args = { buf, count };
int ret = ioctl(fd, READ_ALL_AT_ONCE, &args);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_ipc
* Read data from FIFO in user space, with timeout.
*
* rtf_read_timed reads a block of data from a real-time fifo identified by the
* file descriptor @a fd waiting at most @a delay milliseconds to complete the
* operation.
*
* @param fd is the file descriptor returned at fifo open.
* @param buf points the block of data to be written.
* @param count is the size of the block in bytes.
* @param ms_delay is the timeout time in milliseconds.
*
* @return the number of bytes read is returned on success or timeout. Note that
* this value may be less than @a count if @a count bytes of free space is not
* available in the fifo or a timeout occured.
* @retval -EINVAL if @a fd refers to a not opened fifo.
*
* @note The standard, clumsy, Unix way to achieve the same result is to use
* select.
*/
RTAI_PROTO(int, rtf_read_timed,(int fd, void *buf, int count, int ms_delay))
{
struct { void *buf; long count, delay; } args = { buf, count, ms_delay };
int ret = ioctl(fd, READ_TIMED, &args);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_read_if,(int fd, void *buf, int count))
{
struct { void *buf; long count; } args = { buf, count };
int ret = ioctl(fd, READ_IF, &args);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_ipc
* Write data to FIFO in user space, with timeout.
*
* rtf_write_timed writes a block of data to a real-time fifo identified by the
* file descriptor @a fd waiting at most @æ delay milliseconds to complete the
* operation.
*
* @param fd is the file descriptor returned at fifo open.
* @param buf points the block of data to be written.
* @param count is the size of the block in bytes.
* @param ms_delay is the timeout time in milliseconds.
*
* @return the number of bytes written on succes. Note that this value may
* be less than @a count if @a count bytes of free space is not available in the
* fifo.
* @retval -EINVAL if @a fd refers to a not opened fifo.
*
* @note The standard, clumsy, Unix way to achieve the same result is to use
* select.
*/
RTAI_PROTO(int, rtf_write_timed,(int fd, void *buf, int count, int ms_delay))
{
struct { void *buf; long count, delay; } args = { buf, count, ms_delay };
int ret = ioctl(fd, WRITE_TIMED, &args);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_overwrite,(int fd, void *buf, int count))
{
struct { void *buf; long count; } args = { buf, count };
int ret = ioctl(fd, OVRWRITE, &args);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_write_if,(int fd, void *buf, int count))
{
struct { void *buf; long count; } args = { buf, count };
int ret = ioctl(fd, WRITE_IF, &args);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_sem_init,(int fd, int value))
{
int ret = ioctl(fd, RTF_SEM_INIT, value);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_sem
* Take a semaphore.
*
* rtf_sem_wait waits for a event to be posted (signaled) to a semaphore. The
* semaphore value is set to tested and set to zero. If it was one
* rtf_sem_wait returns immediately. Otherwise the caller process is blocked and
* queued up in a priority order based on is POSIX real time priority.
*
* A process blocked on a semaphore returns when:
* - the caller task is in the first place of the waiting queue and somebody
* issues a rtf_sem_post;
* - an error occurs (e.g. the semaphore is destroyed).
*
* @param fd is the file descriptor returned by standard UNIX open in user space
*
* Since it is blocking rtf_sem_waitcannot be used both in kernel and user
* space.
*
* @retval 0 on success.
* @retval -EINVAL if @a fd_fifo refers to an invalid file descriptor or fifo.
*/
RTAI_PROTO(int, rtf_sem_wait,(int fd))
{
int ret = ioctl(fd, RTF_SEM_WAIT);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_sem_trywait,(int fd))
{
int ret = ioctl(fd, RTF_SEM_TRYWAIT);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_sem
* Wait a semaphore with timeout
*
* rtf_sem_timed_wait is a timed version of the standard semaphore wait
* call. The semaphore value is tested and set to zero. If it was one
* rtf_sem_timed_wait returns immediately. Otherwise the caller process is
* blocked and queued up in a priority order based on is POSIX real time
* priority.
*
* A process blocked on a semaphore returns when:
* - the caller task is in the first place of the waiting queue and somebody
* issues a rtf_sem_post;
* - timeout occurs;
* - an error occurs (e.g. the semaphore is destroyed).
*
* @param fd is the file descriptor returned by standard UNIX open in user
* space. In case of timeout the semaphore value is set to one before return.
* @param ms_delay is in milliseconds and is relative to the Linux current time.
*
* Since it is blocking rtf_sem_timed_wait cannot be used both in kernel and
* user space.
*
* @retval 0 on success.
* @retval -EINVAL if fd_fifo refers to an invalid file descriptor or fifo.
*/
RTAI_PROTO(int, rtf_sem_timed_wait,(int fd, int ms_delay))
{
int ret = ioctl(fd, RTF_SEM_TIMED_WAIT, ms_delay);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_sem_post,(int fd))
{
int ret = ioctl(fd, RTF_SEM_POST);
return ret < 0 ? -errno : ret;
}
RTAI_PROTO(int, rtf_sem_destroy,(int fd))
{
int ret = ioctl(fd, RTF_SEM_DESTROY);
return ret < 0 ? -errno : ret;
}
/**
* @ingroup fifos_ipc
* Activate asynchronous notification of data availability
*
* rtf_set_async_sig activate an asynchronous signals to notify data
* availability by catching a user set signal signum.
*
* @param signum is a user chosen signal number to be used, default is SIGIO.
*
* @retval -EINVAL if fd refers to a not opened fifo.
*/
RTAI_PROTO(int, rtf_set_async_sig,(int fd, int signum))
{
int ret = ioctl(fd, SET_ASYNC_SIG, signum);
return ret < 0 ? -errno : ret;
}
/*
* Support for named FIFOS : Ian Soanes (ians@zentropix.com)
* Based on ideas from Stuart Hughes and David Schleef
*/
RTAI_PROTO_ALWAYS_INLINE(char *, rtf_getfifobyminor,(int minor, char *buf, int len))
{
snprintf(buf,len,CONFIG_RTAI_FIFOS_TEMPLATE,minor);
return buf;
}
RTAI_PROTO(int, rtf_getfifobyname,(const char *name))
{
int fd, minor;
char nm[RTF_NAMELEN+1];
if (strlen(name) > RTF_NAMELEN) {
return -1;
}
if ((fd = open(rtf_getfifobyminor(0,nm,sizeof(nm)), O_RDONLY)) < 0) {
return -errno;
}
strncpy(nm, name, RTF_NAMELEN+1);
minor = ioctl(fd, RTF_NAME_LOOKUP, nm);
close(fd);
return minor < 0 ? -errno : minor;
}
RTAI_PROTO(int, rtf_named_create,(const char *name, int size))
{
int fd, minor;
char nm[RTF_NAMELEN+1];
if (strlen(name) > RTF_NAMELEN) {
return -1;
}
if ((fd = open(rtf_getfifobyminor(0,nm,sizeof(nm)), O_RDONLY)) < 0) {
return -errno;
}
strncpy(nm, name, RTF_NAMELEN+1);
minor = ioctl(fd, RTF_NAMED_CREATE, nm, size);
close(fd);
return minor < 0 ? -errno : minor;
}
RTAI_PROTO(int, rtf_create_named,(const char *name))
{
int fd, minor;
char nm[RTF_NAMELEN+1];
if (strlen(name) > RTF_NAMELEN) {
return -1;
}
if ((fd = open(rtf_getfifobyminor(0,nm,sizeof(nm)), O_RDONLY)) < 0) {
return -errno;
}
strncpy(nm, name, RTF_NAMELEN+1);
minor = ioctl(fd, RTF_CREATE_NAMED, nm);
close(fd);
return minor < 0 ? -errno : minor;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#endif /* !_RTAI_FIFOS_H */

48
include/rtai_hal_names.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright 2015 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_HAL_NAMES_H
#define _RTAI_HAL_NAMES_H
#include <linux/version.h>
#define TSKEXT0 0
#define TSKEXT1 1
#define TSKEXT2 2
#define TSKEXT3 3
#define hal_processor_id ipipe_processor_id
#define hal_domain_struct ipipe_domain
#define hal_root_domain ipipe_root_domain
#define hal_critical_enter ipipe_critical_enter
#define hal_critical_exit ipipe_critical_exit
#define hal_sysinfo_struct ipipe_sysinfo
#define hal_get_sysinfo ipipe_get_sysinfo
#define hal_set_irq_affinity ipipe_set_irq_affinity
#define hal_alloc_irq ipipe_alloc_virq
#define hal_free_irq ipipe_free_virq
#define hal_reenter_root() __ipipe_reenter_root()
#endif /* _RTAI_HAL_NAMES_H */

1494
include/rtai_lxrt.h Normal file

File diff suppressed because it is too large Load Diff

155
include/rtai_malloc.h Normal file
View File

@ -0,0 +1,155 @@
/*
* Copyright (C) 2001,2002,2003,2004 Philippe Gerum <rpm@xenomai.org>.
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, see <http://www.gnu.org/licenses/>.
*
* This file provides the interface to the RTAI dynamic memory
* allocator based on the algorithm described in "Design of a General
* Purpose Memory Allocator for the 4.3BSD Unix Kernel" by Marshall
* K. McKusick and Michael J. Karels.
*/
#ifndef _RTAI_MALLOC_H
#define _RTAI_MALLOC_H
#include <rtai_types.h>
#ifdef __KERNEL__
#ifndef __cplusplus
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
/*
* LIMITS:
*
* Minimum page size is 2 ** RTHEAP_MINLOG2 (must be large enough to
* hold a pointer).
*
* Maximum page size is 2 ** RTHEAP_MAXLOG2.
*
* Minimum block size equals the minimum page size.
*
* Requested block size smaller than the minimum block size is
* rounded to the minimum block size.
*
* Requested block size larger than 2 times the page size is rounded
* to the next page boundary and obtained from the free page
* list. So we need a bucket for each power of two between
* RTHEAP_MINLOG2 and RTHEAP_MAXLOG2 inclusive, plus one to honor
* requests ranging from the maximum page size to twice this size.
*/
#define RTHEAP_MINLOG2 4
#define RTHEAP_MAXLOG2 22
#define RTHEAP_MINALLOCSZ (1 << RTHEAP_MINLOG2)
#define RTHEAP_MINALIGNSZ RTHEAP_MINALLOCSZ
#define RTHEAP_NBUCKETS (RTHEAP_MAXLOG2 - RTHEAP_MINLOG2 + 2)
#define RTHEAP_MAXEXTSZ 0x7FFFFFFF
#define RTHEAP_GLOBALSZ (CONFIG_RTAI_MALLOC_HEAPSZ * 1024)
#define RTHEAP_PFREE 0
#define RTHEAP_PCONT 1
#define RTHEAP_PLIST 2
#define KMALLOC_LIMIT (128 * 1024)
#define RTHEAP_NOMEM (-1)
#define RTHEAP_PARAM (-2)
typedef struct rtextent {
struct list_head link;
caddr_t membase, /* Base address of the page array */
memlim, /* Memory limit of page array */
freelist; /* Head of the free page list */
u_char pagemap[1]; /* Beginning of page map */
} rtextent_t;
/* Creation flag */
#define RTHEAP_EXTENDABLE 0x1
/* Allocation flags */
#define RTHEAP_EXTEND 0x1
typedef struct rtheap {
spinlock_t lock;
int flags;
u_long extentsize,
pagesize,
pageshift,
hdrsize,
npages, /* Number of pages per extent */
ubytes,
maxcont;
struct list_head extents;
caddr_t buckets[RTHEAP_NBUCKETS];
} rtheap_t;
#else /* __cplusplus */
struct rtheap;
typedef struct rtheap rtheap_t;
#endif /* !__cplusplus */
extern rtheap_t rtai_global_heap;
#define rtheap_page_size(heap) ((heap)->pagesize)
#define rtheap_page_count(heap) ((heap)->npages)
#define rtheap_used_mem(heap) ((heap)->ubytes)
#ifdef CONFIG_RTAI_MALLOC
#define rt_malloc(sz) rtheap_alloc(&rtai_global_heap, sz, 0)
#define rt_free(p) rtheap_free(&rtai_global_heap, p)
#else
#define rt_malloc(sz) kmalloc(sz, GFP_KERNEL)
#define rt_free(p) kfree(p)
#endif
#ifdef __cplusplus
extern "C" {
#endif
int __rtai_heap_init(void);
void __rtai_heap_exit(void);
int rtheap_init(rtheap_t *heap, void *heapaddr, u_long heapsize, u_long pagesize, int suprt);
void rtheap_destroy(rtheap_t *heap, int suprt);
void *rtheap_alloc(rtheap_t *heap, u_long size, int flags);
int rtheap_free(rtheap_t *heap, void *block);
#ifdef __cplusplus
}
#endif
#endif /* __KERNEL__ */
#endif /* !_RTAI_MALLOC_H */

288
include/rtai_mbx.h Normal file
View File

@ -0,0 +1,288 @@
/**
* @ingroup lxrt
* @file
*
* @author Paolo Mantegazza
*
* @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_MBX_H
#define _RTAI_MBX_H
#include <rtai_sem.h>
#define RT_MBX_MAGIC 0x3f81aab // nam2num("rtmbx")
struct rt_task_struct;
struct rt_mailbox;
#ifdef __KERNEL__
#ifndef __cplusplus
typedef struct rt_mailbox {
int magic;
SEM sndsem, rcvsem;
struct rt_task_struct *waiting_task, *owndby;
char *bufadr;
int size, fbyte, lbyte, avbs, frbs;
spinlock_t lock;
#ifdef CONFIG_RTAI_RT_POLL
struct rt_poll_ql poll_recv;
struct rt_poll_ql poll_send;
#endif
} MBX;
#else /* __cplusplus */
extern "C" {
#endif /* !__cplusplus */
int __rtai_mbx_init(void);
void __rtai_mbx_exit(void);
RTAI_SYSCALL_MODE int rt_typed_mbx_init(struct rt_mailbox *mbx, int size, int qtype);
int rt_mbx_init(struct rt_mailbox *mbx, int size);
RTAI_SYSCALL_MODE int rt_mbx_delete(struct rt_mailbox *mbx);
RTAI_SYSCALL_MODE int _rt_mbx_send(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_send(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_send(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_send_wp(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_send_wp(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_send_wp(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_send_if(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_send_if(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_send_if(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_send_until(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME timei, int space);
static inline int rt_mbx_send_until(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME time)
{
return _rt_mbx_send_until(mbx, msg, msg_size, time, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_send_timed(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME delay, int space);
static inline int rt_mbx_send_timed(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME delay)
{
return _rt_mbx_send_timed(mbx, msg, msg_size, delay, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_ovrwr_send(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_ovrwr_send(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_ovrwr_send(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_evdrp(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_evdrp(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_evdrp(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_receive(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_receive(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_receive(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_receive_wp(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_receive_wp(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_receive_wp(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_receive_if(struct rt_mailbox *mbx, void *msg, int msg_size, int space);
static inline int rt_mbx_receive_if(struct rt_mailbox *mbx, void *msg, int msg_size)
{
return _rt_mbx_receive_if(mbx, msg, msg_size, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_receive_until(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME time, int space);
static inline int rt_mbx_receive_until(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME time)
{
return _rt_mbx_receive_until(mbx, msg, msg_size, time, 1);
}
RTAI_SYSCALL_MODE int _rt_mbx_receive_timed(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME delay, int space);
static inline int rt_mbx_receive_timed(struct rt_mailbox *mbx, void *msg, int msg_size, RTIME delay)
{
return _rt_mbx_receive_timed(mbx, msg, msg_size, delay, 1);
}
RTAI_SYSCALL_MODE struct rt_mailbox *_rt_typed_named_mbx_init(unsigned long mbx_name, int size, int qtype);
static inline struct rt_mailbox *rt_typed_named_mbx_init(const char *mbx_name, int size, int qtype)
{
return _rt_typed_named_mbx_init(nam2num(mbx_name), size, qtype);
}
RTAI_SYSCALL_MODE int rt_named_mbx_delete(struct rt_mailbox *mbx);
#define rt_named_mbx_init(mbx_name, size) rt_typed_named_mbx_init(mbx_name, size, FIFO_Q)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#include <rtai_lxrt.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
RTAI_PROTO(struct rt_mailbox *, rt_typed_mbx_init, (unsigned long name, int size, int qtype))
{
struct { unsigned long name; long size; long qtype; } arg = { name, size, qtype };
return (struct rt_mailbox *)rtai_lxrt(BIDX, SIZARG, LXRT_MBX_INIT, &arg).v[LOW];
}
/**
* @ingroup lxrt
* Initialize mailbox.
*
* Initializes a mailbox referred to by @a name of size @a size.
*
* It is important to remark that the returned task pointer cannot be used
* directly, they are for kernel space data, but just passed as arguments when
* needed.
*
* @return On success a pointer to the mail box to be used in related calls.
* @return A 0 value is returned if it was not possible to setup the semaphore
* or something using the same name was found.
*/
#define rt_mbx_init(name, size) rt_typed_mbx_init(name, size, FIFO_Q)
RTAI_PROTO(int, rt_mbx_delete, (struct rt_mailbox *mbx))
{
void *arg = mbx;
return rtai_lxrt(BIDX, SIZARG, LXRT_MBX_DELETE, &arg).i[LOW];
}
RTAI_PROTO(struct rt_mailbox *, rt_typed_named_mbx_init, (const char *name, int size, int type))
{
struct { unsigned long name; long size, type; } arg = { nam2num(name), size, type };
return (struct rt_mailbox *)rtai_lxrt(BIDX, SIZARG, NAMED_MBX_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_named_mbx_delete, (struct rt_mailbox *mbx))
{
struct { struct rt_mailbox *mbx; } arg = { mbx };
return rtai_lxrt(BIDX, SIZARG, NAMED_MBX_DELETE, &arg).i[LOW];
}
#define rt_named_mbx_init(mbx_name, size) \
rt_typed_named_mbx_init(mbx_name, size, FIFO_Q)
RTAI_PROTO(int, rt_mbx_send, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_SEND, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_send_wp, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_SEND_WP, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_send_if, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_SEND_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_send_until, (struct rt_mailbox *mbx, void *msg, int msg_size, RTIME time))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; RTIME time; long space; } arg = { mbx, (char *)msg, msg_size, time, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_SEND_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_send_timed, (struct rt_mailbox *mbx, void *msg, int msg_size, RTIME delay))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; RTIME delay; long space; } arg = { mbx, (char *)msg, msg_size, delay, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_SEND_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_ovrwr_send, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_OVRWR_SEND, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_evdrp, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_EVDRP, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_receive, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_RECEIVE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_receive_wp, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_RECEIVE_WP, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_receive_if, (struct rt_mailbox *mbx, void *msg, int msg_size))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; long space; } arg = { mbx, (char *)msg, msg_size, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_RECEIVE_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_receive_until, (struct rt_mailbox *mbx, void *msg, int msg_size, RTIME time))
{
struct { struct rt_mailbox *mbx; void *msg; long msg_size; RTIME time; long space; } arg = { mbx, (char *)msg, msg_size, time, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_RECEIVE_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_mbx_receive_timed, (struct rt_mailbox *mbx, void *msg, int msg_size, RTIME delay))
{
struct { struct rt_mailbox *mbx; char *msg; long msg_size; RTIME delay; long space; } arg = { mbx, (char *)msg, msg_size, delay, 0 };
return (int)rtai_lxrt(BIDX, SIZARG, MBX_RECEIVE_TIMED, &arg).i[LOW];
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#if !defined(__KERNEL__) || defined(__cplusplus)
typedef struct rt_mailbox {
int opaque;
} MBX;
#endif /* !__KERNEL__ || __cplusplus */
#endif /* !_RTAI_MBX_H */

12
include/rtai_modbus.h Normal file
View File

@ -0,0 +1,12 @@
#include <stdio.h>
const int DIGITAL_IN = 0;
const int DIGITAL_OUT = 1;
const int ANALOG_IN = 2;
const int IB_IL_AO = 3;
int rt_modbus_connect(char * hostname);
int rt_modbus_disconnect(int cno);
int rt_modbus_get(int cno, int type, uint16_t addr, uint16_t * value);
int rt_modbus_set(int cno, int type, uint16_t addr, uint16_t value);

706
include/rtai_msg.h Normal file
View File

@ -0,0 +1,706 @@
/*
* Copyright (C) 2002 POSEIDON CONTROLS INC <pcloutier@poseidoncontrols.com>
* Copyright (C) 2002 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_MSG_H
#define _RTAI_MSG_H
#include <rtai_types.h>
#define MSG_ERR ((RT_TASK *)RTE_OBJINV)
struct rt_task_struct;
struct QueueBlock;
struct QueueHook;
#ifdef __KERNEL__
typedef struct t_msgcb { /* Message control block structure. */
int cmd;
void *sbuf;
size_t sbytes;
void *rbuf;
size_t rbytes;
} MSGCB;
#define PROXY_MIN_STACK_SIZE 2048
struct proxy_t {
struct rt_task_struct *receiver;
int nmsgs, nbytes;
char *msg;
};
#define SYNCMSG 0
#define PROXY -1
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int __rtai_msg_init(void);
void __rtai_msg_exit(void);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_send(struct rt_task_struct *task,
unsigned long msg);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_send_if(struct rt_task_struct *task,
unsigned long msg);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_send_until(struct rt_task_struct *task,
unsigned long msg,
RTIME time);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_send_timed(struct rt_task_struct *task,
unsigned long msg,
RTIME delay);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_evdrp(struct rt_task_struct *task,
void *msg);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receive(struct rt_task_struct *task,
void *msg);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receive_if(struct rt_task_struct *task,
void *msg);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receive_until(struct rt_task_struct *task,
void *msg,
RTIME time);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receive_timed(struct rt_task_struct *task,
void *msg,
RTIME delay);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpc(struct rt_task_struct *task,
unsigned long to_do,
void *result);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpc_if(struct rt_task_struct *task,
unsigned long to_do,
void *result);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpc_until(struct rt_task_struct *task,
unsigned long to_do,
void *result,
RTIME time);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpc_timed(struct rt_task_struct *task,
unsigned long to_do,
void *result,
RTIME delay);
RTAI_SYSCALL_MODE int rt_isrpc(struct rt_task_struct *task);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_return(struct rt_task_struct *task,
unsigned long result);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpcx(struct rt_task_struct *task,
void *smsg,
void *rmsg,
int ssize,
int rsize);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpcx_if(struct rt_task_struct *task,
void *smsg,
void *rmsg,
int ssize,
int rsize);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpcx_until(struct rt_task_struct *task,
void *smsg,
void *rmsg,
int ssize,
int rsize,
RTIME time);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_rpcx_timed(struct rt_task_struct *task,
void *smsg,
void *rmsg,
int ssize,
int rsize,
RTIME delay);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_sendx(struct rt_task_struct *task,
void *msg,
int size);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_sendx_if(struct rt_task_struct *task,
void *msg,
int size);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_sendx_until(struct rt_task_struct *task,
void *msg,
int size,
RTIME time);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_sendx_timed(struct rt_task_struct *task,
void *msg,
int size,
RTIME delay);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_returnx(struct rt_task_struct *task,
void *msg,
int size);
#define rt_isrpcx(task) rt_isrpc(task)
RTAI_SYSCALL_MODE struct rt_task_struct *rt_evdrpx(struct rt_task_struct *task,
void *msg,
int size,
long *len);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receivex(struct rt_task_struct *task,
void *msg,
int size,
long *len);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receivex_if(struct rt_task_struct *task,
void *msg,
int size,
long *len);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receivex_until(struct rt_task_struct *task,
void *msg,
int size,
long *len,
RTIME time);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_receivex_timed(struct rt_task_struct *task,
void *msg,
int size,
long *len,
RTIME delay);
struct rt_task_struct *__rt_proxy_attach(void (*func)(long),
struct rt_task_struct *task,
void *msg,
int nbytes,
int priority);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_proxy_attach(struct rt_task_struct *task,
void *msg,
int nbytes,
int priority);
RTAI_SYSCALL_MODE int rt_proxy_detach(struct rt_task_struct *proxy);
RTAI_SYSCALL_MODE struct rt_task_struct *rt_trigger(struct rt_task_struct *proxy);
#define exist(name) rt_get_adr(nam2num(name))
RTAI_SYSCALL_MODE int rt_Send(pid_t pid,
void *smsg,
void *rmsg,
size_t ssize,
size_t rsize);
RTAI_SYSCALL_MODE pid_t rt_Receive(pid_t pid,
void *msg,
size_t maxsize,
size_t *msglen);
RTAI_SYSCALL_MODE pid_t rt_Creceive(pid_t pid,
void *msg,
size_t maxsize,
size_t *msglen,
RTIME delay);
RTAI_SYSCALL_MODE int rt_Reply(pid_t pid,
void *msg,
size_t size);
RTAI_SYSCALL_MODE pid_t rt_Proxy_attach(pid_t pid,
void *msg,
int nbytes,
int priority);
RTAI_SYSCALL_MODE int rt_Proxy_detach(pid_t pid);
RTAI_SYSCALL_MODE pid_t rt_Trigger(pid_t pid);
RTAI_SYSCALL_MODE pid_t rt_Name_attach(const char *name);
RTAI_SYSCALL_MODE pid_t rt_Name_locate(const char *host,
const char *name);
RTAI_SYSCALL_MODE int rt_Name_detach(pid_t pid);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#include <rtai_lxrt.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
RTAI_PROTO(struct rt_task_struct *,rt_send,(struct rt_task_struct *task, unsigned long msg))
{
struct { struct rt_task_struct *task; unsigned long msg; } arg = { task, msg };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SENDMSG, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_send_if,(struct rt_task_struct *task, unsigned long msg))
{
struct { struct rt_task_struct *task; unsigned long msg; } arg = { task, msg };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SEND_IF, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_send_until,(struct rt_task_struct *task, unsigned long msg, RTIME time))
{
struct { struct rt_task_struct *task; unsigned long msg; RTIME time; } arg = { task, msg, time };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SEND_UNTIL, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_send_timed,(struct rt_task_struct *task, unsigned long msg, RTIME delay))
{
struct { struct rt_task_struct *task; unsigned long msg; RTIME delay; } arg = { task, msg, delay };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SEND_TIMED, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_evdrp,(struct rt_task_struct *task, void *msg))
{
struct { struct rt_task_struct *task; void *msg; } arg = { task, msg };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, EVDRP, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receive,(struct rt_task_struct *task, void *msg))
{
struct { struct rt_task_struct *task; void *msg; } arg = { task, msg };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVEMSG, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receive_if,(struct rt_task_struct *task, void *msg))
{
struct { struct rt_task_struct *task; void *msg; } arg = { task, msg };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVE_IF, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receive_until,(struct rt_task_struct *task, void *msg, RTIME time))
{
struct { struct rt_task_struct *task; void *msg; RTIME time; } arg = { task, msg, time };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVE_UNTIL, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receive_timed,(struct rt_task_struct *task, void *msg, RTIME delay))
{
struct { struct rt_task_struct *task; void *msg; RTIME delay; } arg = { task, msg, delay };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVE_TIMED, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpc,(struct rt_task_struct *task, unsigned long to_do, void *result))
{
struct { struct rt_task_struct *task; unsigned long to_do; void *result; } arg = { task, to_do, result };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPCMSG, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpc_if,(struct rt_task_struct *task, unsigned long to_do, void *result))
{
struct { struct rt_task_struct *task; unsigned long to_do; void *result; } arg = { task, to_do, result };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPC_IF, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpc_until,(struct rt_task_struct *task, unsigned long to_do, void *result, RTIME time))
{
struct { struct rt_task_struct *task; unsigned long to_do; void *result; RTIME time; } arg = { task, to_do, result, time };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPC_UNTIL, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpc_timed,(struct rt_task_struct *task, unsigned long to_do, void *result, RTIME delay))
{
struct { struct rt_task_struct *task; unsigned long to_do; void *result; RTIME delay; } arg = { task, to_do, result, delay };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPC_TIMED, &arg).v[LOW];
}
RTAI_PROTO(int, rt_isrpc,(struct rt_task_struct *task))
{
struct { struct rt_task_struct *task; } arg = { task };
return (int)rtai_lxrt(BIDX, SIZARG, ISRPC, &arg).i[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_return,(struct rt_task_struct *task, unsigned long result))
{
struct { struct rt_task_struct *task; unsigned long result; } arg = { task, result };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RETURNMSG, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpcx,(struct rt_task_struct *task, void *smsg, void *rmsg, int ssize, int rsize))
{
struct { struct rt_task_struct *task; void *smsg; void *rmsg; long ssize; long rsize; } arg = { task, smsg, rmsg, ssize, rsize };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPCX, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpcx_if,(struct rt_task_struct *task, void *smsg, void *rmsg, int ssize, int rsize))
{
struct { struct rt_task_struct *task; void *smsg; void *rmsg; long ssize; long rsize; } arg = { task, smsg, rmsg, ssize, rsize };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPCX_IF, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpcx_until,(struct rt_task_struct *task, void *smsg, void *rmsg, int ssize, int rsize, RTIME time))
{
struct { struct rt_task_struct *task; void *smsg; void *rmsg; long ssize; long rsize; RTIME time; } arg = { task, smsg, rmsg, ssize, rsize, time };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPCX_UNTIL, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_rpcx_timed,(struct rt_task_struct *task, void *smsg, void *rmsg, int ssize, int rsize, RTIME delay))
{
struct { struct rt_task_struct *task; void *smsg; void *rmsg; long ssize; long rsize; RTIME delay; } arg = { task, smsg, rmsg, ssize, rsize, delay };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RPCX_TIMED, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_sendx,(struct rt_task_struct *task, void *msg, int size))
{
struct { struct rt_task_struct *task; void *msg; long size; } arg = { task, msg, size };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SENDX, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_sendx_if,(struct rt_task_struct *task, void *msg, int size))
{
struct { struct rt_task_struct *task; void *msg; long size; } arg = { task, msg, size };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SENDX_IF, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_sendx_until,(struct rt_task_struct *task, void *msg, int size, RTIME time))
{
struct { struct rt_task_struct *task; void *msg; long size; RTIME time; } arg = { task, msg, size, time };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SENDX_UNTIL, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_sendx_timed,(struct rt_task_struct *task, void *msg, long size, RTIME delay))
{
struct { struct rt_task_struct *task; void *msg; long size; RTIME delay; } arg = { task, msg, size, delay };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, SENDX_TIMED, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_returnx,(struct rt_task_struct *task, void *msg, int size))
{
struct { struct rt_task_struct *task; void *msg; long size; } arg = { task, msg, size };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RETURNX, &arg).v[LOW];
}
#define rt_isrpcx(task) rt_isrpc(task)
RTAI_PROTO(struct rt_task_struct *,rt_evdrpx,(struct rt_task_struct *task, void *msg, int size, long *len))
{
struct { struct rt_task_struct *task; void *msg; long size; long *len; } arg = { task, msg, size, len };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, EVDRPX, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receivex,(struct rt_task_struct *task, void *msg, int size, long *len))
{
struct { struct rt_task_struct *task; void *msg; long size; long *len; } arg = { task, msg, size, len };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVEX, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receivex_if,(struct rt_task_struct *task, void *msg, int size, long *len))
{
struct { struct rt_task_struct *task; void *msg; long size; long *len; } arg = { task, msg, size, len };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVEX_IF, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receivex_until,(struct rt_task_struct *task, void *msg, int size, long *len, RTIME time))
{
struct { struct rt_task_struct *task; void *msg; long size; long *len; RTIME time; } arg = { task, msg, size, len, time };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVEX_UNTIL, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_receivex_timed,(struct rt_task_struct *task, void *msg, int size, long *len, RTIME delay))
{
struct { struct rt_task_struct *task; void *msg; long size; long *len; RTIME delay; } arg = { task, msg, size, len, delay };
return (struct rt_task_struct *)rtai_lxrt(BIDX, SIZARG, RECEIVEX_TIMED, &arg).v[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_proxy_attach,(struct rt_task_struct *proxy, void *msg, int nbytes, int priority))
{
struct { struct rt_task_struct *proxy; void *msg; long nbytes, priority;} arg = { proxy, msg, nbytes, priority };
return (struct rt_task_struct *) rtai_lxrt(BIDX, SIZARG, PROXY_ATTACH, &arg).v[LOW];
}
RTAI_PROTO(int, rt_proxy_detach,(struct rt_task_struct *proxy))
{
struct { struct rt_task_struct *proxy; } arg = { proxy };
return (pid_t) rtai_lxrt(BIDX, SIZARG, PROXY_DETACH, &arg).i[LOW];
}
RTAI_PROTO(struct rt_task_struct *,rt_trigger,(struct rt_task_struct *proxy))
{
struct { struct rt_task_struct *proxy; } arg = { proxy };
return (struct rt_task_struct *) rtai_lxrt(BIDX, SIZARG, PROXY_TRIGGER, &arg).v[LOW];
}
RTAI_PROTO(int, rt_Send,(pid_t pid, void *smsg, void *rmsg, size_t ssize, size_t rsize ))
{
struct { long pid; void *smsg; void *rmsg; unsigned long ssize, rsize;} arg = { pid, smsg, rmsg, ssize, rsize };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_SEND, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Receive,(pid_t pid, void *msg, size_t maxsize, size_t *msglen))
{
struct { long pid; void *msg; unsigned long maxsize; size_t *msglen; } arg = { pid, msg, maxsize, msglen };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_RECEIVE, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Creceive,(pid_t pid, void *msg, size_t maxsize, size_t *msglen, RTIME delay))
{
struct { long pid; void *msg; unsigned long maxsize; size_t *msglen; RTIME delay;} arg = { pid, msg, maxsize, msglen, delay };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_CRECEIVE, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Reply,(pid_t pid, void *msg, size_t size))
{
struct { long pid; void *msg; unsigned long size;} arg = { pid, msg, size };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_REPLY, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Proxy_attach,(pid_t pid, void *msg, int nbytes, int priority))
{
struct { long pid; void *msg; long nbytes, priority;} arg = { pid, msg, nbytes, priority };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_PROXY_ATTACH, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Proxy_detach,(pid_t pid))
{
struct { long pid; } arg = { pid };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_PROXY_DETACH, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Trigger,(pid_t pid))
{
struct { long pid; } arg = { pid };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_TRIGGER, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Alias_attach,(const char *name))
{
struct { const char *name; } arg = { name};
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_NAME_ATTACH, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_Name_locate,(const char *host, const char *name))
{
struct { const char *host, *name; } arg = { host, name };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_NAME_LOCATE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_Name_detach,(pid_t pid))
{
struct { long pid; } arg = { pid };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_NAME_DETACH, &arg).i[LOW];
}
RTAI_PROTO(int, rt_InitTickQueue,(void))
{
struct { unsigned long dummy; } arg;
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_INITTICKQUEUE, &arg).i[LOW];
}
RTAI_PROTO(void, rt_ReleaseTickQueue,(void))
{
struct { unsigned long dummy; } arg;
rtai_lxrt(BIDX, SIZARG, RT_RELEASETICKQUEUE, &arg);
}
RTAI_PROTO(unsigned long, rt_qDynAlloc,(unsigned long n))
{
struct { unsigned long n; } arg = { n };
return (unsigned long) rtai_lxrt(BIDX, SIZARG, RT_QDYNALLOC, &arg).i[LOW];
}
RTAI_PROTO(unsigned long, rt_qDynFree,(int n))
{
struct { long n; } arg = { n };
return (unsigned long) rtai_lxrt(BIDX, SIZARG, RT_QDYNFREE, &arg).i[LOW];
}
RTAI_PROTO(struct QueueBlock *,rt_qDynInit,(struct QueueBlock **q, void (*fun)(void *, int), void *data, int evn ))
{
struct QueueBlock *r;
struct { struct QueueBlock **q; void (*fun)(void *, int), *data; long evn; } arg = { 0, fun, data, evn };
r = (struct QueueBlock *) rtai_lxrt(BIDX, SIZARG, RT_QDYNINIT, &arg).v[LOW];
if (q) *q = r;
return r;
}
RTAI_PROTO(void, rt_qBlkWait,(struct QueueBlock *q, RTIME t))
{
struct { struct QueueBlock *q; RTIME t; } arg = { q, t } ;
rtai_lxrt(BIDX, SIZARG, RT_QBLKWAIT, &arg);
}
RTAI_PROTO(void, rt_qBlkRepeat,(struct QueueBlock *q, RTIME t))
{
struct { struct QueueBlock *q; RTIME t; } arg = { q, t } ;
rtai_lxrt(BIDX, SIZARG, RT_QBLKREPEAT, &arg);
}
RTAI_PROTO(void, rt_qBlkSoon,(struct QueueBlock *q))
{
struct { struct QueueBlock *q; } arg = { q };
rtai_lxrt(BIDX, SIZARG, RT_QBLKSOON, &arg);
}
RTAI_PROTO(void, rt_qBlkDequeue,(struct QueueBlock *q))
{
struct { struct QueueBlock *q; } arg = { q };
rtai_lxrt(BIDX, SIZARG, RT_QBLKDEQUEUE, &arg);
}
RTAI_PROTO(void, rt_qBlkCancel,(struct QueueBlock *q))
{
struct { struct QueueBlock *q; } arg = { q };
rtai_lxrt(BIDX, SIZARG, RT_QBLKCANCEL, &arg);
}
RTAI_PROTO(void, rt_qBlkBefore,(struct QueueBlock *cur, struct QueueBlock *nxt))
{
struct { struct QueueBlock *cur, *nxt; } arg = { cur, nxt };
rtai_lxrt(BIDX, SIZARG, RT_QBLKBEFORE, &arg);
}
RTAI_PROTO(void, rt_qBlkAfter,(struct QueueBlock *cur, struct QueueBlock *prv))
{
struct { struct QueueBlock *cur, *prv; } arg = { cur, prv };
rtai_lxrt(BIDX, SIZARG, RT_QBLKAFTER, &arg);
}
RTAI_PROTO(struct QueueBlock *,rt_qBlkUnhook,(struct QueueBlock *q))
{
struct { struct QueueBlock *q; } arg = { q };
return (struct QueueBlock *) rtai_lxrt(BIDX, SIZARG, RT_QBLKUNHOOK, &arg).v[LOW];
}
RTAI_PROTO(void, rt_qBlkRelease,(struct QueueBlock *q))
{
struct { struct QueueBlock *q; } arg = { q };
rtai_lxrt(BIDX, SIZARG, RT_QBLKRELEASE, &arg);
}
RTAI_PROTO(void, rt_qBlkComplete,(struct QueueBlock *q))
{
struct { struct QueueBlock *q; } arg = { q };
rtai_lxrt(BIDX, SIZARG, RT_QBLKCOMPLETE, &arg);
}
RTAI_PROTO(int, rt_qSync,(void))
{
struct { unsigned long long dummy; } arg;
return rtai_lxrt(BIDX, SIZARG, RT_QSYNC, &arg).i[LOW];
}
RTAI_PROTO(pid_t, rt_qReceive,(pid_t target, void *buf, size_t maxlen, size_t *msglen))
{
struct { long target; void *buf; unsigned long maxlen; size_t *msglen; } arg = { target, buf, maxlen, msglen };
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_QRECEIVE, &arg).i[LOW];
}
RTAI_PROTO(void, rt_qLoop,(void))
{
struct { unsigned long dummy; } arg;
rtai_lxrt(BIDX, SIZARG, RT_QLOOP, &arg);
}
RTAI_PROTO(RTIME, rt_qStep,(void))
{
struct { unsigned long dummy; } arg;
return rtai_lxrt(BIDX, SIZARG, RT_QSTEP, &arg).rt;
}
RTAI_PROTO(void, rt_qHookFlush,(struct QueueHook *h))
{
struct { struct QueueHook *h; } arg = { h };
rtai_lxrt(BIDX, SIZARG, RT_QHOOKFLUSH, &arg);
}
RTAI_PROTO(void, rt_qBlkAtHead,(struct QueueBlock *q, struct QueueHook *h))
{
struct { struct QueueBlock *q; struct QueueHook *h; } arg = { q, h };
rtai_lxrt(BIDX, SIZARG, RT_QBLKATHEAD, &arg);
}
RTAI_PROTO(void, rt_qBlkAtTail,(struct QueueBlock *q, struct QueueHook *h))
{
struct { struct QueueBlock *q; struct QueueHook *h; } arg = { q, h };
rtai_lxrt(BIDX, SIZARG, RT_QBLKATTAIL, &arg);
}
RTAI_PROTO(struct QueueHook *,rt_qHookInit,(struct QueueHook **h, void (*c)(void *, struct QueueBlock *), void *a))
{
struct QueueHook *r;
struct { struct QueueHook **h; void (*c)(void *, struct QueueBlock *), *a;} arg = { 0, c, a };
r = (struct QueueHook *) rtai_lxrt(BIDX, SIZARG, RT_QHOOKINIT, &arg).v[LOW];
if (h) *h = r;
return r;
}
RTAI_PROTO(void, rt_qHookRelease,(struct QueueHook *h))
{
struct { struct QueueHook *h; } arg = { h };
rtai_lxrt(BIDX, SIZARG, RT_QHOOKRELEASE, &arg);
}
RTAI_PROTO(void, rt_qBlkSchedule,(struct QueueBlock *q, RTIME t))
{
struct { struct QueueBlock *q; RTIME t; } arg = { q, t } ;
rtai_lxrt(BIDX, SIZARG, RT_QBLKSCHEDULE, &arg);
}
RTAI_PROTO(struct QueueHook *,rt_GetTickQueueHook,(void))
{
struct { unsigned long dummy; } arg;
return (struct QueueHook *) rtai_lxrt(BIDX, SIZARG, RT_GETTICKQUEUEHOOK, &arg).v[LOW];
}
RTAI_PROTO(pid_t, rt_vc_reserve,( void ))
{
struct { unsigned long dummy; } arg;
return (pid_t) rtai_lxrt(BIDX, SIZARG, RT_VC_RESERVE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_vc_attach,(pid_t pid))
{
struct { long pid; } arg = { pid };
return rtai_lxrt(BIDX, SIZARG, RT_VC_ATTACH, &arg).i[LOW];
}
RTAI_PROTO(int, rt_vc_release,(pid_t pid))
{
struct { long pid; } arg = { pid };
return rtai_lxrt(BIDX, SIZARG, RT_VC_RELEASE, &arg).i[LOW];
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#if !defined(__KERNEL__) || defined(__cplusplus)
typedef struct t_msgcb {
int opaque;
} MSGCB;
#endif /* !__KERNEL__ || __cplusplus */
#endif /* !_RTAI_MSG_H */

136
include/rtai_nam2num.h Normal file
View File

@ -0,0 +1,136 @@
/**
* @ingroup shm
* @ingroup lxrt
* @ingroup tasklets
* @file
*
* Conversion between 6 characters strings and unsigned long identifiers.
*
* Convert a 6 characters string to un unsigned long, and vice versa, to be used
* as an dentifier for RTAI services, symmetrically available in user and kernel
* space, e.g. @ref shm "shared memory" and @ref lxrt "LXRT and LXRT-INFORMED".
*
* @author Paolo Mantegazza
*
* @note Copyright &copy; 1999-2013 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_NAM2NUM_H
#define _RTAI_NAM2NUM_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <rtai_types.h>
#ifdef __KERNEL__
#include <linux/ctype.h>
#include <linux/string.h>
#define NAM2NUM_PROTO(type, name, arglist) static inline type name arglist
#else
#include <ctype.h>
#include <string.h>
#define NAM2NUM_PROTO RTAI_PROTO
#endif
#define MAX_NAM2NUM 4096000003UL // nam2num("$$$$$$") + 2
/**
* Convert a 6 characters string to an unsigned long.
*
* Converts a 6 characters string name containing an alpha numeric identifier
* to its corresponding unsigned long identifier.
*
* @param name is the name to be converted.
*
* Allowed characters are:
* - english letters (no difference between upper and lower case, the latter
* will always be translated to upper case);
* - decimal digits;
* - '_', '@', '.' and another character of your choice, the latter will
* always be treated as a $ and converted back as such by num2nam().
*
* @return the unsigned long associated with @a name.
*/
NAM2NUM_PROTO(unsigned long, nam2num, (const char *name))
{
unsigned long retval = 0;
int c, i;
for (i = 0; i < 6; i++) {
if (!(c = name[i])) {
break;
}
if (islower(c)) {
c += (10 - 'a');
} else if (isupper(c)) {
c += (10 - 'A');
} else if (isdigit(c)) {
c -= '0';
} else {
c = c == '_' ? 36 : c == '@' ? 37 : c == '.' ? 38 : 39;
}
retval = retval*40 + c;
}
return i > 0 ? retval + 2 : 0xFFFFFFFF;
}
/**
* Convert an unsigned long identifier back to its corresponding 6 characters
* string.
*
* @param num is the unsigned long identifier whose alphanumeric name string has
* to be evaluated;
*
* @param name is a pointer to a 6 characters buffer where the identifier will
* be returned. Recall to dimension it at least to 7.
*/
NAM2NUM_PROTO(void, num2nam, (unsigned long num, char *name))
{
int c, i, k, q;
if (num >= MAX_NAM2NUM) {
strncpy(name, "|null|", 7);
return;
}
i = 5;
num -= 2;
while (num && i >= 0) {
q = num/40;
c = num - q*40;
num = q;
if (c < 36) {
name[i--] = c > 9 ? c + 'A' - 10 : c + '0';
} else {
name[i--] = c == 36 ? '_' : c == 37 ? '@' : c == 38 ? '.' : '$';
}
}
for (k = 0; i < 5; k++) {
name[k] = name[++i];
}
name[k] = 0;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !_RTAI_NAM2NUM_H */

41
include/rtai_names.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2000 POSEIDON CONTROLS INC <pcloutier@poseidoncontrols.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_NAMES_H
#define _RTAI_NAMES_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
pid_t rt_Name_attach(const char *name);
pid_t rt_Name_locate(const char *host,
const char *name);
int rt_Name_detach(pid_t pid);
void rt_boom(void);
void rt_stomp(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !_RTAI_NAMES_H */

118
include/rtai_prinher.h Normal file
View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2006-2008 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_PRINHER_H
#define _RTAI_PRINHER_H
#include <rtai_schedcore.h>
#ifdef __KERNEL__
#ifdef CONFIG_RTAI_FULL_PRINHER
#define task_owns_sems(task) ((task)->resq.next != &(task)->resq)
static inline void enqueue_resqel(QUEUE *resqel, RT_TASK *resownr)
{
QUEUE *resq;
resqel->next = resq = &resownr->resq;
(resqel->prev = resq->prev)->next = resqel;
resq->prev = resqel;
}
#define enqueue_resqtsk(resownr)
#define RESQEL_TASK ((((QUEUE *)resqel->task)->next)->task)
static inline int _set_task_prio_from_resq(RT_TASK *resownr)
{
int hprio;
RT_TASK *task;
QUEUE *resq, *resqel;
hprio = resownr->base_priority;
resqel = resq = &resownr->resq;
while ((resqel = resqel->next) != resq && (task = RESQEL_TASK) && task->priority < hprio) {
hprio = task->priority;
}
return hprio;
}
static inline int dequeue_resqel_reset_task_priority(QUEUE *resqel, RT_TASK *resownr)
{
int hprio, prio;
QUEUE *q;
(resqel->prev)->next = resqel->next;
(resqel->next)->prev = resqel->prev;
hprio = _set_task_prio_from_resq(resownr);
return renq_ready_task(resownr, ((q = resownr->msg_queue.next) != &resownr->msg_queue && (prio = (q->task)->priority) < hprio) ? prio : hprio);
}
static inline int set_task_prio_from_resq(RT_TASK *resownr)
{
int hprio, prio;
QUEUE *q;
hprio = _set_task_prio_from_resq(resownr);
return renq_ready_task(resownr, ((q = resownr->msg_queue.next) != &resownr->msg_queue && (prio = (q->task)->priority) < hprio) ? prio : hprio);
}
#else /* !CONFIG_RTAI_FULL_PRINHER */
#define task_owns_sems(task) ((task)->owndres)
#define enqueue_resqel(resqel, task) \
do { (task)->owndres++; } while (0)
#define enqueue_resqtsk(task)
// do { (task)->owndres += RPCINC; } while (0)
static inline int _set_task_prio_from_resq(RT_TASK *resownr)
{
QUEUE *q;
int prio;
return renq_ready_task(resownr, ((q = resownr->msg_queue.next) != &resownr->msg_queue && (prio = (q->task)->priority) < resownr->base_priority) ? prio : resownr->base_priority);
}
static inline int dequeue_resqel_reset_task_priority(QUEUE *resqel, RT_TASK *resownr)
{
if (--resownr->owndres <= 0) {
resownr->owndres = 0;
return _set_task_prio_from_resq(resownr);
}
return 0;
}
static inline int set_task_prio_from_resq(RT_TASK *resownr)
{
return !resownr->owndres ? _set_task_prio_from_resq(resownr) : 0;
}
#endif /* CONFIG_RTAI_FULL_PRINHER */
#define dequeue_resqel_reset_current_priority(resqel, rt_current) \
dequeue_resqel_reset_task_priority(resqel, rt_current)
#define set_current_prio_from_resq(rt_current) \
set_task_prio_from_resq(rt_current)
#define task_owns_msgs(task) ((task)->msg_queue.next != &(task)->msg_queue)
#define task_owns_res(task) (task_owns_sems(task) || task_owns_msgs(task))
#endif /* __KERNEL__ */
#endif /* !_RTAI_PRINHER_H */

62
include/rtai_proc_fs.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 1999-2017 Paolo Mantegazza <mantegazza@aero.polimi.it>
* Copyright (C) 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_PROC_FS_H
#define _RTAI_PROC_FS_H
extern struct proc_dir_entry *rtai_proc_root;
#include <linux/seq_file.h>
#define PROC_READ_FUN(read_fun_name) \
read_fun_name(struct seq_file *pf, void *v)
#define PROC_READ_OPEN_OPS(rtai_proc_fops, read_fun_name) \
\
static int rtai_proc_open(struct inode *inode, struct file *file) { \
return single_open(file, read_fun_name, NULL); \
} \
\
static const struct file_operations rtai_proc_fops = { \
.owner = THIS_MODULE, \
.open = rtai_proc_open, \
.read = seq_read, \
.llseek = seq_lseek, \
.release = single_release \
};
static inline void *CREATE_PROC_ENTRY(const char *name, umode_t mode, void *parent, const struct file_operations *proc_fops)
{
return !parent ? proc_mkdir(name, NULL) : proc_create(name, mode, parent, proc_fops);
}
#define SET_PROC_READ_ENTRY(entry, read_fun) do { } while(0)
#define PROC_PRINT_VARS
#define PROC_PRINT(fmt, args...) \
do { seq_printf(pf, fmt, ##args); } while(0)
#define PROC_PRINT_RETURN do { goto done; } while(0)
#define PROC_PRINT_DONE do { return 0; } while(0)
// End of proc print macros
#endif /* !_RTAI_PROC_FS_H */

52
include/rtai_proxies.h Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2000 Pierre Cloutier <pcloutier@poseidoncontrols.com>
* Copyright (C) 2000 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_PROXIES_H
#define _RTAI_PROXIES_H
#include <rtai_sched.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
// Create a generic proxy task.
RT_TASK *__rt_proxy_attach(void (*func)(long),
RT_TASK *task,
void *msg,
int nbytes,
int priority);
// Create a raw proxy task.
RTAI_SYSCALL_MODE RT_TASK *rt_proxy_attach(RT_TASK *task,
void *msg,
int nbytes,
int priority);
// Delete a proxy task (a simplified specific rt_task_delete).
RTAI_SYSCALL_MODE int rt_proxy_detach(RT_TASK *proxy);
//Trigger a proxy.
RTAI_SYSCALL_MODE RT_TASK *rt_trigger(RT_TASK *proxy);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !_RTAI_PROXIES_H */

96
include/rtai_registry.h Normal file
View File

@ -0,0 +1,96 @@
/**
* @ingroup lxrt
* @file
*
* @author Paolo Mantegazza
*
* @note Copyright &copy; 1999 Paolo Mantegazza <mantegazza@aero.polimi.it>,
* @note Copyright &copy; 2019 Alec Ari <neotheuser@ymail.com,
* extensions for user space modules are jointly copyrighted (2000) with:
* Pierre Cloutier <pcloutier@poseidoncontrols.com>,
* Steve Papacharalambous <stevep@zentropix.com>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_REGISTRY_H
#define _RTAI_REGISTRY_H
#include <rtai_nam2num.h>
struct task_struct;
struct rt_registry_entry {
unsigned long name; // Numerical representation of resource name
void *adr; // Physical rt memory address of resource
struct task_struct *tsk; // Linux task owner of the resource
int type; // Type of resource
unsigned short count; // Usage registry
unsigned short alink;
unsigned short nlink;
};
#define MAX_SLOTS CONFIG_RTAI_SCHED_LXRT_NUMSLOTS // Max number of registered objects
#define IS_TASK 0 // Used to identify registered resources
#define IS_SEM 1
#define IS_RWL 2
#define IS_SPL 3
#define IS_MBX 4
#define IS_PRX 5
#define IS_HPCK 6
#ifdef __KERNEL__
#include <rtai.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
unsigned long is_process_registered(struct task_struct *tsk);
int rt_register(unsigned long nam,
void *adr,
int typ,
struct task_struct *tsk);
int rt_drg_on_name(unsigned long name);
int rt_drg_on_name_cnt(unsigned long name);
int rt_drg_on_adr(void *adr);
int rt_drg_on_adr_cnt(void *adr);
RTAI_SYSCALL_MODE unsigned long rt_get_name(void *adr);
RTAI_SYSCALL_MODE void *rt_get_adr(unsigned long name);
void *rt_get_adr_cnt(unsigned long name);
int rt_get_type(unsigned long name);
int rt_get_registry_slot(int slot, struct rt_registry_entry *entry);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
#define exist(name) rt_get_adr(nam2num(name))
#endif /* !_RTAI_REGISTRY_H */

172
include/rtai_rwl.h Normal file
View File

@ -0,0 +1,172 @@
/*
* Copyright (C) 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_RWL_H
#define _RTAI_RWL_H
#include <rtai_sem.h>
struct rtai_rwlock;
#ifdef __KERNEL__
#ifndef __cplusplus
typedef struct rtai_rwlock {
SEM wrmtx,
wrsem,
rdsem;
} RWL;
#else /* __cplusplus */
extern "C" {
#endif /* !__cplusplus */
RTAI_SYSCALL_MODE int rt_typed_rwl_init(RWL *rwl, int type);
#define rt_rwl_init(rwl) rt_typed_rwl_init(rwl, RESEM_RECURS)
RTAI_SYSCALL_MODE int rt_rwl_delete(struct rtai_rwlock *rwl);
RTAI_SYSCALL_MODE RWL *_rt_named_rwl_init(unsigned long rwl_name);
RTAI_SYSCALL_MODE int rt_named_rwl_delete(RWL *rwl);
RTAI_SYSCALL_MODE int rt_rwl_rdlock(struct rtai_rwlock *rwl);
RTAI_SYSCALL_MODE int rt_rwl_rdlock_if(struct rtai_rwlock *rwl);
RTAI_SYSCALL_MODE int rt_rwl_rdlock_until(struct rtai_rwlock *rwl, RTIME time);
RTAI_SYSCALL_MODE int rt_rwl_rdlock_timed(struct rtai_rwlock *rwl, RTIME delay);
RTAI_SYSCALL_MODE int rt_rwl_wrlock(struct rtai_rwlock *rwl);
RTAI_SYSCALL_MODE int rt_rwl_wrlock_if(struct rtai_rwlock *rwl);
RTAI_SYSCALL_MODE int rt_rwl_wrlock_until(struct rtai_rwlock *rwl, RTIME time);
RTAI_SYSCALL_MODE int rt_rwl_wrlock_timed(struct rtai_rwlock *rwl, RTIME delay);
RTAI_SYSCALL_MODE int rt_rwl_unlock(struct rtai_rwlock *rwl);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define rt_rwl_init(rwl) rt_typed_rwl_init(rwl, RESEM_RECURS)
RTAI_PROTO(struct rtai_rwlock *, rt_typed_rwl_init,(unsigned long name, int type))
{
struct { unsigned long name; long type; } arg = { name, type };
return (struct rtai_rwlock *)rtai_lxrt(BIDX, SIZARG, LXRT_RWL_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_rwl_delete,(struct rtai_rwlock *rwl))
{
struct { struct rtai_rwlock *rwl; } arg = { rwl };
return rtai_lxrt(BIDX, SIZARG, LXRT_RWL_DELETE, &arg).i[LOW];
}
RTAI_PROTO(struct rtai_rwlock *, rt_named_rwl_init,(const char *name))
{
struct { unsigned long name; } arg = { nam2num(name) };
return (struct rtai_rwlock *)rtai_lxrt(BIDX, SIZARG, NAMED_RWL_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_named_rwl_delete,(struct rtai_rwlock *rwl))
{
struct { struct rtai_rwlock *rwl; } arg = { rwl };
return rtai_lxrt(BIDX, SIZARG, NAMED_RWL_DELETE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_rdlock,(struct rtai_rwlock *rwl))
{
struct { struct rtai_rwlock *rwl; } arg = { rwl };
return rtai_lxrt(BIDX, SIZARG, RWL_RDLOCK, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_rdlock_if,(struct rtai_rwlock *rwl))
{
struct { void *rwl; } arg = { rwl };
return rtai_lxrt(BIDX, SIZARG, RWL_RDLOCK_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_rdlock_until,(struct rtai_rwlock *rwl, RTIME time))
{
struct { struct rtai_rwlock *rwl; RTIME time; } arg = { rwl, time };
return rtai_lxrt(BIDX, SIZARG, RWL_RDLOCK_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_rdlock_timed,(struct rtai_rwlock *rwl, RTIME delay))
{
struct { struct rtai_rwlock *rwl; RTIME delay; } arg = { rwl, delay };
return rtai_lxrt(BIDX, SIZARG, RWL_RDLOCK_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_wrlock,(struct rtai_rwlock *rwl))
{
struct { struct rtai_rwlock *rwl; } arg = { rwl };
return rtai_lxrt(BIDX, SIZARG, RWL_WRLOCK, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_wrlock_if,(struct rtai_rwlock *rwl))
{
struct { struct rtai_rwlock *rwl; } arg = { rwl };
return rtai_lxrt(BIDX, SIZARG, RWL_WRLOCK_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_wrlock_until,(struct rtai_rwlock *rwl, RTIME time))
{
struct { struct rtai_rwlock *rwl; RTIME time; } arg = { rwl, time };
return rtai_lxrt(BIDX, SIZARG, RWL_WRLOCK_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_wrlock_timed,(struct rtai_rwlock *rwl, RTIME delay))
{
struct { struct rtai_rwlock *rwl; RTIME delay; } arg = { rwl, delay };
return rtai_lxrt(BIDX, SIZARG, RWL_WRLOCK_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_rwl_unlock,(struct rtai_rwlock *rwl))
{
struct { struct rtai_rwlock *rwl; } arg = { rwl };
return rtai_lxrt(BIDX, SIZARG, RWL_UNLOCK, &arg).i[LOW];
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#if !defined(__KERNEL__) || defined(__cplusplus)
typedef struct rtai_rwlock {
int opaque;
} RWL;
#endif /* !__KERNEL__ || __cplusplus */
#endif /* !_RTAI_RWL_H */

332
include/rtai_scb.h Normal file
View File

@ -0,0 +1,332 @@
/**
* @ingroup shm
* @file
*
* SCB stand for Shared (memory) Circular Buffer. It is a non blocking
* implementation for just a single writer (producer) and reader
* (consumer) and, under such a constraint, it can be a specific
* substitute for RTAI mailboxes. There are other constraints that
* must be satisfied, so it cannot be a general substitute for the more
* flexible RTAI mailboxes. In fact it provides just functions
* corresponding to RTAI mailboxes non blocking atomic send/receive of
* messages, i.e. the equivalents of rt_mbx_send_if and
* rt_mbx_receive_if. Moreover the circular buffer size must be >= to
* the largest message to be sent/received. At least the double of the
* largest message to be sent/received is strongly recommended.
* Thus sending/receiving a message either succeeds of fails. However
* thanks to the use of shared memory it should be more efficient than
* mailboxes in atomic exchanges of messages from kernel to user space.
* So it is a good candidate for supporting drivers development.
*
* @author Paolo Mantegazza
*
* @note Copyright &copy; 2004-2008 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_SCB_H
#define _RTAI_SCB_H
#include <rtai_shm.h>
#include <asm/rtai_atomic.h>
#define SCB ((void *)(scb))
#define SIZE ((volatile int *)scb)[-3]
#define FBYTE ((volatile int *)scb)[-2]
#define LBYTE ((volatile int *)scb)[-1]
#define HDRSIZ (3*sizeof(int))
struct task_struct;
#ifdef __KERNEL__
#define RTAI_SCB_PROTO(type, name, arglist) static inline type name arglist
#else
#define RTAI_SCB_PROTO RTAI_PROTO
#endif
/**
* Allocate and initialize a shared memory circular buffer.
*
* @internal
*
* rt_scb_init is used to allocate and/or initialize a shared memory circular
* buffer.
*
* @param name is an unsigned long identifier;
*
* @param size is the size of the circular buffer.
*
* @param suprt is the kernel allocation method to be used, it can be:
* - USE_VMALLOC, use vmalloc;
* - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
* - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
* - USE_GFP_DMA, use kmalloc with GFP_DMA.
* - for use in kernel/(multi-threaded)user space only applications the
* user can use "suprt" to pass the address of any memory area (s)he has
* allocated on her/his own. In such a case the actual buffer should be
* greater than the requested size by the amount HDRSIZ at least.
*
* Since @a an unsigned long can be a clumsy identifier, services are provided
* to convert 6 characters identifiers to unsigned long, and vice versa.
*
* @see nam2num() and num2nam().
*
* It must be remarked that only the very first call does a real allocation,
* any following call to allocate with the same name, from anywhere, will just
* increase the usage count and map the circular buffer to the user space, or
* return the related pointer to the already allocated buffer in kernel/user
* space.
* In any case the functions return a pointer to the circular buffer,
* appropriately mapped to the memory space in use. So if one is really sure
* that the named circular buffer has been initted already parameters "size"
* and "suprt" are not used and can be assigned any value.
*
* @returns a valid address on succes, you must use it, 0 on failure.
*
*/
RTAI_SCB_PROTO(void *, rt_scb_init, (unsigned long name, int size, unsigned long suprt))
{
void *scb;
if (suprt > 1000) {
size -= HDRSIZ + 1;
scb = (void *)suprt;
} else {
scb = rt_shm_alloc(name, size + HDRSIZ + 1, suprt);
}
if (scb && !atomic_cmpxchg((atomic_t *)scb, 0, name)) {
((int *)scb)[1] = ((int *)scb)[2] = 0;
((int *)scb)[0] = size + 1;
} else {
while (!((int *)scb)[0]);
}
return scb ? scb + HDRSIZ : 0;
}
/**
* Reset a shared memory circular buffer.
*
* @internal
*
* rt_scb_reset reinitializes a shared memory circular buffer.
*
* @param scb is the pointer returned when the buffer was initted.
*
*/
RTAI_SCB_PROTO(void, rt_scb_reset, (void *scb))
{
LBYTE = FBYTE = 0;
}
/**
* Free a shared memory circular buffer.
*
* @internal
*
* rt_scb_delete is used to release a previously allocated shared memory
* circular buffer.
*
* @param name is the unsigned long identifier used when the buffer was
* allocated;
*
* Analogously to what done by all the named allocation functions the freeing
* calls have just the effect of decrementing a usage count, unmapping any
* user space shared memory being freed, till the last is done, as that is the
* one the really frees any allocated memory.
*
* @returns the size of the succesfully freed buffer, 0 on failure.
*
* No need to call this function if you provided your own memory for the
* circular buffer.
*
*/
RTAI_SCB_PROTO(int, rt_scb_delete, (unsigned long name))
{
return rt_shm_free(name);
}
/**
* Get the number of bytes avaiable in a shared memory circular buffer.
*
* @internal
*
* rt_scb_avbs is used to get the number of bytes avaiable in a shared
* memory circular buffer.
*
* @param scb is the pointer handle returned when the buffer was initted.
*
* @returns the available number of bytes.
*
*/
RTAI_SCB_PROTO (int, rt_scb_avbs, (void *scb))
{
int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
return (lbyte >= fbyte ? lbyte - fbyte : size + lbyte - fbyte);
}
/**
* Get the number of bytes avaiable in a shared memory circular buffer.
*
* @internal
*
* rt_scb_bytes is used to get the number of bytes avaiable in a shared
* memory circular buffer; legacy alias for rt_scb_avbs.
*
* @param scb is the pointer handle returned when the buffer was initted.
*
* @returns the available number of bytes.
*
*/
RTAI_SCB_PROTO (int, rt_scb_bytes, (void *scb))
{
return rt_scb_avbs(scb);
}
/**
* Get the number of free bytes pace in a shared memory circular buffer.
*
* @internal
*
* rt_scb_frbs is used to get the number of free bytes space avaiable in a
* shared memory circular buffer.
*
* @param scb is the pointer handle returned when the buffer was initted.
*
* @returns the number of free bytes.
*
*/
RTAI_SCB_PROTO (int, rt_scb_frbs, (void *scb))
{
int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
return (fbyte <= lbyte ? size + fbyte - lbyte : size - lbyte);
}
/**
* @brief Gets (receives) a message, only if the whole message can be passed
* all at once.
*
* rt_scb_get tries to atomically receive the message @e msg of @e
* msg_size bytes from the shared memory circular buffer @e scb.
* It returns immediately and the caller is never blocked.
*
* @return On success, i.e. message got, it returns 0, msg_size on failure.
*
*/
RTAI_SCB_PROTO(int, rt_scb_get, (void *scb, void *msg, int msg_size))
{
int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
if (msg_size > 0 && ((lbyte -= fbyte) >= 0 ? lbyte : size + lbyte) >= msg_size) {
int tocpy;
if ((tocpy = size - fbyte) > msg_size) {
memcpy(msg, SCB + fbyte, msg_size);
FBYTE = fbyte + msg_size;
} else {
memcpy(msg, SCB + fbyte, tocpy);
memcpy(msg + tocpy, SCB, msg_size -= tocpy);
FBYTE = msg_size;
}
return 0;
}
return msg_size;
}
/**
* @brief eavedrops a message.
*
* rt_scb_evdrp atomically spies the message @e msg of @e
* msg_size bytes from the shared memory circular buffer @e scb.
* It returns immediately and the caller is never blocked. It is like
* rt_scb_get but leaves the message in the shared memory circular buffer.
*
* @return On success, i.e. message got, it returns 0, msg_size on failure.
*
*/
RTAI_SCB_PROTO(int, rt_scb_evdrp, (void *scb, void *msg, int msg_size))
{
int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
if (msg_size > 0 && ((lbyte -= fbyte) >= 0 ? lbyte : size + lbyte) >= msg_size) {
int tocpy;
if ((tocpy = size - fbyte) > msg_size) {
memcpy(msg, SCB + fbyte, msg_size);
} else {
memcpy(msg, SCB + fbyte, tocpy);
memcpy(msg + tocpy, SCB, msg_size - tocpy);
}
return 0;
}
return msg_size;
}
/**
* @brief Puts (sends) a message, only if the whole message can be passed all
* at once.
*
* rt_scb_put tries to atomically send the message @e msg of @e
* msg_size bytes to the shared memory circular buffer @e scb.
* It returns immediately and the caller is never blocked.
*
* @return On success, i.e. message put, it returns 0, msg_size on failure.
*
*/
RTAI_SCB_PROTO(int, rt_scb_put, (void *scb, void *msg, int msg_size))
{
int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
if (msg_size > 0 && ((fbyte -= lbyte) <= 0 ? size + fbyte : fbyte) > msg_size) {
int tocpy;
if ((tocpy = size - lbyte) > msg_size) {
memcpy(SCB + lbyte, msg, msg_size);
LBYTE = lbyte + msg_size;
} else {
memcpy(SCB + lbyte, msg, tocpy);
memcpy(SCB, msg + tocpy, msg_size -= tocpy);
LBYTE = msg_size;
}
return 0;
}
return msg_size;
}
RTAI_SCB_PROTO(int, rt_scb_ovrwr, (void *scb, void *msg, int msg_size))
{
int size = SIZE, lbyte = LBYTE;
if (msg_size > 0 && msg_size < size) {
int tocpy;
if ((tocpy = size - lbyte) > msg_size) {
memcpy(SCB + lbyte, msg, msg_size);
LBYTE = lbyte + msg_size;
} else {
memcpy(SCB + lbyte, msg, tocpy);
memcpy(SCB, msg + tocpy, msg_size -= tocpy);
LBYTE = msg_size;
}
return 0;
}
return msg_size;
}
#endif /* _RTAI_SCB_H */

528
include/rtai_sched.h Normal file
View File

@ -0,0 +1,528 @@
/*
* Copyright (C) 1999-2017 Paolo Mantegazza <mantegazza@aero.polimi.it>
* Copyright (C) 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_SCHED_H
#define _RTAI_SCHED_H
#include <rtai.h>
#ifndef __KERNEL__
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <rtai_types.h>
#endif /* __KERNEL__ */
#define RT_SCHED_UP 1
#define RT_SCHED_SMP 2
#define RT_SCHED_MUP 3
#define RT_SCHED_HIGHEST_PRIORITY 0
#define RT_SCHED_LOWEST_PRIORITY 0x3fffFfff
#define RT_SCHED_LINUX_PRIORITY 0x7fffFfff
#define RT_RESEM_SUSPDEL (-0x7fffFfff)
#define RT_SCHED_READY 1
#define RT_SCHED_SUSPENDED 2
#define RT_SCHED_DELAYED 4
#define RT_SCHED_SEMAPHORE 8
#define RT_SCHED_SEND 16
#define RT_SCHED_RECEIVE 32
#define RT_SCHED_RPC 64
#define RT_SCHED_RETURN 128
#define RT_SCHED_MBXSUSP 256
#define RT_SCHED_SFTRDY 512
#define RT_SCHED_POLL 1024
#define RT_SCHED_SIGSUSP (1 << 15)
#define RT_RWLINV (11) // keep this the highest
#define RT_CHGPORTERR (10)
#define RT_CHGPORTOK (9)
#define RT_NETIMOUT (8)
#define RT_DEADLOK (7)
#define RT_PERM (6)
#define RT_OBJINV (5)
#define RT_OBJREM (4)
#define RT_TIMOUT (3)
#define RT_UNBLKD (2)
#define RT_TMROVRN (1) // keep this the lowest, must be 1
#define RTP_RWLINV ((void *)RT_RWLINV)
#define RTP_CHGPORTERR ((void *)RT_CHGPORTERR)
#define RTP_CHGPORTOK ((void *)RT_CHGPORTOK)
#define RTP_NETIMOUT ((void *)RT_NETIMOUT)
#define RTP_DEADLOK ((void *)RT_DEADLOK)
#define RTP_PERM ((void *)RT_PERM)
#define RTP_OBJINV ((void *)RT_OBJINV)
#define RTP_OBJREM ((void *)RT_OBJREM)
#define RTP_TIMOUT ((void *)RT_TIMOUT)
#define RTP_UNBLKD ((void *)RT_UNBLKD)
#define RTP_TMROVRN ((void *)RT_TMROVRN)
#define RTP_HIGERR (RTP_RWLINV)
#define RTP_LOWERR (RTP_TMROVRN)
#if CONFIG_RTAI_USE_NEWERR
#define RTE_BASE (0x3FFFFF00)
#define RTE_RWLINV (RTE_BASE + RT_RWLINV)
#define RTE_CHGPORTERR (RTE_BASE + RT_CHGPORTERR)
#define RTE_CHGPORTOK (RTE_BASE + RT_CHGPORTOK)
#define RTE_NETIMOUT (RTE_BASE + RT_NETIMOUT)
#define RTE_DEADLOK (RTE_BASE + RT_DEADLOK)
#define RTE_PERM (RTE_BASE + RT_PERM)
#define RTE_OBJINV (RTE_BASE + RT_OBJINV)
#define RTE_OBJREM (RTE_BASE + RT_OBJREM)
#define RTE_TIMOUT (RTE_BASE + RT_TIMOUT)
#define RTE_UNBLKD (RTE_BASE + RT_UNBLKD)
#define RTE_TMROVRN (RTE_BASE + RT_TMROVRN)
#define RTE_HIGERR (RTE_RWLINV)
#define RTE_LOWERR (RTE_TMROVRN)
#else
#define RTE_BASE (0xFFFB)
#define RTE_RWLINV (RTE_BASE + RT_RWLINV)
#define RTE_CHGPORTERR (RTE_BASE + RT_CHGPORTERR)
#define RTE_CHGPORTOK (RTE_BASE + RT_CHGPORTOK)
#define RTE_NETIMOUT (RTE_BASE + RT_NETIMOUT)
#define RTE_DEADLOK (RTE_BASE + RT_DEADLOK)
#define RTE_PERM (RTE_BASE + RT_PERM)
#define RTE_OBJINV (RTE_BASE + RT_OBJREM)
#define RTE_OBJREM (RTE_BASE + RT_OBJREM)
#define RTE_TIMOUT (RTE_BASE + RT_TIMOUT)
#define RTE_UNBLKD (RTE_BASE + RT_UNBLKD)
#define RTE_TMROVRN (RTE_BASE + RT_TMROVRN)
#define RTE_HIGERR (RTE_RWLINV)
#define RTE_LOWERR (RTE_TMROVRN)
#endif
#define RT_EINTR (RTE_UNBLKD)
#define rt_is_reterr(i) (i >= RTE_LOWERR)
#define RT_IRQ_TASK 0
#define RT_IRQ_TASKLET 1
#define RT_IRQ_TASK_ERR 0x7FFFFFFF
struct rt_task_struct;
typedef struct rt_task_info {
RTIME period; long base_priority, priority;
} RT_TASK_INFO;
#ifdef __KERNEL__
#include <linux/time.h>
#include <linux/errno.h>
#if defined(CONFIG_RTAI_LONG_TIMED_LIST)
#include <linux/rbtree.h>
typedef struct rb_node rb_node_t;
typedef struct rb_root rb_root_t;
#endif
#define RT_TASK_MAGIC 0x9ad25f6f // nam2num("rttask")
#ifndef __cplusplus
#include <linux/sched.h>
typedef struct rt_queue {
struct rt_queue *prev;
struct rt_queue *next;
struct rt_task_struct *task;
} QUEUE;
struct mcb_t {
void *sbuf;
int sbytes;
void *rbuf;
int rbytes;
};
/*Exit handler functions are called like C++ destructors in rt_task_delete().*/
typedef struct rt_ExitHandler {
struct rt_ExitHandler *nxt;
void (*fun) (void *arg1, int arg2);
void *arg1;
int arg2;
} XHDL;
struct rt_heap_t { void *heap, *kadr, *uadr; };
#define RTAI_MAX_NAME_LENGTH 32
typedef struct rt_task_struct {
long *stack __attribute__ ((__aligned__ (L1_CACHE_BYTES)));
int uses_fpu;
int magic;
volatile int state, running;
unsigned long runnable_on_cpus;
long *stack_bottom;
volatile int priority;
int base_priority;
int policy;
int sched_lock_priority;
struct rt_task_struct *prio_passed_to;
RTIME period;
RTIME resume_time;
RTIME periodic_resume_time;
RTIME yield_time;
int rr_quantum, rr_remaining;
int suspdepth;
struct rt_queue queue;
int owndres;
struct rt_queue *blocked_on;
struct rt_queue msg_queue;
int tid; /* trace ID */
unsigned long msg;
struct rt_queue ret_queue;
void (*signal)(void);
FPU_ENV fpu_reg __attribute__ ((__aligned__ (L1_CACHE_BYTES)));
struct rt_task_struct *prev, *next;
struct rt_task_struct *tprev, *tnext;
struct rt_task_struct *rprev, *rnext;
/* For calls from LINUX. */
long *fun_args;
long *bstack;
struct task_struct *lnxtsk;
long long retval;
char *msg_buf[2];
long max_msg_size[2];
char task_name[RTAI_MAX_NAME_LENGTH];
void *system_data_ptr;
struct rt_task_struct *nextp, *prevp;
RT_TRAP_HANDLER task_trap_handler[RTAI_NR_TRAPS];
long unblocked;
void *rt_signals;
volatile unsigned long pstate;
unsigned long usp_flags;
unsigned long usp_flags_mask;
unsigned long force_soft;
volatile int is_hard;
int kerrno;
long busy_time_align;
void *linux_syscall_server;
/* For use by watchdog. */
int resync_frame;
/* For use by exit handler functions. */
XHDL *ExitHook;
RTIME exectime[2];
struct mcb_t mcb;
/* Real time heaps. */
struct rt_heap_t heap[2];
long scheduler;
#ifdef CONFIG_RTAI_LONG_TIMED_LIST
rb_root_t rbr;
rb_node_t rbn;
#endif
struct rt_queue resq;
unsigned long resumsg;
int schedlat;
} RT_TASK __attribute__ ((__aligned__ (L1_CACHE_BYTES)));
#else /* __cplusplus */
extern "C" {
#endif /* !__cplusplus */
int set_rtext(RT_TASK *task, int priority, int uses_fpu, void(*signal)(void), unsigned int cpuid);
int rt_task_init(struct rt_task_struct *task,
void (*rt_thread)(long),
long data,
int stack_size,
int priority,
int uses_fpu,
void(*signal)(void));
int rt_task_init_cpuid(struct rt_task_struct *task,
void (*rt_thread)(long),
long data,
int stack_size,
int priority,
int uses_fpu,
void(*signal)(void),
unsigned run_on_cpu);
void rt_thread_create(void *fun, void *args, struct task_struct **thread);
RT_TASK *rt_thread_init(unsigned long name, int priority, int make_hard, int policy, int cpus_allowed);
int rt_thread_delete(RT_TASK *rt_task);
int rt_kthread_init(struct rt_task_struct *task,
void (*rt_thread)(long),
long data,
int stack_size,
int priority,
int uses_fpu,
void(*signal)(void));
int rt_kthread_init_cpuid(struct rt_task_struct *task,
void (*rt_thread)(long),
long data,
int stack_size,
int priority,
int uses_fpu,
void(*signal)(void),
unsigned run_on_cpu);
RTAI_SYSCALL_MODE void rt_set_runnable_on_cpus(struct rt_task_struct *task,
unsigned long cpu_mask);
RTAI_SYSCALL_MODE void rt_set_runnable_on_cpuid(struct rt_task_struct *task,
unsigned cpuid);
RTAI_SYSCALL_MODE void rt_set_sched_policy(struct rt_task_struct *task,
int policy,
int rr_quantum_ns);
int rt_task_delete(struct rt_task_struct *task);
int rt_get_task_state(struct rt_task_struct *task);
void rt_gettimeorig(RTIME time_orig[]);
int rt_get_timer_cpu(void);
int rt_is_hard_timer_running(void);
void rt_set_periodic_mode(void);
void rt_set_oneshot_mode(void);
RTAI_SYSCALL_MODE RTIME start_rt_timer(int period);
#define start_rt_timer_ns(period) start_rt_timer(nano2count((period)))
RTAI_SYSCALL_MODE void start_rt_apic_timers(struct apic_timer_setup_data *setup_mode,
unsigned rcvr_jiffies_cpuid);
void stop_rt_timer(void);
struct rt_task_struct *rt_whoami(void);
int rt_sched_type(void);
RTAI_SYSCALL_MODE int rt_task_signal_handler(struct rt_task_struct *task,
void (*handler)(void));
RTAI_SYSCALL_MODE int rt_task_use_fpu(struct rt_task_struct *task,
int use_fpu_flag);
void rt_linux_use_fpu(int use_fpu_flag);
RTAI_SYSCALL_MODE int rt_hard_timer_tick_count(void);
RTAI_SYSCALL_MODE int rt_hard_timer_tick_count_cpuid(int cpuid);
RTAI_SYSCALL_MODE RTIME count2nano(RTIME timercounts);
RTAI_SYSCALL_MODE RTIME nano2count(RTIME nanosecs);
RTAI_SYSCALL_MODE RTIME count2nano_cpuid(RTIME timercounts, unsigned cpuid);
RTAI_SYSCALL_MODE RTIME nano2count_cpuid(RTIME nanosecs, unsigned cpuid);
RTIME rt_get_time(void);
RTAI_SYSCALL_MODE RTIME rt_get_time_cpuid(unsigned cpuid);
RTIME rt_get_time_ns(void);
RTAI_SYSCALL_MODE RTIME rt_get_time_ns_cpuid(unsigned cpuid);
RTIME rt_get_cpu_time_ns(void);
RTIME rt_get_real_time(void);
RTIME rt_get_real_time_ns(void);
int rt_get_prio(struct rt_task_struct *task);
int rt_get_inher_prio(struct rt_task_struct *task);
RTAI_SYSCALL_MODE int rt_task_get_info(RT_TASK *task, RT_TASK_INFO *task_info);
RTAI_SYSCALL_MODE int rt_get_priorities(struct rt_task_struct *task, int *priority, int *base_priority);
RTAI_SYSCALL_MODE void rt_spv_RMS(int cpuid);
RTAI_SYSCALL_MODE int rt_change_prio(struct rt_task_struct *task,
int priority);
void rt_sched_lock(void);
void rt_sched_unlock(void);
void rt_task_yield(void);
RTAI_SYSCALL_MODE int rt_task_suspend(struct rt_task_struct *task);
RTAI_SYSCALL_MODE int rt_task_suspend_if(struct rt_task_struct *task);
RTAI_SYSCALL_MODE int rt_task_suspend_until(struct rt_task_struct *task, RTIME until);
RTAI_SYSCALL_MODE int rt_task_suspend_timed(struct rt_task_struct *task, RTIME delay);
RTAI_SYSCALL_MODE int rt_task_resume(struct rt_task_struct *task);
RTAI_SYSCALL_MODE int rt_set_linux_syscall_mode(long sync_async, void (*callback_fun)(long, long));
struct linux_syscalls_list;
void rt_exec_linux_syscall(RT_TASK *rt_current, struct linux_syscalls_list *syscalls, struct pt_regs *regs);
RTAI_SYSCALL_MODE void rt_return_linux_syscall(RT_TASK *task, unsigned long retval);
RTAI_SYSCALL_MODE int rt_irq_wait(unsigned irq);
RTAI_SYSCALL_MODE int rt_irq_wait_if(unsigned irq);
RTAI_SYSCALL_MODE int rt_irq_wait_until(unsigned irq, RTIME until);
RTAI_SYSCALL_MODE int rt_irq_wait_timed(unsigned irq, RTIME delay);
RTAI_SYSCALL_MODE void rt_irq_signal(unsigned irq);
RTAI_SYSCALL_MODE int rt_request_irq_task (unsigned irq, void *handler, int type, int affine2task);
RTAI_SYSCALL_MODE int rt_release_irq_task (unsigned irq);
RTAI_SYSCALL_MODE int rt_task_make_periodic_relative_ns(struct rt_task_struct *task,
RTIME start_delay,
RTIME period);
RTAI_SYSCALL_MODE int rt_task_make_periodic(struct rt_task_struct *task,
RTIME start_time,
RTIME period);
RTAI_SYSCALL_MODE void rt_task_set_resume_end_times(RTIME resume,
RTIME end);
RTAI_SYSCALL_MODE int rt_set_resume_time(struct rt_task_struct *task,
RTIME new_resume_time);
RTAI_SYSCALL_MODE int rt_set_period(struct rt_task_struct *task,
RTIME new_period);
int rt_task_wait_period(void);
void rt_schedule(void);
RTIME next_period(void);
RTAI_SYSCALL_MODE void rt_busy_sleep(int nanosecs);
RTAI_SYSCALL_MODE int rt_sleep(RTIME delay);
RTAI_SYSCALL_MODE int rt_sleep_until(RTIME time);
RTAI_SYSCALL_MODE int rt_task_masked_unblock(struct rt_task_struct *task, unsigned long mask);
#define rt_task_wakeup_sleeping(t) rt_task_masked_unblock(t, RT_SCHED_DELAYED)
RTAI_SYSCALL_MODE struct rt_task_struct *rt_named_task_init(const char *task_name,
void (*thread)(long),
long data,
int stack_size,
int prio,
int uses_fpu,
void(*signal)(void));
RTAI_SYSCALL_MODE struct rt_task_struct *rt_named_task_init_cpuid(const char *task_name,
void (*thread)(long),
long data,
int stack_size,
int prio,
int uses_fpu,
void(*signal)(void),
unsigned run_on_cpu);
RTAI_SYSCALL_MODE int rt_named_task_delete(struct rt_task_struct *task);
RT_TRAP_HANDLER rt_set_task_trap_handler(struct rt_task_struct *task,
unsigned vec,
RT_TRAP_HANDLER handler);
static inline RTIME timeval2count(struct timeval *t)
{
return nano2count(t->tv_sec*1000000000LL + t->tv_usec*1000);
}
static inline void count2timeval(RTIME rt, struct timeval *t)
{
t->tv_sec = rtai_ulldiv(count2nano(rt), 1000000000, (unsigned long *)&t->tv_usec);
t->tv_usec /= 1000;
}
static inline RTIME timespec2count(const struct timespec *t)
{
return nano2count(t->tv_sec*1000000000LL + t->tv_nsec);
}
static inline void count2timespec(RTIME rt, struct timespec *t)
{
t->tv_sec = rtai_ulldiv(count2nano(rt), 1000000000, (unsigned long *)&t->tv_nsec);
}
static inline RTIME timespec2nanos(const struct timespec *t)
{
return t->tv_sec*1000000000LL + t->tv_nsec;
}
static inline void nanos2timespec(RTIME rt, struct timespec *t)
{
t->tv_sec = rtai_ulldiv(rt, 1000000000, (unsigned long *)&t->tv_nsec);
}
void rt_make_hard_real_time(RT_TASK *task);
void rt_make_soft_real_time(RT_TASK *task);
#ifdef __cplusplus
}
#else /* !__cplusplus */
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#if !defined(__KERNEL__) || defined(__cplusplus)
typedef struct rt_task_struct {
int opaque;
} RT_TASK;
typedef struct QueueBlock {
int opaque;
} QBLK;
typedef struct QueueHook {
int opaque;
} QHOOK;
#endif /* !__KERNEL__ || __cplusplus */
#endif /* !_RTAI_SCHED_H */

599
include/rtai_schedcore.h Normal file
View File

@ -0,0 +1,599 @@
/*
* Copyright (C) 1999-2013 Paolo Mantegazza <mantegazza@aero.polimi.it>
* Copyright (C) 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_SCHEDCORE_H
#define _RTAI_SCHEDCORE_H
#ifdef __KERNEL__
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/timex.h>
#include <linux/sched.h>
#include <asm/param.h>
#include <asm/io.h>
#include <linux/oom.h>
#include <rtai_lxrt.h>
#include <rtai_sched.h>
#include <rtai_malloc.h>
#include <rtai_trace.h>
#include <rtai_sem.h>
#include <rtai_rwl.h>
#include <rtai_spl.h>
#include <rtai_scb.h>
#include <rtai_mbx.h>
#include <rtai_msg.h>
#include <rtai_fifos.h>
#include <rtai_shm.h>
#ifdef OOM_DISABLE
#define RTAI_OOM_DISABLE() \
do { current->signal->oom_score_adj = OOM_DISABLE; } while (0)
#else
#define RTAI_OOM_DISABLE()
#endif
#define NON_RTAI_TASK_SUSPEND(task) \
do { (task->lnxtsk)->state = TASK_SOFTREALTIME; } while (0)
#define NON_RTAI_TASK_RESUME(ready_task) \
do { pend_wake_up_srq(ready_task->lnxtsk, rtai_cpuid()); } while (0)
#define REQUEST_RESUME_SRQs_STUFF() \
do { \
if (!(wake_up_srq[0].srq = hal_alloc_irq())) { \
printk("*** ABORT, NO VIRQ AVAILABLE FOR THE WAKING UP SRQ. ***\n"); \
return -1; \
} \
ipipe_request_irq(hal_root_domain, wake_up_srq[0].srq, (void *)wake_up_srq_handler, NULL, NULL); \
} while (0)
#define RELEASE_RESUME_SRQs_STUFF() \
do { \
ipipe_free_irq(hal_root_domain, wake_up_srq[0].srq); \
hal_free_irq(wake_up_srq[0].srq); \
} while (0)
extern RT_TASK rt_smp_linux_task[];
extern RT_TASK *rt_smp_current[];
extern RTIME rt_smp_time_h[];
extern volatile int rt_sched_timed;
RT_TASK *rt_get_base_linux_task(RT_TASK **base_linux_task);
RT_TASK *rt_alloc_dynamic_task(void);
void rt_enq_ready_edf_task(RT_TASK *ready_task);
void rt_enq_ready_task(RT_TASK *ready_task);
int rt_renq_ready_task(RT_TASK *ready_task,
int priority);
void rt_rem_ready_task(RT_TASK *task);
void rt_rem_ready_current(RT_TASK *rt_current);
void rt_enq_timed_task(RT_TASK *timed_task);
void rt_rem_timed_task(RT_TASK *task);
void rt_dequeue_blocked(RT_TASK *task);
#ifdef CONFIG_RTAI_MALLOC
#ifdef CONFIG_RTAI_MALLOC_BUILTIN
#define sched_mem_init() \
{ if(__rtai_heap_init() != 0) { \
return(-ENOMEM); \
} }
#define sched_mem_end() __rtai_heap_exit()
#else /* CONFIG_RTAI_MALLOC_BUILTIN */
#define sched_mem_init()
#define sched_mem_end()
#endif /* !CONFIG_RTAI_MALLOC_BUILTIN */
#define call_exit_handlers(task) __call_exit_handlers(task)
#define set_exit_handler(task, fun, arg1, arg2) __set_exit_handler(task, fun, arg1, arg2)
#else /* !CONFIG_RTAI_MALLOC */
#define sched_mem_init()
#define sched_mem_end()
#define call_exit_handlers(task)
#define set_exit_handler(task, fun, arg1, arg2)
#endif /* CONFIG_RTAI_MALLOC */
#define SEMHLF 0x0000FFFF
#define RPCHLF 0xFFFF0000
#define RPCINC 0x00010000
#define DECLARE_RT_CURRENT int cpuid; RT_TASK *rt_current
#define ASSIGN_RT_CURRENT rt_current = rt_smp_current[cpuid = rtai_cpuid()]
#define RT_CURRENT rt_smp_current[rtai_cpuid()]
#define MAX_LINUX_RTPRIO 99
#define MIN_LINUX_RTPRIO 1
#ifdef CONFIG_RTAI_SCHED_ISR_LOCK
void rtai_handle_isched_lock(int nesting);
#endif /* CONFIG_RTAI_SCHED_ISR_LOCK */
#ifdef CONFIG_SMP
#define rt_time_h (rt_smp_time_h[cpuid])
#define rt_linux_task (rt_smp_linux_task[cpuid])
#else
#define rt_time_h (rt_smp_time_h[0])
#define rt_linux_task (rt_smp_linux_task[0])
#endif
/*
* WATCH OUT for the max expected number of arguments of rtai funs and
* their scattered around different calling ways.
*/
#define RTAI_MAX_FUN_ARGS 9
struct fun_args { unsigned long a[RTAI_MAX_FUN_ARGS]; RTAI_SYSCALL_MODE long long (*fun)(unsigned long, ...); };
//used in sys.c
#define RTAI_FUN_ARGS arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],arg[7],arg[RTAI_MAX_FUN_ARGS - 1]
//used in sched.c (generalised calls from soft threads)
#define RTAI_FUNARGS funarg->a[0],funarg->a[1],funarg->a[2],funarg->a[3],funarg->a[4],funarg->a[5],funarg->a[6],funarg->a[7],funarg->a[RTAI_MAX_FUN_ARGS - 1]
#ifdef CONFIG_SMP
static inline void send_sched_ipi(unsigned long dest)
{
_send_sched_ipi(dest);
}
#define RT_SCHEDULE_MAP(schedmap) \
do { if (schedmap) send_sched_ipi(schedmap); } while (0)
#define RT_SCHEDULE_MAP_BOTH(schedmap) \
do { if (schedmap) send_sched_ipi(schedmap); rt_schedule(); } while (0)
#define RT_SCHEDULE(task, cpuid) \
do { \
if ((task)->runnable_on_cpus != (cpuid)) { \
send_sched_ipi(1 << (task)->runnable_on_cpus); \
} else { \
rt_schedule(); \
} \
} while (0)
#define RT_SCHEDULE_BOTH(task, cpuid) \
{ \
if ((task)->runnable_on_cpus != (cpuid)) { \
send_sched_ipi(1 << (task)->runnable_on_cpus); \
} \
rt_schedule(); \
}
#else /* !CONFIG_SMP */
#define send_sched_ipi(dest)
#define RT_SCHEDULE_MAP_BOTH(schedmap) rt_schedule()
#define RT_SCHEDULE_MAP(schedmap) rt_schedule()
#define RT_SCHEDULE(task, cpuid) rt_schedule()
#define RT_SCHEDULE_BOTH(task, cpuid) rt_schedule()
#endif /* CONFIG_SMP */
#define BASE_SOFT_PRIORITY 1000000000
#ifndef TASK_NOWAKEUP
#define TASK_NOWAKEUP TASK_UNINTERRUPTIBLE
#endif
#define TASK_HARDREALTIME (TASK_INTERRUPTIBLE) // | TASK_NOWAKEUP)
#define TASK_RTAISRVSLEEP (TASK_INTERRUPTIBLE) // | TASK_NOWAKEUP)
#define TASK_SOFTREALTIME TASK_INTERRUPTIBLE
static inline void enq_ready_edf_task(RT_TASK *ready_task)
{
RT_TASK *task;
#ifdef CONFIG_SMP
task = rt_smp_linux_task[ready_task->runnable_on_cpus].rnext;
#else
task = rt_smp_linux_task[0].rnext;
#endif
while (task->policy < 0 && ready_task->period >= task->period) {
task = task->rnext;
}
task->rprev = (ready_task->rprev = task->rprev)->rnext = ready_task;
ready_task->rnext = task;
}
struct epoch_struct { spinlock_t lock; volatile int touse; volatile RTIME time[2][2]; };
#ifdef CONFIG_RTAI_CLOCK_REALTIME
#define REALTIME2COUNT(rtime) \
if (rtime > boot_epoch.time[boot_epoch.touse][0]) { \
rtime -= boot_epoch.time[boot_epoch.touse][0]; \
}
#else
#define REALTIME2COUNT(rtime)
#endif
#define MAX_WAKEUP_SRQ (1 << 6)
struct klist_t { int srq; volatile unsigned long in, out; void *task[MAX_WAKEUP_SRQ]; };
extern struct klist_t wake_up_srq[];
#define pend_wake_up_srq(lnxtsk, cpuid) \
do { \
wake_up_srq[cpuid].task[wake_up_srq[cpuid].in++ & (MAX_WAKEUP_SRQ - 1)] = lnxtsk; \
hal_pend_uncond(wake_up_srq[0].srq, cpuid); \
} while (0)
static inline void enq_ready_task(RT_TASK *ready_task)
{
RT_TASK *task;
if (ready_task->is_hard) {
#ifdef CONFIG_SMP
task = rt_smp_linux_task[ready_task->runnable_on_cpus].rnext;
#else
task = rt_smp_linux_task[0].rnext;
#endif
while (ready_task->priority >= task->priority) {
if ((task = task->rnext)->priority < 0) break;
}
task->rprev = (ready_task->rprev = task->rprev)->rnext = ready_task;
ready_task->rnext = task;
} else {
ready_task->state |= RT_SCHED_SFTRDY;
NON_RTAI_TASK_RESUME(ready_task);
}
}
static inline int renq_ready_task(RT_TASK *ready_task, int priority)
{
int retval;
if ((retval = ready_task->priority != priority)) {
ready_task->priority = priority;
if (ready_task->state == RT_SCHED_READY) {
(ready_task->rprev)->rnext = ready_task->rnext;
(ready_task->rnext)->rprev = ready_task->rprev;
enq_ready_task(ready_task);
}
}
return retval;
}
static inline void rem_ready_task(RT_TASK *task)
{
if (task->state == RT_SCHED_READY) {
if (!task->is_hard) {
NON_RTAI_TASK_SUSPEND(task);
}
// task->unblocked = 0;
(task->rprev)->rnext = task->rnext;
(task->rnext)->rprev = task->rprev;
}
}
static inline void rem_ready_current(RT_TASK *rt_current)
{
if (!rt_current->is_hard) {
NON_RTAI_TASK_SUSPEND(rt_current);
}
// rt_current->unblocked = 0;
(rt_current->rprev)->rnext = rt_current->rnext;
(rt_current->rnext)->rprev = rt_current->rprev;
}
#ifdef CONFIG_RTAI_LONG_TIMED_LIST
/* BINARY TREE */
static inline void enq_timed_task(RT_TASK *timed_task)
{
RT_TASK *taskh, *tsknxt, *task;
rb_node_t **rbtn, *rbtpn = NULL;
#ifdef CONFIG_SMP
task = taskh = &rt_smp_linux_task[timed_task->runnable_on_cpus];
#else
task = taskh = &rt_smp_linux_task[0];
#endif
rbtn = &taskh->rbr.rb_node;
while (*rbtn) {
rbtpn = *rbtn;
tsknxt = rb_entry(rbtpn, RT_TASK, rbn);
if (timed_task->resume_time > tsknxt->resume_time) {
rbtn = &(rbtpn)->rb_right;
} else {
rbtn = &(rbtpn)->rb_left;
task = tsknxt;
}
}
rb_link_node(&timed_task->rbn, rbtpn, rbtn);
rb_insert_color(&timed_task->rbn, &taskh->rbr);
task->tprev = (timed_task->tprev = task->tprev)->tnext = timed_task;
timed_task->tnext = task;
}
#define rb_erase_task(task, cpuid) \
rb_erase(&(task)->rbn, &rt_smp_linux_task[cpuid].rbr);
#else /* !CONFIG_RTAI_LONG_TIMED_LIST */
/* LINEAR */
static inline void enq_timed_task(RT_TASK *timed_task)
{
RT_TASK *task;
#ifdef CONFIG_SMP
task = rt_smp_linux_task[timed_task->runnable_on_cpus].tnext;
#else
task = rt_smp_linux_task[0].tnext;
#endif
while (timed_task->resume_time > task->resume_time) {
task = task->tnext;
}
task->tprev = (timed_task->tprev = task->tprev)->tnext = timed_task;
timed_task->tnext = task;
}
#define rb_erase_task(task, cpuid)
#endif /* !CONFIG_RTAI_LONG_TIMED_LIST */
static inline void rem_timed_task(RT_TASK *task)
{
if ((task->state & RT_SCHED_DELAYED)) {
(task->tprev)->tnext = task->tnext;
(task->tnext)->tprev = task->tprev;
#ifdef CONFIG_SMP
rb_erase_task(task, task->runnable_on_cpus);
#else
rb_erase_task(task, 0);
#endif
}
}
static inline void wake_up_timed_tasks(int cpuid)
{
RT_TASK *taskh, *task;
#ifdef CONFIG_SMP
task = (taskh = &rt_smp_linux_task[cpuid])->tnext;
#else
task = (taskh = &rt_smp_linux_task[0])->tnext;
#endif
if (task->resume_time - task->schedlat <= rt_time_h) {
do {
if ((task->state & RT_SCHED_SUSPENDED) && task->suspdepth > 0) {
task->suspdepth = 0;
}
if ((task->state &= ~(RT_SCHED_DELAYED | RT_SCHED_SUSPENDED | RT_SCHED_SEMAPHORE | RT_SCHED_RECEIVE | RT_SCHED_SEND | RT_SCHED_RPC | RT_SCHED_RETURN | RT_SCHED_MBXSUSP | RT_SCHED_POLL)) == RT_SCHED_READY) {
if (task->policy < 0) {
enq_ready_edf_task(task);
} else {
enq_ready_task(task);
}
#if ((CONFIG_RTAI_USER_BUSY_ALIGN_RET_DELAY > 0 || CONFIG_RTAI_KERN_BUSY_ALIGN_RET_DELAY > 0))
task->busy_time_align = 1;
#endif
}
rb_erase_task(task, cpuid);
task = task->tnext;
} while (task->resume_time <= rt_time_h);
#ifdef CONFIG_SMP
rt_smp_linux_task[cpuid].tnext = task;
task->tprev = &rt_smp_linux_task[cpuid];
#else
rt_smp_linux_task[0].tnext = task;
task->tprev = &rt_smp_linux_task[0];
#endif
}
}
#define get_time() rt_get_time()
static inline void enqueue_blocked(RT_TASK *task, QUEUE *queue, int qtype)
{
QUEUE *q;
task->blocked_on = (q = queue);
if (!qtype) {
while ((q = q->next) != queue && (q->task)->priority <= task->priority);
}
q->prev = (task->queue.prev = q->prev)->next = &(task->queue);
task->queue.next = q;
}
static inline void dequeue_blocked(RT_TASK *task)
{
task->prio_passed_to = NULL;
(task->queue.prev)->next = task->queue.next;
(task->queue.next)->prev = task->queue.prev;
task->blocked_on = NULL;
}
static inline unsigned long pass_prio(RT_TASK *to, RT_TASK *from)
{
QUEUE *q, *blocked_on;
#ifdef CONFIG_SMP
RT_TASK *rhead;
unsigned long schedmap;
schedmap = 0;
#endif
// from->prio_passed_to = to;
while (to && to->priority > from->priority) {
to->priority = from->priority;
if (to->state == RT_SCHED_READY) {
if ((to->rprev)->priority > to->priority || (to->rnext)->priority < to->priority) {
#ifdef CONFIG_SMP
rhead = rt_smp_linux_task[to->runnable_on_cpus].rnext;
#endif
(to->rprev)->rnext = to->rnext;
(to->rnext)->rprev = to->rprev;
enq_ready_task(to);
#ifdef CONFIG_SMP
if (rhead != rt_smp_linux_task[to->runnable_on_cpus].rnext) {
__set_bit(to->runnable_on_cpus & 0x1F, &schedmap);
}
#endif
}
break;
// } else if ((void *)(q = to->blocked_on) > RTE_HIGERR && !((to->state & RT_SCHED_SEMAPHORE) && ((SEM *)q)->qtype)) {
} else if ((unsigned long)(blocked_on = to->blocked_on) > RTE_HIGERR && (((to->state & RT_SCHED_SEMAPHORE) && ((SEM *)blocked_on)->type > 0) || (to->state & (RT_SCHED_SEND | RT_SCHED_RPC | RT_SCHED_RETURN)))) {
if (to->queue.prev != blocked_on) {
q = blocked_on;
(to->queue.prev)->next = to->queue.next;
(to->queue.next)->prev = to->queue.prev;
while ((q = q->next) != blocked_on && (q->task)->priority <= to->priority);
q->prev = (to->queue.prev = q->prev)->next = &(to->queue);
to->queue.next = q;
if (to->queue.prev != blocked_on) {
break;
}
}
to = (to->state & RT_SCHED_SEMAPHORE) ? ((SEM *)blocked_on)->owndby : blocked_on->task;
}
// to = to->prio_passed_to;
}
#ifdef CONFIG_SMP
return schedmap;
#else
return 0;
#endif
}
static inline RT_TASK *_rt_whoami(void)
{
#ifdef CONFIG_SMP
RT_TASK *rt_current;
unsigned long flags;
flags = rt_global_save_flags_and_cli();
rt_current = RT_CURRENT;
rt_global_restore_flags(flags);
return rt_current;
#else
return rt_smp_current[0];
#endif
}
static inline void __call_exit_handlers(RT_TASK *task)
{
XHDL *pt, *tmp;
pt = task->ExitHook; // Initialise ExitHook in rt_task_init()
while ( pt ) {
(*pt->fun) (pt->arg1, pt->arg2);
tmp = pt;
pt = pt->nxt;
rt_free(tmp);
}
task->ExitHook = 0;
}
static inline XHDL *__set_exit_handler(RT_TASK *task, void (*fun) (void *, int), void *arg1, int arg2)
{
XHDL *p;
// exit handler functions are automatically executed at terminattion time by rt_task_delete()
// in the reverse order they were created (like C++ destructors behave).
if (task->magic != RT_TASK_MAGIC) return 0;
if (!(p = (XHDL *) rt_malloc (sizeof(XHDL)))) return 0;
p->fun = fun;
p->arg1 = arg1;
p->arg2 = arg2;
p->nxt = task->ExitHook;
return (task->ExitHook = p);
}
static inline int rtai_init_features (void)
{
#ifdef CONFIG_RTAI_SEM_BUILTIN
__rtai_sem_init();
#endif /* CONFIG_RTAI_SEM_BUILTIN */
#ifdef CONFIG_RTAI_MSG_BUILTIN
__rtai_msg_init();
#endif /* CONFIG_RTAI_MSG_BUILTIN */
#ifdef CONFIG_RTAI_MBX_BUILTIN
__rtai_mbx_init();
#endif /* CONFIG_RTAI_MBX_BUILTIN */
#ifdef CONFIG_RTAI_FIFOS_BUILTIN
__rtai_fifos_init();
#endif /* CONFIG_RTAI_FIFOS_BUILTIN */
#ifdef CONFIG_RTAI_SHM_BUILTIN
__rtai_shm_init();
#endif /* CONFIG_RTAI_SHM_BUILTIN */
#ifdef CONFIG_RTAI_MATH_BUILTIN
__rtai_math_init();
#endif /* CONFIG_RTAI_MATH_BUILTIN */
return 0;
}
static inline void rtai_cleanup_features (void) {
#ifdef CONFIG_RTAI_MATH_BUILTIN
__rtai_math_exit();
#endif /* CONFIG_RTAI_MATH_BUILTIN */
#ifdef CONFIG_RTAI_SHM_BUILTIN
__rtai_shm_exit();
#endif /* CONFIG_RTAI_SHM_BUILTIN */
#ifdef CONFIG_RTAI_FIFOS_BUILTIN
__rtai_fifos_exit();
#endif /* CONFIG_RTAI_FIFOS_BUILTIN */
#ifdef CONFIG_RTAI_MBX_BUILTIN
__rtai_mbx_exit();
#endif /* CONFIG_RTAI_MBX_BUILTIN */
#ifdef CONFIG_RTAI_MSG_BUILTIN
__rtai_msg_exit();
#endif /* CONFIG_RTAI_MSG_BUILTIN */
#ifdef CONFIG_RTAI_SEM_BUILTIN
__rtai_sem_exit();
#endif /* CONFIG_RTAI_SEM_BUILTIN */
}
int rt_check_current_stack(void);
int rt_kthread_init_old(RT_TASK *task,
void (*rt_thread)(long),
long data,
int stack_size,
int priority,
int uses_fpu,
void(*signal)(void));
int rt_kthread_init_cpuid(RT_TASK *task,
void (*rt_thread)(long),
long data,
int stack_size,
int priority,
int uses_fpu,
void(*signal)(void),
unsigned int cpuid);
#else /* !__KERNEL__ */
#endif /* __KERNEL__ */
#endif /* !_RTAI_SCHEDCORE_H */

429
include/rtai_sem.h Normal file
View File

@ -0,0 +1,429 @@
/**
* @ingroup lxrt
* @file
*
* @author Paolo Mantegazza
*
* @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
* @note Copyright &copy; 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_SEM_H
#define _RTAI_SEM_H
#include <rtai_types.h>
#include <rtai_nam2num.h>
#include <rtai_sched.h>
#define RT_SEM_MAGIC 0x3f83ebb // nam2num("rtsem")
#define SEM_ERR (RTE_OBJINV)
#define SEM_TIMOUT (RTE_TIMOUT)
struct rt_poll_s { void *what; unsigned long forwhat; };
// do not use 0 for any "forwhat" below
#define RT_POLL_NOT_TO_USE 0
#define RT_POLL_MBX_RECV 1
#define RT_POLL_MBX_SEND 2
#define RT_POLL_SEM_WAIT_ALL 3
#define RT_POLL_SEM_WAIT_ONE 4
#if defined(__KERNEL__) && !defined(__cplusplus)
struct rt_poll_ql { QUEUE pollq; spinlock_t pollock; };
struct rt_poll_enc { unsigned long offset; int (*topoll)(void *); };
extern struct rt_poll_enc rt_poll_ofstfun[];
typedef struct rt_semaphore {
struct rt_queue queue; /* <= Must be first in struct. */
int magic;
int type, restype;
int count;
struct rt_task_struct *owndby;
int qtype;
struct rt_queue resq;
#ifdef CONFIG_RTAI_RT_POLL
struct rt_poll_ql poll_wait_all;
struct rt_poll_ql poll_wait_one;
#endif
} SEM;
#ifdef CONFIG_RTAI_RT_POLL
RTAI_SYSCALL_MODE int _rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout, int space);
static inline int rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout)
{
return _rt_poll(pdsa, nr, timeout, 1);
}
void rt_wakeup_pollers(struct rt_poll_ql *ql, int reason);
#else
static inline int rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout)
{
return RTE_OBJINV;
}
#define rt_wakeup_pollers(ql, reason)
#endif
#else /* !__KERNEL__ || __cplusplus */
typedef struct rt_semaphore {
int opaque;
} SEM;
#endif /* __KERNEL__ && !__cplusplus */
typedef SEM CND;
#ifdef __KERNEL__
#include <linux/errno.h>
typedef SEM psem_t;
typedef SEM pmutex_t;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int __rtai_sem_init(void);
void __rtai_sem_exit(void);
RTAI_SYSCALL_MODE void rt_typed_sem_init(SEM *sem,
int value,
int type);
RTAI_SYSCALL_MODE int rt_sem_delete(SEM *sem);
RTAI_SYSCALL_MODE SEM *_rt_typed_named_sem_init(unsigned long sem_name,
int value,
int type,
unsigned long *handle);
static inline SEM *rt_typed_named_sem_init(const char *sem_name,
int value,
int type) {
return _rt_typed_named_sem_init(nam2num(sem_name), value, type, NULL);
}
RTAI_SYSCALL_MODE int rt_named_sem_delete(SEM *sem);
void rt_sem_init(SEM *sem,
int value);
RTAI_SYSCALL_MODE int rt_sem_signal(SEM *sem);
RTAI_SYSCALL_MODE int rt_sem_broadcast(SEM *sem);
RTAI_SYSCALL_MODE int rt_sem_wait(SEM *sem);
RTAI_SYSCALL_MODE int rt_sem_wait_if(SEM *sem);
int rt_cntsem_wait_if_and_lock(SEM *sem);
RTAI_SYSCALL_MODE int rt_sem_wait_until(SEM *sem,
RTIME time);
RTAI_SYSCALL_MODE int rt_sem_wait_timed(SEM *sem,
RTIME delay);
RTAI_SYSCALL_MODE int rt_sem_wait_barrier(SEM *sem);
RTAI_SYSCALL_MODE int rt_sem_count(SEM *sem);
RTAI_SYSCALL_MODE int rt_cond_signal(CND *cnd);
RTAI_SYSCALL_MODE int rt_cond_wait(CND *cnd,
SEM *mtx);
RTAI_SYSCALL_MODE int rt_cond_wait_until(CND *cnd,
SEM *mtx,
RTIME time);
RTAI_SYSCALL_MODE int rt_cond_wait_timed(CND *cnd,
SEM *mtx,
RTIME delay);
#define rt_named_sem_init(sem_name, value) rt_typed_named_sem_init(sem_name, value, CNT_SEM)
static inline int rt_psem_init(psem_t *sem, int pshared, unsigned int value)
{
if (value < SEM_TIMOUT) {
rt_typed_sem_init(sem, value, pshared | PRIO_Q);
return 0;
}
return -EINVAL;
}
static inline int rt_psem_destroy(psem_t *sem)
{
if (rt_sem_wait_if(sem) >= 0) {
rt_sem_signal(sem);
return rt_sem_delete(sem);
}
return -EBUSY;
}
static inline int rt_psem_wait(psem_t *sem) {
return rt_sem_wait(sem) < SEM_TIMOUT ? 0 : -1;
}
static inline int rt_psem_timedwait(psem_t *sem, struct timespec *abstime) {
return rt_sem_wait_until(sem, timespec2count(abstime)) < SEM_TIMOUT ? 0 : -1;
}
static inline int rt_psem_trywait(psem_t *sem) {
return rt_sem_wait_if(sem) > 0 ? 0 : -EAGAIN;
}
static inline int rt_psem_post(psem_t *sem) {
return rt_sem_signal(sem);
}
static inline int rt_psem_getvalue(psem_t *sem, int *sval)
{
if ((*sval = rt_sem_wait_if(sem)) > 0) {
rt_sem_signal(sem);
}
return 0;
}
static inline int rt_pmutex_init(pmutex_t *mutex, void *mutexattr)
{
rt_typed_sem_init(mutex, 1, RES_SEM);
return 0;
}
static inline int rt_pmutex_destroy(pmutex_t *mutex)
{
if (rt_sem_wait_if(mutex) > 0) {
rt_sem_signal(mutex);
return rt_sem_delete(mutex);
}
return -EBUSY;
}
static inline int rt_pmutex_lock(pmutex_t *mutex) {
return rt_sem_wait(mutex) < SEM_TIMOUT ? 0 : -EINVAL;
}
static inline int rt_pmutex_trylock(pmutex_t *mutex) {
return rt_sem_wait_if(mutex) > 0 ? 0 : -EBUSY;
}
static inline int rt_pmutex_timedlock(pmutex_t *sem, struct timespec *abstime) {
return rt_sem_wait_until(sem, timespec2count(abstime)) < SEM_TIMOUT ? 0 : -1;
}
static inline int rt_pmutex_unlock(pmutex_t *mutex) {
return rt_sem_signal(mutex);
}
#undef rt_mutex_init
#define rt_mutex_init(mtx) rt_typed_sem_init(mtx, 1, RES_SEM)
#define rt_mutex_delete(mtx) rt_sem_delete(mtx)
#define rt_mutex_destroy(mtx) rt_sem_delete(mtx)
#define rt_mutex_trylock(mtx) rt_sem_wait_if(mtx)
#define rt_mutex_lock(mtx) rt_sem_wait(mtx)
#define rt_mutex_timedlock(mtx, time) rt_sem_wait_until(mtx, time)
#define rt_mutex_unlock(mtx) rt_sem_signal(mtx)
#define rt_cond_init(cnd) rt_typed_sem_init(cnd, 0, BIN_SEM | PRIO_Q)
#define rt_cond_delete(cnd) rt_sem_delete(cnd)
#define rt_cond_destroy(cnd) rt_sem_delete(cnd)
#define rt_cond_broadcast(cnd) rt_sem_broadcast(cnd)
static inline int rt_cond_timedwait(CND *cnd, SEM *mtx, RTIME time) {
return rt_cond_wait_until(cnd, mtx, time) < SEM_TIMOUT ? 0 : -1;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#include <rtai_lxrt.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
RTAI_PROTO(SEM *, rt_typed_sem_init,(unsigned long name, int value, int type))
{
struct { unsigned long name; long value, type; } arg = { name ? name : rt_get_name(NULL), value, type };
return (SEM *)rtai_lxrt(BIDX, SIZARG, LXRT_SEM_INIT, &arg).v[LOW];
}
/**
* @ingroup lxrt
* Initialize a counting semaphore.
*
* Allocates and initializes a semaphore to be referred by @a name.
*
* @param name name of the semaphore.
*
* @param value is the initial value of the semaphore
*
* It is important to remark that the returned task pointer cannot be used
* directly, they are for kernel space data, but just passed as arguments when
* needed.
*
* @return a pointer to the semaphore to be used in related calls or 0 if an
* error has occured.
*/
#define rt_sem_init(name, value) rt_typed_sem_init(name, value, CNT_SEM)
#define rt_named_sem_init(sem_name, value) \
rt_typed_named_sem_init(sem_name, value, CNT_SEM)
RTAI_PROTO(int, rt_sem_delete,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, LXRT_SEM_DELETE, &arg).i[LOW];
}
RTAI_PROTO(SEM *, rt_typed_named_sem_init,(const char *name, int value, int type))
{
struct { unsigned long name; long value, type; unsigned long *handle; } arg = { nam2num(name), value, type, NULL };
return (SEM *)rtai_lxrt(BIDX, SIZARG, NAMED_SEM_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_named_sem_delete,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, NAMED_SEM_DELETE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_signal,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, SEM_SIGNAL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_broadcast,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, SEM_BROADCAST, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_wait,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, SEM_WAIT, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_wait_if,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_wait_until,(SEM *sem, RTIME time))
{
struct { SEM *sem; RTIME time; } arg = { sem, time };
return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_wait_timed,(SEM *sem, RTIME delay))
{
struct { SEM *sem; RTIME delay; } arg = { sem, delay };
return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_wait_barrier,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_BARRIER, &arg).i[LOW];
}
RTAI_PROTO(int, rt_sem_count,(SEM *sem))
{
struct { SEM *sem; } arg = { sem };
return rtai_lxrt(BIDX, SIZARG, SEM_COUNT, &arg).i[LOW];
}
/**
* @ingroup lxrt
* Initialize a condition variable.
*
* Allocates and initializes a condition variable to be referred by @a name.
*
* @param name name of the condition variable.
*
* It is important to remark that the returned pointer cannot be used
* directly, it is for kernel space data, but just passed as arguments when
* needed.
*
* @return a pointer to the condition variable to be used in related calls or 0
* if an error has occured.
*/
#define rt_cond_init(name) rt_typed_sem_init(name, 0, BIN_SEM)
#define rt_cond_delete(cnd) rt_sem_delete(cnd)
#define rt_cond_destroy(cnd) rt_sem_delete(cnd)
#define rt_cond_broadcast(cnd) rt_sem_broadcast(cnd)
#define rt_cond_timedwait(cnd, mtx, time) rt_cond_wait_until(cnd, mtx, time)
RTAI_PROTO(int, rt_cond_signal,(CND *cnd))
{
struct { CND *cnd; } arg = { cnd };
return rtai_lxrt(BIDX, SIZARG, COND_SIGNAL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_cond_wait,(CND *cnd, SEM *mutex))
{
struct { CND *cnd; SEM *mutex; } arg = { cnd, mutex };
return rtai_lxrt(BIDX, SIZARG, COND_WAIT, &arg).i[LOW];
}
RTAI_PROTO(int, rt_cond_wait_until,(CND *cnd, SEM *mutex, RTIME time))
{
struct { CND *cnd; SEM *mutex; RTIME time; } arg = { cnd, mutex, time };
return rtai_lxrt(BIDX, SIZARG, COND_WAIT_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_cond_wait_timed,(CND *cnd, SEM *mutex, RTIME delay))
{
struct { CND *cnd; SEM *mutex; RTIME delay; } arg = { cnd, mutex, delay };
return rtai_lxrt(BIDX, SIZARG, COND_WAIT_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_poll, (struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout))
{
#ifdef CONFIG_RTAI_RT_POLL
struct { struct rt_poll_s *pdsa; unsigned long nr; RTIME timeout; long space; } arg = { pdsa, nr, timeout, 0 };
return rtai_lxrt(BIDX, SIZARG, SEM_RT_POLL, &arg).i[LOW];
#else
(void)pdsa; (void)nr; (void)timeout;
return RTE_OBJINV;
#endif
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#endif /* !_RTAI_SEM_H */

512
include/rtai_shm.h Normal file
View File

@ -0,0 +1,512 @@
/**
* @ingroup shm
* @file
*
* Interface of the @ref shm "RTAI SHM module".
*
* @author Paolo Mantegazza
*
* @note Copyright &copy; 1999-2017 Paolo Mantegazza <mantegazza@aero.polimi.it>
* @note Copyright &copy; 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
ACKNOWLEDGMENTS:
- The suggestion and the code for mmapping at a user specified address is due to Trevor Woolven (trevw@zentropix.com).
*/
#ifndef _RTAI_SHM_H
#define _RTAI_SHM_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** @addtogroup shm
*@{*/
#define GLOBAL_HEAP_ID 0x9ac6d9e7 // nam2num("RTGLBH");
#define USE_VMALLOC 0
#define USE_GFP_KERNEL 1
#define USE_GFP_ATOMIC 2
#define USE_GFP_DMA 3
/**
* Allocate a chunk of memory to be shared inter-intra kernel modules and
* Linux processes.
*
* @internal
*
* rtai_kalloc is used to allocate shared memory from kernel space.
*
* @param name is an unsigned long identifier;
*
* @param size is the amount of required shared memory;
*
* rtai_kmalloc is a legacy helper macro, the real job is carried out by a
* call to rt_shm_alloc() with the same name, size and with vmalloc support.
* This function should not be used in newly developed applications. See
* rt_shm_alloc for more details.
*
* @returns a valid address on succes, 0 on failure.
*
*/
#define rtai_kmalloc(name, size) \
rt_shm_alloc(name, size, USE_VMALLOC) // legacy
/**
* Free a chunk of shared memory being shared inter-intra kernel modules and
* Linux processes.
*
* rtai_kfree is used to free a shared memory chunk from kernel space.
*
* @param name is the unsigned long identifier used when the memory was
* allocated;
*
* rtai_kfree is a legacy helper macro, the real job is carried out by a
* call to rt_shm_free with the same name. This function should not be used
* in newly developed applications. See rt_shm_free for more details.
*
* @returns the size of the succesfully freed memory, 0 on failure.
*
*/
#define rtai_kfree(name) \
rt_shm_free(name) // legacy
#if defined(__KERNEL__)
#include <linux/module.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#define UVIRT_TO_KVA(adr) uvirt_to_kva(pgd_offset_k(adr), (adr))
static inline int remap_page_range(struct vm_area_struct *vma, unsigned long uvaddr, unsigned long paddr, unsigned long size, pgprot_t prot)
{
return remap_pfn_range(vma, uvaddr, paddr >> PAGE_SHIFT, size, prot);
}
#include <rtai.h>
#include <rtai_malloc.h>
static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
{
if (!pgd_none(*pgd) && !pgd_bad(*pgd)) {
pmd_t *pmd;
pmd = pmd_offset(pud_offset((void *)pgd, adr), adr);
if (!pmd_none(*pmd)) {
pte_t *ptep, pte;
ptep = pte_offset_kernel(pmd, adr);
pte = *ptep;
if (pte_present(pte)) {
return (((unsigned long)page_address(pte_page(pte))) | (adr & (PAGE_SIZE - 1)));
}
}
}
return 0UL;
}
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
return virt_to_phys((void *)uvirt_to_kva(pgd_offset_k(adr), adr));
}
int __rtai_shm_init(void);
void __rtai_shm_exit(void);
void *rt_shm_alloc(unsigned long name,
int size,
int suprt);
#define rt_shm_alloc_adr(adr, name, size) \
rt_shm_alloc(name, size, suprt)
RTAI_SYSCALL_MODE int rt_shm_free(unsigned long name);
void *rt_heap_open(unsigned long name,
int size,
int suprt);
#define rt_heap_open_adr(adr, name, size, suprt) \
rt_heap_open(name, size, suprt)
RTAI_SYSCALL_MODE void *rt_halloc(int size);
RTAI_SYSCALL_MODE void rt_hfree(void *addr);
RTAI_SYSCALL_MODE void *rt_named_halloc(unsigned long name, int size);
RTAI_SYSCALL_MODE void rt_named_hfree(void *addr);
void *rt_named_malloc(unsigned long name,
int size);
void rt_named_free(void *addr);
void *rvmalloc(unsigned long size);
void rvfree(void *mem,
unsigned long size);
int rvmmap(void *mem,
unsigned long memsize,
struct vm_area_struct *vma);
void *rkmalloc(int *size,
int suprt);
void rkfree(void *mem,
unsigned long size);
int rkmmap(void *mem,
unsigned long memsize,
struct vm_area_struct *vma);
#else /* !__KERNEL__ */
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <rtai_lxrt.h>
//#define SHM_USE_LXRT
#define RTAI_SHM_DEV "/dev/rtai_shm"
RTAI_PROTO (void *, _rt_shm_alloc, (void *start, unsigned long name, int size, int suprt, int isheap))
{
int hook;
void *adr = NULL;
if ((hook = open(RTAI_SHM_DEV, O_RDWR)) <= 0) {
return NULL;
} else {
struct { unsigned long name; long arg, suprt; } arg = { name, size, suprt };
#ifdef SHM_USE_LXRT
if ((size = rtai_lxrt(BIDX, SIZARG, SHM_ALLOC, &arg).i[LOW])) {
#else
if ((size = ioctl(hook, SHM_ALLOC, (unsigned long)(&arg)))) {
#endif
if ((adr = mmap(start, size, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_LOCKED, hook, 0)) == MAP_FAILED) {;
#ifdef SHM_USE_LXRT
rtai_lxrt(BIDX, sizeof(name), SHM_FREE, &name);
#else
ioctl(hook, SHM_FREE, &name);
#endif
} else if (isheap) {
arg.arg = (unsigned long)adr;
#ifdef SHM_USE_LXRT
rtai_lxrt(BIDX, SIZARG, HEAP_SET, &arg);
#else
ioctl(hook, HEAP_SET, &arg);
#endif
}
}
}
close(hook);
return adr;
}
#define rt_shm_alloc(name, size, suprt) \
_rt_shm_alloc(0, name, size, suprt, 0)
#define rt_heap_open(name, size, suprt) \
_rt_shm_alloc(0, name, size, suprt, 1)
/**
* Allocate a chunk of memory to be shared inter-intra kernel modules and
* Linux processes.
*
* @internal
*
* rtai_malloc is used to allocate shared memory from user space.
*
* @param name is an unsigned long identifier;
*
* @param size is the amount of required shared memory;
*
* rtai_malloc is a legacy helper macro, the real job is carried out by a
* call to rt_shm_alloc() with the same name, size and with vmalloc support.
* This function should not be used in newly developed applications. See
* rt_shm_alloc fro more details.
*
* @returns a valid address on succes, on failure: 0 if it was unable to
* allocate any memory, MAP_FAILED if it was possible to allocate the
* required memory but failed to mmap it to user space, in which case the
* allocated memory is freed anyhow.
*
*/
#define rtai_malloc(name, size) \
_rt_shm_alloc(0, name, size, USE_VMALLOC, 0) // legacy
/**
* Allocate a chunk of memory to be shared inter-intra kernel modules and Linux
* processes.
*
* rt_shm_alloc_adr is used to allocate in user space.
*
* @param start_address is a user desired address where the allocated memory
* should be mapped in user space;
*
* @param name is an unsigned long identifier;
*
* @param size is the amount of required shared memory.
*
* @param suprt is the kernel allocation method to be used, it can be:
* - USE_VMALLOC, use vmalloc;
* - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
* - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
* - USE_GFP_DMA, use kmalloc with GFP_DMA.
*
* Since @c name can be a clumsy identifier, services are provided to
* convert 6 characters identifiers to unsigned long, and vice versa.
*
* @see the functions nam2num() and num2nam().
*
* It must be remarked that only the very first call does a real allocation,
* any subsequent call to allocate with the same name from anywhere will just
* increase the usage count and map the area to user space, or return the
* related pointer to the already allocated space in kernel space. The function
* returns a pointer to the allocated memory, appropriately mapped to the memory
* space in use. So if one is really sure that the named shared memory has been
* allocated already parameters size and suprt are not used and can be
* assigned any value.
*
* @note If the same process calls rtai_malloc_adr and rtai_malloc() twice in
* the same process it get a zero return value on the second call.
*
* @returns a valid address on succes, on failure: 0 if it was unable to
* allocate any memory, MAP_FAILED if it was possible to allocate the
* required memory but failed to mmap it to user space, in which case the
* allocated memory is freed anyhow.
*
*/
#define rt_shm_alloc_adr(start_address, name, size, suprt) \
_rt_shm_alloc(start_address, name, size, suprt, 0)
#define rt_heap_open_adr(start, name, size, suprt) \
_rt_shm_alloc(start, name, size, suprt, 1)
/**
* Allocate a chunk of memory to be shared inter-intra kernel modules and
* Linux processes.
*
* @internal
*
* rtai_malloc_adr is used to allocate shared memory from user space.
*
* @param start_address is the adr were the shared memory should be mapped.
*
* @param name is an unsigned long identifier;
*
* @param size is the amount of required shared memory;
*
* rtai_malloc_adr is a legacy helper macro, the real job is carried out by a
* call to rt_shm_alloc_adr() with the same name, size and with vmalloc support.
* This function should not be used in newly developed applications. See
* rt_shm_alloc_adr for more details.
*
* @returns a valid address on succes, 0 on failure.
*
*/
#define rtai_malloc_adr(start_address, name, size) \
_rt_shm_alloc(start_address, name, size, USE_VMALLOC, 0) // legacy
RTAI_PROTO(int, rt_shm_free, (unsigned long name))
{
int hook, size;
struct { void *nameadr; } arg = { &name };
if ((hook = open(RTAI_SHM_DEV, O_RDWR)) <= 0) {
return 0;
}
// no SHM_FREE needed, we release it all and munmap will do it through
// the vma close operation provided by shm.c
#ifdef SHM_USE_LXRT
if ((size = rtai_lxrt(BIDX, SIZARG, SHM_SIZE, &arg).i[LOW])) {
#else
if ((size = ioctl(hook, SHM_SIZE, (unsigned long)&arg))) {
#endif
if (munmap((void *)name, size)) {
size = 0;
}
}
close(hook);
return size;
}
/**
* Free a chunk of shared memory being shared inter-intra
* kernel modules and Linux processes.
*
* rtai_free is used to free a shared memory chunk from user space.
*
* @param name is the unsigned long identifier used when the memory was
* allocated;
*
* @param adr is not used.
*
* rtai_free is a legacy helper macro, the real job is carried out by a
* call to rt_shm_free with the same name. This function should not be used
* in newly developed applications. See rt_shm_alloc_adr for more details.
*
* @returns the size of the succesfully freed memory, 0 on failure.
*
*/
#define rtai_free(name, adr) \
rt_shm_free(name) // legacy
RTAI_PROTO(void *, rt_halloc, (int size))
{
struct { long size; } arg = { size };
return rtai_lxrt(BIDX, SIZARG, HEAP_ALLOC, &arg).v[LOW];
}
RTAI_PROTO(void, rt_hfree, (void *addr))
{
struct { void *addr; } arg = { addr };
rtai_lxrt(BIDX, SIZARG, HEAP_FREE, &arg);
}
RTAI_PROTO(void *, rt_named_halloc, (unsigned long name, int size))
{
struct { unsigned long name; long size; } arg = { name, size };
return rtai_lxrt(BIDX, SIZARG, HEAP_NAMED_ALLOC, &arg).v[LOW];
}
RTAI_PROTO(void, rt_named_hfree, (void *addr))
{
struct { void *addr; } arg = { addr };
rtai_lxrt(BIDX, SIZARG, HEAP_NAMED_FREE, &arg);
}
RTAI_PROTO(void *, rt_malloc, (int size))
{
struct { long size; } arg = { size };
return rtai_lxrt(BIDX, SIZARG, MALLOC, &arg).v[LOW];
}
RTAI_PROTO(void, rt_free, (void *addr))
{
struct { void *addr; } arg = { addr };
rtai_lxrt(BIDX, SIZARG, FREE, &arg);
}
RTAI_PROTO(void *, rt_named_malloc, (unsigned long name, int size))
{
struct { unsigned long name; long size; } arg = { name, size };
return rtai_lxrt(BIDX, SIZARG, NAMED_MALLOC, &arg).v[LOW];
}
RTAI_PROTO(void, rt_named_free, (void *addr))
{
struct { void *addr; } arg = { addr };
rtai_lxrt(BIDX, SIZARG, NAMED_FREE, &arg);
}
#endif /* __KERNEL__ */
/**
* Close a real time group heap being shared inter-intra kernel modules and
* Linux processes.
*
* @internal
*
* rt_heap_close is used to close a previously opened real time group heap.
*
* @param name is the unsigned long identifier used to identify the heap.
*
* @param adr is not used.
*
* Analogously to what done by any allocation function this group real time
* heap closing call have just the effect of decrementing a usage count,
* unmapping any user space heap being closed, till the last is done, as that
* is the one the really closes the group heap, freeing any allocated memory.
*
* @returns the size of the succesfully freed heap, 0 on failure.
*
*/
#define rt_heap_close(name, adr) rt_shm_free(name)
// aliases in use already, different heads different choices
#define rt_heap_init rt_heap_open
#define rt_heap_create rt_heap_open
#define rt_heap_acquire rt_heap_open
#define rt_heap_init_adr rt_heap_open_adr
#define rt_heap_create_adr rt_heap_open_adr
#define rt_heap_acquire_adr rt_heap_open_adr
#define rt_heap_delete rt_heap_close
#define rt_heap_destroy rt_heap_close
#define rt_heap_release rt_heap_close
// these have no aliases, and never will
/**
* Open the global real time heap to be shared inter-intra kernel modules and
* Linux processes.
*
* @internal
*
* rt_global_heap_open is used to open the global real time heap.
*
* The global heap is created by the shared memory module and its opening is
* needed in user space to map it to the process address space. In kernel
* space opening the global heap in a task is not required but should be done
* anyhow, both for symmetry and to register its usage.
*
*/
#define rt_global_heap_open() rt_heap_open(GLOBAL_HEAP_ID, 0, 0)
/**
* Close the global real time heap being shared inter-intra kernel modules and
* Linux processes.
*
* @internal
*
* rt_global_heap_close is used to close the global real time heap.
*
* Closing a global heap in user space has just the effect of deregistering
* its use and unmapping the related memory from a process address space.
* In kernel tasks just the deregistration is performed.
* The global real time heap is destroyed just a the rmmoding of the shared
* memory module.
*
*/
#define rt_global_heap_close() rt_heap_close(GLOBAL_HEAP_ID, 0)
/*@}*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !_RTAI_SHM_H */

128
include/rtai_signal.h Normal file
View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2006 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef _RTAI_SIGNAL_H_
#define _RTAI_SIGNAL_H_
#define RTAI_SIGNALS_IDX BIDX
#include <rtai_sched.h>
#define MAXSIGNALS 16
#define SIGNAL_TASK_INIPRIO 0
struct rt_signal_t { unsigned long flags; RT_TASK *sigtask; };
struct sigsuprt_t { RT_TASK *sigtask; RT_TASK *task; long signal; void (*sighdl)(long, RT_TASK *); unsigned long cpuid; };
#ifdef __KERNEL__
#define SIGNAL_ENBIT 0
#define SIGNAL_PNDBIT 1
#define SIGNAL_TASK_STACK_SIZE 8192
RTAI_SYSCALL_MODE int rt_signal_helper(RT_TASK *task);
int rt_request_signal(long signal, void (*sighdl)(long, RT_TASK *));
RTAI_SYSCALL_MODE int rt_request_signal_(RT_TASK *sigtask, RT_TASK *task, long signal);
RTAI_SYSCALL_MODE int rt_release_signal(long signal, RT_TASK *task);
RTAI_SYSCALL_MODE void rt_enable_signal(long signal, RT_TASK *task);
RTAI_SYSCALL_MODE void rt_disable_signal(long signal, RT_TASK *task);
RTAI_SYSCALL_MODE void rt_trigger_signal(long signal, RT_TASK *task);
RTAI_SYSCALL_MODE int rt_wait_signal(RT_TASK *sigtask, RT_TASK *task);
#else /* !__KERNEL__ */
#include <sys/mman.h>
#include <rtai_lxrt.h>
#define SIGNAL_TASK_STACK_SIZE 64*1024
#ifndef __SIGNAL_SUPPORT_FUN__
#define __SIGNAL_SUPPORT_FUN__
static void signal_suprt_fun(struct sigsuprt_t *funarg)
{
struct sigtsk_t { RT_TASK *sigtask; RT_TASK *task; };
struct sigreq_t { RT_TASK *sigtask; RT_TASK *task; long signal; void (*sighdl)(int, RT_TASK *); };
struct sigsuprt_t arg = *funarg;
if ((arg.sigtask = rt_thread_init(rt_get_name(0), SIGNAL_TASK_INIPRIO, 0, SCHED_FIFO, 1 << arg.cpuid))) {
if (!rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(struct sigreq_t), RT_SIGNAL_REQUEST, &arg).i[LOW]) {
rt_grow_and_lock_stack(SIGNAL_TASK_STACK_SIZE/2);
rt_make_hard_real_time();
while (rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(struct sigtsk_t), RT_SIGNAL_WAITSIG, &arg).i[LOW]) {
arg.sighdl(arg.signal, arg.task);
}
rt_make_soft_real_time();
}
rt_task_delete(arg.sigtask);
}
}
#endif /* __SIGNAL_SUPPORT_FUN__ */
RTAI_PROTO(int, rt_request_signal, (long signal, void (*sighdl)(long, RT_TASK *)))
{
if (signal >= 0 && sighdl) {
struct sigsuprt_t arg = { NULL, rt_buddy(), signal, sighdl };
arg.cpuid = rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(void *), RT_SIGNAL_HELPER, &arg.sigtask).i[LOW];
if (rt_thread_create((void *)signal_suprt_fun, &arg, SIGNAL_TASK_STACK_SIZE)) {
return rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(RT_TASK *), RT_SIGNAL_HELPER, &arg.task).i[LOW];
}
}
return -EINVAL;
}
RTAI_PROTO(int, rt_release_signal, (long signal, RT_TASK *task))
{
struct { long signal; RT_TASK *task; } arg = { signal, task };
return rtai_lxrt(RTAI_SIGNALS_IDX, SIZARG, RT_SIGNAL_RELEASE, &arg).i[LOW];
}
RTAI_PROTO(void, rt_enable_signal, (long signal, RT_TASK *task))
{
struct { long signal; RT_TASK *task; } arg = { signal, task };
rtai_lxrt(RTAI_SIGNALS_IDX, SIZARG, RT_SIGNAL_ENABLE, &arg);
}
RTAI_PROTO(void, rt_disable_signal, (long signal, RT_TASK *task))
{
struct { long signal; RT_TASK *task; } arg = { signal, task };
rtai_lxrt(RTAI_SIGNALS_IDX, SIZARG, RT_SIGNAL_DISABLE, &arg);
}
RTAI_PROTO(void, rt_trigger_signal, (long signal, RT_TASK *task))
{
struct { long signal; RT_TASK *task; } arg = { signal, task };
rtai_lxrt(RTAI_SIGNALS_IDX, SIZARG, RT_SIGNAL_TRIGGER, &arg);
}
#endif /* __KERNEL__ */
#endif /* !_RTAI_SIGNAL_H_ */

129
include/rtai_spl.h Normal file
View File

@ -0,0 +1,129 @@
/*
* Copyright (C) 2002,2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_SPL_H
#define _RTAI_SPL_H
#include <rtai_sem.h>
struct rtai_spl;
#ifdef __KERNEL__
#ifndef __cplusplus
typedef struct rtai_spl {
void *owndby;
int count;
unsigned long flags;
} SPL;
#else /* __cplusplus */
extern "C" {
#endif /* !__cplusplus */
RTAI_SYSCALL_MODE int rt_spl_init(struct rtai_spl *spl);
RTAI_SYSCALL_MODE int rt_spl_delete(struct rtai_spl *spl);
RTAI_SYSCALL_MODE SPL *_rt_named_spl_init(unsigned long spl_name);
RTAI_SYSCALL_MODE int rt_named_spl_delete(SPL *spl);
RTAI_SYSCALL_MODE int rt_spl_lock(struct rtai_spl *spl);
RTAI_SYSCALL_MODE int rt_spl_lock_if(struct rtai_spl *spl);
RTAI_SYSCALL_MODE int rt_spl_lock_timed(struct rtai_spl *spl,
unsigned long ns);
RTAI_SYSCALL_MODE int rt_spl_unlock(struct rtai_spl *spl);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
RTAI_PROTO(struct rtai_spl *, rt_spl_init,(unsigned long name))
{
struct { unsigned long name; } arg = { name };
return (struct rtai_spl *)rtai_lxrt(BIDX, SIZARG, LXRT_SPL_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_spl_delete,(struct rtai_spl *spl))
{
struct { struct rtai_spl *spl; } arg = { spl };
return rtai_lxrt(BIDX, SIZARG, LXRT_SPL_DELETE, &arg).i[LOW];
}
RTAI_PROTO(struct rtai_spl *, rt_named_spl_init,(const char *name))
{
struct { unsigned long name; } arg = { nam2num(name) };
return (struct rtai_spl *)rtai_lxrt(BIDX, SIZARG, NAMED_SPL_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_named_spl_delete,(struct rtai_spl *spl))
{
struct { struct rtai_spl *spl; } arg = { spl };
return rtai_lxrt(BIDX, SIZARG, NAMED_SPL_DELETE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_spl_lock,(struct rtai_spl *spl))
{
struct { struct rtai_spl *spl; } arg = { spl };
return rtai_lxrt(BIDX, SIZARG, SPL_LOCK, &arg).i[LOW];
}
RTAI_PROTO(int, rt_spl_lock_if,(struct rtai_spl *spl))
{
struct { struct rtai_spl *spl; } arg = { spl };
return rtai_lxrt(BIDX, SIZARG, SPL_LOCK_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_spl_lock_timed,(struct rtai_spl *spl, RTIME delay))
{
struct { struct rtai_spl *spl; RTIME delay; } arg = { spl, delay };
return rtai_lxrt(BIDX, SIZARG, SPL_LOCK_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_spl_unlock,(struct rtai_spl *spl))
{
struct { struct rtai_spl *spl; } arg = { spl };
return rtai_lxrt(BIDX, SIZARG, SPL_UNLOCK, &arg).i[LOW];
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#if !defined(__KERNEL__) || defined(__cplusplus)
typedef struct rtai_spl {
int opaque;
} SPL;
#endif /* !__KERNEL__ || __cplusplus */
#endif /* !_RTAI_SPL_H */

77
include/rtai_taskq.h Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2008-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_TASKQ_H
#define _RTAI_TASKQ_H
#include <rtai_schedcore.h>
extern struct epoch_struct boot_epoch;
typedef struct rt_task_queue {
struct rt_queue queue; /* <= Must be first in struct. */
int qtype;
unsigned long status;
} TASKQ;
#define XNTIMEO 0x00000001 // RTE_TIMOUT
#define XNRMID 0x00000002 // RTE_OBJREM
#define XNBREAK 0x00000004 // RTE_UNBLKD
#define TASKQ_PRIO 0x0
#define TASKQ_FIFO 0x1
#define RT_SCHED_TASKQ RT_SCHED_SEMAPHORE
#ifdef CONFIG_SMP
extern volatile unsigned long tosched_mask;
#define TOSCHED_TASK(task) \
do { tosched_mask |= (1 << (task)->runnable_on_cpus); } while (0)
#else /* !CONFIG_SMP */
#define TOSCHED_TASK(task)
#endif /* CONFIG_SMP */
void rt_schedule_readied(void);
void rt_taskq_init(TASKQ *taskq, unsigned int type);
RT_TASK *rt_taskq_ready_one(TASKQ *taskq);
int rt_taskq_ready_all(TASKQ *taskq, unsigned long why);
void rt_taskq_wait(TASKQ *taskq);
void rt_taskq_wait_until(TASKQ *taskq, RTIME time);
#define rt_taskq_delete(taskq) rt_taskq_ready_all(taskq, RTE_OBJREM)
#define rt_taskq_wait_timed(taskq, delay) \
do { rt_taskq_wait_until(taskq, get_time() + delay); } while (0)
static inline int rt_task_test_taskq_retval(RT_TASK *task, unsigned long mask)
{
return ((task)->retval & mask);
}
#endif /* !_RTAI_TASKQ_H */

513
include/rtai_trace.h Normal file
View File

@ -0,0 +1,513 @@
/*
* This file contains the necessary definitions for the RTAI tracer.
*
* Copyright (C) 2000, Karim Yaghmour <karym@opersys.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_TRACE_H
#define _RTAI_TRACE_H
#include <rtai_types.h>
#if defined(CONFIG_RTAI_TRACE) && defined(__KERNEL__)
#include <linux/trace.h>
/* Is RTAI tracing enabled */
/* The functions to the tracer management code */
int rt_register_tracer
(tracer_call /* The tracer function */);
int rt_unregister_tracer
(tracer_call /* The tracer function */);
int rt_trace_event
(uint8_t /* Event ID (as defined in this header file) */,
void* /* Structure describing the event */);
/* Generic macros */
#define RT_TRACE_EVENT(ID, DATA) rt_trace_event(ID, DATA)
#define TRACE_RTAI_START TRACE_EV_MAX
/* Traced events */
#define TRACE_RTAI_EV_MOUNT TRACE_RTAI_START + 1 /* The RTAI subsystem was mounted */
#define TRACE_RTAI_EV_UMOUNT TRACE_RTAI_START + 2 /* The RTAI subsystem was unmounted */
#define TRACE_RTAI_EV_GLOBAL_IRQ_ENTRY TRACE_RTAI_START + 3 /* Entry in a global IRQ */
#define TRACE_RTAI_EV_GLOBAL_IRQ_EXIT TRACE_RTAI_START + 4 /* Exit from a global IRQ */
#define TRACE_RTAI_EV_OWN_IRQ_ENTRY TRACE_RTAI_START + 5 /* Entry in a CPU own IRQ */
#define TRACE_RTAI_EV_OWN_IRQ_EXIT TRACE_RTAI_START + 6 /* Exit from a CPU own IRQ */
#define TRACE_RTAI_EV_TRAP_ENTRY TRACE_RTAI_START + 7 /* Entry in a trap */
#define TRACE_RTAI_EV_TRAP_EXIT TRACE_RTAI_START + 8 /* Exit from a trap */
#define TRACE_RTAI_EV_SRQ_ENTRY TRACE_RTAI_START + 9 /* Entry in a SRQ */
#define TRACE_RTAI_EV_SRQ_EXIT TRACE_RTAI_START + 10 /* Exit from a SRQ */
#define TRACE_RTAI_EV_SWITCHTO_LINUX TRACE_RTAI_START + 11 /* Switch a CPU to Linux */
#define TRACE_RTAI_EV_SWITCHTO_RT TRACE_RTAI_START + 12 /* Switch a CPU to real-time */
#define TRACE_RTAI_EV_SCHED_CHANGE TRACE_RTAI_START + 13 /* A scheduling change has occured */
#define TRACE_RTAI_EV_TASK TRACE_RTAI_START + 14 /* Hit key part of task services */
#define TRACE_RTAI_EV_TIMER TRACE_RTAI_START + 15 /* Hit key part of timer services */
#define TRACE_RTAI_EV_SEM TRACE_RTAI_START + 16 /* Hit key part of semaphore services */
#define TRACE_RTAI_EV_MSG TRACE_RTAI_START + 17 /* Hit key part of message services */
#define TRACE_RTAI_EV_RPC TRACE_RTAI_START + 18 /* Hit key part of RPC services */
#define TRACE_RTAI_EV_MBX TRACE_RTAI_START + 19 /* Hit key part of mail box services */
#define TRACE_RTAI_EV_FIFO TRACE_RTAI_START + 20 /* Hit key part of FIFO services */
#define TRACE_RTAI_EV_SHM TRACE_RTAI_START + 21 /* Hit key part of shared memory services */
#define TRACE_RTAI_EV_LXRT TRACE_RTAI_START + 22 /* Hit key part of LXRT services */
#define TRACE_RTAI_EV_LXRTI TRACE_RTAI_START + 23 /* Hit key part of LXRT-Informed services */
/* Max number of traced events */
#define TRACE_RTAI_EV_MAX TRACE_RTAI_EV_LXRTI
/* Structures and macros for traced events */
/* TRACE_RTAI_MOUNT */
#define TRACE_RTAI_MOUNT() rt_trace_event(TRACE_RTAI_EV_MOUNT, NULL)
/* TRACE_RTAI_UMOUNT */
#define TRACE_RTAI_UMOUNT() rt_trace_event(TRACE_RTAI_EV_UMOUNT, NULL)
/* TRACE_RTAI_GLOBAL_IRQ_ENTRY */
typedef struct _trace_rtai_global_irq_entry
{
uint8_t irq_id; /* IRQ number */
uint8_t kernel; /* Are we executing kernel code */
} LTT_PACKED_STRUCT trace_rtai_global_irq_entry;
#define TRACE_RTAI_GLOBAL_IRQ_ENTRY(ID, __dummy) \
do \
{\
uint32_t eflags, xcs; \
trace_rtai_global_irq_entry irq_entry;\
irq_entry.irq_id = ID;\
__asm__ __volatile__("pushfl; pop %0": "=g" (eflags)); \
__asm__ __volatile__("pushl %%cs; pop %0": "=g" (xcs)); \
irq_entry.kernel = !((VM_MASK & eflags) || (3 & xcs));\
rt_trace_event(TRACE_RTAI_EV_GLOBAL_IRQ_ENTRY, &irq_entry);\
} while(0)
/* TRACE_RTAI_GLOBAL_IRQ_EXIT */
#define TRACE_RTAI_GLOBAL_IRQ_EXIT() rt_trace_event(TRACE_RTAI_EV_GLOBAL_IRQ_EXIT, NULL)
/* TRACE_RTAI_OWN_IRQ_ENTRY */
typedef struct _trace_rtai_own_irq_entry
{
uint8_t irq_id; /* IRQ number */
uint8_t kernel; /* Are we executing kernel code */
} LTT_PACKED_STRUCT trace_rtai_own_irq_entry;
#define TRACE_RTAI_OWN_IRQ_ENTRY(ID) \
do \
{\
uint32_t eflags, xcs; \
trace_rtai_own_irq_entry irq_entry;\
irq_entry.irq_id = ID;\
__asm__ __volatile__("pushfl; pop %0": "=g" (eflags)); \
__asm__ __volatile__("pushl %%cs; pop %0": "=g" (xcs)); \
irq_entry.kernel = !((VM_MASK & eflags) || (3 & xcs));\
rt_trace_event(TRACE_RTAI_EV_OWN_IRQ_ENTRY, &irq_entry);\
} while(0)
/* TRACE_RTAI_OWN_IRQ_EXIT */
#define TRACE_RTAI_OWN_IRQ_EXIT() rt_trace_event(TRACE_RTAI_EV_OWN_IRQ_EXIT, NULL)
/* TRACE_RTAI_TRAP_ENTRY */
typedef struct _trace_rtai_trap_entry
{
uint8_t trap_id; /* Trap number */
uint32_t address; /* Address where trap occured */
} LTT_PACKED_STRUCT trace_rtai_trap_entry;
#define TRACE_RTAI_TRAP_ENTRY(ID,ADDR) \
do \
{\
trace_rtai_trap_entry trap_event;\
trap_event.trap_id = ID;\
trap_event.address = ADDR; \
rt_trace_event(TRACE_RTAI_EV_TRAP_ENTRY, &trap_event);\
} while(0)
/*
uint32_t eip; \
__asm__ __volatile__("pushl %%ip; pop %0": "=g" (eip)); \
trap_event.address = eip;\
*/
/* TRACE_RTAI_TRAP_EXIT */
#define TRACE_RTAI_TRAP_EXIT() rt_trace_event(TRACE_RTAI_EV_TRAP_EXIT, NULL)
/* TRACE_RTAI_SRQ_ENTRY */
typedef struct _trace_rtai_srq_entry
{
uint8_t srq_id; /* SRQ number */
uint8_t kernel; /* Are we executing kernel code */
} LTT_PACKED_STRUCT trace_rtai_srq_entry;
#define TRACE_RTAI_SRQ_ENTRY(ID) \
do \
{\
uint32_t eflags, xcs; \
trace_rtai_srq_entry srq_entry;\
srq_entry.srq_id = ID;\
__asm__ __volatile__("pushfl; pop %0": "=g" (eflags)); \
__asm__ __volatile__("pushl %%cs; pop %0": "=g" (xcs)); \
srq_entry.kernel = !((VM_MASK & eflags) || (3 & xcs));\
rt_trace_event(TRACE_RTAI_EV_SRQ_ENTRY, &srq_entry);\
} while(0)
/* TRACE_RTAI_SRQ_EXIT */
#define TRACE_RTAI_SRQ_EXIT() rt_trace_event(TRACE_RTAI_EV_SRQ_EXIT, NULL)
/* TRACE_RTAI_SWITCHTO_LINUX */
typedef struct _trace_rtai_switchto_linux
{
uint8_t cpu_id; /* The CPUID being switched to Linux */
} LTT_PACKED_STRUCT trace_rtai_switchto_linux;
#define TRACE_RTAI_SWITCHTO_LINUX(ID) \
do \
{\
trace_rtai_switchto_linux switch_event; \
switch_event.cpu_id = (uint8_t) ID; \
rt_trace_event(TRACE_RTAI_EV_SWITCHTO_LINUX, &switch_event); \
} while(0)
/* TRACE_RTAI_SWITCHTO_RT */
typedef struct _trace_rtai_switchto_rt
{
uint8_t cpu_id; /* The CPUID being switched to RT */
} LTT_PACKED_STRUCT trace_rtai_switchto_rt;
#define TRACE_RTAI_SWITCHTO_RT(ID) \
do \
{\
trace_rtai_switchto_rt switch_event; \
switch_event.cpu_id = (uint8_t) ID; \
rt_trace_event(TRACE_RTAI_EV_SWITCHTO_RT, &switch_event); \
} while(0)
/* TRACE_RTAI_SCHED_CHANGE */
typedef struct _trace_rtai_sched_change
{
uint32_t out; /* Outgoing process */
uint32_t in; /* Incoming process */
uint32_t out_state; /* Outgoing process' state */
} LTT_PACKED_STRUCT trace_rtai_sched_change;
#define TRACE_RTAI_SCHED_CHANGE(OUT, IN, OUT_STATE) \
do \
{\
trace_rtai_sched_change sched_event;\
sched_event.out = (uint32_t) OUT;\
sched_event.in = (uint32_t) IN;\
sched_event.out_state = (uint32_t) OUT_STATE; \
rt_trace_event(TRACE_RTAI_EV_SCHED_CHANGE, &sched_event);\
} while(0)
/* TRACE_RTAI_TASK */
#define TRACE_RTAI_EV_TASK_INIT 1 /* Initialize task */
#define TRACE_RTAI_EV_TASK_DELETE 2 /* Delete task */
#define TRACE_RTAI_EV_TASK_SIG_HANDLER 3 /* Set signal handler */
#define TRACE_RTAI_EV_TASK_YIELD 4 /* Yield CPU control */
#define TRACE_RTAI_EV_TASK_SUSPEND 5 /* Suspend task */
#define TRACE_RTAI_EV_TASK_RESUME 6 /* Resume task */
#define TRACE_RTAI_EV_TASK_MAKE_PERIOD_RELATIVE 7 /* Make task periodic relative in nanoseconds */
#define TRACE_RTAI_EV_TASK_MAKE_PERIOD 8 /* Make task periodic */
#define TRACE_RTAI_EV_TASK_WAIT_PERIOD 9 /* Wait until the next period */
#define TRACE_RTAI_EV_TASK_BUSY_SLEEP 10 /* Busy sleep */
#define TRACE_RTAI_EV_TASK_SLEEP 11 /* Sleep */
#define TRACE_RTAI_EV_TASK_SLEEP_UNTIL 12 /* Sleep until */
typedef struct _trace_rtai_task
{
uint8_t event_sub_id; /* Task event ID */
uint32_t event_data1; /* Event data */
uint64_t event_data2; /* Event data 2 */
uint64_t event_data3; /* Event data 3 */
} LTT_PACKED_STRUCT trace_rtai_task;
#define TRACE_RTAI_TASK(ID, DATA1, DATA2, DATA3) \
do \
{\
trace_rtai_task task_event;\
task_event.event_sub_id = (uint8_t) ID;\
task_event.event_data1 = (uint32_t) DATA1; \
task_event.event_data2 = (uint64_t) DATA2; \
task_event.event_data3 = (uint64_t) DATA3; \
rt_trace_event(TRACE_RTAI_EV_TASK, &task_event);\
} while(0)
/* TRACE_RTAI_TIMER */
#define TRACE_RTAI_EV_TIMER_REQUEST 1 /* Request timer */
#define TRACE_RTAI_EV_TIMER_FREE 2 /* Free timer */
#define TRACE_RTAI_EV_TIMER_REQUEST_APIC 3 /* Request APIC timers */
#define TRACE_RTAI_EV_TIMER_APIC_FREE 4 /* Free APIC timers */
#define TRACE_RTAI_EV_TIMER_HANDLE_EXPIRY 5 /* Handle timer expiry */
typedef struct _trace_rtai_timer
{
uint8_t event_sub_id; /* Timer event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
} LTT_PACKED_STRUCT trace_rtai_timer;
#define TRACE_RTAI_TIMER(ID, DATA1, DATA2) \
do \
{\
trace_rtai_timer timer_event; \
timer_event.event_sub_id = (uint8_t) ID; \
timer_event.event_data1 = (uint32_t) DATA1; \
timer_event.event_data2 = (uint32_t) DATA2; \
rt_trace_event(TRACE_RTAI_EV_TIMER, &timer_event); \
} while(0)
/* TRACE_RTAI_SEM */
#define TRACE_RTAI_EV_SEM_INIT 1 /* Initialize semaphore */
#define TRACE_RTAI_EV_SEM_DELETE 2 /* Delete semaphore */
#define TRACE_RTAI_EV_SEM_SIGNAL 3 /* Signal semaphore */
#define TRACE_RTAI_EV_SEM_WAIT 4 /* Wait on semaphore */
#define TRACE_RTAI_EV_SEM_WAIT_IF 5 /* Take semaphore if possible */
#define TRACE_RTAI_EV_SEM_WAIT_UNTIL 6 /* Wait on semaphore until a certain time */
typedef struct _trace_rtai_sem
{
uint8_t event_sub_id; /* Semaphore event ID */
uint32_t event_data1; /* Event data 1 */
uint64_t event_data2; /* Event data 2 */
} LTT_PACKED_STRUCT trace_rtai_sem;
#define TRACE_RTAI_SEM(ID, DATA1, DATA2) \
do \
{\
trace_rtai_sem sem_event; \
sem_event.event_sub_id = (uint8_t) ID; \
sem_event.event_data1 = (uint32_t) DATA1; \
sem_event.event_data2 = (uint64_t) DATA2; \
rt_trace_event(TRACE_RTAI_EV_SEM, &sem_event); \
} while(0)
/* TRACE_RTAI_MSG */
#define TRACE_RTAI_EV_MSG_SEND 1 /* Send a message */
#define TRACE_RTAI_EV_MSG_SEND_IF 2 /* Send if possible */
#define TRACE_RTAI_EV_MSG_SEND_UNTIL 3 /* Try sending until a certain time */
#define TRACE_RTAI_EV_MSG_RECV 4 /* Receive a message */
#define TRACE_RTAI_EV_MSG_RECV_IF 5 /* Receive if possible */
#define TRACE_RTAI_EV_MSG_RECV_UNTIL 6 /* Try receiving until a certain time */
typedef struct _trace_rtai_msg
{
uint8_t event_sub_id; /* Message event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
uint64_t event_data3; /* Event data 3 */
} LTT_PACKED_STRUCT trace_rtai_msg;
#define TRACE_RTAI_MSG(ID, DATA1, DATA2, DATA3) \
do \
{\
trace_rtai_msg msg_event; \
msg_event.event_sub_id = (uint8_t) ID; \
msg_event.event_data1 = (uint32_t) DATA1; \
msg_event.event_data2 = (uint32_t) DATA2; \
msg_event.event_data3 = (uint64_t) DATA3; \
rt_trace_event(TRACE_RTAI_EV_MSG, &msg_event); \
} while(0)
/* TRACE_RTAI_RPC */
#define TRACE_RTAI_EV_RPC_MAKE 1 /* Make a remote procedure call */
#define TRACE_RTAI_EV_RPC_MAKE_IF 2 /* Make RPC if receiver is ready */
#define TRACE_RTAI_EV_RPC_MAKE_UNTIL 3 /* Try making an RPC until a certain time */
#define TRACE_RTAI_EV_RPC_RETURN 4 /* Send result of RPC back to caller */
typedef struct _trace_rtai_rpc
{
uint8_t event_sub_id; /* RPC event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
uint64_t event_data3; /* Event data 3 */
} LTT_PACKED_STRUCT trace_rtai_rpc;
#define TRACE_RTAI_RPC(ID, DATA1, DATA2, DATA3) \
do \
{\
trace_rtai_rpc rpc_event; \
rpc_event.event_sub_id = (uint8_t) ID; \
rpc_event.event_data1 = (uint32_t) DATA1; \
rpc_event.event_data2 = (uint32_t) DATA2; \
rpc_event.event_data3 = (uint64_t) DATA3; \
rt_trace_event(TRACE_RTAI_EV_RPC, &rpc_event); \
} while(0)
/* TRACE_RTAI_MBX */
#define TRACE_RTAI_EV_MBX_INIT 1 /* Initialize Message BoX */
#define TRACE_RTAI_EV_MBX_DELETE 2 /* Delete message box */
#define TRACE_RTAI_EV_MBX_SEND 3 /* Send a message to a message box */
#define TRACE_RTAI_EV_MBX_SEND_WP 4 /* Send as many bytes as possible */
#define TRACE_RTAI_EV_MBX_SEND_IF 5 /* Send a message if possible */
#define TRACE_RTAI_EV_MBX_SEND_UNTIL 6 /* Try sending until a certain time */
#define TRACE_RTAI_EV_MBX_RECV 7 /* Receive a message */
#define TRACE_RTAI_EV_MBX_RECV_WP 8 /* Receive as many bytes as possible */
#define TRACE_RTAI_EV_MBX_RECV_IF 9 /* Receive a message if available */
#define TRACE_RTAI_EV_MBX_RECV_UNTIL 10 /* Try receiving until a certain time */
typedef struct _trace_rtai_mbx
{
uint8_t event_sub_id; /* Message Box event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
uint64_t event_data3; /* Event data 3 */
} LTT_PACKED_STRUCT trace_rtai_mbx;
#define TRACE_RTAI_MBX(ID, DATA1, DATA2, DATA3) \
do \
{\
trace_rtai_mbx mbx_event; \
mbx_event.event_sub_id = (uint8_t) ID; \
mbx_event.event_data1 = (uint32_t) DATA1; \
mbx_event.event_data2 = (uint32_t) DATA2; \
mbx_event.event_data3 = (uint64_t) DATA3; \
rt_trace_event(TRACE_RTAI_EV_MBX, &mbx_event); \
} while(0)
/* TRACE_RTAI_FIFO */
#define TRACE_RTAI_EV_FIFO_CREATE 1 /* Create FIFO */
#define TRACE_RTAI_EV_FIFO_DESTROY 2 /* Destroy FIFO */
#define TRACE_RTAI_EV_FIFO_RESET 3 /* Reset FIFO */
#define TRACE_RTAI_EV_FIFO_RESIZE 4 /* Resize FIFO */
#define TRACE_RTAI_EV_FIFO_PUT 5 /* Write data to FIFO */
#define TRACE_RTAI_EV_FIFO_GET 6 /* Get data from FIFO */
#define TRACE_RTAI_EV_FIFO_CREATE_HANDLER 7 /* Install FIFO handler */
#define TRACE_RTAI_EV_FIFO_OPEN 8 /* Open FIFO */
#define TRACE_RTAI_EV_FIFO_RELEASE 9 /* Release FIFO */
#define TRACE_RTAI_EV_FIFO_READ 10 /* Read from FIFO */
#define TRACE_RTAI_EV_FIFO_WRITE 11 /* Write to FIFO */
#define TRACE_RTAI_EV_FIFO_READ_TIMED 12 /* Read with time limit */
#define TRACE_RTAI_EV_FIFO_WRITE_TIMED 13 /* Write with time limit */
#define TRACE_RTAI_EV_FIFO_READ_ALLATONCE 14 /* Read all the data from FIFO */
#define TRACE_RTAI_EV_FIFO_LLSEEK 15 /* Seek position into FIFO */
#define TRACE_RTAI_EV_FIFO_FASYNC 16 /* Asynchronous notification */
#define TRACE_RTAI_EV_FIFO_IOCTL 17 /* IO control on FIFO */
#define TRACE_RTAI_EV_FIFO_POLL 18 /* Poll FIFO */
#define TRACE_RTAI_EV_FIFO_SUSPEND_TIMED 19 /* Suspend task for given period */
#define TRACE_RTAI_EV_FIFO_SET_ASYNC_SIG 20 /* Set asynchrounous signal */
#define TRACE_RTAI_EV_FIFO_SEM_INIT 21 /* Initialize semaphore */
#define TRACE_RTAI_EV_FIFO_SEM_POST 22 /* Post semaphore */
#define TRACE_RTAI_EV_FIFO_SEM_WAIT 23 /* Wait on semaphore */
#define TRACE_RTAI_EV_FIFO_SEM_TRY_WAIT 24 /* Try waiting on semaphore */
#define TRACE_RTAI_EV_FIFO_SEM_TIMED_WAIT 25 /* Wait on semaphore until a certain time */
#define TRACE_RTAI_EV_FIFO_SEM_DESTROY 26 /* Destroy semaphore */
typedef struct _trace_rtai_fifo
{
uint8_t event_sub_id; /* FIFO event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
} LTT_PACKED_STRUCT trace_rtai_fifo;
#define TRACE_RTAI_FIFO(ID, DATA1, DATA2) \
do \
{\
trace_rtai_fifo fifo_event; \
fifo_event.event_sub_id = (uint8_t) ID; \
fifo_event.event_data1 = (uint32_t) DATA1; \
fifo_event.event_data2 = (uint32_t) DATA2; \
rt_trace_event(TRACE_RTAI_EV_FIFO, &fifo_event); \
} while(0)
/* TRACE_RTAI_SHM */
#define TRACE_RTAI_EV_SHM_MALLOC 1 /* Allocate shared memory */
#define TRACE_RTAI_EV_SHM_KMALLOC 2 /* Allocate shared memory in kernel space */
#define TRACE_RTAI_EV_SHM_GET_SIZE 3 /* Get the size of the shared memory area */
#define TRACE_RTAI_EV_SHM_FREE 4 /* Free shared memory */
#define TRACE_RTAI_EV_SHM_KFREE 5 /* Free kernel space shared memory */
typedef struct _trace_rtai_shm
{
uint8_t event_sub_id; /* SHared Memory event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
uint32_t event_data3; /* Event data 3 */
} LTT_PACKED_STRUCT trace_rtai_shm;
#define TRACE_RTAI_SHM(ID, DATA1, DATA2, DATA3) \
do \
{\
trace_rtai_shm shm_event; \
shm_event.event_sub_id = (uint8_t) ID; \
shm_event.event_data1 = (uint32_t) DATA1; \
shm_event.event_data2 = (uint32_t) DATA2; \
shm_event.event_data3 = (uint32_t) DATA3; \
rt_trace_event(TRACE_RTAI_EV_SHM, &shm_event); \
} while(0)
/* TRACE_RTAI_LXRT */
#define TRACE_RTAI_EV_LXRT_RTAI_SYSCALL_ENTRY 1 /* Entry in LXRT syscall */
#define TRACE_RTAI_EV_LXRT_RTAI_SYSCALL_EXIT 2 /* Exit from LXRT syscall */
#define TRACE_RTAI_EV_LXCHANGE 3 /* Scheduling change */
#define TRACE_RTAI_EV_LXRT_STEAL_TASK 4 /* Take task control from Linux */
#define TRACE_RTAI_EV_LXRT_GIVE_BACK_TASK 5 /* Give task control back to Linux */
#define TRACE_RTAI_EV_LXRT_SUSPEND 6 /* Suspend a task */
#define TRACE_RTAI_EV_LXRT_RESUME 7 /* Resume task's execution */
#define TRACE_RTAI_EV_LXRT_HANDLE 8 /* Handle a request for an RTAI service */
typedef struct _trace_rtai_lxrt
{
uint8_t event_sub_id; /* LXRT event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
uint32_t event_data3; /* Event data 3 */
} LTT_PACKED_STRUCT trace_rtai_lxrt;
#define TRACE_RTAI_LXRT(ID, DATA1, DATA2, DATA3) \
do \
{\
trace_rtai_lxrt lxrt_event; \
lxrt_event.event_sub_id = (uint8_t) ID; \
lxrt_event.event_data1 = (uint32_t) DATA1; \
lxrt_event.event_data2 = (uint32_t) DATA2; \
lxrt_event.event_data3 = (uint32_t) DATA3; \
rt_trace_event(TRACE_RTAI_EV_LXRT, &lxrt_event); \
} while(0)
/* TRACE_RTAI_LXRTI */
#define TRACE_RTAI_EV_LXRTI_NAME_ATTACH 1 /* Register current process as name */
#define TRACE_RTAI_EV_LXRTI_NAME_LOCATE 2 /* Locate a given process usint it's name */
#define TRACE_RTAI_EV_LXRTI_NAME_DETACH 3 /* Detach process from name */
#define TRACE_RTAI_EV_LXRTI_SEND 4 /* Send message to PID */
#define TRACE_RTAI_EV_LXRTI_RECV 5 /* Receive message */
#define TRACE_RTAI_EV_LXRTI_CRECV 6 /* Non-blocking receive */
#define TRACE_RTAI_EV_LXRTI_REPLY 7 /* Reply to message received */
#define TRACE_RTAI_EV_LXRTI_PROXY_ATTACH 8 /* Attach proxy to process */
#define TRACE_RTAI_EV_LXRTI_PROXY_DETACH 9 /* Detach proxy from process */
#define TRACE_RTAI_EV_LXRTI_TRIGGER 10 /* Trigger proxy */
typedef struct _trace_rtai_lxrti
{
uint8_t event_sub_id; /* LXRT event ID */
uint32_t event_data1; /* Event data 1 */
uint32_t event_data2; /* Event data 2 */
uint64_t event_data3; /* Event data 3 */
} LTT_PACKED_STRUCT trace_rtai_lxrti;
#define TRACE_RTAI_LXRTI(ID, DATA1, DATA2, DATA3) \
do \
{\
trace_rtai_lxrti lxrti_event; \
lxrti_event.event_sub_id = (uint8_t) ID; \
lxrti_event.event_data1 = (uint32_t) DATA1; \
lxrti_event.event_data2 = (uint32_t) DATA2; \
lxrti_event.event_data3 = (uint64_t) DATA3; \
rt_trace_event(TRACE_RTAI_EV_LXRTI, &lxrti_event); \
} while(0)
#else /* !(CONFIG_RTAI_TRACE && __KERNEL__) */
#define RT_TRACE_EVENT(ID, DATA)
#define TRACE_RTAI_MOUNT()
#define TRACE_RTAI_UMOUNT()
#define TRACE_RTAI_GLOBAL_IRQ_ENTRY(ID,X)
#define TRACE_RTAI_GLOBAL_IRQ_EXIT()
#define TRACE_RTAI_OWN_IRQ_ENTRY(ID)
#define TRACE_RTAI_OWN_IRQ_EXIT()
#define TRACE_RTAI_TRAP_ENTRY(ID,ADDR)
#define TRACE_RTAI_TRAP_EXIT()
#define TRACE_RTAI_SRQ_ENTRY(a)
#define TRACE_RTAI_SRQ_EXIT()
#define TRACE_RTAI_SWITCHTO_LINUX(ID)
#define TRACE_RTAI_SWITCHTO_RT(ID)
#define TRACE_RTAI_SCHED_CHANGE(OUT, IN, OUT_STATE)
#define TRACE_RTAI_TASK(ID, DATA1, DATA2, DATA3)
#define TRACE_RTAI_TIMER(ID, DATA1, DATA2)
#define TRACE_RTAI_SEM(ID, DATA1, DATA2)
#define TRACE_RTAI_MSG(ID, DATA1, DATA2, DATA3)
#define TRACE_RTAI_RPC(ID, DATA1, DATA2, DATA3)
#define TRACE_RTAI_MBX(ID, DATA1, DATA2, DATA3)
#define TRACE_RTAI_FIFO(ID, DATA1, DATA2)
#define TRACE_RTAI_SHM(ID, DATA1, DATA2, DATA3)
#define TRACE_RTAI_LXRT(ID, DATA1, DATA2, DATA3)
#define TRACE_RTAI_LXRTI(ID, DATA1, DATA2, DATA3)
#endif /* CONFIG_RTAI_TRACE && __KERNEL__ */
#endif /* !_RTAI_TRACE_H */

60
include/rtai_types.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
* Copyright (C) 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_TYPES_H
#define _RTAI_TYPES_H
#include <rtai_config.h>
#include <rtai_wrappers.h>
#define PRIO_Q 0
#define FIFO_Q 4
#define RES_Q 3
#define BIN_SEM 1
#define CNT_SEM 2
#define RES_SEM 3
#define RESEM_RECURS 1
#define RESEM_BINSEM 0
#define RESEM_CHEKWT -1
#define RT_SCHED_FIFO 0
#define RT_SCHED_RR 1
#define RTAI_PROTO(type,name,arglist) static inline type name arglist
#define RTAI_PROTO_ALWAYS_INLINE(type,name,arglist) static inline type name arglist
struct pt_regs;
struct rt_task_struct;
typedef long long RTIME;
typedef int (*RT_TRAP_HANDLER)(int, int, struct pt_regs *,void *);
struct rt_times {
int linux_tick;
int periodic_tick;
RTIME tick_time;
RTIME linux_time;
RTIME intr_time;
};
#endif /* !_RTAI_TYPES_H */

88
include/rtai_wrappers.h Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2004-2017 Philippe Gerum <rpm@xenomai.org>
* Copyright (C) 2019 Alec Ari <neotheuser@ymail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _RTAI_WRAPPERS_H
#define _RTAI_WRAPPERS_H
#ifdef __KERNEL__
#include <linux/version.h>
#ifndef __cplusplus
#include <linux/module.h>
#endif /* !__cplusplus */
#include <linux/moduleparam.h>
#define RTAI_MODULE_PARM(name, type) \
module_param(name, type, 0444)
#ifndef DEFINE_SPINLOCK
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
#endif
#ifndef DECLARE_MUTEX_LOCKED
#ifndef __DECLARE_SEMAPHORE_GENERIC
#define DECLARE_MUTEX_LOCKED(name) \
struct semaphore name = __SEMAPHORE_INITIALIZER(name, 0)
#else
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
#endif
#endif
#ifndef cpu_online_map
#define cpu_online_map (*(cpumask_t *)cpu_online_mask)
#endif
#ifndef init_MUTEX_LOCKED
#define init_MUTEX_LOCKED(sem) sema_init(sem, 0)
#endif
#define RTAI_MODULE_PARM_ARRAY(name, type, addr, size) \
module_param_array(name, type, addr, 0400);
/* Basic class macros */
#include <linux/device.h>
typedef struct class class_t;
#define CLASS_DEVICE_CREATE(cls, devt, device, fmt, arg...) device_create(cls, NULL, devt, NULL, fmt, ##arg)
#define class_device_destroy(a, b) device_destroy(a, b)
#define mm_remap_page_range(vma,from,to,size,prot) remap_page_range(vma,from,to,size,prot)
#define get_tsk_addr_limit(t) ((t)->thread_info->addr_limit.seg)
#define self_daemonize(name) daemonize(name)
#define get_thread_ptr(t) ((t)->thread_info)
#define RTAI_LINUX_IRQ_HANDLED IRQ_HANDLED
#define CPUMASK_T(name) ((cpumask_t){ { name } })
#define CPUMASK(name) (name.bits[0])
#include <linux/pid.h>
#define find_task_by_pid(nr) \
find_task_by_pid_ns(nr, &init_pid_ns)
#define kill_proc(pid, sig, priv) \
kill_proc_info(sig, (priv) ? SEND_SIG_PRIV : SEND_SIG_NOINFO, pid)
#endif /* __KERNEL__ */
#endif /* !_RTAI_WRAPPERS_H */