diff --git a/mps/code/fri4gc.gmk b/mps/code/fri4gc.gmk index 1184a0bc4f4..3bc48a35a79 100644 --- a/mps/code/fri4gc.gmk +++ b/mps/code/fri4gc.gmk @@ -1,4 +1,4 @@ -# fri4gc.gmk: BUILD FOR FreeBSD/INTEL/GCC PLATFORM +# fri4gc.gmk: BUILD FOR FreeBSD/i386/GCC PLATFORM # # $Id$ # Copyright (c) 2001 Ravenbrook Limited. See end of file for license. @@ -7,8 +7,8 @@ PFM = fri4gc PFMDEFS = -D_REENTRANT -MPMPF = lockix.c thfri4.c pthrdext.c vmix.c \ - protix.c protsgix.c prmcan.c ssixi3.c span.c +MPMPF = lockix.c thix.c pthrdext.c vmix.c \ + protix.c protsgix.c prmcan.c prmci3fr.c ssixi3.c span.c SWPF = than.c vmfr.c protsw.c prmcan.c ssan.c LIBS = -lm -pthread diff --git a/mps/code/fri6gc.gmk b/mps/code/fri6gc.gmk new file mode 100644 index 00000000000..291c2e7706b --- /dev/null +++ b/mps/code/fri6gc.gmk @@ -0,0 +1,70 @@ +# fri6gc.gmk: BUILD FOR FreeBSD/amd64/GCC PLATFORM +# +# $Id$ +# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + +PFM = fri6gc + +PFMDEFS = -D_REENTRANT + +MPMPF = lockix.c thix.c pthrdext.c vmix.c \ + protix.c protsgix.c prmcan.c prmci6fr.c ssixi6.c span.c +SWPF = than.c vmfr.c protsw.c prmcan.c ssan.c + +LIBS = -lm -pthread + +include gc.gmk + +CFLAGSCOMPILER := $(subst -pedantic,,$(CFLAGSCOMPILER)) +CFLAGSDEBUG = -g3 +CFLAGSOPT = -O -g3 + +CC = cc + +# Suppress some warnings (SuSE). +# .void: -Wpointer-arith cannot be used because the string.h header does +# arithmetic on void*. +#CFLAGSCOMPILER := $(subst -Wpointer-arith,,$(CFLAGSCOMPILER)) + +include comm.gmk + + +# C. COPYRIGHT AND LICENSE +# +# Copyright (C) 2001-2002 Ravenbrook Limited . +# All rights reserved. This is an open source license. Contact +# Ravenbrook for commercial licensing options. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Redistributions in any form must be accompanied by information on how +# to obtain complete source code for this software and any accompanying +# software that uses this software. The source code must either be +# included in the distribution or be available for no more than the cost +# of distribution plus a nominal fee, and must be freely redistributable +# under reasonable conditions. For an executable file, complete source +# code means the source code for all modules it contains. It does not +# include source code for modules or files that typically accompany the +# major components of the operating system on which the executable file +# runs. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/mpstd.h b/mps/code/mpstd.h index c6343b7db59..3977e63a5af 100644 --- a/mps/code/mpstd.h +++ b/mps/code/mpstd.h @@ -217,8 +217,7 @@ #define MPS_WORD_SHIFT 5 #define MPS_PF_ALIGN 8 /* @@@@ not tested */ -/* GCC 2.95.3, gcc -E -dM - */ +/* GCC 2.95.3, gcc -E -dM */ #elif defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__) #if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI4GC) @@ -235,6 +234,21 @@ #define MPS_WORD_SHIFT 5 #define MPS_PF_ALIGN 4 +#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__) +#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI6GC) +#error "specified CONFIG_PF_... inconsistent with detected fri6gc" +#endif +#define MPS_PF_FRI6GC +#define MPS_PF_STRING "fri6gc" +#define MPS_OS_FR +#define MPS_ARCH_I6 +#define MPS_BUILD_GC +#define MPS_T_WORD unsigned long +#define MPS_T_ULONGEST unsigned long +#define MPS_WORD_WIDTH 64 +#define MPS_WORD_SHIFT 6 +#define MPS_PF_ALIGN 8 + #else #error "Unable to detect target platform" #endif diff --git a/mps/code/prmci3fr.c b/mps/code/prmci3fr.c new file mode 100644 index 00000000000..6dbe5de09ae --- /dev/null +++ b/mps/code/prmci3fr.c @@ -0,0 +1,93 @@ +/* prmci3fr.c: PROTECTION MUTATOR CONTEXT INTEL 386 (FREEBSD) + * + * $Id$ + * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * + * .purpose: This module implements the part of the protection module + * that decodes the MutatorFaultContext. + * + * + * SOURCES + * + * .source.i486: Intel486 Microprocessor Family Programmer's + * Reference Manual + * + * + * ASSUMPTIONS + * + * .sp: The stack pointer in the context is ESP (x86) or RSP (x86_64). + * + * .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX (or + * their x86_64 equivalents) are assumed to be recorded in the context at + * pointer-aligned boundaries. + */ + +#include "prmcix.h" +#include "prmci3.h" + +SRCID(prmci3fr, "$Id$"); + + +Addr MutatorFaultContextSP(MutatorFaultContext mfc) +{ + return (Addr)mfc->ucontext->uc_mcontext.mc_esp; /* .sp */ +} + + +Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) +{ + Res res; + + /* This scans the root registers (.context.regroots). It also unnecessarily + scans the rest of the context. The optimisation to scan only relevant + parts would be machine dependent. */ + res = TraceScanAreaTagged( + ss, + (Addr *)mfc->ucontext, + (Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))) + ); + + return res; +} + + +/* C. COPYRIGHT AND LICENSE + * + * Copyright (C) 2001-2002 Ravenbrook Limited . + * All rights reserved. This is an open source license. Contact + * Ravenbrook for commercial licensing options. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Redistributions in any form must be accompanied by information on how + * to obtain complete source code for this software and any accompanying + * software that uses this software. The source code must either be + * included in the distribution or be available for no more than the cost + * of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source + * code means the source code for all modules it contains. It does not + * include source code for modules or files that typically accompany the + * major components of the operating system on which the executable file + * runs. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/mps/code/prmci6fr.c b/mps/code/prmci6fr.c new file mode 100644 index 00000000000..811d2c8f99d --- /dev/null +++ b/mps/code/prmci6fr.c @@ -0,0 +1,87 @@ +/* prmci6li.c: PROTECTION MUTATOR CONTEXT x64 (FREEBSD) + * + * $Id$ + * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * + * .purpose: This module implements the part of the protection module + * that decodes the MutatorFaultContext. + * + * + * ASSUMPTIONS + * + * .sp: The stack pointer in the context is ESP (x86) or RSP (x86_64). + * + * .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX (or + * their x86_64 equivalents) are assumed to be recorded in the context at + * pointer-aligned boundaries. + */ + +#include "prmcix.h" +#include "prmci6.h" + +SRCID(prmci6fr, "$Id$"); + + +Addr MutatorFaultContextSP(MutatorFaultContext mfc) +{ + return (Addr)mfc->ucontext->uc_mcontext.mc_rsp; /* .sp */ +} + + +Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) +{ + Res res; + + /* This scans the root registers (.context.regroots). It also unnecessarily + scans the rest of the context. The optimisation to scan only relevant + parts would be machine dependent. */ + res = TraceScanAreaTagged( + ss, + (Addr *)mfc->ucontext, + (Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))) + ); + + return res; +} + + +/* C. COPYRIGHT AND LICENSE + * + * Copyright (C) 2001-2002 Ravenbrook Limited . + * All rights reserved. This is an open source license. Contact + * Ravenbrook for commercial licensing options. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Redistributions in any form must be accompanied by information on how + * to obtain complete source code for this software and any accompanying + * software that uses this software. The source code must either be + * included in the distribution or be available for no more than the cost + * of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source + * code means the source code for all modules it contains. It does not + * include source code for modules or files that typically accompany the + * major components of the operating system on which the executable file + * runs. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/mps/code/thfri4.c b/mps/code/thfri4.c deleted file mode 100644 index 8e109d2b788..00000000000 --- a/mps/code/thfri4.c +++ /dev/null @@ -1,345 +0,0 @@ -/* thfri3.c: Threads Manager for Intel x86 systems on FreeBSD - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This is a pthreads implementation of the threads manager. - * This implements . - * - * .design: See . - * - * .thread.id: The thread id is used to identify the current thread. - * - * ASSUMPTIONS - * - * .error.resume: PThreadextResume is assumed to succeed unless the thread - * has been destroyed. - * .error.suspend: PThreadextSuspend is assumed to succeed unless the thread - * has been destroyed. In this case, the suspend context is set to NULL; - * - * .stack.full-descend: assumes full descending stack. - * i.e. stack pointer points to the last allocated location; - * stack grows downwards. - * - * .stack.below-bottom: it's legal for the stack pointer to be at a - * higher address than the registered bottom of stack. This might - * happen if the stack of another thread doesn't contain any frames - * belonging to the client language. In this case, the stack should - * not be scanned. - * - * .stack.align: assume roots on the stack are always word-aligned, - * but don't assume that the stack pointer is necessarily - * word-aligned at the time of reading the context of another thread. - * - * .sp: The stack pointer in the context is ESP. - * .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX are - * assumed to be recorded in the context at pointer-aligned boundaries. - */ - -#include "prmcix.h" -#include "mpm.h" - -#if !defined(MPS_OS_FR) || !defined(MPS_ARCH_I4) -#error "Compiling thfri4 when MPS_OS_FR or MPS_ARCH_I4 not defined." -#endif - -#include -#include "pthrdext.h" - -SRCID(thfri4, "$Id$"); - - -/* ThreadStruct -- thread desriptor */ - -typedef struct ThreadStruct { /* PThreads thread structure */ - Sig sig; /* */ - Serial serial; /* from arena->threadSerial */ - Arena arena; /* owning arena */ - RingStruct arenaRing; /* threads attached to arena */ - PThreadextStruct thrextStruct; /* PThreads extension */ - pthread_t id; /* Pthread object of thread */ - MutatorFaultContext mfc; /* Context if thread is suspended */ -} ThreadStruct; - - -/* ThreadCheck -- check a thread */ - -Bool ThreadCheck(Thread thread) -{ - CHECKS(Thread, thread); - CHECKU(Arena, thread->arena); - CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); - CHECKD(PThreadext, &thread->thrextStruct); - return TRUE; -} - -Bool ThreadCheckSimple(Thread thread) -{ - CHECKS(Thread, thread); - return TRUE; -} - - -/* ThreadRegister -- register a thread with an arena */ - -Res ThreadRegister(Thread *threadReturn, Arena arena) -{ - Res res; - Thread thread; - void *p; - - AVER(threadReturn != NULL); - AVERT(Arena, arena); - - res = ControlAlloc(&p, arena, sizeof(ThreadStruct), - /* withReservoirPermit */ FALSE); - if(res != ResOK) - return res; - thread = (Thread)p; - - thread->id = pthread_self(); - - RingInit(&thread->arenaRing); - - thread->sig = ThreadSig; - thread->serial = arena->threadSerial; - ++arena->threadSerial; - thread->arena = arena; - thread->mfc = NULL; - - PThreadextInit(&thread->thrextStruct, thread->id); - - AVERT(Thread, thread); - - RingAppend(ArenaThreadRing(arena), &thread->arenaRing); - - *threadReturn = thread; - return ResOK; -} - - -/* ThreadDeregister -- deregister a thread from an arena */ - -void ThreadDeregister(Thread thread, Arena arena) -{ - AVERT(Thread, thread); - AVERT(Arena, arena); - - RingRemove(&thread->arenaRing); - - thread->sig = SigInvalid; - - RingFinish(&thread->arenaRing); - - PThreadextFinish(&thread->thrextStruct); - - ControlFree(arena, thread, sizeof(ThreadStruct)); -} - - -/* mapThreadRing -- map over threads on ring calling a function on each one - * except the current thread - */ - -static void mapThreadRing(Ring threadRing, void (*func)(Thread)) -{ - Ring node, next; - pthread_t self; - - AVERT(Ring, threadRing); - - self = pthread_self(); - RING_FOR(node, threadRing, next) { - Thread thread = RING_ELT(Thread, arenaRing, node); - AVERT(Thread, thread); - if(! pthread_equal(self, thread->id)) /* .thread.id */ - (*func)(thread); - } -} - - -/* ThreadRingSuspend -- suspend all threads on a ring, expect the current one */ - - -static void threadSuspend(Thread thread) -{ - /* .error.suspend */ - /* In the error case (PThreadextSuspend returning ResFAIL), we */ - /* assume the thread has been destroyed. */ - /* In which case we simply continue. */ - Res res; - res = PThreadextSuspend(&thread->thrextStruct, &thread->mfc); - if(res != ResOK) - thread->mfc = NULL; -} - - - -void ThreadRingSuspend(Ring threadRing) -{ - mapThreadRing(threadRing, threadSuspend); -} - - -/* ThreadRingResume -- resume all threads on a ring (expect the current one) */ - - -static void threadResume(Thread thread) -{ - /* .error.resume */ - /* If the previous suspend failed (thread->mfc == NULL), */ - /* or in the error case (PThreadextResume returning ResFAIL), */ - /* assume the thread has been destroyed. */ - /* In which case we simply continue. */ - if(thread->mfc != NULL) { - (void)PThreadextResume(&thread->thrextStruct); - thread->mfc = NULL; - } -} - -void ThreadRingResume(Ring threadRing) -{ - mapThreadRing(threadRing, threadResume); -} - - -/* ThreadRingThread -- return the thread at the given ring element */ - -Thread ThreadRingThread(Ring threadRing) -{ - Thread thread; - AVERT(Ring, threadRing); - thread = RING_ELT(Thread, arenaRing, threadRing); - AVERT(Thread, thread); - return thread; -} - - -/* ThreadArena -- get the arena of a thread - * - * Must be thread-safe. See . - */ - -Arena ThreadArena(Thread thread) -{ - /* Can't check thread as that would not be thread-safe. */ - return thread->arena; -} - - -/* ThreadScan -- scan the state of a thread (stack and regs) */ - -Res ThreadScan(ScanState ss, Thread thread, void *stackBot) -{ - pthread_t self; - Res res; - - AVERT(Thread, thread); - self = pthread_self(); - if(pthread_equal(self, thread->id)) { - /* scan this thread's stack */ - res = StackScan(ss, stackBot); - if(res != ResOK) - return res; - } else { - MutatorFaultContext mfc; - Addr *stackBase, *stackLimit, stackPtr; - - mfc = thread->mfc; - if(mfc == NULL) { - /* .error.suspend */ - /* We assume that the thread must have been destroyed. */ - /* We ignore the situation by returning immediately. */ - return ResOK; - } - - stackPtr = (Addr)mfc->ucontext->uc_mcontext.mc_esp; /* .i3.sp */ - /* .stack.align */ - stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); - stackLimit = (Addr *)stackBot; - if (stackBase >= stackLimit) - return ResOK; /* .stack.below-bottom */ - - /* scan stack inclusive of current sp and exclusive of - * stackBot (.stack.full-descend) - */ - res = TraceScanAreaTagged(ss, stackBase, stackLimit); - if(res != ResOK) - return res; - - /* (.context.regroots) - * This scans the root registers (.context.regroots). It also - * unecessarily scans the rest of the context. The optimisation - * to scan only relevent parts would be machine dependent. - */ - res = TraceScanAreaTagged(ss, (Addr *)mfc->ucontext, - (Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext)))); - if(res != ResOK) - return res; - } - - return ResOK; -} - - -/* ThreadDescribe -- describe a thread */ - -Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) -{ - Res res; - - res = WriteF(stream, - "Thread $P ($U) {\n", (WriteFP)thread, (WriteFU)thread->serial, - " arena $P ($U)\n", - (WriteFP)thread->arena, (WriteFU)thread->arena->serial, - " id $U\n", (WriteFU)thread->id, - "} Thread $P ($U)\n", (WriteFP)thread, (WriteFU)thread->serial, - NULL); - if(res != ResOK) - return res; - - return ResOK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */