00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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 }