parent
ed75b5e575
commit
d795038445
171
Bearbeiten2.c
171
Bearbeiten2.c
|
@ -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)
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
||||||
|
![SDL Diagramm](https://files.joethei.space/documentation/diagram.png)
|
|
@ -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
|
Binary file not shown.
|
@ -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 */
|
|
@ -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 */
|
|
@ -0,0 +1,797 @@
|
||||||
|
/**
|
||||||
|
* @ingroup fifos
|
||||||
|
* @ingroup fifos_ipc
|
||||||
|
* @ingroup fifos_sem
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Interface of the @ref fifos "RTAI FIFO module".
|
||||||
|
*
|
||||||
|
* @note Copyright © 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 */
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -0,0 +1,288 @@
|
||||||
|
/**
|
||||||
|
* @ingroup lxrt
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @author Paolo Mantegazza
|
||||||
|
*
|
||||||
|
* @note Copyright © 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 */
|
|
@ -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);
|
|
@ -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 */
|
|
@ -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 © 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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -0,0 +1,96 @@
|
||||||
|
/**
|
||||||
|
* @ingroup lxrt
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @author Paolo Mantegazza
|
||||||
|
*
|
||||||
|
* @note Copyright © 1999 Paolo Mantegazza <mantegazza@aero.polimi.it>,
|
||||||
|
* @note Copyright © 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 */
|
|
@ -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 */
|
|
@ -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 © 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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -0,0 +1,429 @@
|
||||||
|
/**
|
||||||
|
* @ingroup lxrt
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @author Paolo Mantegazza
|
||||||
|
*
|
||||||
|
* @note Copyright © 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||||
|
* @note Copyright © 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 */
|
|
@ -0,0 +1,512 @@
|
||||||
|
/**
|
||||||
|
* @ingroup shm
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Interface of the @ref shm "RTAI SHM module".
|
||||||
|
*
|
||||||
|
* @author Paolo Mantegazza
|
||||||
|
*
|
||||||
|
* @note Copyright © 1999-2017 Paolo Mantegazza <mantegazza@aero.polimi.it>
|
||||||
|
* @note Copyright © 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 */
|
|
@ -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_ */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
Loading…
Reference in New Issue