从SIMD指令捕获SIGFPE

问题描述:

我试图清除浮点除零标志忽略该异常。我期待与标志设置(没有改变我相信的默认行为,并在下面注释),我的错误处理程序将触发。然而,_mm_div_ss似乎没有提高SIGFPE。有任何想法吗?从上面的代码从SIMD指令捕获SIGFPE

#include <stdio.h> 
#include <signal.h> 
#include <string.h> 
#include <xmmintrin.h> 

static void sigaction_sfpe(int signal, siginfo_t *si, void *arg) 
{ 
    printf("inside SIGFPE handler\nexit now."); 
    exit(1); 
} 

int main() 
{ 
    struct sigaction sa; 

    memset(&sa, 0, sizeof(sa)); 
    sigemptyset(&sa.sa_mask); 
    sa.sa_sigaction = sigaction_sfpe; 
    sa.sa_flags = SA_SIGINFO; 
    sigaction(SIGFPE, &sa, NULL); 

    //_mm_setcsr(0x00001D80); // catch all FPE except divide by zero 

    __m128 s1, s2; 
    s1 = _mm_set_ps(1.0, 1.0, 1.0, 1.0); 
    s2 = _mm_set_ps(0.0, 0.0, 0.0, 0.0); 
    _mm_div_ss(s1, s2); 

    printf("done (no error).\n"); 

    return 0; 
} 

输出:

$ gcc a.c 
$ ./a.out 
done (no error). 

正如你看到的,我的处理程序是从来没有达到过。附注:我已经尝试了几个不同的编译器标志(-msse3,-march = native),没有任何改变。

GCC(Debian的5.3.1-7)5.3.1 20160121

从/ proc一些信息内/ cpuinfo

model name  : Intel(R) Core(TM) i3 CPU  M 380 @ 2.53GHz 
flags   : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 popcnt lahf_lm arat dtherm tpr_shadow vnmi flexpriority ept vpid 
+1

我认为你必须揭露MXCSR中的相关异常。所有FP异常在默认情况下都被屏蔽。我还没有试过编写一个从FP异常中产生信号的程序,但是如果这个常量是正确的,我会猜测你的'_mm_setcsr'会起作用。对于测试,您可以实际触发x86 Linux上的SIGFPE,除了POSIX所要求的整数除以零。 (http://*.com/questions/37262572/on-which-platforms-does-integer-divide-by-zero-trigger-a-floating-point-exceptio) –

+0

即使有'_mm_setcsr(0x00001F80)'什么也没有发生。你是对的,我可以测试整数除零的SIGFPE,但我试图让MXCSR来控制是否发生这种情况。 – BurnsBA

+0

无法编辑我的评论,但'_mm_setcsr(0x00000000)'具有相同的效果(未引发任何信号)。 – BurnsBA

两件事情。

首先,我误解了文档。例外情况需要被捕获未被掩盖的。调用_mm_setcsr(0x00001D80);将允许SIGFPE在被零除之前触发。

其次,即使使用-O0,gcc也在优化我的除法指令。

鉴于源极线

_mm_div_ss(s1, s2); 

gcc -S -O0 -msse2 a.c编译给出

76  movaps -24(%ebp), %xmm0 
77  movaps %xmm0, -72(%ebp) 
78  movaps -40(%ebp), %xmm0 
79  movaps %xmm0, -88(%ebp) 

a1  subl $12, %esp  ; renumbered to show insertion below 
a2  pushl $.LC2 
a3  call puts 
a4  addl $16, %esp 

虽然源线

s2 = _mm_div_ss(s1, s2); // add "s2 = " 

给出

76  movaps -24(%ebp), %xmm0 
77  movaps %xmm0, -72(%ebp) 
78  movaps -40(%ebp), %xmm0 
79  movaps %xmm0, -88(%ebp) 
     movaps -72(%ebp), %xmm0 
     divss -88(%ebp), %xmm0 
     movaps %xmm0, -40(%ebp) 
a1  subl $12, %esp 
a2  pushl $.LC2 
a3  call puts 
a4  addl $16, %esp 

通过这些更改,SIGFPE处理程序根据MXCSR中的除零标志被调用。