001 // This file is part of the program FRYSK. 002 // 003 // Copyright 2007, 2008, Red Hat Inc. 004 // 005 // FRYSK is free software; you can redistribute it and/or modify it 006 // under the terms of the GNU General Public License as published by 007 // the Free Software Foundation; version 2 of the License. 008 // 009 // FRYSK is distributed in the hope that it will be useful, but 010 // WITHOUT ANY WARRANTY; without even the implied warranty of 011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 // General Public License for more details. 013 // 014 // You should have received a copy of the GNU General Public License 015 // along with FRYSK; if not, write to the Free Software Foundation, 016 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 017 // 018 // In addition, as a special exception, Red Hat, Inc. gives You the 019 // additional right to link the code of FRYSK with code not covered 020 // under the GNU General Public License ("Non-GPL Code") and to 021 // distribute linked combinations including the two, subject to the 022 // limitations in this paragraph. Non-GPL Code permitted under this 023 // exception must only link to the code of FRYSK through those well 024 // defined interfaces identified in the file named EXCEPTION found in 025 // the source code files (the "Approved Interfaces"). The files of 026 // Non-GPL Code may instantiate templates or use macros or inline 027 // functions from the Approved Interfaces without causing the 028 // resulting work to be covered by the GNU General Public 029 // License. Only Red Hat, Inc. may make changes or additions to the 030 // list of Approved Interfaces. You must obey the GNU General Public 031 // License in all respects for all of the FRYSK code and other code 032 // used in conjunction with FRYSK except the Non-GPL Code covered by 033 // this exception. If you modify this file, you may extend this 034 // exception to your version of the file, but you are not obligated to 035 // do so. If you do not wish to provide this exception without 036 // modification, you must delete this exception statement from your 037 // version and license this file solely under the GPL without 038 // exception. 039 040 package frysk.rt; 041 042 import java.util.Iterator; 043 import frysk.rsl.Log; 044 import frysk.proc.Action; 045 import frysk.proc.Observable; 046 import frysk.proc.Task; 047 import frysk.proc.TaskObserver; 048 import frysk.stepping.SteppingEngine; 049 050 public class Breakpoint implements TaskObserver.Code { 051 private static final Log fine = Log.fine(Breakpoint.class); 052 053 protected long address; 054 055 protected int triggered; 056 057 protected boolean added; 058 059 protected boolean removed; 060 061 protected Object monitor = new Object(); 062 063 protected SteppingEngine steppingEngine; 064 065 public Breakpoint (SteppingEngine steppingEngine) { 066 this.steppingEngine = steppingEngine; 067 } 068 069 public Breakpoint (SteppingEngine steppingEngine, long address) { 070 // System.out.println("Setting address to 0x" + Long.toHexString(address)); 071 this.steppingEngine = steppingEngine; 072 this.address = address; 073 } 074 075 public Action updateHit (Task task, long address) { 076 077 fine.log(this, "updateHit task", task, "address", address); 078 if (address != this.address) { 079 fine.log(this, "updateHit task", task, "address", address, 080 "wrong address!"); 081 return Action.CONTINUE; 082 } 083 else { 084 fine.log(this, "updateHit calling blockedByActionPoint", task, 085 "address", address); 086 this.steppingEngine.blockedByActionPoint(task, this); 087 task.requestUnblock(this); 088 } 089 090 ++triggered; 091 return Action.BLOCK; 092 } 093 094 public int getTriggered () { 095 return triggered; 096 } 097 098 public void addFailed (Object observable, Throwable w) { 099 w.printStackTrace(); 100 } 101 102 public void addedTo (Object observable) { 103 synchronized (monitor) { 104 added = true; 105 removed = false; 106 monitor.notifyAll(); 107 } 108 // System.err.println("BreakPoint.addedTo"); 109 ((Task) observable).requestDeleteInstructionObserver(this.steppingEngine.getSteppingObserver()); 110 } 111 112 public boolean isAdded () { 113 return added; 114 } 115 116 public void deletedFrom (Object observable) { 117 synchronized (monitor) { 118 removed = true; 119 added = false; 120 monitor.notifyAll(); 121 } 122 } 123 124 public boolean isRemoved () { 125 return removed; 126 } 127 128 public long getAddress() { 129 return address; 130 } 131 132 static public class PersistentBreakpoint extends Breakpoint { 133 134 /* 135 * A breakpoint added by a high-level action e.g., set by the 136 * user. It is not meant to be transient and applies only to one task. 137 */ 138 private Observable observable; 139 private final Task targetTask; 140 141 public Task getTargetTask() { 142 return targetTask; 143 } 144 145 public PersistentBreakpoint(Task targetTask, long address, 146 SteppingEngine steppingEngine) { 147 super(steppingEngine, address); 148 observable = new Observable(this); 149 this.targetTask = targetTask; 150 } 151 152 // These operations synchronize on the breakpoint, not the 153 // observable object, so that other users of PersistentBreakpoint 154 // can synchronize too without having to make the observable public. 155 public synchronized void addObserver(BreakpointObserver observer) { 156 observable.add(observer); 157 } 158 159 public synchronized void deleteObserver(BreakpointObserver observer) { 160 observable.delete(observer); 161 } 162 163 public Iterator observersIterator() { 164 return observable.iterator(); 165 } 166 167 public synchronized int numberOfObservers() { 168 return observable.numberOfObservers(); 169 } 170 171 public synchronized void removeAllObservers() { 172 observable.removeAllObservers(); 173 } 174 175 public Action updateHit(Task task, long address) { 176 if (task != targetTask) 177 return Action.CONTINUE; 178 fine.log(this, "updateHit task", task, "address", address); 179 Action action = super.updateHit(task, address); 180 181 synchronized (SteppingEngine.class) { 182 steppingEngine.getRunningTasks().remove(task); 183 } 184 185 synchronized (this) { 186 Iterator iterator = observable.iterator(); 187 while (iterator.hasNext()) { 188 BreakpointObserver observer 189 = (BreakpointObserver)iterator.next(); 190 observer.updateHit(this, task, address); 191 } 192 } 193 return action; 194 } 195 196 public void addedTo (Object observable) { 197 synchronized (monitor) { 198 added = true; 199 removed = false; 200 monitor.notifyAll(); 201 } 202 // Don't remove the current insturction observer. 203 } 204 } 205 206 // public PersistentBreakpoint getTaskPersistentBreakpoint(Task task) 207 // { 208 // return (PersistentBreakpoint) SteppingEngine.getTaskBreakpoint(task); 209 // } 210 211 public void addPersistentBreakpoint(Task task, PersistentBreakpoint bp) { 212 task.requestAddCodeObserver(bp, bp.getAddress()); 213 } 214 215 public void deletePersistentBreakpoint(Task task, PersistentBreakpoint bp) { 216 task.requestDeleteCodeObserver(bp, bp.getAddress()); 217 } 218 }