Skip to content

Commit cd97372

Browse files
committed
Add hal_get_realtime_type() and deprecate rtapi_is_realtimei()
rtapi_is_realtime() was always unrelaiable. hal_get_realtime_type() returns now the true running realtime type trought the HAL for user and realtime components. This function is also exposed trought python hal.
1 parent d28f74f commit cd97372

10 files changed

Lines changed: 94 additions & 9 deletions

File tree

docs/src/config/python-hal-interface.adoc

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ Message level constants:
4848
* `hal.MSG_DBG` - Additionally include debugging information
4949
* `hal.MSG_ALL` - Print all messages encountered, disregarding level
5050

51+
Realtime type constants:
52+
53+
* `hal.REALTIME_TYPE_UNINITIALIZED` - Real time module not running
54+
* `hal.REALTIME_TYPE_NONE` - No realtime available
55+
* `hal.REALTIME_TYPE_RTAI` - RTAI kernel mode
56+
* `hal.REALTIME_TYPE_PREEMPT_DYNAMIC` - Preempt dynamic: avaliable in vanilla kernel, not recommended
57+
* `hal.REALTIME_TYPE_PREEMPT_RT` - Preempt RT
58+
* `hal.REALTIME_TYPE_LXRT` - LXRT, userspace implementation for RTAI
59+
* `hal.REALTIME_TYPE_XENOMAI` - Xenomai 3
60+
* `hal.REALTIME_TYPE_XENOMAI_EVL` - Xenomai 4 aka Xenomai EVL
61+
5162
System information:
5263

5364
* `hal.is_kernelspace` - One (1) if RTAPI runs in the kernel, otherwise zero (0)
@@ -76,9 +87,14 @@ comp_name = f"halpy{os.getpid()}"
7687
if not hal.is_initialized():
7788
comp = hal.component(comp_name)
7889
79-
ret = hal.component_exists("passthrough")
90+
type = hal.get_realtime_type()
8091
----
8192

93+
hal.get_realtime_type()::
94+
Returns the type of the running realtime system.
95+
Might return `hal.REALTIME_TYPE_UNINITIALIZED` if `rtapi_app` is not running.
96+
See xref:_hal_constants[realtime type constants].
97+
8298
hal.component_exists(_name_:string)::
8399
Returns a boolean to indicate whether or not the specified component exist at this time.
84100

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
:manvolnum: 3
2+
3+
= hal_get_realtime_type(3)
4+
5+
== NAME
6+
7+
hal_get_realtime_type - Get the type of the running realtime
8+
9+
== SYNTAX
10+
11+
hal_realtime_type_t hal_get_realtime_type()
12+
13+
== RETURN VALUE
14+
15+
*hal_get_realtime_type* returns the type of the running realtime system.
16+
17+
For uspace, this returns *REALTIME_TYPE_UNINITIALIZED* if *rtapi_all* is not running. It is save to assume
18+
this never happens in realtime components. But userspace components can be loaded withouth *rtapi_all* being
19+
started.
20+
21+
For rtai, this always returns *REALTIME_TYPE_RTAI*.

docs/src/man/man3/rtapi_is.3.adoc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ rtapi_is - details of rtapi configuration
99
[source,c]
1010
----
1111
int rtapi_is_kernelspace();
12-
int rtapi_is_realtime();
12+
int rtapi_is_realtime(); (DEPRECATED)
1313
----
1414

1515
== DESCRIPTION
@@ -18,15 +18,18 @@ int rtapi_is_realtime();
1818
and zero when they run in userspace (e.g., under uspace).
1919

2020
*rtapi_is_realtime()* returns nonzero when capable of running with realtime guarantees.
21+
22+
(DEPRECATED) use *hal_get_realtime_type()* instead. *rtapi_is_realtime()* works only in realtime context.
23+
2124
For rtai, this always returns nonzero (but actually loading realtime modules will fail if not running under the appropriate kernel).
22-
For uspace, this returns nonzero when the running kernel indicates it is capable of realtime performance.
23-
If *rtapi_app* is not setuid root,
24-
this returns nonzero even though *rtapi_app* will not be able to obtain realtime scheduling or hardware access,
25-
so e.g., attempting to *loadrt* a hardware driver will fail.
25+
For uspace, this returns nonzero when the running kernel indicates it is capable of realtime performance and *rtapi_app* has the
26+
required capabilities or is setuid root.
27+
If *rtapi_app* is not setuid root or setcap with the proper capabilities,
28+
this returns zero.
2629

2730
== REALTIME CONSIDERATIONS
2831

