mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
Update the linux threading implementation, this means using the new posix style pthreads, which is much closer to the bsd implementation. prmcfr.h and prmcli.h have now been replaced by prmcix.h. this doesn't quite compile yet.
Copied from Perforce Change: 178790 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
d03df26a42
commit
4a8232b9c9
8 changed files with 78 additions and 204 deletions
|
|
@ -8,7 +8,9 @@ PFM = lii4gc
|
|||
THREADSRC = lockli.c thlii4.c pthrdext.c
|
||||
THREADLIB = -lpthread
|
||||
|
||||
PFMDEFS = -D_REENTRANT
|
||||
# _XOPEN_SOURCE is to get the modern POSIX signal handling
|
||||
# _GNU_SOURCE is to get register numbers in prmci3li.c
|
||||
PFMDEFS = -D_REENTRANT -D_XOPEN_SOURCE=500 -D_GNU_SOURCE
|
||||
|
||||
MPMPF = ${THREADSRC} vmix.c \
|
||||
protix.c protlii3.c proti3.c prmci3li.c ssixi3.c span.c
|
||||
|
|
@ -23,7 +25,7 @@ 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))
|
||||
CFLAGSCOMPILER := -pthread $(subst -Wpointer-arith,,$(CFLAGSCOMPILER))
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@
|
|||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
/* prmcli.h will include mpm.h after defining open sesame magic */
|
||||
#include "prmcli.h"
|
||||
#include "prmcix.h"
|
||||
#include "prmci3.h"
|
||||
|
||||
SRCID(prmci3li, "$Id$");
|
||||
|
|
@ -30,26 +29,26 @@ SRCID(prmci3li, "$Id$");
|
|||
|
||||
/* Prmci3AddressHoldingReg -- return an address of a register in a context */
|
||||
|
||||
MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
|
||||
MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
struct sigcontext *scp;
|
||||
gregset_t *gregs;
|
||||
|
||||
AVER(regnum <= 7);
|
||||
AVER(regnum >= 0);
|
||||
|
||||
scp = context->scp;
|
||||
gregs = &mfc->ucontext->uc_mcontext.gregs;
|
||||
|
||||
/* .source.i486 */
|
||||
/* .assume.regref */
|
||||
switch (regnum) {
|
||||
case 0: return (MRef)&scp->eax;
|
||||
case 1: return (MRef)&scp->ecx;
|
||||
case 2: return (MRef)&scp->edx;
|
||||
case 3: return (MRef)&scp->ebx;
|
||||
case 4: return (MRef)&scp->esp;
|
||||
case 5: return (MRef)&scp->ebp;
|
||||
case 6: return (MRef)&scp->esi;
|
||||
case 7: return (MRef)&scp->edi;
|
||||
case 0: return (MRef)&gregs[REG_EAX];
|
||||
case 1: return (MRef)&gregs[REG_ECX];
|
||||
case 2: return (MRef)&gregs[REG_EDX];
|
||||
case 3: return (MRef)&gregs[REG_EBX];
|
||||
case 4: return (MRef)&gregs[REG_ESP];
|
||||
case 5: return (MRef)&gregs[REG_EBP];
|
||||
case 6: return (MRef)&gregs[REG_ESI];
|
||||
case 7: return (MRef)&gregs[REG_EDI];
|
||||
}
|
||||
NOTREACHED;
|
||||
return (MRef)NULL; /* Avoids compiler warning. */
|
||||
|
|
@ -60,29 +59,19 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
|
|||
|
||||
void Prmci3DecodeFaultContext(MRef *faultmemReturn,
|
||||
Byte **insvecReturn,
|
||||
MutatorFaultContext context)
|
||||
MutatorFaultContext mfc)
|
||||
{
|
||||
struct sigcontext *scp;
|
||||
|
||||
scp = context->scp;
|
||||
|
||||
/* Assert that this is a page fault exception. The computation of */
|
||||
/* faultmem depends on this. See .source.i486 (9.9.14). */
|
||||
AVER(scp->trapno == 14);
|
||||
|
||||
/* cr2 contains the address which caused the fault. */
|
||||
/* See .source.i486 (9.9.14) and */
|
||||
/* .source.linux.kernel (linux/arch/i386/mm/fault.c). */
|
||||
*faultmemReturn = (MRef)scp->cr2;
|
||||
*insvecReturn = (Byte*)scp->eip;
|
||||
*faultmemReturn = (MRef)mfc->info->si_addr;
|
||||
*insvecReturn = (Byte*)mfc->ucontext->uc_mcontext.gregs[REG_EIP];
|
||||
}
|
||||
|
||||
|
||||
/* Prmci3StepOverIns -- modify context to step over instruction */
|
||||
|
||||
void Prmci3StepOverIns(MutatorFaultContext context, Size inslen)
|
||||
void Prmci3StepOverIns(MutatorFaultContext mfc, Size inslen)
|
||||
{
|
||||
context->scp->eip += (unsigned long)inslen;
|
||||
mfc->ucontext->uc_mcontext.gregs[REG_EIP] += (unsigned long)inslen;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* prmcfr.h: PROTECTION MUTATOR CONTEXT (FREEBSD)
|
||||
/* prmcix.h: PROTECTION MUTATOR CONTEXT (UNIX)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
|
|
@ -6,19 +6,20 @@
|
|||
* .readership: MPS developers.
|
||||
*/
|
||||
|
||||
#ifndef prmcfr_h
|
||||
#define prmcfr_h
|
||||
#ifndef prmcix_h
|
||||
#define prmcix_h
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
#include <ucontext.h>
|
||||
|
||||
typedef struct MutatorFaultContextStruct { /* Protection fault context data */
|
||||
siginfo_t *info;
|
||||
ucontext_t *ucontext;
|
||||
} MutatorFaultContextStruct;
|
||||
|
||||
|
||||
#endif /* prmcfr_h */
|
||||
#endif /* prmcix_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/* prmcli.h: PROTECTION MUTATOR CONTEXT (Linux)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .readership: MPS developers.
|
||||
*/
|
||||
|
||||
#ifndef prmcli_h
|
||||
#define prmcli_h
|
||||
|
||||
|
||||
/* open sesame magic */
|
||||
#define _BSD_SOURCE 1
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
typedef struct MutatorFaultContextStruct { /* Protection fault context data */
|
||||
struct sigcontext *scp; /* Linux sigcontext */
|
||||
} MutatorFaultContextStruct;
|
||||
|
||||
|
||||
#endif /* prmcli_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* 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.
|
||||
*/
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
* .source.linux.kernel: Linux kernel source files.
|
||||
*/
|
||||
|
||||
#include "prmcli.h"
|
||||
#include "prmcix.h"
|
||||
|
||||
#ifndef MPS_OS_LI
|
||||
#error "protlii3.c is Linux-specific, but MPS_OS_LI is not set"
|
||||
|
|
@ -27,20 +27,11 @@
|
|||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
SRCID(protlii3, "$Id$");
|
||||
|
||||
|
||||
/* Useful stuff that doesn't appear to be in any header files. */
|
||||
|
||||
/* Interrupt number 14 is Page Fault. */
|
||||
#define TRAPNO_PAGE_FAULT 14
|
||||
|
||||
/* Bits in err field of sigcontext for interrupt 14 (page fault) */
|
||||
#define PAGE_FAULT_ERR_PAGEPROT 0x1
|
||||
#define PAGE_FAULT_ERR_WRITE 0x2
|
||||
#define PAGE_FAULT_ERR_USERMODE 0x4
|
||||
|
||||
|
||||
/* The previously-installed signal action, as returned by */
|
||||
/* sigaction(3). See ProtSetup. */
|
||||
|
|
@ -62,39 +53,44 @@ typedef void (*__real_lii3_sighandler_t)(int, struct sigcontext);
|
|||
* then sigHandle does its best to pass the signal on to the
|
||||
* previously installed signal handler (sigNext).
|
||||
*
|
||||
* .sigh.args: There is no officially documented way of getting the
|
||||
* sigcontext, but on x86 Linux at least it is passed BY VALUE as a
|
||||
* second argument to the signal handler. The prototype doesn't
|
||||
* include this arg.
|
||||
* See .source.linux.kernel (linux/arch/i386/kernel/signal.c).
|
||||
*
|
||||
* .sigh.context: We only know how to handle interrupt 14, where
|
||||
* context.err gives the page fault error code and context.cr2 gives
|
||||
* the fault address. See .source.i486 (9.9.14) and
|
||||
* .sigh.context: We check si_code for being a memory access
|
||||
* si_addr gives the fault address. See
|
||||
* .source.linux.kernel (linux/arch/i386/mm/fault.c).
|
||||
*
|
||||
* .sigh.addr: We assume that the OS decodes the address to something
|
||||
* sensible
|
||||
*/
|
||||
/* This is defined here to keep the sources closer to those in protsgix.c
|
||||
* They can't be merged yet because protsgix doesn't pass the context to
|
||||
* ArenaAccess */
|
||||
|
||||
static void sigHandle(int sig, struct sigcontext context) /* .sigh.args */
|
||||
#define PROT_SIGNAL SIGSEGV
|
||||
|
||||
static void sigHandle(int sig, siginfo_t *info, void *context) /* .sigh.args */
|
||||
{
|
||||
AVER(sig == SIGSEGV);
|
||||
int e;
|
||||
/* sigset renamed to asigset due to clash with global on Darwin. */
|
||||
sigset_t asigset, oldset;
|
||||
struct sigaction sa;
|
||||
|
||||
if(context.trapno == TRAPNO_PAGE_FAULT) { /* .sigh.context */
|
||||
AVER(sig == PROT_SIGNAL);
|
||||
|
||||
if(info->si_code == SEGV_ACCERR) { /* .sigh.context */
|
||||
AccessSet mode;
|
||||
Addr base, limit;
|
||||
Addr base;
|
||||
ucontext_t *ucontext;
|
||||
MutatorFaultContextStruct mfContext;
|
||||
|
||||
mfContext.scp = &context;
|
||||
ucontext = (ucontext_t *)context;
|
||||
mfContext.ucontext = ucontext;
|
||||
mfContext.info = info;
|
||||
|
||||
mode = ((context.err & PAGE_FAULT_ERR_WRITE) != 0) /* .sigh.context */
|
||||
? (AccessREAD | AccessWRITE)
|
||||
: AccessREAD;
|
||||
/* on linux we used to be able to tell whether this was a read or a write */
|
||||
mode = AccessREAD | AccessWRITE;
|
||||
|
||||
/* We assume that the access is for one word at the address. */
|
||||
base = (Addr)context.cr2; /* .sigh.addr */
|
||||
limit = AddrAdd(base, (Size)sizeof(Addr));
|
||||
base = (Addr)info->si_addr; /* .sigh.addr */
|
||||
/* limit = AddrAdd(base, (Size)sizeof(Addr)); */
|
||||
|
||||
/* Offer each protection structure the opportunity to handle the */
|
||||
/* exception. If it succeeds, then allow the mutator to continue. */
|
||||
|
|
@ -106,21 +102,17 @@ static void sigHandle(int sig, struct sigcontext context) /* .sigh.args */
|
|||
/* The exception was not handled by any known protection structure, */
|
||||
/* so throw it to the previously installed handler. */
|
||||
|
||||
/* @@@@ This is really weak. */
|
||||
/* Need to implement rest of the contract of sigaction */
|
||||
/* We might also want to set SA_RESETHAND in the flags and explicitly */
|
||||
/* reinstall the handler from withint itself so the SIG_DFL/SIG_IGN */
|
||||
/* case can work properly by just returning. */
|
||||
switch ((int)sigNext.sa_handler) {
|
||||
case (int)SIG_DFL:
|
||||
case (int)SIG_IGN:
|
||||
abort();
|
||||
NOTREACHED;
|
||||
break;
|
||||
default:
|
||||
(*(__real_lii3_sighandler_t)sigNext.sa_handler)(sig, context);
|
||||
break;
|
||||
}
|
||||
e = sigaction(PROT_SIGNAL, &sigNext, &sa);
|
||||
AVER(e == 0);
|
||||
sigemptyset(&asigset);
|
||||
sigaddset(&asigset, PROT_SIGNAL);
|
||||
e = sigprocmask(SIG_UNBLOCK, &asigset, &oldset);
|
||||
AVER(e == 0);
|
||||
kill(getpid(), PROT_SIGNAL);
|
||||
e = sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
AVER(e == 0);
|
||||
e = sigaction(PROT_SIGNAL, &sa, NULL);
|
||||
AVER(e == 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -142,15 +134,14 @@ void ProtSetup(void)
|
|||
struct sigaction sa;
|
||||
int result;
|
||||
|
||||
sa.sa_handler = (__sighandler_t)sigHandle; /* .sigh.args */
|
||||
sa.sa_sigaction = sigHandle;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
|
||||
result = sigaction(SIGSEGV, &sa, &sigNext);
|
||||
result = sigaction(PROT_SIGNAL, &sa, &sigNext);
|
||||
AVER(result == 0);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
|
|
|
|||
|
|
@ -15,12 +15,6 @@
|
|||
|
||||
#include "mpm.h"
|
||||
|
||||
#if defined(MPS_OS_LI)
|
||||
/* open sesame magic */
|
||||
#define _BSD_SOURCE 1
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -79,34 +73,7 @@ static RingStruct suspendedRing; /* PThreadext suspend ring */
|
|||
* suspend protocol.
|
||||
*/
|
||||
|
||||
#if defined(MPS_OS_LI)
|
||||
|
||||
#include "prmcli.h"
|
||||
|
||||
static void suspendSignalHandler(int sig, struct sigcontext scp)
|
||||
{
|
||||
sigset_t signal_set;
|
||||
MutatorFaultContextStruct mfContext;
|
||||
|
||||
AVER(sig == PTHREADEXT_SIGSUSPEND);
|
||||
UNUSED(sig);
|
||||
|
||||
AVER(suspendingVictim != NULL);
|
||||
mfContext.scp = &scp;
|
||||
suspendingVictim->suspendedMFC = &mfContext;
|
||||
/* Block all signals except PTHREADEXT_SIGRESUME while suspended. */
|
||||
sigfillset(&signal_set);
|
||||
sigdelset(&signal_set, PTHREADEXT_SIGRESUME);
|
||||
sem_post(&pthreadextSem);
|
||||
sigsuspend(&signal_set);
|
||||
|
||||
/* Once here, the resume signal handler has run to completion. */
|
||||
return;
|
||||
}
|
||||
|
||||
#elif defined(MPS_OS_FR)
|
||||
|
||||
#include "prmcfr.h"
|
||||
#include "prmcix.h"
|
||||
|
||||
static void suspendSignalHandler(int sig,
|
||||
siginfo_t *info,
|
||||
|
|
@ -135,8 +102,6 @@ static void suspendSignalHandler(int sig,
|
|||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* resumeSignalHandler -- signal handler called when resuming a thread
|
||||
*
|
||||
|
|
@ -184,15 +149,8 @@ static void PThreadextModuleInit(void)
|
|||
status = sigaddset(&pthreadext_sigsuspend.sa_mask, PTHREADEXT_SIGRESUME);
|
||||
AVER(status == 0);
|
||||
|
||||
#if defined(MPS_OS_LI)
|
||||
pthreadext_sigsuspend.sa_flags = 0;
|
||||
pthreadext_sigsuspend.sa_handler = (__sighandler_t)suspendSignalHandler;
|
||||
|
||||
#elif defined(MPS_OS_FR)
|
||||
pthreadext_sigsuspend.sa_flags = SA_SIGINFO;
|
||||
pthreadext_sigsuspend.sa_sigaction = suspendSignalHandler;
|
||||
#endif
|
||||
|
||||
pthreadext_sigresume.sa_flags = 0;
|
||||
pthreadext_sigresume.sa_handler = resumeSignalHandler;
|
||||
status = sigemptyset(&pthreadext_sigresume.sa_mask);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
* assumed to be recorded in the context at pointer-aligned boundaries.
|
||||
*/
|
||||
|
||||
#include "prmcfr.h"
|
||||
#include "prmcix.h"
|
||||
#include "mpm.h"
|
||||
|
||||
#if !defined(MPS_OS_FR) || !defined(MPS_ARCH_I4)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* thlii3.c: Threads Manager for Intel x86 systems with LinuxThreads
|
||||
/* thlii4.c: Threads Manager for Intel x86 systems with LinuxThreads
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
* assumed to be recorded in the context at pointer-aligned boundaries.
|
||||
*/
|
||||
|
||||
#include "prmcli.h"
|
||||
#include "prmcix.h"
|
||||
#include "mpm.h"
|
||||
|
||||
#if !defined(MPS_OS_LI) || !defined(MPS_ARCH_I4)
|
||||
|
|
@ -243,18 +243,18 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
if(res != ResOK)
|
||||
return res;
|
||||
} else {
|
||||
struct sigcontext *scp;
|
||||
MutatorFaultContext mfc;
|
||||
Addr *stackBase, *stackLimit, stackPtr;
|
||||
|
||||
scp = thread->mfc->scp;
|
||||
if(scp == NULL) {
|
||||
mcontext_t *mc;
|
||||
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)scp->esp; /* .i3.sp */
|
||||
stackPtr = (Addr)mfc->ucontext->uc_stack.ss_sp; /* .i3.sp */
|
||||
/* .stack.align */
|
||||
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr));
|
||||
stackLimit = (Addr *)stackBot;
|
||||
|
|
@ -273,8 +273,9 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
* unecessarily scans the rest of the context. The optimisation
|
||||
* to scan only relevent parts would be machine dependent.
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, (Addr *)scp,
|
||||
(Addr *)((char *)scp + sizeof(*scp)));
|
||||
mc = &mfc->ucontext->uc_mcontext;
|
||||
res = TraceScanAreaTagged(ss, (Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue