[PATCH] Check for NEON using a signal handler to catch SIGILL

Mike McCormack mj.mccormack at samsung.com
Wed Dec 8 20:31:41 PST 2010


---
 pixman/pixman-cpu.c |   87 ++++++++++++++++++++++++---------------------------
 1 files changed, 41 insertions(+), 46 deletions(-)

diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c
index e4fb1e4..8e0dd15 100644
--- a/pixman/pixman-cpu.c
+++ b/pixman/pixman-cpu.c
@@ -246,60 +246,55 @@ pixman_have_arm_neon (void)
 
 #else /* linux ELF */
 
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <string.h>
-#include <elf.h>
+#include <signal.h>
+#include <setjmp.h>
 
-static pixman_bool_t arm_has_v7 = FALSE;
 static pixman_bool_t arm_has_v6 = FALSE;
-static pixman_bool_t arm_has_vfp = FALSE;
 static pixman_bool_t arm_has_neon = FALSE;
-static pixman_bool_t arm_has_iwmmxt = FALSE;
 static pixman_bool_t arm_tests_initialized = FALSE;
 
+static sigjmp_buf cpu_jmpbuf;
+
 static void
-pixman_arm_read_auxv ()
+pixman_catch_sigill(int sig)
 {
-    int fd;
-    Elf32_auxv_t aux;
+    siglongjmp(cpu_jmpbuf, 1);
+}
+
+static void
+pixman_arm_check_neon (void)
+{
+    struct sigaction sa, old_sa;
 
-    fd = open ("/proc/self/auxv", O_RDONLY);
-    if (fd >= 0)
+    /* setup the sigaction */
+    sa.sa_handler = pixman_catch_sigill;
+    sa.sa_flags = SA_RESTART;
+    sigemptyset(&sa.sa_mask);
+    sigaction(SIGILL, &sa, &old_sa);
+
+#if defined(USE_ARM_NEON)
+    if (!sigsetjmp(cpu_jmpbuf, 1))
     {
-	while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
-	{
-	    if (aux.a_type == AT_HWCAP)
-	    {
-		uint32_t hwcap = aux.a_un.a_val;
-		/* hardcode these values to avoid depending on specific
-		 * versions of the hwcap header, e.g. HWCAP_NEON
-		 */
-		arm_has_vfp = (hwcap & 64) != 0;
-		arm_has_iwmmxt = (hwcap & 512) != 0;
-		/* this flag is only present on kernel 2.6.29 */
-		arm_has_neon = (hwcap & 4096) != 0;
-	    }
-	    else if (aux.a_type == AT_PLATFORM)
-	    {
-		const char *plat = (const char*) aux.a_un.a_val;
-		if (strncmp (plat, "v7l", 3) == 0)
-		{
-		    arm_has_v7 = TRUE;
-		    arm_has_v6 = TRUE;
-		}
-		else if (strncmp (plat, "v6l", 3) == 0)
-		{
-		    arm_has_v6 = TRUE;
-		}
-	    }
-	}
-	close (fd);
+        asm volatile (
+		".fpu neon\n"
+		"\tvqadd.u8 d0, d1, d0\n"
+	);
+        arm_has_neon = TRUE;
     }
+#endif
+
+#if defined(USE_ARM_SIMD)
+    if (!sigsetjmp(cpu_jmpbuf, 1))
+    {
+	asm volatile (
+		".arch armv6\n"
+		"\tuqadd8 r1, r1, r2\n"
+		 : : :"r1", "r2");
+	arm_has_v6 = TRUE;
+    }
+#endif
+
+    sigaction(SIGILL, &old_sa, NULL);
 
     arm_tests_initialized = TRUE;
 }
@@ -309,7 +304,7 @@ pixman_bool_t
 pixman_have_arm_simd (void)
 {
     if (!arm_tests_initialized)
-	pixman_arm_read_auxv ();
+	pixman_arm_check_neon ();
 
     return arm_has_v6;
 }
@@ -321,7 +316,7 @@ pixman_bool_t
 pixman_have_arm_neon (void)
 {
     if (!arm_tests_initialized)
-	pixman_arm_read_auxv ();
+	pixman_arm_check_neon ();
 
     return arm_has_neon;
 }
-- 
1.7.0.4


--Boundary_(ID_sf2VkKyGRW0LeIkqox76Ag)--



More information about the Pixman mailing list