我有一个在ARM Cortex A57(ARMv8)上的RT_PREEMPT linux上运行的多线程用户空间应用程序。 linux版本是4.14.0,带有相应的RT_PREEMPT补丁。以下代码是重新创建问题的简化版本。当使用优化级别-O1和更高的级别编译代码时,一段时间后错误就消失了,第24行的fl_val中有随机值(thr_fn中的乘积结果)。查看编译的汇编代码并通过gdb后,请注意,在第21行循环开始之前,将0.002的值加载到浮点寄存器(s8)中。然后,将s8寄存器的值与在第24行存储frand值的寄存器相乘。在随机时间,s8中的值具有垃圾值,并且进程按预期中止。看起来,在内核上下文切换期间,它没有正确地重新存储浮点寄存器的值。在相同硬件的相同版本的非RT内核上,相同的代码可以正常工作而没有任何错误。
我的问题
1)我应该在RT_PREEMPT内核中设置与浮点相关的内核设置吗?我已将eagerfpu = on设置为默认值(即使默认情况下处于启用状态)
2)正在阅读有关Cortex-M4的“延迟堆叠”,但不确定是否适用于Cortex A57
任何评论将不胜感激。
-------测试代码--------------------------
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdint>
4 #include <ctime>
5 #include <random>
6 #include <pthread.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <signal.h>
11
12 #define MAX_THR 30
13
14 typedef float float32_t;
15 int32_t gflag = 0;
16
17 void *thr_fn(void *arg) {
18 //pthread_t cur_tid = pthread_self();
19 std::random_device rd; // non-deterministic generator
20 std::mt19937 gen(rd());
21 while (1) {
22 uint32_t rand_num = gen() % 1000;
23 float32_t frand = static_cast<float32_t>(rand_num);
24 float32_t fl_val = (frand * 0.002F);
25 if ((fl_val < 0.0F) || (fl_val > 2.0F)) {
26 gflag = -1;
27 // Keep sleeping till the process gets aborted by the main thread
28 while(1){usleep(2000);}
29 }
30 usleep(1000);
31 }
32 }
33
34 int main() {
35 int thr_cnt;
36 int res = 0;
37 pthread_t tid;
38 for (thr_cnt = 0; thr_cnt < MAX_THR; thr_cnt++) {
39 res = pthread_create(&tid, NULL, thr_fn, NULL);
40 if (res != 0) {
41 std::cout <<"Error creating pthread: " <<strerror(errno);
42 }
43 }
44 while(1){
45 if (gflag != 0) {
46 kill(getpid(), SIGABRT);
47 }
48 usleep(1000 * 1000 * 1);
49 }
50 return (0);
51 }