29-
May be called from non-realtime or from realtime setup code.
32+
May only be called from realtime setup code.
3033
*rtapi_is_realtime()* may perform filesystem I/O.
3134

3235
== RETURN VALUE

src/hal/hal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ extern int hal_unready(int comp_id);
237237
*/
238238
extern char* hal_comp_name(int comp_id);
239239

240+
/** hal_get_realtime_type() returns the type of the running real time
241+
*/
242+
typedef rtapi_realtime_type_t hal_realtime_type_t;
243+
extern hal_realtime_type_t hal_get_realtime_type(void);
244+
240245
/** The HAL maintains lists of variables, functions, and so on in
241246
a central database, located in shared memory so all components
242247
can access it. To prevent contention, functions that may

src/hal/hal_lib.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
5454
*/
5555

56+
#define RTAPI_HAL_PRIV /* Use rtapi/hal private functions */
5657
#include <rtapi.h> /* RTAPI realtime OS API */
5758
#include "hal.h" /* HAL public API decls */
5859
#include "hal_priv.h" /* HAL private decls */
@@ -537,6 +538,15 @@ char *hal_comp_name(int comp_id)
537538
return result;
538539
}
539540

541+
hal_realtime_type_t hal_get_realtime_type() {
542+
if (hal_data == 0) {
543+
rtapi_print_msg(RTAPI_MSG_ERR,
544+
"HAL: ERROR: hal_get_realtime_type called before init\n");
545+
return -EINVAL;
546+
}
547+
return hal_data->realtime_type;
548+
}
549+
540550
/***********************************************************************
541551
* "LOCKING" FUNCTIONS *
542552
************************************************************************/
@@ -3111,13 +3121,18 @@ int rtapi_app_main(void)
31113121
/* done */
31123122
rtapi_print_msg(RTAPI_MSG_DBG,
31133123
"HAL_LIB: kernel lib installed successfully\n");
3124+
3125+
hal_data->realtime_type = rtapi_get_realtime_type();
3126+
31143127
return 0;
31153128
}
31163129

