summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2005-02-02 01:01:49 +0000
committerDavid Schleef <ds@schleef.org>2005-02-02 01:01:49 +0000
commit6420cbe9eaa99050266e99ce7c670f2b44c97bfd (patch)
tree9fd11c08b9051a073362d25ddaa9d0721ea680ad
parentea487b28c0f206723c3bb89dece59c1fc1fd0796 (diff)
downloadliboil-6420cbe9eaa99050266e99ce7c670f2b44c97bfd.tar.gz
* liboil/liboilcpu.c: (test_altivec), (oil_cpu_powerpc_getflags),
(illegal_instruction_handler), (oil_cpu_fault_check_enable), (oil_cpu_fault_check_try), (oil_cpu_fault_check_disable): Add illegal instruction checking. * liboil/liboilcpu.h: * liboil/liboilfunction.c: (oil_init): * liboil/liboiltest.c: (oil_test_check_function), (oil_test_check_impl):
-rw-r--r--ChangeLog11
-rw-r--r--liboil/liboilcpu.c83
-rw-r--r--liboil/liboilcpu.h5
-rw-r--r--liboil/liboilfunction.c3
-rw-r--r--liboil/liboiltest.c16
5 files changed, 85 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 6612664..93b044c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2005-02-01 David Schleef <ds@schleef.org>
+
+ * liboil/liboilcpu.c: (test_altivec), (oil_cpu_powerpc_getflags),
+ (illegal_instruction_handler), (oil_cpu_fault_check_enable),
+ (oil_cpu_fault_check_try), (oil_cpu_fault_check_disable): Add
+ illegal instruction checking.
+ * liboil/liboilcpu.h:
+ * liboil/liboilfunction.c: (oil_init):
+ * liboil/liboiltest.c: (oil_test_check_function),
+ (oil_test_check_impl):
+
2005-01-31 David Schleef <ds@schleef.org>
* doc/Makefile.am: Stop abusing _LDFLAGS
diff --git a/liboil/liboilcpu.c b/liboil/liboilcpu.c
index 993db6a..5ff2fa1 100644
--- a/liboil/liboilcpu.c
+++ b/liboil/liboilcpu.c
@@ -36,10 +36,8 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-#if defined(__powerpc__)
#include <setjmp.h>
#include <signal.h>
-#endif
#if defined(__i386__)
static char * get_cpuinfo_flags_string (char *cpuinfo);
@@ -128,46 +126,26 @@ oil_cpu_i386_getflags(void)
#endif
#ifdef __powerpc__
-static jmp_buf jump_env;
-
-static int
-test_altivec (void)
+static void
+test_altivec (void *)
{
- int ret;
char x[16] = { 0, };
- ret = setjmp (jump_env);
- if (!ret) {
- asm volatile (
- " lvx %%v0, %0, %%r0 \n"
- :: "r" (x));
- }
-
- return (ret==0);
-}
-
-static void
-illegal_instruction_handler (int num)
-{
- longjmp (jump_env, 1);
+ asm volatile (
+ " lvx %%v0, %0, %%r0 \n"
+ :: "r" (x));
}
static void
oil_cpu_powerpc_getflags(void)
{
- struct sigaction act;
- struct sigaction oldact;
- memset (&act, 0, sizeof(act));
- act.sa_handler = &illegal_instruction_handler;
- sigaction (SIGILL, &act, &oldact);
-
- if (test_altivec()) {
+ oil_cpu_fault_check_enable ();
+ if (oil_cpu_fault_check_try(test_altivec, NULL)) {
OIL_DEBUG ("cpu flag altivec");
oil_cpu_flags |= OIL_IMPL_FLAG_ALTIVEC;
}
-
- sigaction (SIGILL, &oldact, NULL);
+ oil_cpu_fault_check_disable ();
}
#endif
@@ -263,3 +241,48 @@ _strndup (const char *s, int n)
}
#endif
+static jmp_buf jump_env;
+static struct sigaction action;
+static struct sigaction oldaction;
+static int in_try_block;
+
+static void
+illegal_instruction_handler (int num)
+{
+ if (in_try_block) {
+ longjmp (jump_env, 1);
+ } else {
+ abort ();
+ }
+}
+
+void
+oil_cpu_fault_check_enable (void)
+{
+ memset (&action, 0, sizeof(action));
+ action.sa_handler = &illegal_instruction_handler;
+ sigaction (SIGILL, &action, &oldaction);
+ in_try_block = 0;
+}
+
+int
+oil_cpu_fault_check_try (void (*func) (void *), void *priv)
+{
+ int ret;
+
+ in_try_block = 1;
+ ret = setjmp (jump_env);
+ if (!ret) {
+ func (priv);
+ }
+ in_try_block = 0;
+
+ return (ret == 0);
+}
+
+void
+oil_cpu_fault_check_disable (void)
+{
+ sigaction (SIGILL, &oldaction, NULL);
+}
+
diff --git a/liboil/liboilcpu.h b/liboil/liboilcpu.h
index c6245d6..c15a509 100644
--- a/liboil/liboilcpu.h
+++ b/liboil/liboilcpu.h
@@ -31,5 +31,10 @@
void _oil_cpu_init (void);
unsigned int oil_cpu_get_flags (void);
+void oil_cpu_fault_check_enable (void);
+void oil_cpu_fault_check_disable (void);
+
+int oil_cpu_fault_check_try (void (*func)(void *), void *priv);
+
#endif
diff --git a/liboil/liboilfunction.c b/liboil/liboilfunction.c
index b72b12f..9181816 100644
--- a/liboil/liboilfunction.c
+++ b/liboil/liboilfunction.c
@@ -68,7 +68,10 @@ oil_init (void)
_oil_cpu_init ();
oil_init_pointers ();
oil_init_structs ();
+
+ oil_cpu_fault_check_enable ();
oil_optimize_all ();
+ oil_cpu_fault_check_disable ();
stop = oil_profile_stamp_gtod ();
diff --git a/liboil/liboiltest.c b/liboil/liboiltest.c
index 638680c..7041b36 100644
--- a/liboil/liboiltest.c
+++ b/liboil/liboiltest.c
@@ -33,6 +33,7 @@
#include <liboil/liboildebug.h>
#include <liboil/liboilrandom.h>
#include <liboil/liboilprofile.h>
+#include <liboil/liboilcpu.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -121,8 +122,9 @@ oil_test_set_iterations (OilTest *test, int iterations)
}
static void
-oil_test_check_function (OilTest *test)
+oil_test_check_function (void * priv)
{
+ OilTest *test = priv;
int i;
int j;
unsigned long args[10];
@@ -140,7 +142,7 @@ oil_test_check_function (OilTest *test)
}
}
- OIL_LOG("calling reference function %s", test->impl->name);
+ OIL_LOG("calling function %s", test->impl->name);
pointer_mask = 1;
for(i=0;i<test->proto->n_params;i++){
@@ -222,6 +224,7 @@ oil_test_check_impl (OilTest *test, OilFunctionImpl *impl)
int i;
int n;
int fail = 0;
+ int ret;
if (test->proto->n_params > 10) {
OIL_ERROR ("function has too many parameters");
@@ -233,7 +236,14 @@ oil_test_check_impl (OilTest *test, OilFunctionImpl *impl)
}
test->impl = impl;
- oil_test_check_function (test);
+ ret = oil_cpu_fault_check_try (oil_test_check_function, test);
+ if (!ret) {
+ OIL_ERROR ("illegal instruction in %s", test->impl->name);
+ test->impl->profile_ave = 0;
+ test->impl->profile_std = 0;
+
+ return 0;
+ }
x = 0;
n = 0;