Hello,

I have isolated the bare minimum of math functions that need to be provided by 
rtai_math.ko for LinuxCNC.

Currently, in both my master branch and RTAI mainline, rtai_math.ko depends on 
a C library (such as musl) to provide the math functions. Two problems come 
with this:

1.) It is undeniably clumsy to have such a library integrated into a kernel 
module.

2.) Warnings, lots of them. rtai_math.ko gets built (with a lot of 
EXPORT_SYMBOLS that are undefined right away) then becomes linked with a C 
library after the fact, which defines all those symbols that just spammed your 
terminal.

Everything works as-is but this is not good practice. To solve the issue, I 
have imported the old RTAI math code (from RTAI 3 and 4) down to only what is 
needed:

https://github.com/NTULINUX/RTAI/tree/tiny-math

However it is to the best of my knowledge that LinuxCNC should also go with 
this patch along with that RTAI branch:

diff --git a/src/rtapi/rtapi_math.h b/src/rtapi/rtapi_math.h
index 1f3788081..99e16fd79 100644
--- a/src/rtapi/rtapi_math.h
+++ b/src/rtapi/rtapi_math.h
@@ -32,18 +32,19 @@
 #if defined(__KERNEL__)
 extern double sin(double);
 extern double cos(double);
-extern double tan(double);
-extern double sqrt(double);
-extern double fabs(double);
-extern double atan(double);
-extern double atan2(double, double);
-extern double asin(double);
-extern double acos(double);
-extern double exp(double);
-extern double pow(double, double);
+#define tan(x) __builtin_tan(x)
+#define sqrt(x) __builtin_sqrt(x)
+#define fabs(x) __builtin_fabs(x)
+#define atan(x) __builtin_atan(x)
+#define atan2(y, x) __builtin_atan2(y, x)
+#define asin(x) __builtin_asin(x)
+#define acos(x) __builtin_acos(x)
+#define exp(x) __builtin_exp(x)
+#define pow(x, y) __builtin_pow(x, y)
+#define fmod(x, y) __builtin_fmod(x, y)
+
 extern double fmin(double, double);
-extern double fmax(double, double);
-extern double fmod(double, double);
+#define fmax(x,y) __builtin_fmax(x,y)
 
 extern double round(double);
 extern double ceil(double);
@@ -57,21 +58,6 @@ extern double floor(double);
 #define isinf(x) __builtin_isinf((x))
 #define isfinite(x) __builtin_isfinite((x))
 
-extern __inline double atan (double __y) {
-    return atan2(__y, 1.);
-}
-
-extern __inline double asin (double __x) {
-    return atan2(__x, sqrt (1.0 - __x * __x));
-}
-
-extern __inline double acos (double __x) {
-    return atan2(sqrt(1.0 - __x * __x), __x);
-}
-
-extern __inline double fmax(double __y, double __x) {
-    return __y > __x || __builtin_isnan(__x) ? __y : __x;
-}
 extern __inline double fmin(double __y, double __x) {
     return __y < __x || __builtin_isnan(__x) ? __y : __x;
 }

The use of built-ins are fine since most of them aren't even used with RT, as 
noted in src/tests/mathtests.c:

  extern double sin(double);            used in posemath, siggen, & 
noncartesian kins
  extern double cos(double);            used in posemath, siggen, & 
noncartesian kins
  extern double tan(double);            not used in RT
  extern double asin(double);           not used in RT
  extern double acos(double);           used in posemath & noncartesian kins
  extern double atan2(double, double);  used in posemath & noncartesian kins
  extern double sinh(double);           not used in RT
  extern double cosh(double);           not used in RT
  extern double tanh(double);           not used in RT
  extern double exp(double);            not used in RT
  extern double log(double);            not used in RT
  extern double log10(double);          not used in RT
  extern double pow(double, double);    not used in RT
  extern double sqrt(double);           used in tc, segmot, & noncartesean kins.
  extern double ceil(double);           used in segmot & emcpid
  extern double floor(double);          used by siggen & segmot
  extern double fabs(double);           used a lot in RT
  extern double ldexp(double, int);     not used in RT

I haven't tested the `tiny-math` RTAI branch paired with the use of LinuxCNC 
using GCC built-ins in a real world scenario, but runtests completed 
successfully, including the tests for math.

I spoke to the musl developers on IRC, and they informed me that aside from 
some IEEE elementary functions, GCC does not actually define math functions. 
This information however conflicts with the information from RTAI 
(math/README.KLIBM) as noted here:

***************************** A FINAL IMPORTANT REMARK 
*****************************
Nowadays, depending of the gcc version and enabled compiler standard options 
(e.g. ISOC99)
most of the functions provided by the RTAI kernel math support (rtai_math.ko) 
are compiler
builtins. Therefore, it is likely that your applications will end in not using 
any of the rtai_math.ko
functions. Thus, even if it is insmoded, it will do nothing. To check if such 
is the case
and what functions of rtai_math.ko are being used eventually, you have just to 
insmod your
application module without insmoding rtai_math.ko. You will then be able to 
see, just by
using dmesg, the missing functions, if any, that will be provided by 
rtai_math.ko.

"Most of the functions" (RTAI) is vague, but so is "aside from some IEEE 
elementary functions" (musl developers.)

According to this page:

https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

GCC takes care of the following math functions actually used in LinuxCNC's RT 
code:

acos (ISO C90 built-in)
atan2 (ISO C90 built-in)
sqrt (ISO C90 built-in)
ceil (ISO C90 built-in)
floor (ISO C90 built-in)

Here is the interesting part:

In the GCC doc in the link above, it says both sin and cos are _also_ ISO C90 
built-ins however sincos (sincos, all one word) becomes undefined symbol in 
several LinuxCNC drivers when sin and cos are both switched to built-ins (like 
the other ones in the patch above) in src/rtapi/rtapi_math.h

The problem might be related to these:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40393
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46926

I'm not sure how to fix this, I haven't played with LinuxCNC's CFLAGS much, 
perhaps someone can chime in and hopefully provide some insight.

In any case, just to make sure the functions that have been switched to 
built-ins in this example still work, how much effort would it be to test this 
change and make sure things like acos, atan2, sqrt, ceil and floor are in fact 
working the way they should?

With proper implementation, we could move away from depending on rtai_math.ko 
at all (at least according to the GCC docs and the documentation written by the 
RTAI developers) making all of this a non-issue.

Open to any thoughts, opinions, and advice. Anything at all to try, I'm all 
ears!

Thank you so much!

Alec


_______________________________________________
Emc-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/emc-developers

Reply via email to