mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-28 01:00:52 -07:00
Merging branch/2012-07-26/linux-catchup.
Copied from Perforce Change: 178816 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
6b9cf31fa2
24 changed files with 125 additions and 263 deletions
|
|
@ -168,7 +168,7 @@ Res ABQPeek(ABQ abq, CBSBlock *blockReturn)
|
|||
/* ABQDelete -- delete a block from the ABQ */
|
||||
Res ABQDelete(ABQ abq, CBSBlock block)
|
||||
{
|
||||
Index index, next, elements, in;
|
||||
Index index, next, in;
|
||||
CBSBlock *queue;
|
||||
|
||||
AVERT(ABQ, abq);
|
||||
|
|
@ -178,7 +178,6 @@ Res ABQDelete(ABQ abq, CBSBlock block)
|
|||
|
||||
index = abq->out;
|
||||
in = abq->in;
|
||||
elements = abq->elements;
|
||||
queue = abq->queue;
|
||||
|
||||
while (index != in) {
|
||||
|
|
|
|||
|
|
@ -206,9 +206,7 @@ static void test(mps_ap_t leafap, mps_ap_t exactap, mps_ap_t weakap,
|
|||
|
||||
for(j = 0; j < ITERATIONS; ++j) {
|
||||
for(i = 0; i < TABLE_SLOTS; ++i) {
|
||||
mps_word_t *string;
|
||||
|
||||
string = alloc_string("spong", leafap);
|
||||
(void)alloc_string("spong", leafap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -211,9 +211,7 @@ static void test(mps_ap_t leafap, mps_ap_t exactap, mps_ap_t weakap,
|
|||
|
||||
for(j = 0; j < ITERATIONS; ++j) {
|
||||
for(i = 0; i < TABLE_SLOTS; ++i) {
|
||||
mps_word_t *string;
|
||||
|
||||
string = alloc_string("spong", leafap);
|
||||
(void)alloc_string("spong", leafap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,13 +176,11 @@ static void *test(void *arg, size_t s)
|
|||
die(mps_arena_collect(arena), "collect");
|
||||
printf(" Done.\n");
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_word_t obj;
|
||||
mps_addr_t objaddr;
|
||||
cdie(mps_message_get(&message, arena,
|
||||
mps_message_type_finalization()),
|
||||
"get");
|
||||
mps_message_finalization_ref(&objaddr, arena, message);
|
||||
obj = (mps_word_t)objaddr;
|
||||
mps_message_discard(arena, message);
|
||||
++ final_this_time;
|
||||
}
|
||||
|
|
@ -216,13 +214,11 @@ static void *test(void *arg, size_t s)
|
|||
die(mps_arena_collect(arena), "collect");
|
||||
printf(" Done.\n");
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_word_t obj;
|
||||
mps_addr_t objaddr;
|
||||
cdie(mps_message_get(&message, arena,
|
||||
mps_message_type_finalization()),
|
||||
"get");
|
||||
mps_message_finalization_ref(&objaddr, arena, message);
|
||||
obj = (mps_word_t)objaddr;
|
||||
mps_message_discard(arena, message);
|
||||
++ final_this_time;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,24 +129,30 @@ int dylan_wrapper_check(mps_word_t *w)
|
|||
/* The first field is traceable, the second field can be traced, */
|
||||
/* but doesn't need to be. */
|
||||
assert((ww[WP] == 1) || (ww[WP] == 3));
|
||||
|
||||
unused(ww);
|
||||
|
||||
/* Unpack the wrapper. */
|
||||
|
||||
class = w[WC]; /* class */
|
||||
unused(class);
|
||||
fh = w[WF]; /* fixed part header word */
|
||||
fl = fh >> 2; /* fixed part length */
|
||||
ff = fh & 3; /* fixed part format code */
|
||||
vh = w[WV]; /* variable part header */
|
||||
version = (vh >> (MPS_WORD_WIDTH - 8)) & 0xff;
|
||||
assert(version == 2); /* Code in this file only works for version 2 */
|
||||
unused(version);
|
||||
reserved = (vh >> 8) & 0xff;
|
||||
assert(reserved == 0);
|
||||
unused(reserved);
|
||||
vb = (vh >> 16) & 0xff;
|
||||
unused(vb);
|
||||
es = (vh & 0xff) >> 3;/* element size */
|
||||
vf = vh & 7; /* variable part format code */
|
||||
vt = w[WS]; /* vector total word (Dylan-tagged) */
|
||||
t = vt >> 2; /* vector total length */
|
||||
|
||||
unused(t);
|
||||
|
||||
/* The second word is the class of the wrapped object. */
|
||||
/* It would be good to check which pool this is in. */
|
||||
|
||||
|
|
@ -160,23 +166,26 @@ int dylan_wrapper_check(mps_word_t *w)
|
|||
|
||||
/* Fixed part format 3 is reserved. */
|
||||
assert(ff != 3);
|
||||
unused(ff);
|
||||
|
||||
/* Zero length fixed part is only legal in format 0. */
|
||||
/* Current Dylan run-time does not honour this so I remove it for now */
|
||||
/* We probably want this check as then we can scan without having to */
|
||||
/* check for 0 fixed length fields as a special case */
|
||||
/* assert(ff == 0 || fl != 0); */
|
||||
|
||||
unused(fl);
|
||||
/* The fourth word contains the variable part format and element */
|
||||
/* size. This assumes that DylanWorks is only going to use byte */
|
||||
/* vectors in the non-word case. */
|
||||
|
||||
/* Variable part format 6 is reserved. */
|
||||
assert(vf != 6);
|
||||
|
||||
unused(vf);
|
||||
|
||||
/* There should be no shift in word vector formats. */
|
||||
assert((vf & 6) == 4 || es == 0);
|
||||
|
||||
unused(es);
|
||||
|
||||
/* The fifth word is the number of patterns in the pattern */
|
||||
/* vector. This can be calculated from the fixed part length. */
|
||||
/* The word is also tagged like a DylanWorks integer. */
|
||||
|
|
@ -247,9 +256,11 @@ extern mps_addr_t dylan_weak_dependent(mps_addr_t parent)
|
|||
ff = fword & 3;
|
||||
/* traceable fixed part */
|
||||
assert(ff == 1);
|
||||
unused(ff);
|
||||
fl = fword & ~(mps_word_t)3;
|
||||
/* at least one fixed field */
|
||||
assert(fl >= 1);
|
||||
unused(fl);
|
||||
return (mps_addr_t) object[1];
|
||||
}
|
||||
|
||||
|
|
@ -555,7 +566,8 @@ extern mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io)
|
|||
h = (mps_word_t)p[0];
|
||||
/* object should not be forwarded (as there is no forwarding method) */
|
||||
assert((h & 3) == 0);
|
||||
|
||||
unused(h);
|
||||
|
||||
res = mps_fix(mps_ss, p);
|
||||
if ( res != MPS_RES_OK ) return res;
|
||||
|
||||
|
|
@ -576,7 +588,8 @@ extern mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io)
|
|||
|
||||
/* weak vectors should have traceable fixed format */
|
||||
assert(ff == 1);
|
||||
|
||||
unused(ff);
|
||||
|
||||
assoc = (mps_addr_t *)p[0];
|
||||
|
||||
vword = w[WV];
|
||||
|
|
@ -585,7 +598,8 @@ extern mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io)
|
|||
|
||||
/* weak vectors should be non-stretchy traceable */
|
||||
assert(vf == 2);
|
||||
|
||||
unused(vf);
|
||||
|
||||
/* q is end of the object. There are fl fixed fields, vl variable */
|
||||
/* fields and another slot that contains the vector length */
|
||||
q = p + fl + vl + 1;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -300,7 +300,8 @@ Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace)
|
|||
" (of $U)", (WriteFU)chain->genCount,
|
||||
" of this chain $P.", (WriteFP)chain,
|
||||
NULL ));
|
||||
|
||||
UNUSED(topCondemnedGenSerial); /* only used for DIAG */
|
||||
|
||||
/* Condemn everything in these zones. */
|
||||
if (condemnedSet != ZoneSetEMPTY) {
|
||||
res = TraceCondemnZones(trace, condemnedSet);
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
if(collections != c) {
|
||||
collections = c;
|
||||
printf("\nCollection %"PRIuLONGEST", %lu objects.\n", (ulongest_t)c, (unsigned long)i);
|
||||
printf("\nCollection %"PRIuLONGEST", %lu objects.\n", (ulongest_t)c, i);
|
||||
for(r = 0; r < exactRootsCOUNT; ++r) {
|
||||
cdie(exactRoots[r] == objNULL || dylan_check(exactRoots[r]),
|
||||
"all roots check");
|
||||
|
|
|
|||
|
|
@ -1583,7 +1583,6 @@ static Res amcScanNailed(Bool *totalReturn, ScanState ss, Pool pool,
|
|||
static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
||||
{
|
||||
Addr base, limit;
|
||||
Arena arena;
|
||||
Format format;
|
||||
AMC amc;
|
||||
Res res;
|
||||
|
|
@ -1597,7 +1596,6 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
|
||||
|
||||
format = pool->format;
|
||||
arena = pool->arena;
|
||||
|
||||
if(amcSegHasNailboard(seg)) {
|
||||
return amcScanNailed(totalReturn, ss, pool, seg, amc);
|
||||
|
|
|
|||
|
|
@ -234,7 +234,6 @@ static Bool loSegFindFree(Addr *bReturn, Addr *lReturn,
|
|||
Index baseIndex, limitIndex;
|
||||
LO lo;
|
||||
Seg seg;
|
||||
Arena arena;
|
||||
Count agrains;
|
||||
Count bits;
|
||||
Addr segBase;
|
||||
|
|
@ -246,7 +245,6 @@ static Bool loSegFindFree(Addr *bReturn, Addr *lReturn,
|
|||
lo = loseg->lo;
|
||||
seg = LOSegSeg(loseg);
|
||||
AVER(SizeIsAligned(size, LOPool(lo)->alignment));
|
||||
arena = PoolArena(LOPool(lo));
|
||||
|
||||
/* agrains is the number of grains corresponding to the size */
|
||||
/* of the allocation request */
|
||||
|
|
@ -547,7 +545,6 @@ static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
Ring node, nextNode;
|
||||
LO lo;
|
||||
LOSeg loseg;
|
||||
Arena arena;
|
||||
Addr base, limit;
|
||||
|
||||
AVER(baseReturn != NULL);
|
||||
|
|
@ -562,8 +559,6 @@ static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(SizeIsAligned(size, PoolAlignment(pool)));
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
|
||||
arena = PoolArena(pool);
|
||||
|
||||
/* Try to find a segment with enough space already. */
|
||||
RING_FOR(node, &pool->segRing, nextNode) {
|
||||
Seg seg = SegOfPoolRing(node);
|
||||
|
|
@ -619,7 +614,6 @@ static void LOBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
Seg seg;
|
||||
LOSeg loseg;
|
||||
Index baseIndex, initIndex, limitIndex;
|
||||
Arena arena;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
lo = PARENT(LOStruct, poolStruct, pool);
|
||||
|
|
@ -634,7 +628,6 @@ static void LOBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
AVERT(LOSeg, loseg);
|
||||
AVER(loseg->lo == lo);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
base = BufferBase(buffer);
|
||||
segBase = SegBase(seg);
|
||||
|
||||
|
|
|
|||
|
|
@ -477,9 +477,6 @@ static MessageClassStruct MRGMessageClassStruct = {
|
|||
*/
|
||||
static void MRGSegPairDestroy(MRGRefSeg refseg, MRG mrg)
|
||||
{
|
||||
Pool pool;
|
||||
|
||||
pool = MRG2Pool(mrg);
|
||||
RingRemove(&refseg->mrgRing);
|
||||
RingFinish(&refseg->mrgRing);
|
||||
refseg->sig = SigInvalid;
|
||||
|
|
|
|||
|
|
@ -824,7 +824,6 @@ size_t mps_mv_size(mps_pool_t mps_pool)
|
|||
Pool pool;
|
||||
MV mv;
|
||||
MVSpan span;
|
||||
Arena arena;
|
||||
Size f = 0;
|
||||
Ring spans, node = NULL, nextNode; /* gcc whinge stop */
|
||||
|
||||
|
|
@ -833,7 +832,6 @@ size_t mps_mv_size(mps_pool_t mps_pool)
|
|||
AVERT(Pool, pool);
|
||||
mv = Pool2MV(pool);
|
||||
AVERT(MV, mv);
|
||||
arena = PoolArena(pool);
|
||||
|
||||
spans = &mv->spans;
|
||||
RING_FOR(node, spans, nextNode) {
|
||||
|
|
|
|||
|
|
@ -643,8 +643,8 @@ static void SNCWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
|||
limit = SegLimit(seg);
|
||||
|
||||
while(object < limit) {
|
||||
(*f)(object, pool->format, pool, p, s);
|
||||
nextObject = (*pool->format->skip)(object);
|
||||
(*f)(object, format, pool, p, s);
|
||||
nextObject = (*format->skip)(object);
|
||||
AVER(nextObject > object);
|
||||
object = nextObject;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,28 @@ 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 */
|
||||
/* The REG_EAX etc. symbols are only present if _GNU_SOURCE is defined.
|
||||
Currently this is in lii4gc.gmk in PFMDEFS. */
|
||||
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 +61,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. */
|
||||
|
|
@ -48,9 +39,6 @@ SRCID(protlii3, "$Id$");
|
|||
static struct sigaction sigNext;
|
||||
|
||||
|
||||
typedef void (*__real_lii3_sighandler_t)(int, struct sigcontext);
|
||||
|
||||
|
||||
/* sigHandle -- protection signal handler
|
||||
*
|
||||
* This is the signal handler installed by ProtSetup to deal with
|
||||
|
|
@ -62,39 +50,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. */
|
||||
|
|
@ -104,23 +97,21 @@ 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. */
|
||||
/* so throw it to the previously installed handler. That handler won't */
|
||||
/* get an accurate context (the MPS would fail if it were the second in */
|
||||
/* line) but it's the best we can do. */
|
||||
|
||||
/* @@@@ 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 +133,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);
|
||||
|
|
|
|||
|
|
@ -215,7 +215,6 @@ static void reservoirShrink(Reservoir reservoir, Size want)
|
|||
Res ReservoirWithdraw(Addr *baseReturn, Tract *baseTractReturn,
|
||||
Reservoir reservoir, Size size, Pool pool)
|
||||
{
|
||||
Pool respool;
|
||||
Arena arena;
|
||||
|
||||
AVER(baseReturn != NULL);
|
||||
|
|
@ -226,7 +225,6 @@ Res ReservoirWithdraw(Addr *baseReturn, Tract *baseTractReturn,
|
|||
AVER(SizeIsAligned(size, ArenaAlign(arena)));
|
||||
AVER(size > 0);
|
||||
AVERT(Pool, pool);
|
||||
respool = &reservoir->poolStruct;
|
||||
|
||||
/* @@@@ As a short-term measure, we only permit the reservoir to */
|
||||
/* allocate single-page regions. */
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ failInit:
|
|||
static void SegFinish(Seg seg)
|
||||
{
|
||||
Arena arena;
|
||||
Addr addr, base, limit;
|
||||
Addr addr, limit;
|
||||
Tract tract;
|
||||
SegClass class;
|
||||
|
||||
|
|
@ -231,8 +231,8 @@ static void SegFinish(Seg seg)
|
|||
/* See <code/shield.c#shield.flush> */
|
||||
ShieldFlush(PoolArena(SegPool(seg)));
|
||||
|
||||
base = SegBase(seg);
|
||||
limit = SegLimit(seg);
|
||||
|
||||
TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) {
|
||||
AVER(TractCheck(tract)); /* <design/check/#type.no-sig> */
|
||||
TractSetWhite(tract, TraceSetEMPTY);
|
||||
|
|
|
|||
|
|
@ -433,14 +433,10 @@ static Bool AMSSegRegionIsFree(Seg seg, Addr base, Addr limit)
|
|||
*/
|
||||
static void AMSUnallocateRange(Seg seg, Addr base, Addr limit)
|
||||
{
|
||||
Pool pool;
|
||||
AMS ams;
|
||||
AMSSeg amsseg;
|
||||
Index baseIndex, limitIndex;
|
||||
/* parameters checked by caller */
|
||||
|
||||
pool = SegPool(seg);
|
||||
ams = Pool2AMS(pool);
|
||||
amsseg = Seg2AMSSeg(seg);
|
||||
|
||||
baseIndex = AMS_ADDR_INDEX(seg, base);
|
||||
|
|
@ -475,14 +471,10 @@ static void AMSUnallocateRange(Seg seg, Addr base, Addr limit)
|
|||
*/
|
||||
static void AMSAllocateRange(Seg seg, Addr base, Addr limit)
|
||||
{
|
||||
Pool pool;
|
||||
AMS ams;
|
||||
AMSSeg amsseg;
|
||||
Index baseIndex, limitIndex;
|
||||
/* parameters checked by caller */
|
||||
|
||||
pool = SegPool(seg);
|
||||
ams = Pool2AMS(pool);
|
||||
amsseg = Seg2AMSSeg(seg);
|
||||
|
||||
baseIndex = AMS_ADDR_INDEX(seg, base);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
*
|
||||
* .source.callees.saves: Set of callee-saved registers taken from
|
||||
* CALL_USED_REGISTERS in <gcc-sources>/config/i386/i386.h.
|
||||
* ebp added to the list because gcc now doesn't always use it as
|
||||
* a frame pointer so it could contain a root.
|
||||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
|
|
@ -49,20 +51,23 @@ SRCID(ssixi3, "$Id$");
|
|||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
{
|
||||
Addr calleeSaveRegs[4];
|
||||
Addr *stackTop;
|
||||
Res res;
|
||||
|
||||
/* .assume.asm.stack */
|
||||
ASMV("push %ebx"); /* These registers are callee-saved */
|
||||
ASMV("push %esi"); /* and so may contain roots. They are pushed */
|
||||
ASMV("push %edi"); /* for scanning. See .source.callees.saves. */
|
||||
/* Store the callee save registers on the stack so they get scanned
|
||||
* as they may contain roots.
|
||||
*/
|
||||
ASMV("mov %%ebx, %0" : "=m" (calleeSaveRegs[0]));
|
||||
ASMV("mov %%esi, %0" : "=m" (calleeSaveRegs[1]));
|
||||
ASMV("mov %%edi, %0" : "=m" (calleeSaveRegs[2]));
|
||||
ASMV("mov %%ebp, %0" : "=m" (calleeSaveRegs[3]));
|
||||
ASMV("mov %%esp, %0" : "=r" (stackTop) :); /* stackTop = esp */
|
||||
|
||||
AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .assume.align */
|
||||
res = TraceScanArea(ss, stackTop, stackBot);
|
||||
|
||||
ASMV("add $12, %esp"); /* pop 3 regs to restore the stack pointer */
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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