Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

xdprof.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2001, John Lambert jlambert@jlambert.com
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are 
00006 permitted provided that the following conditions are met:
00007 
00008 Redistributions of source code must retain the above copyright notice, this list of 
00009 conditions and the following disclaimer.
00010 
00011 Redistributions in binary form must reproduce the above copyright notice, this list
00012 of conditions and the following disclaimer in the documentation and/or other
00013 materials provided with the distribution. 
00014 
00015 Neither the name of the xdProf project nor the names of its contributors may be used
00016 to endorse or promote products derived from this software without specific prior 
00017 written permission. 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
00020 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00021 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00022 SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00023 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00024 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
00025 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00026 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
00027 WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028 */
00029 
00030 /*
00031 $Header: /xdprof-dll/xdprof.cpp 26    5/09/01 5:29a Admin $ 
00032  */
00033 #include "xdprof.h"
00034 
00036 MethodMap Methods;
00037 
00039 ThreadMap Threads;
00040 
00042 ClassMethopMap ClassMethods;
00043 
00045 ClassInfoMap Classes;
00046 
00048 // TODO: figure out emptying them out
00049 MethodMap MethodCache;
00050 ClassInfoMap ClassCache;
00051 
00052 
00054 static set<ThreadID> DeadThreads;
00055 
00057 
00058 
00060 static bool CaughtVM = false;
00061 
00062 static unsigned long threadcount = 0;
00063 
00067 inline void ThreadStartHandler(ThreadID thread_id, const ThreadInfo & ti)
00068 {
00069     Lock(threads_lock);
00070     ti.setStarted(++threadcount);
00071     Threads[thread_id] = ti;
00072     Unlock(threads_lock);
00073 }
00074 
00075 static void DeleteMethods()
00076 {
00077     for (MethodMap::iterator mi = Methods.begin(); mi != Methods.end(); ++mi)
00078         delete mi->second;
00079 }
00080 
00084 inline void ThreadEndHandler(JNIEnv *thread_id)
00085 {
00086     Lock(threads_lock);
00088     debug("thread end", thread_id , Threads.size());
00089     int k = Threads.erase(thread_id);
00090     DeadThreads.insert(thread_id);
00091     assert(k == 1);
00092     debug("remove ", thread_id, k);
00093     Unlock(threads_lock);
00094 }
00095 
00102 void NotifyEvent(JVMPI_Event *event)
00103 {
00104     switch(event->event_type)
00105     {
00106     case JVMPI_EVENT_CLASS_LOAD: 
00107     case JVMPI_EVENT_CLASS_LOAD | JVMPI_REQUESTED_EVENT:
00108         Lock(methods_lock);
00109         ClassLoadEvent(event->env_id, 
00110                     const_cast<char**>(& event->u.class_load.class_name),
00111                    &event->u.class_load.source_name,
00112                    event->u.class_load.num_interfaces,
00113                    event->u.class_load.num_static_fields,
00114                    event->u.class_load.statics,
00115                    event->u.class_load.num_instance_fields,
00116                    event->u.class_load.instances,
00117                    event->u.class_load.num_methods,
00118                    event->u.class_load.methods,
00119                    event->u.class_load.class_id,
00120                    event->event_type);
00121         Unlock(methods_lock);
00122         return;
00123 
00124     case JVMPI_EVENT_CLASS_UNLOAD: 
00125         ClassUnloadEvent(event->u.class_unload.class_id);
00126         return;
00127     
00128     case JVMPI_EVENT_THREAD_START:
00129     case JVMPI_EVENT_THREAD_START | JVMPI_REQUESTED_EVENT:
00130         {
00131             debug("threadstart: ", event->env_id, event->u.thread_start.thread_env_id, (event->u.thread_start.thread_name != null) ? event->u.thread_start.thread_name : "null");
00132             ThreadInfo ti(event->u.thread_start.thread_name,
00133                 event->u.thread_start.group_name,
00134                 event->u.thread_start.parent_name,
00135                 event->u.thread_start.thread_id,
00136                 event->u.thread_start.thread_env_id);
00137             //cerr << event->u.thread_start.thread_env_id << endl;
00138             ThreadStartHandler(event->u.thread_start.thread_env_id, ti);
00139         }
00140         return;
00141         
00142     case JVMPI_EVENT_THREAD_END:
00143         //cerr << "remove " << event->env_id << endl;
00144         ThreadEndHandler(event->env_id);
00145         return;
00146 
00147     case JVMPI_EVENT_OBJECT_ALLOC:
00148         {
00149             if (event->u.obj_alloc.class_id == null)
00150                 return;
00151 
00152             debug("alloc", event->env_id, event->u.obj_alloc.class_id, event->u.obj_alloc.obj_id);
00153 
00154             // if we haven't caught the VM loading classes, we want to see if we can
00155             if (!CaughtVM)
00156             {
00157                 // check thread
00158                 Lock(threads_lock);
00159                 bool loadThread = (Threads.find(event->env_id) == Threads.end()) &&
00160                                   (DeadThreads.find(event->env_id) == DeadThreads.end());
00161                 Unlock(threads_lock);
00162 
00163                 if (loadThread)
00164                 {
00165                     jobjectID o = CALL(GetThreadObject)(event->env_id);
00166                     if ((o != null) && (o != event->u.obj_alloc.obj_id))
00167                     {
00168                         debug("in alloc, about to call RequestEvent JVMPI_EVENT_THREAD_START" , o);
00169                         CHECKEDCALL(RequestEvent(JVMPI_EVENT_THREAD_START, o));
00170                         debug("back from thread start");
00171                         CaughtVM = true;
00172                         CHECKEDCALL(DisableEvent(JVMPI_EVENT_OBJECT_ALLOC, NULL));
00173                     }
00174                 }
00175             }
00176             else
00177             {
00178             //  debug("CaughtVM == true!");
00179                 // should never be reached
00180             }
00181         }
00182         return;
00183 
00184     case JVMPI_EVENT_JVM_SHUT_DOWN:
00185         {
00186         ShutdownRequested = true;
00187         CALL(RawMonitorNotifyAll(BackgroundMonitor));
00188         
00189         //{ for (int tdu = 0; tdu < 10; ++tdu) ThreadDump("???\n", event->env_id); }
00190 
00191         //Lock(output_lock);
00192         ShutdownCommunications();
00193         //Unlock(output_lock);
00194         
00195         ShutdownMonitors();
00196         //DeleteMethods();
00197         }
00198         return;
00199 
00200     case JVMPI_EVENT_JVM_INIT_DONE:
00201         debug("Init done!!!", event->env_id );
00202         CreateBackgroundThread();
00203         return;
00204 
00205 
00206     default:
00207         unsafe_debug("Unhandled event", event->event_type);
00208         return;
00209     } // end switch
00210 } // end notifyEvent
00211 
00212 
00213 

Generated at Sun Jun 24 20:57:16 2001 for xdprof by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001