Skip to content

Commit 804fdc8

Browse files
authored
Merge pull request #3903 from hdiethelm/xenomai4
Xenomai4 Userspace + other fixes
2 parents 1bcf98e + ea5ef85 commit 804fdc8

File tree

9 files changed

+382
-49
lines changed

9 files changed

+382
-49
lines changed

src/Makefile.inc.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ CONFIG_USPACE_XENOMAI=@CONFIG_USPACE_XENOMAI@
232232
XENOMAI_CFLAGS=@XENOMAI_CFLAGS@
233233
XENOMAI_LDFLAGS=@XENOMAI_LDFLAGS@
234234

235+
CONFIG_USPACE_XENOMAI_EVL=@CONFIG_USPACE_XENOMAI_EVL@
236+
XENOMAI_EVL_CFLAGS=@XENOMAI_EVL_CFLAGS@
237+
XENOMAI_EVL_LDFLAGS=@XENOMAI_EVL_LDFLAGS@
238+
235239
LIBTIRPC_CFLAGS=@LIBTIRPC_CFLAGS@
236240
LIBTIRPC_LIBS=@LIBTIRPC_LIBS@
237241
PYTHON_CPPFLAGS=@PYTHON_CPPFLAGS@

src/configure.ac

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ AC_SUBST([RTAI_CONFIG])
212212
AC_PATH_PROG([XENOMAI_CONFIG], [xeno-config], [none])
213213
AC_SUBST([XENOMAI_CONFIG])
214214

215+
#Xenomai evl
216+
HAS_EVL=n
217+
AC_CHECK_HEADER([evl/evl.h],[
218+
HAS_EVL=y
219+
])
220+
215221
AC_MSG_CHECKING([for realtime API(s) to use])
216222
if test "$RTS" = uspace || test -z "$RTS" -a "$RTAI_CONFIG" = "none" ; then
217223
RTS=uspace
@@ -243,11 +249,29 @@ if test "$RTS" = uspace || test -z "$RTS" -a "$RTAI_CONFIG" = "none" ; then
243249
XENOMAI_LDFLAGS=`$XENOMAI_CONFIG --skin posix --ldflags`
244250
AC_DEFINE([USPACE_XENOMAI], [], [Define if uspace realtime should optionally support Xenomai])
245251
fi
252+
246253
AC_SUBST([CONFIG_USPACE_XENOMAI])
247254
AC_SUBST([XENOMAI_CFLAGS])
248255
AC_SUBST([XENOMAI_LDFLAGS])
249256

250-
AC_MSG_RESULT([$RTS$USPACE_RTAI$USPACE_XENOMAI])
257+
if test "$HAS_EVL" = "n" ; then
258+
USPACE_XENOMAI_EVL=
259+
CONFIG_USPACE_XENOMAI_EVL=n
260+
XENOMAI_EVL_CFLAGS=
261+
XENOMAI_EVL_LDFLAGS=
262+
else
263+
USPACE_XENOMAI_EVL=+xenomai4
264+
CONFIG_USPACE_XENOMAI_EVL=y
265+
XENOMAI_EVL_CFLAGS=
266+
XENOMAI_EVL_LDFLAGS=-levl
267+
AC_DEFINE([USPACE_XENOMAI_EVL], [], [Define if uspace realtime should optionally support Xenomai-evl])
268+
fi
269+
270+
AC_SUBST([CONFIG_USPACE_XENOMAI_EVL])
271+
AC_SUBST([XENOMAI_EVL_CFLAGS])
272+
AC_SUBST([XENOMAI_EVL_LDFLAGS])
273+
274+
AC_MSG_RESULT([$RTS$USPACE_RTAI$USPACE_XENOMAI$USPACE_XENOMAI_EVL])
251275

