我有一个在 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 的“Lazy Stacking”,但不确定它是否适用于 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 }