3

我有一个在 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 }
4

0 回答 0