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

sampling.cpp

00001 /*
00002  *                         Sun Public License Notice
00003  *
00004  * The contents of this file are subject to the Sun Public License
00005  * Version 1.0 (the "License"); you may not use this file except
00006  * in compliance with the License. A copy of the License is available
00007  * at http://www.sun.com/
00008  *
00009  * The Original Code is the Java Profiler module.  The Initial Developers
00010  * of the Original Code are Jan Stola, Pavel Vacha, Michal Pise, Petr Luner,
00011  * Lukas Petru and Marek Przeczek.
00012  *
00013  * Portions created by Jan Stola are Copyright (C) 2000-2001.
00014  * All Rights Reserved.
00015  *
00016  * Portions created by Pavel Vacha are Copyright (C) 2000-2001.
00017  * All Rights Reserved.
00018  *
00019  * Portions created by Michal Pise are Copyright (C) 2000-2001.
00020  * All Rights Reserved.
00021  *
00022  * Portions created by Petr Luner are Copyright (C) 2000-2001.
00023  * All Rights Reserved.
00024  *
00025  * Portions created by Lukas Petru are Copyright (C) 2000-2001.
00026  * All Rights Reserved.
00027  *
00028  * Portions created by Marek Przeczek are Copyright (C) 2000-2001.
00029  * All Rights Reserved.
00030  *
00031  * Contributors: Jan Stola, Pavel Vacha, Michal Pise, Petr Luner,
00032  *               Lukas Petru and Marek Przeczek.
00033  */
00034 
00035 #include "../cpu/sampling.h"
00036 #include "../prof/prof.h"
00037 #include "../delay/delay.h"
00038 #include "../prof/synchronized.h"
00039 #include "../cpu/cpuThreadMethod.h"
00040 #include "../cpu/cpuThreadTrace.h"
00041 #include "../cpu/cpuTrace.h"
00042 
00043 Sampling::Sampling( JVMPI_Interface* jvmpi) :
00044 
00045 #ifdef USE_RAW_MONITORS
00046         _lock( "_sampling_raw_monitor", jvmpi),
00047 #endif
00048         _terminated( 1) {
00049 
00050         _cmd = CMD_TURN_ON;
00051 
00052 #ifndef USE_RAW_MONITORS
00053 #ifdef WIN32
00054         _turnedOn = CreateEvent(NULL, TRUE, TRUE, NULL);
00055         InitializeCriticalSection(&_cs);
00056 #else
00057         pthread_cond_init(&_cond, NULL);
00058         pthread_mutex_init(&_mutex, NULL);
00059 #endif
00060 #endif
00061 
00062 #ifdef _DEBUG
00063         start = 0;
00064         finish = 0;
00065         samples = 0;
00066 #endif
00067 }
00068 
00069 Sampling::~Sampling() {
00070 
00071 #ifndef USE_RAW_MONITORS
00072 #ifdef WIN32
00073         CloseHandle(_turnedOn);
00074         DeleteCriticalSection(&_cs);
00075 #else
00076         pthread_cond_destroy(&_cond);
00077         pthread_mutex_destroy(&_mutex);
00078 #endif
00079 #endif
00080 }
00081 
00082 void Sampling::main() {
00083 
00084         _terminated = 0;
00085 
00086         Prof* _prof = &Prof::prof();
00087         unsigned long waitTime = 1;
00088         unsigned long avgSampleTime = 1;
00089         unsigned long lastSampleTime;
00090         unsigned long startTime;
00091         unsigned long endTime;
00092 
00093 #ifdef _DEBUG
00094         start = Delay::getMilliticks();
00095 #endif
00096 
00097         for (;;) {
00098 
00099 #ifndef USE_RAW_MONITORS
00100 #ifdef WIN32
00101                 WaitForSingleObject(_turnedOn, INFINITE);
00102 #else
00103                 pthread_mutex_lock(&_mutex);
00104                 while (_cmd == CMD_TURN_OFF)
00105                         pthread_cond_wait(&_cond, &_mutex);
00106                 pthread_mutex_unlock(&_mutex);
00107 #endif
00108 #endif
00109 
00110 #ifdef USE_RAW_MONITORS
00111                 Synchronized sync( _lock);
00112 #endif
00113 
00114                 if (_cmd == CMD_TERMINATE) {
00115 
00116                         _terminated = 1;
00117                         return;
00118                 }
00119 
00120 #ifdef USE_RAW_MONITORS
00121                 sync.release();
00122 #endif
00123 
00124                 _prof->gcLock.wait();
00125                 _prof->jvmpiInterface->DisableGC(); 
00126                 _prof->dataLock.wait();
00127 
00128                 if (_cmd != CMD_TURN_ON) {
00129                         _prof->dataLock.release();
00130                         _prof->jvmpiInterface->EnableGC(); 
00131                         _prof->gcLock.release(); 
00132                         continue;
00133                 }
00134 
00135                 startTime = Delay::getMilliticks();
00136                 doOneSample();
00137                 endTime = Delay::getMilliticks();
00138 
00139 #ifdef _DEBUG
00140                 finish = endTime;
00141 #endif
00142 
00143                 _prof->dataLock.release();
00144                 _prof->jvmpiInterface->EnableGC(); 
00145                 _prof->gcLock.release(); 
00146 
00147                 if (endTime > startTime) {
00148 
00149                         lastSampleTime = endTime - startTime;
00150                         avgSampleTime = (int)(.9 * avgSampleTime + .1 * lastSampleTime);
00151                         if (avgSampleTime == 0) avgSampleTime = 1;
00152 
00153                         waitTime = avgSampleTime;
00154                         if (waitTime == 0) waitTime = 1;
00155                 }
00156 
00157                 if (_cmd != CMD_TURN_ON) continue;
00158 
00159                 Delay::delay(waitTime);
00160         }
00161 }
00162 
00163 int Sampling::startThread(int turnedOn) {
00164 
00165 #ifndef USE_RAW_MONITORS
00166 #ifdef WIN32
00167         if (turnedOn) {
00168 
00169                 _cmd = CMD_TURN_ON;
00170                 SetEvent(_turnedOn);
00171         }
00172         else {
00173                 
00174                 _cmd = CMD_TURN_OFF;
00175                 ResetEvent(_turnedOn);
00176         }
00177 #else
00178         if (turnedOn) _cmd = CMD_TURN_ON;
00179         else _cmd = CMD_TURN_OFF;
00180 #endif
00181 #else
00182         if( !turnedOn) {
00183 
00184                 _cmd = CMD_TURN_OFF;
00185                 return 0;
00186         }
00187 #endif
00188 
00189         if (Prof::prof().jvmpiInterface->CreateSystemThread((char*)SAMPLING_THREAD,
00190                         JVMPI_NORMAL_PRIORITY, Sampling::samplingMain) == JNI_OK) return 0;
00191         return -1;
00192 }
00193 
00194 void Sampling::terminateThread() {
00195 
00196 #ifndef USE_RAW_MONITORS
00197 #ifdef WIN32
00198         EnterCriticalSection(&_cs);
00199 
00200         _cmd = CMD_TERMINATE;
00201         SetEvent(_turnedOn);
00202 
00203         LeaveCriticalSection(&_cs);
00204 #else
00205         pthread_mutex_lock(&_mutex);
00206 
00207         _cmd = CMD_TERMINATE;
00208         pthread_cond_signal(&_cond);
00209 
00210         pthread_mutex_unlock(&_mutex);
00211 #endif
00212 #else
00213         Synchronized sync( _lock);
00214         _cmd = CMD_TERMINATE;
00215 #endif
00216 }
00217 
00218 #ifndef USE_RAW_MONITORS
00219 void Sampling::turnOn() {
00220 
00221 #ifdef WIN32
00222         EnterCriticalSection(&_cs);
00223 
00224         if (_cmd != CMD_TERMINATE) {
00225 
00226                 _cmd = CMD_TURN_ON;
00227                 SetEvent(_turnedOn);
00228         }
00229 
00230         LeaveCriticalSection(&_cs);
00231 #else
00232         pthread_mutex_lock(&_mutex);
00233 
00234         if (_cmd != CMD_TERMINATE) {
00235 
00236                 _cmd = CMD_TURN_ON;
00237                 pthread_cond_signal(&_cond);
00238         }
00239 
00240         pthread_mutex_unlock(&_mutex);
00241 #endif
00242 }
00243 
00244 void Sampling::turnOff() {
00245 
00246 #ifdef WIN32
00247         EnterCriticalSection(&_cs);
00248 
00249         if (_cmd != CMD_TERMINATE) {
00250 
00251                 _cmd = CMD_TURN_OFF;
00252                 ResetEvent(_turnedOn);
00253         }
00254 
00255         LeaveCriticalSection(&_cs);
00256 #else
00257         pthread_mutex_lock(&_mutex);
00258 
00259         if (_cmd != CMD_TERMINATE) {
00260 
00261                 _cmd = CMD_TURN_OFF;
00262         }
00263 
00264         pthread_mutex_unlock(&_mutex);
00265 #endif
00266 }
00267 #endif // !USE_RAW_MONITORS
00268 
00269 void Sampling::doOneSample() {
00270 
00271         Prof* _prof = &Prof::prof();
00272         Thread* suspendList = NULL;
00273         Thread* thread;
00274         JNIEnv* envId;
00275         jint status;
00276         JVMPI_CallTrace* trace;
00277         JVMPI_CallFrame* frames;
00278         int traceDepth;
00279         int numFrames;
00280         CpuStatData* stat;
00281 
00282 #ifdef _DEBUG
00283         samples++;
00284 #endif
00285 
00286         if (_prof->setup.cpu.level == Setup::LEVEL_METHOD) traceDepth = 1;
00287         else traceDepth = _prof->setup.cpu.traceDepth; 
00288 
00289         thread = _prof->sampledThreads.first();
00290         while (thread) {
00291 
00292                 envId = thread->threadEnvId; 
00293                 status = _prof->jvmpiInterface->GetThreadStatus(envId);
00294 
00295                 if ((status & (~JVMPI_THREAD_INTERRUPTED)) == JVMPI_THREAD_RUNNABLE) {
00296 
00297                         _prof->jvmpiInterface->SuspendThread(envId);
00298                         thread->nextSuspended = suspendList;
00299                         suspendList = thread;
00300                 }
00301 
00302                 thread = _prof->sampledThreads.next(thread);
00303         }
00304 
00305         for (thread = suspendList; thread; thread = thread->nextSuspended) {
00306 
00307                 envId = thread->threadEnvId; 
00308                 thread->hasRun = (_prof->jvmpiInterface->ThreadHasRun(envId) == JNI_TRUE);
00309 
00310                 if (thread->hasRun) { 
00311 
00312                         trace = &thread->callTrace; 
00313                         trace->env_id = envId;
00314                         trace->num_frames = traceDepth;
00315                         
00316                         _prof->jvmpiInterface->GetCallTrace(trace, traceDepth);
00317                 }
00318         }
00319 
00320         for (thread = suspendList; thread; thread = thread->nextSuspended)
00321                 _prof->jvmpiInterface->ResumeThread(thread->threadEnvId);
00322 
00323         for (thread = suspendList; thread; thread = thread->nextSuspended) {
00324 
00325                 if (thread->hasRun) {
00326 
00327                         envId = thread->threadEnvId; 
00328                         numFrames = thread->callTrace.num_frames;
00329                         frames = thread->callTrace.frames;
00330                         
00331                         if (numFrames > 0) {
00332 
00333                                 if (_prof->setup.cpu.threadsEnabled) {
00334 
00335                                         if (_prof->setup.cpu.level == Setup::LEVEL_METHOD) {
00336 
00337                                                 if (!(stat = _prof->getCpuThreadMethod(envId, frames[0].method_id))) {
00338                                                         PROF_ERROR("CPU SAMPLE", "Cannot get CpuThreadMethod");
00339                                                         continue;
00340                                                 }
00341                                         }
00342                                         else {
00343 
00344                                                 if (!(stat = _prof->getCpuThreadTrace(envId, numFrames, frames))) {
00345                                                         PROF_ERROR("CPU SAMPLE", "Cannot get CpuThreadTrace");
00346                                                         continue;
00347                                                 }
00348                                         }
00349                                 }
00350                                 else {
00351 
00352                                         if (_prof->setup.cpu.level == Setup::LEVEL_METHOD) {
00353 
00354                                                 if (!(stat = _prof->getMethod(frames[0].method_id))) {
00355                                                         PROF_ERROR("CPU SAMPLE", "Method not found");
00356                                                         continue;
00357                                                 }
00358                                         }
00359                                         else {
00360 
00361                                                 if (!(stat = _prof->getCpuTrace(numFrames, frames))) {
00362                                                         PROF_ERROR("CPU SAMPLE", "Cannot get CPU trace");
00363                                                         continue;
00364                                                 }
00365                                         }
00366                                 }
00367                                 
00368                                 stat->addCpuStat((jlong)1, (jlong)0);
00369                         }
00370                 }
00371         }
00372 }
00373 
00374 void Sampling::samplingMain( void*) {
00375         
00376         Prof::prof().sampling.main();
00377 }
00378 
00379 int Sampling::isTerminated() {
00380 
00381 #ifdef USE_RAW_MONITORS
00382         Synchronized sync( _lock);
00383 #endif
00384 
00385         return _terminated;
00386 }

Generated on Mon Jan 28 14:53:27 2002 for Java Profiler Dynamic Library by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001