001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.mm.mmtk.gcspy;
014    
015    import org.mmtk.utility.Log;
016    import org.mmtk.vm.VM;
017    import org.mmtk.utility.gcspy.GCspy;
018    
019    import static org.jikesrvm.runtime.SysCall.sysCall;
020    import org.jikesrvm.objectmodel.JavaHeaderConstants;
021    
022    import org.vmmagic.unboxed.*;
023    import org.vmmagic.pragma.*;
024    
025    /**
026     * Generic GCspy Server Interpreter
027     *
028     * This class implements the GCspy server.
029     * The server runs as a separate pthread and communicates with GCspy
030     * clients. It handles commands from the client and passes data to it.
031     * Mostly it forwards calls to the C gcspy library.
032     */
033    @Uninterruptible public class ServerInterpreter extends org.mmtk.vm.gcspy.ServerInterpreter
034      implements JavaHeaderConstants {
035    
036    
037      /**
038       * Create a new ServerInterpreter singleton.
039       * @param name The name of the server
040       * @param port The number of the port on which to communicate
041       * @param verbose Whether the server is to run verbosely
042       */
043      @Interruptible
044      public void init(String name, int port, boolean verbose) {
045        if (org.jikesrvm.VM.BuildWithGCSpy) {
046          if (VM.VERIFY_ASSERTIONS)
047            VM.assertions._assert(!initialised, "Tried to re-init server interpreter");
048          initialised = true;
049    
050          if (DEBUG)
051            Log.writeln("-- Initialising main server on port ",port);
052    
053          Address tmp = GCspy.util.getBytes(name);
054          server = sysCall.gcspyMainServerInit(port, MAX_LEN, tmp, verbose?1:0);
055    
056          if (DEBUG) {
057            Log.writeln("gcspy_main_server_t address = "); Log.writeln(server);
058          }
059    
060          GCspy.util.free(tmp);
061          // Set up the list of ServerSpaces
062          spaces = new org.jikesrvm.mm.mmtk.gcspy.ServerSpace[MAX_SPACES];
063        }
064      }
065    
066      /**
067       * Add an event to the ServerInterpreter.
068       * @param num the event number
069       * @param name the event name
070       */
071      public void addEvent(int num, String name) {
072        if (org.jikesrvm.VM.BuildWithGCSpy) {
073          if (VM.VERIFY_ASSERTIONS)
074            VM.assertions._assert(initialised,
075                           "ServerInterpreter.addEvent: server not initiialised");
076    
077          Address tmp = GCspy.util.getBytes(name);
078          sysCall.gcspyMainServerAddEvent(server, num, tmp);
079          GCspy.util.free(tmp);
080        }
081      }
082    
083      /**
084       * Set the general info for the ServerInterpreter.
085       * @param info the information
086       */
087      public void setGeneralInfo(String info) {
088        if (org.jikesrvm.VM.BuildWithGCSpy) {
089          if (VM.VERIFY_ASSERTIONS)
090            VM.assertions._assert(initialised,
091                           "ServerInterpreter.setGeneralInfo: server not initiialised");
092    
093          Address tmp = GCspy.util.getBytes(info);
094          sysCall.gcspyMainServerSetGeneralInfo(server, tmp);
095          GCspy.util.free(tmp);
096        }
097      }
098    
099      /**
100       * Start the server, running its main loop in a pthread.
101       * @param wait Whether to wait for the client to connect
102       */
103      public void startServer(boolean wait) {
104        if (org.jikesrvm.VM.BuildWithGCSpy) {
105          if (DEBUG) { Log.write("Starting GCSpy server, wait="); Log.writeln(wait); }
106    
107          Address serverOuterLoop = sysCall.gcspyMainServerOuterLoop();
108          sysCall.gcspyStartserver(server, wait?1:0, serverOuterLoop);
109        }
110      }
111    
112      /**
113       * Are we connected to a GCspy client?
114       * @param event The current event
115       * @return true if we are connected
116       */
117      public boolean isConnected(int event) {
118        if (org.jikesrvm.VM.BuildWithGCSpy) {
119          if (DEBUG)
120            Log.writeln("ServerInterpreter.isConnected, server=", server);
121    
122          if (!initialised)
123            return false;
124          int res = sysCall.gcspyMainServerIsConnected(server, event);
125          return (res != 0);
126        } else {
127          return false;
128        }
129      }
130    
131      /**
132       * Start compensation timer so that time spent gathering data is
133       * not confused with the time spent in the application and the VM.
134       */
135      public void startCompensationTimer() {
136        if (org.jikesrvm.VM.BuildWithGCSpy) {
137          if (VM.VERIFY_ASSERTIONS)
138            VM.assertions._assert(initialised,
139                           "ServerInterpreter.startCompensationTimer: server not initiialised");
140    
141          sysCall.gcspyMainServerStartCompensationTimer(server);
142        }
143      }
144    
145      /**
146       * Stop compensation timer so that time spent gathering data is
147       * not confused with the time spent in the application and the VM.r
148       */
149      public void stopCompensationTimer() {
150        if (org.jikesrvm.VM.BuildWithGCSpy) {
151          if (VM.VERIFY_ASSERTIONS)
152            VM.assertions._assert(initialised,
153                           "ServerInterpreter.stopCompensationTimer: server not initiialised");
154    
155          sysCall.gcspyMainServerStopCompensationTimer(server);
156        }
157      }
158    
159      /**
160       * Indicate that we are at a server safe point (e.g. the end of a GC).
161       * This is a point at which the server can pause, play one, etc.
162       * @param event The current event
163       */
164      public void serverSafepoint(int event) {
165        if (org.jikesrvm.VM.BuildWithGCSpy) {
166          if (DEBUG)
167            Log.writeln("ServerInterpreter.serverSafepoint, server=", server);
168    
169          if (!initialised)
170            return;
171          sysCall.gcspyMainServerSafepoint(server, event);
172        }
173      }
174    
175      /**
176       * Discover the smallest header size for objects.
177       * @return the size in bytes
178       */
179      public int computeHeaderSize() {
180        return JAVA_HEADER_BYTES+OTHER_HEADER_BYTES;
181      }
182    }