252276
AC_MSG_CHECKING([whether to enable userspace PCI access])
253277
AC_ARG_ENABLE(userspace-pci,

src/rtapi/Submakefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,14 @@ $(call TOOBJSDEPS, $(USPACE_XENOMAI_SRCS)): EXTRAFLAGS += -fPIC $(XENOMAI_CFLAGS
6868
TARGETS += ../lib/libuspace-xenomai.so.0
6969
TARGETS += ../lib/libuspace-xenomai.so
7070
endif
71+
72+
ifeq ($(CONFIG_USPACE_XENOMAI_EVL),y)
73+
USPACE_XENOMAI_EVL_SRCS := rtapi/uspace_xenomai_evl.cc
74+
USERSRCS += $(USPACE_XENOMAI_EVL_SRCS)
75+
$(call TOOBJSDEPS, $(USPACE_XENOMAI_EVL_SRCS)): EXTRAFLAGS += -fPIC $(XENOMAI_EVL_CFLAGS)
76+
../lib/libuspace-xenomai-evl.so.0: $(call TOOBJS, $(USPACE_XENOMAI_EVL_SRCS))
77+
$(ECHO) Linking $(notdir $@)
78+
$(Q)$(CXX) -shared $(LDFLAGS) -o $@ $^ $(XENOMAI_EVL_LDFLAGS) -Wl,-soname,$(notdir $@)
79+
TARGETS += ../lib/libuspace-xenomai-evl.so.0
80+
TARGETS += ../lib/libuspace-xenomai-evl.so
81+
endif

src/rtapi/rtapi_uspace.hh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct RtapiApp
7575
virtual int prio_lowest() const;
7676
int prio_higher_delta() const;
7777
int prio_bound(int prio) const;
78+
bool prio_check(int prio) const;
7879
int prio_next_higher(int prio) const;
7980
int prio_next_lower(int prio) const;
8081
long clock_set_period(long int period_nsec);
@@ -106,6 +107,8 @@ T *rtapi_get_task(int task_id) {
106107
return static_cast<T*>(RtapiApp::get_task(task_id));
107108
}
108109

110+
int find_rt_cpu_number();
111+
109112
#define MAX_TASKS 64
110113
#define TASK_MAGIC 21979 /* random numbers used as signatures */
111114
#define TASK_MAGIC_INIT ((rtapi_task*)(-1))

src/rtapi/uspace_common.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,15 +382,27 @@ static int detect_rtai() {
382382
#endif
383383
#ifdef USPACE_XENOMAI
384384
static int detect_xenomai() {
385-
struct utsname u;
386-
uname(&u);
387-
return strcasestr (u.release, "-xenomai") != 0;
385+
struct stat sb;
386+
//Running xenomai has /proc/xenomai
387+
return stat("/proc/xenomai", &sb) == 0;
388388
}
389389
#else
390390
static int detect_xenomai() {
391391
return 0;
392392
}
393393
#endif
394+
#ifdef USPACE_XENOMAI_EVL
395+
static int detect_xenomai_evl() {
396+
struct stat sb;
397+
//Running xenomai evl has /dev/evl but no /proc/xenomai
398+
return stat("/dev/evl", &sb) == 0;
399+
}
400+
#else
401+
static int detect_xenomai_evl() {
402+
return 0;
403+
}
404+
#endif
405+
394406
static int detect_env_override() {
395407
char *p = getenv("LINUXCNC_FORCE_REALTIME");
396408
return p != NULL && atoi(p) != 0;
@@ -401,7 +413,7 @@ static int detect_realtime() {
401413
if ((stat(EMC2_BIN_DIR "/rtapi_app", &st) < 0)
402414
|| st.st_uid != 0 || !(st.st_mode & S_ISUID))
403415
return 0;
404-
return detect_env_override() || detect_preempt_rt() || detect_rtai() || detect_xenomai();
416+
return detect_env_override() || detect_preempt_rt() || detect_rtai() || detect_xenomai() || detect_xenomai_evl();
405417
}
406418

407419
int rtapi_is_realtime() {

src/rtapi/uspace_rtai.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,18 @@ struct RtaiApp : RtapiApp {
8181
static void *wrapper(void *arg) {
8282
auto task = reinterpret_cast<RtaiTask*>(arg);
8383
pthread_setspecific(key, arg);
84-
task->rt_task = rt_task_init(task->id, task->prio, 0, 0);
84+
85+
int nprocs = sysconf( _SC_NPROCESSORS_ONLN );
86+
int cpus_allowed = 1 << (nprocs-1); //Use last CPU as default
87+
const static int rt_cpu_number = find_rt_cpu_number();
88+
if(rt_cpu_number != -1) {
89+
rtapi_print_msg(RTAPI_MSG_INFO, "rt_cpu_number = %i\n", rt_cpu_number);
90+
cpus_allowed = 1 << rt_cpu_number;
91+
}
92+
task->rt_task = rt_task_init_schmod(task->id, task->prio, 0, 0, SCHED_FIFO, cpus_allowed);
8593
rt_set_periodic_mode();
8694
start_rt_timer(nano2count(task->period));
8795
if(task->uses_fp) rt_task_use_fpu(task->rt_task, 1);
88-
// assumes processor numbers are contiguous
89-
int nprocs = sysconf( _SC_NPROCESSORS_ONLN );
90-
rt_set_runnable_on_cpus(task->rt_task, 1u << (nprocs - 1));
9196
rt_make_hard_real_time();
9297
rt_task_make_periodic_relative_ns(task->rt_task, task->period, task->period);
9398
(task->taskcode) (task->arg);
@@ -115,6 +120,7 @@ struct RtaiApp : RtapiApp {
115120
}
116121

117122
int task_pll_set_correction(long value) {
123+
(void)value;
118124
// PLL functions not supported
119125
return -EINVAL;
120126
}
@@ -133,6 +139,7 @@ struct RtaiApp : RtapiApp {
133139
#ifdef HAVE_SYS_IO_H
134140
return inb(port);
135141
#else
142+
(void)port;
136143
return 0;
137144
#endif
138145
}
@@ -141,6 +148,7 @@ struct RtaiApp : RtapiApp {
141148
#ifdef HAVE_SYS_IO_H
142149
return outb(val, port);
143150
#else
151+
(void)port;
144152
return 0;
145153
#endif
146154
}

src/rtapi/uspace_rtapi_app.cc

Lines changed: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,10 @@ static RtapiApp *makeApp()
855855
}
856856
WithRoot r;
857857
void *dll = nullptr;
858-
if(detect_xenomai()) {
858+
if(detect_xenomai_evl()) {
859+
dll = dlopen(EMC2_HOME "/lib/libuspace-xenomai-evl.so.0", RTLD_NOW);
860+
if(!dll) fprintf(stderr, "dlopen: %s\n", dlerror());
861+
}else if(detect_xenomai()) {
859862
dll = dlopen(EMC2_HOME "/lib/libuspace-xenomai.so.0", RTLD_NOW);
860863
if(!dll) fprintf(stderr, "dlopen: %s\n", dlerror());
861864
} else if(detect_rtai()) {
@@ -918,6 +921,14 @@ int RtapiApp::prio_bound(int prio) const {
918921
return prio;
919922
}
920923

924+
bool RtapiApp::prio_check(int prio) const {
925+
if(rtapi_prio_highest() > rtapi_prio_lowest()) {
926+
return (prio <= rtapi_prio_highest()) && (prio >= rtapi_prio_lowest());
927+
} else {
928+
return (prio <= rtapi_prio_lowest()) && (prio >= rtapi_prio_highest());
929+
}
930+
}
931+
921932
int RtapiApp::prio_next_higher(int prio) const
922933
{
923934
prio = prio_bound(prio);
@@ -948,8 +959,10 @@ int RtapiApp::allocate_task_id()
948959
int RtapiApp::task_new(void (*taskcode) (void*), void *arg,
949960
int prio, int owner, unsigned long int stacksize, int uses_fp) {
950961
/* check requested priority */
951-
if ((prio > rtapi_prio_highest()) || (prio < rtapi_prio_lowest()))
962+
if (!prio_check(prio))
952963
{
964+
rtapi_print_msg(RTAPI_MSG_ERR,"rtapi:task_new prio is not in bound lowest %i prio %i highest %i\n",
965+
rtapi_prio_lowest(), prio, rtapi_prio_highest());
953966
return -EINVAL;
954967
}
955968

@@ -1010,48 +1023,72 @@ int Posix::task_delete(int id)
10101023
return 0;
10111024
}
10121025

1013-
static int find_rt_cpu_number() {
1026+
//parse_cpu_list from https://gitlab.com/Xenomai/xenomai4/libevl/-/blob/11e6a1fb183a315ae861762e7650fd5e10d83ff5/tests/helpers.c
1027+
//License: MIT
1028+
static void parse_cpu_list(const char *path, cpu_set_t *cpuset)
1029+
{
1030+
char *p, *range, *range_p = NULL, *id, *id_r;
1031+
int start, end, cpu;
1032+
char buf[BUFSIZ];
1033+
FILE *fp;
1034+
1035+
CPU_ZERO(cpuset);
1036+
1037+
fp = fopen(path, "r");
1038+
if (fp == NULL)
1039+
return;
1040+
1041+
if (!fgets(buf, sizeof(buf), fp))
1042+
goto out;
1043+
1044+
p = buf;
1045+
while ((range = strtok_r(p, ",", &range_p)) != NULL) {
1046+
if (*range == '\0' || *range == '\n')
1047+
goto next;
1048+
end = -1;
1049+
id = strtok_r(range, "-", &id_r);
1050+
if (id) {
1051+
start = atoi(id);
1052+
id = strtok_r(NULL, "-", &id_r);
1053+
if (id)
1054+
end = atoi(id);
1055+
else if (end < 0)
1056+
end = start;
1057+
for (cpu = start; cpu <= end; cpu++)
1058+
CPU_SET(cpu, cpuset);
1059+
}
1060+
next:
1061+
p = NULL;
1062+
}
1063+
out:
1064+
fclose(fp);
1065+
}
1066+
1067+
int find_rt_cpu_number() {
10141068
if(getenv("RTAPI_CPU_NUMBER")) return atoi(getenv("RTAPI_CPU_NUMBER"));
10151069

10161070
#ifdef __linux__
1017-
cpu_set_t cpuset_orig;
1018-
int r = sched_getaffinity(getpid(), sizeof(cpuset_orig), &cpuset_orig);
1019-
if(r < 0)
1020-
// if getaffinity fails, (it shouldn't be able to), just use CPU#0
1021-
return 0;
1022-
1071+
const char* isolated_file="/sys/devices/system/cpu/isolated";
10231072
cpu_set_t cpuset;
1024-
CPU_ZERO(&cpuset);
1025-
long top_probe = sysconf(_SC_NPROCESSORS_CONF);
1026-
// in old glibc versions, it was an error to pass to sched_setaffinity bits
1027-
// that are higher than an imagined/probed kernel-side CPU mask size.
1028-
// this caused the message
1029-
// sched_setaffinity: Invalid argument
1030-
// to be printed at startup, and the probed CPU would not take into
1031-
// account CPUs masked from this process by default (whether by
1032-
// isolcpus or taskset). By only setting bits up to the "number of
1033-
// processes configured", the call is successful on glibc versions such as
1034-
// 2.19 and older.
1035-
for(long i=0; i<top_probe && i<CPU_SETSIZE; i++) CPU_SET(i, &cpuset);
1036-
1037-
r = sched_setaffinity(getpid(), sizeof(cpuset), &cpuset);
1038-
if(r < 0)
1039-
// if setaffinity fails, (it shouldn't be able to), go on with
1040-
// whatever the default CPUs were.
1041-
perror("sched_setaffinity");
1042-
1043-
r = sched_getaffinity(getpid(), sizeof(cpuset), &cpuset);
1044-
if(r < 0) {
1045-
// if getaffinity fails, (it shouldn't be able to), copy the
1046-
// original affinity list in and use it
1047-
perror("sched_getaffinity");
1048-
CPU_AND(&cpuset, &cpuset_orig, &cpuset);
1073+
1074+
parse_cpu_list(isolated_file, &cpuset);
1075+
1076+
//Print list
1077+
rtapi_print_msg(RTAPI_MSG_INFO, "cpuset isolated ");
1078+
for(int i=0; i<CPU_SETSIZE; i++) {
1079+
if(CPU_ISSET(i, &cpuset)){
1080+
rtapi_print_msg(RTAPI_MSG_INFO, "%i ", i);
1081+
}
10491082
}
1083+
rtapi_print_msg(RTAPI_MSG_INFO, "\n");
10501084

10511085
int top = -1;
10521086
for(int i=0; i<CPU_SETSIZE; i++) {
10531087
if(CPU_ISSET(i, &cpuset)) top = i;
10541088
}
1089+
if(top == -1){
1090+
rtapi_print_msg(RTAPI_MSG_ERR, "No isolated CPU's found, expect some latency or set RTAPI_CPU_NUMBER to select CPU\n");
1091+
}
10551092
return top;
10561093
#else
10571094
return (-1);
@@ -1091,6 +1128,7 @@ int Posix::task_start(int task_id, unsigned long int period_nsec)
10911128
return -ret;
10921129
if(nprocs > 1) {
10931130
const static int rt_cpu_number = find_rt_cpu_number();
1131+
rtapi_print_msg(RTAPI_MSG_INFO, "rt_cpu_number = %i\n", rt_cpu_number);
10941132
if(rt_cpu_number != -1) {
10951133
#ifdef __FreeBSD__
10961134
cpuset_t cpuset;

src/rtapi/uspace_xenomai.cc

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,7 @@ struct XenomaiApp : RtapiApp {
5252
task->pll_correction_limit = period_nsec / 100;
5353
task->pll_correction = 0;
5454

55-
cpu_set_t cpuset;
56-
CPU_ZERO(&cpuset);
5755
int nprocs = sysconf( _SC_NPROCESSORS_ONLN );
58-
CPU_SET(nprocs-1, &cpuset); // assumes processor numbers are contiguous
5956

6057
int ret;
6158
pthread_attr_t attr;
@@ -69,9 +66,17 @@ struct XenomaiApp : RtapiApp {
6966
return -ret;
7067
if((ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) != 0)
7168
return -ret;
72-
if(nprocs > 1)
73-
if((ret = pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset)) != 0)
74-
return -ret;
69+
if(nprocs > 1){
70+
const static int rt_cpu_number = find_rt_cpu_number();
71+
rtapi_print_msg(RTAPI_MSG_INFO, "rt_cpu_number = %i\n", rt_cpu_number);
72+
if(rt_cpu_number != -1) {
73+
cpu_set_t cpuset;
74+
CPU_ZERO(&cpuset);
75+
CPU_SET(rt_cpu_number, &cpuset);
76+
if((ret = pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset)) != 0)
77+
return -ret;
78+
}
79+
}
7580
if((ret = pthread_create(&task->thr, &attr, &wrapper, reinterpret_cast<void*>(task))) != 0)
7681
return -ret;
7782

@@ -99,10 +104,12 @@ struct XenomaiApp : RtapiApp {
99104
}
100105

101106
int task_pause(int task_id) {
107+
(void)task_id;
102108
return -ENOSYS;
103109
}
104110

105111
int task_resume(int task_id) {
112+
(void)task_id;
106113
return -ENOSYS;
107114
}
108115

0 commit comments

Comments
 (0)