From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15927 invoked by alias); 2 Aug 2007 11:26:20 -0000 Received: (qmail 15861 invoked by uid 22791); 2 Aug 2007 11:26:12 -0000 X-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,DK_POLICY_SIGNSOME,FORGED_RCVD_HELO,HK_OBFDOM X-Spam-Check-By: sourceware.org Received: from wildebeest.demon.nl (HELO gnu.wildebeest.org) (83.160.170.119) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 02 Aug 2007 11:26:05 +0000 Received: from dijkstra.wildebeest.org ([192.168.1.29]) by gnu.wildebeest.org with esmtp (Exim 4.43) id 1IGYr1-0007PQ-UE for frysk@sourceware.org; Thu, 02 Aug 2007 13:28:34 +0200 Subject: Re: [patch] LogicalMemoryBuffer From: Mark Wielaard To: frysk In-Reply-To: <1184932926.3611.58.camel@dijkstra.wildebeest.org> References: <1184932926.3611.58.camel@dijkstra.wildebeest.org> Content-Type: multipart/mixed; boundary="=-G/hYcuwqLnVXsOHFKG9+" Date: Thu, 02 Aug 2007 11:26:00 -0000 Message-Id: <1186053948.15044.61.camel@dijkstra.wildebeest.org> Mime-Version: 1.0 X-Mailer: Evolution 2.8.3 (2.8.3-2.fc6) X-Spam-Score: -4.4 (----) X-Virus-Checked: Checked by ClamAV on sourceware.org X-IsSubscribed: yes Mailing-List: contact frysk-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: frysk-owner@sourceware.org X-SW-Source: 2007-q3/txt/msg00261.txt.bz2 --=-G/hYcuwqLnVXsOHFKG9+ Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 3049 Hi, On Fri, 2007-07-20 at 14:02 +0200, Mark Wielaard wrote: > - LogicalMemoryBuffer is a filter on top of AddressSpaceByteBuffer but > really should be on top of MemorySpaceByteBuffer which is more > effecient. The used to be interface compatible, but a recent change to > MemorySpaceByteBuffer changed that and made that it less easy to wrap. > MemorySpaceByteBuffer is really just an optimization of > AddressSpaceByteBuffer (in the case of AddressSpace.TEXT/DATA) and all > code should go through the optimized path (StateLessFile) for accessing > memory if the AddressSpace allows it. So I am going to merge the two > (and fix up the places that currently use the slow path). Then I'll also > add the ByteBuffer.get() optimization that Chris pointed out. This patch implements the above and fixes bug #4827 and #4760 by adding a bulk put ByteBuffer method as Andrew suggested and using the StateLessFile support for this as Chris implemented. It also updates RegisterSetByteBuffer in the same way. LogicalMemoryBuffer is now marked as read only to signal that to change memory you should go through the raw memory view (if you need this, then you are probably interfering with the breakpoint support, so need to update that code to deal with other ways the underlying memory could change). Various methods have been updated to use the bulk put methods now. frysk-core/frysk/proc/live/ChangeLog 2007-08-02 Mark Wielaard * AddressSpaceByteBuffer.java (mem): New field. (pokesRequest): Likewise. (AddressSpaceByteBuffer): Initialize mem and pokesRequest. (PeeksRequest.peek): New method. (PeeksRequest.execute): use peek(). (PeeksRequest.request): Likewise. (PokesRequest): New inner class. (poke): New method. * LinuxTask.java (getRawMemory): Use AddressSpaceByteBuffer. * LogicalMemoryBuffer.java (poke): New methods marked as unsupported. * MemorySpaceByteBuffer.java: Removed. * RegisterSetByteBuffer.java (peek): Use System.arraycopy(). (poke): New method. * TestMemorySpaceByteBuffer.java: Removed. * TestByteBuffer.java: Merged in TestMemorySpaceByteBuffer tests, made test more generic to test all possible buffers, add bulk put tests. frysk-core/frysk/proc/ChangeLog 2007-08-02 Mark Wielaard * Breakpoint.java (set): Use raw memory and bulk put method. (reset): Likewise. * BreakpointAddresses.java: Make public. * Instruction.java (setupExecuteOutOfLine): use raw memory and bulk put method. frysk-sys/inua/ChangeLog 2007-08-02 Mark Wielaard * ByteBuffer.java (put(byte[],int,int)): New bulk put method. (put(byte[])): likewise. The biggest part of the patch is actually the removal of now redundant classes and the addition of more tests and making those tests more generic to test all possible ByteBuffers. Yeah, less code, more tests! :) All new ByteBuffer tests PASS and no new regressions as tested on x86 (F7) and x86_64 (FC6). Cheers, Mark --=-G/hYcuwqLnVXsOHFKG9+ Content-Disposition: inline; filename=buf.patch Content-Type: text/x-patch; name=buf.patch; charset=utf-8 Content-Transfer-Encoding: 7bit Content-length: 32643 Index: frysk-core/frysk/proc/Breakpoint.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/Breakpoint.java,v retrieving revision 1.14 diff -u -r1.14 Breakpoint.java --- frysk-core/frysk/proc/Breakpoint.java 20 Jul 2007 11:36:06 -0000 1.14 +++ frysk-core/frysk/proc/Breakpoint.java 2 Aug 2007 10:48:33 -0000 @@ -138,7 +138,7 @@ */ private void set(Task task) { - ByteBuffer buffer = task.getMemory(); + ByteBuffer buffer = task.getRawMemory(); Isa isa = task.getIsa(); Instruction bpInstruction = isa.getBreakpointInstruction(); @@ -147,8 +147,7 @@ // Put in the breakpoint. byte[] bs = bpInstruction.getBytes(); buffer.position(address); - for (int index = 0; index < bs.length; index++) - buffer.putByte(bs[index]); + buffer.put(bs); } /** @@ -174,7 +173,7 @@ */ private void reset(Task task) { - ByteBuffer buffer = task.getMemory(); + ByteBuffer buffer = task.getRawMemory(); buffer.position(address); Isa isa = task.getIsa(); @@ -185,8 +184,7 @@ // Only need to put back the part of the original instruction // covered by the breakpoint instruction bytes. - for (int index = 0; index < bp.length; index++) - buffer.putByte(bs[index]); + buffer.put(bs, 0, bp.length); } /** Index: frysk-core/frysk/proc/BreakpointAddresses.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/BreakpointAddresses.java,v retrieving revision 1.7 diff -u -r1.7 BreakpointAddresses.java --- frysk-core/frysk/proc/BreakpointAddresses.java 20 Jul 2007 11:36:06 -0000 1.7 +++ frysk-core/frysk/proc/BreakpointAddresses.java 2 Aug 2007 10:48:33 -0000 @@ -79,7 +79,7 @@ /** * Package private constructor used by the Proc when created. */ - BreakpointAddresses(Proc proc) + public BreakpointAddresses(Proc proc) { this.proc = proc; map = new HashMap(); Index: frysk-core/frysk/proc/Instruction.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/Instruction.java,v retrieving revision 1.2 diff -u -r1.2 Instruction.java --- frysk-core/frysk/proc/Instruction.java 2 Jul 2007 10:05:18 -0000 1.2 +++ frysk-core/frysk/proc/Instruction.java 2 Aug 2007 10:48:33 -0000 @@ -140,10 +140,9 @@ */ public void setupExecuteOutOfLine(Task task, long pc, long address) { - ByteBuffer buffer = task.getMemory(); + ByteBuffer buffer = task.getRawMemory(); buffer.position(address); - for (int i = 0; i < instr.length; i++) - buffer.putByte(instr[i]); + buffer.put(instr); task.getIsa().setPC(task, address); } Index: frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java,v retrieving revision 1.3 diff -u -r1.3 AddressSpaceByteBuffer.java --- frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java 30 Jul 2007 12:42:08 -0000 1.3 +++ frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java 2 Aug 2007 10:48:33 -0000 @@ -40,7 +40,9 @@ package frysk.proc.live; import inua.eio.ByteBuffer; +import frysk.sys.Errno; import frysk.sys.Ptrace.AddressSpace; +import frysk.sys.proc.Mem; import frysk.event.Request; import frysk.proc.Manager; @@ -50,6 +52,9 @@ protected final AddressSpace addressSpace; protected final int pid; + // Direct files access if possible, or null otherwise. + final Mem mem; + protected AddressSpaceByteBuffer (int pid, AddressSpace addressSpace, long lowerExtreem, long upperExtreem) { @@ -59,6 +64,13 @@ peekRequest = new PeekRequest(); pokeRequest = new PokeRequest(); peeksRequest = new PeeksRequest(); + pokesRequest = new PokesRequest(); + + if (addressSpace == AddressSpace.TEXT + || addressSpace == AddressSpace.DATA) + mem = new Mem(pid); + else + mem = null; } public AddressSpaceByteBuffer (int pid, AddressSpace addressSpace) { @@ -137,15 +149,34 @@ { super(Manager.eventLoop); } + + private int peek(long index, byte[] bytes, int offset, int length) + { + if (mem != null) + { + try + { + return mem.pread(index, bytes, offset, length); + } + catch (Errno e) + { + // try again through address space. + } + } + + return addressSpace.peek(pid, index, length, bytes, offset); + } + public void execute () { - length = addressSpace.peek(pid, index, length, bytes, offset); + length = peek(index, bytes, offset, length); } + public int request (long index, byte[] bytes, int offset, int length) { if (isEventLoopThread()) - return addressSpace.peek(pid, index, length, bytes, offset); + return peek(index, bytes, offset, length); else synchronized (this) { this.index = index; this.bytes = bytes; @@ -162,6 +193,67 @@ return peeksRequest.request(index, bytes, offset, length); } + + private class PokesRequest + extends Request + { + private long index; + private int length; + private int offset; + private byte[] bytes; + + PokesRequest() + { + super(Manager.eventLoop); + } + + private int poke(long index, byte[] bytes, int offset, int length) + { + if (mem != null) + { + try + { + return mem.pwrite(index, bytes, offset, length); + } + catch (Errno e) + { + // try again through address space. + } + } + + // We lose here since AddressSpace isn't optimized for bulk poke. + for (int i = offset; i < length; i++) + addressSpace.poke(pid, index + i, bytes[i]); + return length; + } + + public void execute () + { + length = poke(index, bytes, offset, length); + } + + public int request (long index, byte[] bytes, + int offset, int length) + { + if (isEventLoopThread()) + return poke(index, bytes, offset, length); + else synchronized (this) { + this.index = index; + this.bytes = bytes; + this.offset = offset; + this.length = length; + request(); + return length; + } + } + } + + private final PokesRequest pokesRequest; + protected int poke(long index, byte[] bytes, int off, int len) + { + return pokesRequest.request(index, bytes, off, len); + } + protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem, long upperExtreem) { Index: frysk-core/frysk/proc/live/LinuxTask.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/live/LinuxTask.java,v retrieving revision 1.5 diff -u -r1.5 LinuxTask.java --- frysk-core/frysk/proc/live/LinuxTask.java 30 Jul 2007 12:42:08 -0000 1.5 +++ frysk-core/frysk/proc/live/LinuxTask.java 2 Aug 2007 10:48:33 -0000 @@ -91,13 +91,14 @@ /** - * Return the raw memory byte-buffer. + * Return the raw memory byte-buffer. This is the TEXT/DATA area. */ public ByteBuffer getRawMemory () { logger.log(Level.FINE, "Begin fillMemory\n", this); ByteOrder byteOrder = getIsa().getByteOrder(); - ByteBuffer memory = new MemorySpaceByteBuffer(getTid()); + ByteBuffer memory = new AddressSpaceByteBuffer(getTid(), + AddressSpace.DATA); memory.order(byteOrder); logger.log(Level.FINE, "End fillMemory\n", this); return memory; Index: frysk-core/frysk/proc/live/LogicalMemoryBuffer.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java,v retrieving revision 1.2 diff -u -r1.2 LogicalMemoryBuffer.java --- frysk-core/frysk/proc/live/LogicalMemoryBuffer.java 30 Jul 2007 12:42:08 -0000 1.2 +++ frysk-core/frysk/proc/live/LogicalMemoryBuffer.java 2 Aug 2007 10:48:33 -0000 @@ -127,7 +127,17 @@ return super.peek(index + r, bytes, offset + r, length - r) + r; } } + + protected void poke (long index, int value) + { + throw new UnsupportedOperationException("read only memory buffer"); + } + protected int poke(long index, byte[] bytes, int offset, int length) + { + throw new UnsupportedOperationException("read only memory buffer"); + } + protected ByteBuffer subBuffer(ByteBuffer parent, long lower, long upper) { Index: frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java =================================================================== RCS file: frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java diff -N frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java --- frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java 30 Jul 2007 12:42:08 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,193 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2007 Oracle Corporation. -// Copyright 2007, Red Hat Inc. -// -// FRYSK is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License as published by -// the Free Software Foundation; version 2 of the License. -// -// FRYSK is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with FRYSK; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// In addition, as a special exception, Red Hat, Inc. gives You the -// additional right to link the code of FRYSK with code not covered -// under the GNU General Public License ("Non-GPL Code") and to -// distribute linked combinations including the two, subject to the -// limitations in this paragraph. Non-GPL Code permitted under this -// exception must only link to the code of FRYSK through those well -// defined interfaces identified in the file named EXCEPTION found in -// the source code files (the "Approved Interfaces"). The files of -// Non-GPL Code may instantiate templates or use macros or inline -// functions from the Approved Interfaces without causing the -// resulting work to be covered by the GNU General Public -// License. Only Red Hat, Inc. may make changes or additions to the -// list of Approved Interfaces. You must obey the GNU General Public -// License in all respects for all of the FRYSK code and other code -// used in conjunction with FRYSK except the Non-GPL Code covered by -// this exception. If you modify this file, you may extend this -// exception to your version of the file, but you are not obligated to -// do so. If you do not wish to provide this exception without -// modification, you must delete this exception statement from your -// version and license this file solely under the GPL without -// exception. - -package frysk.proc.live; - -import inua.eio.ByteBuffer; -import frysk.sys.Ptrace.AddressSpace; -import frysk.sys.Errno; -import frysk.sys.proc.Mem; -import frysk.event.Request; -import frysk.proc.Manager; - -public class MemorySpaceByteBuffer - extends ByteBuffer -{ - private MemorySpaceByteBuffer (long lowerExtreem, - long upperExtreem, - PeekRequest peekRequest, - PokeRequest pokeRequest, - PeeksRequest peeksRequest) - { - super (lowerExtreem, upperExtreem); - this.peekRequest = peekRequest; - this.pokeRequest = pokeRequest; - this.peeksRequest = peeksRequest; - } - public MemorySpaceByteBuffer (int pid) - { - this (0, AddressSpace.TEXT.length (), new PeekRequest(pid), - new PokeRequest(pid), new PeeksRequest(pid)); - } - - private static class PeekRequest - extends Request - { - private long index; - private int value; - private final int pid; - PeekRequest(int pid) - { - super(Manager.eventLoop); - this.pid = pid; - } - public void execute () - { - value = AddressSpace.TEXT.peek(pid, index); - } - public int request (long index) - { - if (isEventLoopThread()) - return AddressSpace.TEXT.peek(pid, index); - else synchronized (this) { - this.index = index; - request(); - return value; - } - } - } - private final PeekRequest peekRequest; - protected int peek (long index) - { - return peekRequest.request (index); - } - - private static class PokeRequest - extends Request - { - private long index; - private int value; - private final int pid; - PokeRequest(int pid) - { - super(Manager.eventLoop); - this.pid = pid; - } - public void execute () - { - AddressSpace.TEXT.poke(pid, index, value); - } - public void request (long index, int value) - { - if (isEventLoopThread()) - AddressSpace.TEXT.poke(pid, index, value); - else synchronized (this) { - this.index = index; - this.value = value; - request(); - } - } - } - private final PokeRequest pokeRequest; - protected void poke (long index, int value) - { - pokeRequest.request (index, value); - } - - private static class PeeksRequest - extends Request - { - private long index; - private int length; - private int offset; - private byte[] bytes; - private Mem mem; - private final int pid; - PeeksRequest(int pid) { - super(Manager.eventLoop); - mem = new Mem(pid); - this.pid = pid; - } - private int peek(long index, byte[] bytes, int offset, int length) { - if (mem != null) { - try { - return mem.pread (index, bytes, offset, length); - } catch (Errno ioe) { - mem = null; - } - } - return AddressSpace.TEXT.peek(pid, index, length, bytes, offset); - } - public void execute () - { - length = peek(index, bytes, offset, length); - } - public int request (long index, byte[] bytes, - int offset, int length) - { - if (isEventLoopThread()) { - return peek(index, bytes, offset, length); - } - else synchronized (this) { - this.index = index; - this.bytes = bytes; - this.offset = offset; - this.length = length; - request(); - return length; - } - } - } - private final PeeksRequest peeksRequest; - protected int peek (long index, byte[] bytes, int offset, int length) - { - return peeksRequest.request(index, bytes, offset, length); - } - - protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem, - long upperExtreem) - { - MemorySpaceByteBuffer up = (MemorySpaceByteBuffer)parent; - return new MemorySpaceByteBuffer (lowerExtreem, upperExtreem, - up.peekRequest, - up.pokeRequest, - up.peeksRequest); - } -} Index: frysk-core/frysk/proc/live/RegisterSetByteBuffer.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java,v retrieving revision 1.1 diff -u -r1.1 RegisterSetByteBuffer.java --- frysk-core/frysk/proc/live/RegisterSetByteBuffer.java 26 Jun 2007 22:12:52 -0000 1.1 +++ frysk-core/frysk/proc/live/RegisterSetByteBuffer.java 2 Aug 2007 10:48:33 -0000 @@ -137,14 +137,20 @@ setRegs(); } - protected long peek (long index, byte[] bytes, long off, long len) + protected int peek (long index, byte[] bytes, int off, int len) { getRegs(); - for (int i = 0; i < len; i++) { - bytes[(int)off + i] = this.bytes[(int)index + i]; - } + System.arraycopy(this.bytes, (int) index, bytes, off, len); return len; } + + protected int poke (long index, byte[] bytes, int off, int len) + { + getRegs(); + System.arraycopy(bytes, off, this.bytes, (int) index, len); + setRegs(); + return len; + } protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem, long upperExtreem) Index: frysk-core/frysk/proc/live/TestByteBuffer.java =================================================================== RCS file: /cvs/frysk/frysk-core/frysk/proc/live/TestByteBuffer.java,v retrieving revision 1.2 diff -u -r1.2 TestByteBuffer.java --- frysk-core/frysk/proc/live/TestByteBuffer.java 18 Jul 2007 20:00:31 -0000 1.2 +++ frysk-core/frysk/proc/live/TestByteBuffer.java 2 Aug 2007 10:48:33 -0000 @@ -41,64 +41,125 @@ import inua.eio.ByteBuffer; import frysk.junit.TestCase; -import frysk.testbed.TearDownProcess; import frysk.testbed.AttachedSelf; import frysk.testbed.LocalMemory; import frysk.sys.Ptrace.RegisterSet; import frysk.sys.Ptrace.AddressSpace; import frysk.proc.Manager; +import frysk.proc.BreakpointAddresses; + +import java.util.Arrays; public class TestByteBuffer extends TestCase { - public void tearDown() + // There are 2 sets of byte buffers to check, those that hold memory + // and those that hold various register values. + private ByteBuffer[] addressBuffers; + private ByteBuffer[] registerBuffers; + + public void setUp () throws Exception { - TearDownProcess.tearDown(); + int pid; + ByteBuffer addressSpaceByteBufferText; + ByteBuffer addressSpaceByteBufferData; + ByteBuffer memorySpaceByteBuffer; + ByteBuffer usrByteBuffer; + ByteBuffer registerByteBuffer; + ByteBuffer fpregisterByteBuffer; + ByteBuffer fpxregisterByteBuffer; + + // Watch for spawned processes, etc. + super.setUp(); + + pid = new AttachedSelf().hashCode(); + + // Text and Data are the same, but can be accessed independently. + addressSpaceByteBufferText + = new AddressSpaceByteBuffer (pid, AddressSpace.TEXT); + addressSpaceByteBufferData + = new AddressSpaceByteBuffer (pid, AddressSpace.DATA); + + // Cheat with the proc, it is not actually used if no + // breakpoints are set (testing with breakpoints set is done through + // TestTaskObserverCode in the various BreakpointMemoryView tests). + // LogicalMemory isn't writable atm, so we exclude it from those + // tests (the raw variant is of course). + frysk.proc.Proc proc = new frysk.proc.dummy.Proc(); + BreakpointAddresses breakpoints = new BreakpointAddresses(proc); + memorySpaceByteBuffer = new LogicalMemoryBuffer(pid, + AddressSpace.TEXT, + breakpoints); + + addressBuffers = new ByteBuffer[] { addressSpaceByteBufferText, + addressSpaceByteBufferData, + memorySpaceByteBuffer }; + + // The USER area is seen as a register buffer. + usrByteBuffer = new AddressSpaceByteBuffer(pid, AddressSpace.USR); + + // See how many other register sets there are. + if (RegisterSet.REGS != null) + { + registerByteBuffer + = new RegisterSetByteBuffer (pid, RegisterSet.REGS); + if (RegisterSet.FPREGS != null) + { + fpregisterByteBuffer + = new RegisterSetByteBuffer (pid, RegisterSet.FPREGS); + if (RegisterSet.FPXREGS != null) + { + fpxregisterByteBuffer + = new RegisterSetByteBuffer (pid, RegisterSet.FPXREGS); + registerBuffers = new ByteBuffer[] { usrByteBuffer, + registerByteBuffer, + fpregisterByteBuffer, + fpxregisterByteBuffer }; + } + else + registerBuffers = new ByteBuffer[] { usrByteBuffer, + registerByteBuffer, + fpregisterByteBuffer }; + } + else + registerBuffers = new ByteBuffer[] { usrByteBuffer, + registerByteBuffer }; + } + else + registerBuffers = new ByteBuffer[] { usrByteBuffer }; } - private int pid; - private ByteBuffer addressSpaceByteBuffer; - private ByteBuffer memorySpaceByteBuffer; - private ByteBuffer registerByteBuffer; - public void setUp () + public void tearDown() throws Exception { - pid = new AttachedSelf().hashCode(); - addressSpaceByteBuffer - = new AddressSpaceByteBuffer (pid, AddressSpace.TEXT); - memorySpaceByteBuffer = new MemorySpaceByteBuffer (pid); - if (RegisterSet.REGS != null) { - registerByteBuffer - = new RegisterSetByteBuffer (pid, RegisterSet.REGS); - } + addressBuffers = null; + registerBuffers = null; + + // Clean up any left stuff processes/open files/etc. + super.tearDown(); } - public void verifySlice(ByteBuffer buffer, long addr, long length) + public void verifySlice(ByteBuffer buffer, long addr, int length) { ByteBuffer slice = buffer.slice (addr, length); - byte bytes[] = new byte[ (int)length]; - buffer.get (addr, bytes, 0, (int)length); + byte bytes[] = new byte[length]; + buffer.get (addr, bytes, 0, length); for (int i = 0; i < length; i++) { assertEquals ("byte at " + i, bytes[i], slice.get (i)); } } - public void testSliceAddressSpace() - { - verifySlice(addressSpaceByteBuffer, LocalMemory.getFuncAddr(), - LocalMemory.getFuncBytes().length); - } - public void testSliceMemorySpace() + + public void testSliceAddressBuffers() { - verifySlice(memorySpaceByteBuffer, LocalMemory.getFuncAddr(), + for (int i = 0; i < addressBuffers.length; i++) + verifySlice(addressBuffers[i], LocalMemory.getFuncAddr(), LocalMemory.getFuncBytes().length); } - public void testSliceRegisterSet() + + public void testSliceRegisterBuffers() { - if (registerByteBuffer == null) { - System.out.print("<>"); - return; - } - verifySlice(registerByteBuffer, 4, 4); + for (int i = 0; i < registerBuffers.length; i++) + verifySlice(registerBuffers[i], 4, 4); } private void verifyModify(ByteBuffer buffer, long addr) @@ -108,21 +169,18 @@ buffer.putByte(addr, (byte)~oldByte); assertEquals ("modified", (byte)~oldByte, buffer.get(addr)); } - public void testModifyRegisterSet() - { - if (RegisterSet.REGS == null) { - System.out.print("<>"); - return; - } - verifyModify(registerByteBuffer, 0); - } - public void testModifyAddressSpace() + + public void testModifyRegisterBuffers() { - verifyModify(addressSpaceByteBuffer, LocalMemory.getFuncAddr()); + for (int i = 0; i < registerBuffers.length; i++) + verifyModify(registerBuffers[i], 0); } - public void testModifyMemorySpace() + + public void testModifyAddressBuffers() { - verifyModify(memorySpaceByteBuffer, LocalMemory.getFuncAddr()); + for (int i = 0; i < addressBuffers.length; i++) + if (! (addressBuffers[i] instanceof LogicalMemoryBuffer)) + verifyModify(addressBuffers[i], LocalMemory.getFuncAddr()); } private void verifyAsyncModify(ByteBuffer buffer, long addr) { @@ -171,19 +229,137 @@ asyncModify.newByte); } } - public void testAsyncRegisterSet() { - if (registerByteBuffer == null) { - System.out.print("<>"); - return; - } - verifyAsyncModify(registerByteBuffer, 0); - } - public void testAsyncAddressSpace() { - verifyAsyncModify(addressSpaceByteBuffer, - LocalMemory.getFuncAddr()); - } - public void testAsyncMemorySpace() { - verifyAsyncModify(memorySpaceByteBuffer, - LocalMemory.getFuncAddr()); + public void testAsyncRegisterBuffers() { + for (int i = 0; i < registerBuffers.length; i++) + verifyAsyncModify(registerBuffers[0], 0); + } + + public void testAsyncAddressBuffers() { + for (int i = 0; i < addressBuffers.length; i++) + if (! (addressBuffers[i] instanceof LogicalMemoryBuffer)) + verifyAsyncModify(addressBuffers[i], + LocalMemory.getFuncAddr()); + } + + public void verifyPeeks(ByteBuffer buffer, long addr, byte[] origBytes) + { + byte bytes[] = new byte[origBytes.length]; + buffer.get(addr, bytes, 0, bytes.length); + for (int i = 0; i < bytes.length; i++) + assertEquals ("byte at " + i, bytes[i], origBytes[i]); + } + + public void testAddressBufferPeeks() + { + long addr = LocalMemory.getFuncAddr(); + byte[] origBytes = LocalMemory.getFuncBytes(); + for (int i = 0; i < addressBuffers.length; i++) + verifyPeeks(addressBuffers[i], addr, origBytes); + } + + public void testRegisterBufferPeeks() + { + // Check that simple get loop is similar to bulk get. + long addr = 4; + byte[] origBytes = new byte[16]; + for (int i = 0; i < registerBuffers.length; i++) + { + for (int j = 0; j < origBytes.length; j++) + origBytes[j] = registerBuffers[i].get(addr + j); + verifyPeeks(registerBuffers[i], addr, origBytes); + } + } + private class AsyncPeeks + implements Runnable + { + private ByteBuffer buffer; + private long addr; + private int length; + private byte[] bytes; + private Exception e; + AsyncPeeks (ByteBuffer buffer, long addr, int length) + { + this.buffer = buffer; + this.addr = addr; + this.length = length; + this.bytes = new byte[length]; + } + public void run () + { + try { + buffer.get (addr, bytes, 0, length); + } + catch (Exception e) { + this.e = e; + } + Manager.eventLoop.requestStop(); + } + void call (byte[] origBytes) + { + // Force the event loop to running on this thread. Ugly, and is to + // to be removed when bug #4688 is resolved. + Manager.eventLoop.runPolling(1); + new Thread (this).start(); + assertTrue("waiting for async peeks", + Manager.eventLoop.runPolling(getTimeoutMilliseconds())); + if (e != null) + throw new RuntimeException (e); + for (int i = 0; i < length; i++) { + assertEquals ("byte at " + i, bytes[i], origBytes[i]); + } + } + } + + public void testAsyncPeeks () + { + byte[] origBytes = LocalMemory.getFuncBytes(); + for (int i = 0; i < addressBuffers.length; i++) + new AsyncPeeks(addressBuffers[i], LocalMemory.getFuncAddr(), + LocalMemory.getFuncBytes().length).call(origBytes); + } + + public void testAsycnPeeksRegisters() + { + // Check position() and (async) get() + int length = 8; + byte[] origBytes = new byte[length]; + long address = 4; + for (int i = 0; i < registerBuffers.length; i++) + { + registerBuffers[i].position(address); + registerBuffers[i].get(origBytes); + new AsyncPeeks(registerBuffers[i], address, + length).call(origBytes); + } } + + private void verifyBulkPut(ByteBuffer buffer, long addr, int len) + { + // Pasting the same bytes back over the old buffer in bulk + // and read it back in. + byte[] oldBytes = new byte[len]; + buffer.position(addr); + buffer.get(oldBytes); + buffer.position(addr); + buffer.put(oldBytes); + byte[] newBytes = new byte[len]; + buffer.position(addr); + buffer.get(newBytes); + assertTrue(Arrays.equals(oldBytes, newBytes)); + } + + public void testBulkPutRegisterBuffers() + { + for (int i = 0; i < registerBuffers.length; i++) + verifyBulkPut(registerBuffers[i], 4, 4); + } + + public void testBulkPutAddressBuffers() + { + for (int i = 0; i < addressBuffers.length; i++) + if (! (addressBuffers[i] instanceof LogicalMemoryBuffer)) + verifyBulkPut(addressBuffers[i], LocalMemory.getFuncAddr(), + LocalMemory.getFuncBytes().length); + } + } Index: frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java =================================================================== RCS file: frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java diff -N frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java --- frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java 30 Jul 2007 12:42:08 -0000 1.3 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,123 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2007 Oracle Corporation. -// Copyright 2007, Red Hat Inc. -// -// FRYSK is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License as published by -// the Free Software Foundation; version 2 of the License. -// -// FRYSK is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with FRYSK; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// In addition, as a special exception, Red Hat, Inc. gives You the -// additional right to link the code of FRYSK with code not covered -// under the GNU General Public License ("Non-GPL Code") and to -// distribute linked combinations including the two, subject to the -// limitations in this paragraph. Non-GPL Code permitted under this -// exception must only link to the code of FRYSK through those well -// defined interfaces identified in the file named EXCEPTION found in -// the source code files (the "Approved Interfaces"). The files of -// Non-GPL Code may instantiate templates or use macros or inline -// functions from the Approved Interfaces without causing the -// resulting work to be covered by the GNU General Public -// License. Only Red Hat, Inc. may make changes or additions to the -// list of Approved Interfaces. You must obey the GNU General Public -// License in all respects for all of the FRYSK code and other code -// used in conjunction with FRYSK except the Non-GPL Code covered by -// this exception. If you modify this file, you may extend this -// exception to your version of the file, but you are not obligated to -// do so. If you do not wish to provide this exception without -// modification, you must delete this exception statement from your -// version and license this file solely under the GPL without -// exception. - -package frysk.proc.live; - -import frysk.junit.TestCase; -import frysk.testbed.TearDownProcess; -import frysk.testbed.AttachedSelf; -import frysk.testbed.LocalMemory; -import frysk.proc.Manager; - -public class TestMemorySpaceByteBuffer - extends TestCase -{ - public void tearDown() - { - TearDownProcess.tearDown(); - } - private int pid; - private MemorySpaceByteBuffer memorySpaceByteBuffer; - - public void setUp () - { - pid = new AttachedSelf().hashCode(); - memorySpaceByteBuffer = new MemorySpaceByteBuffer (pid); - } - - public void testPeeks () - { - long addr = LocalMemory.getFuncAddr(); - int length = LocalMemory.getFuncBytes().length; - byte bytes[] = new byte[(int)length]; - memorySpaceByteBuffer.peek (addr, bytes, 0, length); - byte[] origBytes = LocalMemory.getFuncBytes(); - for (int i = 0; i < length; i++) { - assertEquals ("byte at " + i, bytes[i], origBytes[i]); - } - } - - private class AsyncPeeks - implements Runnable - { - private MemorySpaceByteBuffer buffer; - private long addr; - private int length; - private byte[] bytes; - private Exception e; - AsyncPeeks (MemorySpaceByteBuffer buffer, long addr, int length) - { - this.buffer = buffer; - this.addr = addr; - this.length = length; - this.bytes = new byte[length]; - } - public void run () - { - try { - buffer.peek (addr, bytes, 0, length); - } - catch (Exception e) { - this.e = e; - } - Manager.eventLoop.requestStop(); - } - void call () - { - // Force the event loop to running on this thread. Ugly, and is to - // to be removed when bug #4688 is resolved. - Manager.eventLoop.runPolling(1); - new Thread (this).start(); - assertTrue("waiting for async peeks", - Manager.eventLoop.runPolling(getTimeoutMilliseconds())); - if (e != null) - throw new RuntimeException (e); - byte[] origBytes = LocalMemory.getFuncBytes(); - for (int i = 0; i < length; i++) { - assertEquals ("byte at " + i, bytes[i], origBytes[i]); - } - } - } - public void testAsyncPeeks () - { - new AsyncPeeks(memorySpaceByteBuffer, LocalMemory.getFuncAddr(), - LocalMemory.getFuncBytes().length).call(); - } -} Index: frysk-sys/inua/eio/ByteBuffer.java =================================================================== RCS file: /cvs/frysk/frysk-sys/inua/eio/ByteBuffer.java,v retrieving revision 1.2 diff -u -r1.2 ByteBuffer.java --- frysk-sys/inua/eio/ByteBuffer.java 30 Jul 2007 12:42:09 -0000 1.2 +++ frysk-sys/inua/eio/ByteBuffer.java 2 Aug 2007 10:48:35 -0000 @@ -372,6 +372,21 @@ return get(dst, 0, dst.length); } + public ByteBuffer put (byte[] src, int off, int len) + throws BufferUnderflowException + { + if (ULong.GT(len, remaining())) + throw new BufferUnderflowException(); + poke(cursor, src, off, len); + cursor += len; + return this; + } + + public final ByteBuffer put (byte[] src) throws BufferUnderflowException + { + return put(src, 0, src.length); + } + protected ByteOrdered byteOrdered; public final ByteOrder order () --=-G/hYcuwqLnVXsOHFKG9+--