31173130
void rtapi_app_exit(void)
31183131
{
31193132
hal_thread_t *thread;
31203133

3134+
hal_data->realtime_type = REALTIME_TYPE_UNINITIALIZED;
3135+
31213136
rtapi_print_msg(RTAPI_MSG_DBG, "HAL_LIB: removing kernel lib\n");
31223137
hal_proc_clean();
31233138
/* grab mutex before manipulating list */
@@ -3275,6 +3290,7 @@ static int init_hal_data(void)
32753290
list_init_entry(&(hal_data->funct_entry_free));
32763291
hal_data->thread_free_ptr = 0;
32773292
hal_data->exact_base_period = 0;
3293+
hal_data->realtime_type = REALTIME_TYPE_UNINITIALIZED;
32783294
/* set up for shmalloc_xx() */
32793295
hal_data->shmem_bot = sizeof(hal_data_t);
32803296
hal_data->shmem_top = HAL_SIZE;

src/hal/hal_priv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
*/
119119

120120
#define HAL_KEY 0x48414C32 /* key used to open HAL shared memory */
121-
#define HAL_VER 0x00000010 /* version code */
121+
#define HAL_VER 0x00000011 /* version code */
122122
#define HAL_SIZE (256*4096)
123123
#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */
124124

@@ -275,6 +275,7 @@ typedef struct hal_data_t {
275275
SHMFIELD(hal_thread_t) thread_free_ptr; /* list of free thread structs */
276276
int exact_base_period; /* if set, pretend that rtapi satisfied our
277277
period request exactly */
278+
rtapi_realtime_type_t realtime_type; /* reflects the running realtime type */
278279
unsigned char lock; /* hal locking, can be one of the HAL_LOCK_* types */
279280
} hal_data_t;
280281

src/hal/halmodule.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,6 +1830,12 @@ PyObject *get_info_params(PyObject * /*self*/, PyObject * /*args*/) {
18301830
return python_list;
18311831
}
18321832

1833+
static PyObject *pyhal_get_realtime_type(PyObject * /*self*/, PyObject * /*o*/) {
1834+
TEST_HAL_SHMEM_BASE(__FUNCTION__);
1835+
int res = hal_get_realtime_type();
1836+
return PyLong_FromLong(res);
1837+
}
1838+
18331839
static PyObject *pyhal_is_initialized(PyObject * /*self*/, PyObject * /*o*/) {
18341840
return PyBool_FromLong(hal_shmem_base != NULL);
18351841
}
@@ -2304,6 +2310,8 @@ static PyMethodDef module_methods[] = {
23042310
".get_info_signals(): Get a list of dicts for all the signals; {NAME:, VALUE:}"},
23052311
{"get_info_params", get_info_params, METH_VARARGS,
23062312
".get_info_params(): Get a list of dicts for all the parameters; {NAME:, VALUE:}"},
2313+
{"get_realtime_type", pyhal_get_realtime_type, METH_NOARGS,
2314+
".get_realtime_type(): Return the type of the running realtime"},
23072315
{"is_initialized", pyhal_is_initialized, METH_NOARGS,
23082316
".is_initialized(): Return true if hal is initialized, false otherwhise"},
23092317
{},
@@ -2385,6 +2393,14 @@ PyMODINIT_FUNC PyInit__hal(void)
23852393
PyModule_AddIntConstant(m, "HAL_OUT", HAL_OUT);
23862394
PyModule_AddIntConstant(m, "HAL_IO", HAL_IO);
23872395

2396+
PyModule_AddIntConstant(m, "REALTIME_TYPE_UNINITIALIZED", REALTIME_TYPE_UNINITIALIZED);
2397+
PyModule_AddIntConstant(m, "REALTIME_TYPE_NONE", REALTIME_TYPE_NONE);
2398+
PyModule_AddIntConstant(m, "REALTIME_TYPE_RTAI", REALTIME_TYPE_RTAI);
2399+
PyModule_AddIntConstant(m, "REALTIME_TYPE_PREEMPT_DYNAMIC", REALTIME_TYPE_PREEMPT_DYNAMIC);
2400+
PyModule_AddIntConstant(m, "REALTIME_TYPE_PREEMPT_RT", REALTIME_TYPE_PREEMPT_RT);
2401+
PyModule_AddIntConstant(m, "REALTIME_TYPE_LXRT", REALTIME_TYPE_LXRT);
2402+
PyModule_AddIntConstant(m, "REALTIME_TYPE_XENOMAI", REALTIME_TYPE_XENOMAI);
2403+
PyModule_AddIntConstant(m, "REALTIME_TYPE_XENOMAI_EVL", REALTIME_TYPE_XENOMAI_EVL);
23882404

23892405
//Call realtime verify to gather realtime status
23902406
//Most probably we don't have realtime running yet

src/rtapi/rtai_rtapi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
#include <rtai_shm.h>
8484
#include <rtai_fifos.h>
8585

86+
#define RTAPI_HAL_PRIV /* Use rtapi/hal private functions */
8687
#include "rtapi.h" /* public RTAPI decls */
8788
#include <rtapi_mutex.h>
8889
#include "rtapi_common.h" /* shared realtime/nonrealtime stuff */

src/rtapi/rtapi.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,8 @@ int rtapi_spawnp_as_root(pid_t *pid, const char *path,
986986

987987
extern int rtapi_is_kernelspace(void);
988988

989+
//If changing anything here:
990+
//Update also halmodule.cc PyInit__hal()
989991
//You can use type > REALTIME_TYPE_NONE to check if you have realtime at all
990992
typedef enum{
991993
REALTIME_TYPE_UNINITIALIZED = -1, //Realtime not running, type unknown
@@ -998,8 +1000,10 @@ typedef enum{
9981000
REALTIME_TYPE_XENOMAI_EVL = 6,
9991001
} rtapi_realtime_type_t;
10001002

1003+
#if defined(RTAPI) && defined(RTAPI_HAL_PRIV)
1004+
//Only available in real time context, private use between hal and rtapi
1005+
//Always use hal_get_realtime_type()
10011006
extern int rtapi_is_realtime(void);
1002-
#ifdef RTAPI
10031007
extern rtapi_realtime_type_t rtapi_get_realtime_type(void);
10041008
#endif
10051009

src/rtapi/uspace_rtapi_main.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include <fmt/format.h>
5656
#include <boost/lockfree/queue.hpp>
5757

58+
#define RTAPI_HAL_PRIV //Use rtapi/hal private functions
5859
#include "rtapi.h"
5960
#include <hal.h>
6061
#include "hal/hal_priv.h"
@@ -862,6 +863,7 @@ static int master(int fd, const std::vector<std::string> &args) {
862863
//Process commands as long as master should not exit
863864
while(master_process_socket_command(fd));
864865
out:
866+
do_unload_cmd("hal_lib");
865867
pthread_cancel(queue_thread);
866868
pthread_join(queue_thread, nullptr);
867869
rtapi_msg_queue.consume_all([](const message_t &m) {

0 commit comments

Comments
 (0)