sl@0: /* sl@0: * LIBOIL - Library of Optimized Inner Loops sl@0: * Copyright (c) 2003,2004 David A. Schleef sl@0: * All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * 1. Redistributions of source code must retain the above copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in the sl@0: * documentation and/or other materials provided with the distribution. sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR sl@0: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED sl@0: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE sl@0: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, sl@0: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES sl@0: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR sl@0: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, sl@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING sl@0: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE sl@0: * POSSIBILITY OF SUCH DAMAGE. sl@0: */ sl@0: sl@0: //Portions Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. sl@0: sl@0: sl@0: #ifdef HAVE_CONFIG_H sl@0: #include "config.h" sl@0: #endif sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #ifndef __SYMBIAN32__ sl@0: #ifndef _WIN32 sl@0: #include sl@0: #endif sl@0: #endif sl@0: sl@0: static jmp_buf jump_env; sl@0: #ifdef HAVE_SIGACTION sl@0: static struct sigaction action; sl@0: static struct sigaction oldaction; sl@0: #else sl@0: static void * oldhandler; sl@0: #endif sl@0: static int in_try_block; sl@0: static int enable_level; sl@0: sl@0: #ifdef __SYMBIAN32__ sl@0: #ifdef __WINSCW__ sl@0: #pragma warn_unusedarg off sl@0: #endif//__WINSCW__ sl@0: #endif//__SYMBIAN32__ sl@0: sl@0: #if 0 sl@0: #ifndef _WIN32 sl@0: static LONG __stdcall sl@0: illegal_instruction_handler (EXCEPTION_POINTERS *e) sl@0: { sl@0: if (in_try_block) { sl@0: /* according to the laws of win32, this isn't allowed. sl@0: * It does, however, work. */ sl@0: longjmp (jump_env, 1); sl@0: } sl@0: /* kill the process */ sl@0: return EXCEPTION_EXECUTE_HANDLER; sl@0: } sl@0: #endif sl@0: #endif sl@0: //#else sl@0: static void sl@0: illegal_instruction_handler (int num) sl@0: { sl@0: if (in_try_block) { sl@0: #ifdef HAVE_SIGPROCMASK sl@0: sigset_t set; sl@0: sigemptyset (&set); sl@0: sigaddset (&set, SIGILL); sl@0: sigprocmask (SIG_UNBLOCK, &set, NULL); sl@0: longjmp (jump_env, 1); sl@0: } else { sl@0: abort (); sl@0: #endif sl@0: } sl@0: } sl@0: sl@0: /** sl@0: * oil_fault_check_enable: sl@0: * sl@0: * Enables fault checking mode. This function may be called multiple times. sl@0: * Each call to this function must be paired with a corresponding call sl@0: * to oil_fault_check_disable(). sl@0: * sl@0: * This function sets a signal handler for SIGILL. sl@0: */ sl@0: #ifdef __SYMBIAN32__ sl@0: EXPORT_C sl@0: #endif sl@0: void sl@0: oil_fault_check_enable (void) sl@0: { sl@0: #ifndef __SYMBIAN32__ sl@0: if (enable_level == 0) { sl@0: sl@0: sl@0: #ifndef _WIN32 sl@0: #ifdef HAVE_SIGACTION sl@0: memset (&action, 0, sizeof(action)); sl@0: action.sa_handler = &illegal_instruction_handler; sl@0: sigaction (SIGILL, &action, &oldaction); sl@0: #else sl@0: oldhandler = signal (SIGILL, illegal_instruction_handler); sl@0: #endif sl@0: #else sl@0: oldhandler = SetUnhandledExceptionFilter(illegal_instruction_handler); sl@0: #endif sl@0: sl@0: in_try_block = 0; sl@0: OIL_INFO("enabling SIGILL handler. Make sure to continue past " sl@0: "any SIGILL signals caught by gdb."); sl@0: } sl@0: enable_level++; sl@0: #endif sl@0: } sl@0: sl@0: /** sl@0: * oil_fault_check_try: sl@0: * @func: the function to attempt sl@0: * @priv: a value to pass to the function sl@0: * sl@0: * Calls to this sl@0: * function must be preceded by a call to oil_fault_check_enable() sl@0: * to enable fault checking mode. This function sets up recovery sl@0: * information and then calls the function @func with the parameter sl@0: * @priv. If @func or any other functions it calls attempt to execute sl@0: * an illegal instruction, the exception will be caught and recovered from. sl@0: * sl@0: * Returns: 1 if the function was executed sucessfully, 0 if the sl@0: * function attempted to execute an illegal instruction. sl@0: */ sl@0: #ifdef __SYMBIAN32__ sl@0: EXPORT_C sl@0: #endif sl@0: int sl@0: oil_fault_check_try (void (*func) (void *), void *priv) sl@0: { sl@0: int ret; sl@0: sl@0: in_try_block = 1; sl@0: ret = setjmp (jump_env); sl@0: if (!ret) { sl@0: func (priv); sl@0: } sl@0: in_try_block = 0; sl@0: sl@0: return (ret == 0); sl@0: } sl@0: sl@0: /** sl@0: * oil_fault_check_disable: sl@0: * sl@0: * Disables fault checking mode. See oil_fault_check_enable() sl@0: * for details. sl@0: */ sl@0: #ifdef __SYMBIAN32__ sl@0: EXPORT_C sl@0: #endif sl@0: void sl@0: oil_fault_check_disable (void) sl@0: { sl@0: #ifndef __SYMBIAN32__ sl@0: enable_level--; sl@0: sl@0: if (enable_level == 0) { sl@0: #ifndef _WIN32 sl@0: #ifdef HAVE_SIGACTION sl@0: sigaction (SIGILL, &oldaction, NULL); sl@0: #else sl@0: signal (SIGILL, oldhandler); sl@0: #endif sl@0: #else sl@0: SetUnhandledExceptionFilter(oldhandler); sl@0: #endif sl@0: OIL_INFO("disabling SIGILL handler"); sl@0: } sl@0: #endif sl@0: } sl@0: