00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef WIN32
00024
00025 #ifdef Darwin
00026 #include <mach/thread_act.h>
00027 #include <mach/thread_info.h>
00028 #include <mach/mach_init.h>
00029 #include <mach/task.h>
00030 #include <mach/semaphore.h>
00031 #endif
00032
00033 namespace cmlabs {
00034
00035
00036
00037
00038
00039 int NumberOfCPUs = 0;
00040 double OSMemory = 0;
00041 double CPUSpeed = 0;
00042 char* CPUArch = NULL;
00043 char* OSVersion = NULL;
00044 char* OSName = NULL;
00045
00046
00047
00048
00049
00050 JThread::JThread(bool shouldStart, int pri) {
00051 threadStartTime.setInvalid();
00052 threadEndTime.setInvalid();
00053 linuxThreadHasFinished = true;
00054 hThread = NULL;
00055 publicSemaphore = NULL;
00056 testSemaphore = NULL;
00057 priority = pri;
00058
00059 procLastStat = procStartStat = getCPUUsage(NULL);
00060
00061 if (shouldStart) start();
00062 }
00063
00064 JThread::~JThread() {
00065 linuxThreadHasFinished = true;
00066 terminate();
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 HANDLE JThread::getCallingThreadID() {
00083 pthread_t* p = new pthread_t;
00084 *p = pthread_self();
00085 return p;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094 bool JThread::start() {
00095 if (hThread != NULL) {
00096
00097 return true;
00098 }
00099
00100 pthread_attr_t attr;
00101 pthread_attr_init(&attr);
00102
00103 pthread_attr_setschedpolicy(&attr, SCHED_RR);
00104 pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
00105
00106
00107
00108 int res;
00109 hThread = new pthread_t;
00110 if ((res=pthread_create(hThread, &attr, staticRunThread, (void*) this)) != 0) {
00111 if (res == EAGAIN) {
00112 if (DEBUGLEVEL(DEBUG))
00113 printf("******* Thread could not be created, too many exist!!! *******\n");
00114 }
00115 else if (res == EFAULT) {
00116 if (DEBUGLEVEL(DEBUG))
00117 printf("******* Thread could not be created, thread or attr is an invalid pointer.!!! *******\n");
00118 }
00119 else if (res == EINVAL) {
00120 if (DEBUGLEVEL(DEBUG))
00121 printf("******* Thread could not be created, attr is not an initialized thread attribute object!!! *******\n");
00122 }
00123 else {
00124 if (DEBUGLEVEL(DEBUG))
00125 printf("******* Thread could not be created, error code given: %d!!! *******\n", res);
00126 }
00127 return false;
00128 }
00129 int oldstate;
00130
00131 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
00132 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
00133
00134
00135 setPriority(priority);
00136 addToAllThreadsStats(hThread);
00137 this->waitThread(0);
00138 return true;
00139 }
00140
00141 bool JThread::join()
00142 {
00143 int res = 0;
00144 res = pthread_join(*hThread, 0);
00145
00146 if (res!=0)
00147 return false;
00148 return true;
00149 }
00150
00151
00152 bool JThread::terminate() {
00153 if (!hThread) {
00154
00155 return true;
00156 }
00157
00158
00159
00160 pthread_cancel(*hThread);
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 if (pthread_join(*hThread, NULL) != 0)
00171 return false;
00172
00173 delete(hThread);
00174 removeFromAllThreadsStats(hThread);
00175
00176 hThread = NULL;
00177 return true;
00178 }
00179
00180 bool JThread::suspend() {
00181
00182 #ifdef Darwin
00183 return false;
00184 #else
00185 return (pthread_kill(*hThread, SIGSTOP) == 0);
00186 #endif
00187 }
00188
00189 bool JThread::resume() {
00190
00191 #ifdef Darwin
00192 return false;
00193 #else
00194 return (pthread_kill(*hThread, SIGCONT) == 0);
00195 #endif
00196 }
00197
00198 void JThread::yield() {
00199 pthread_testcancel();
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 bool JThread::isRunning() {
00209
00210 return (!linuxThreadHasFinished);
00211
00212
00213 }
00214
00215
00216 ThreadStat JThread::getCPUUsage(HANDLE aThread) {
00217
00218 ThreadStat newStat;
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 struct tms tm;
00241 struct rusage us;
00242
00243 struct timezone tz;
00244
00245 if (aThread == NULL) {
00246 newStat = getAllThreadsStats();
00247 }
00248 else {
00249 getrusage(RUSAGE_SELF, &us);
00250 newStat.userLast = (us.ru_utime.tv_sec * 1000000) + us.ru_utime.tv_usec;
00251 newStat.kernelLast = (us.ru_stime.tv_sec * 1000000) + us.ru_stime.tv_usec;
00252
00253 }
00254
00255 gettimeofday(&newStat.timeLast, &tz);
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 return newStat;
00271
00272 }
00273
00274 bool JThread::isThread() {
00275 return (*hThread == pthread_self()) ? true : false;
00276 }
00277
00278
00279
00280
00281
00282
00283
00284 int JThread::getPriority() {
00285
00286 if (hThread == NULL)
00287 return 0;
00288
00289 #ifdef Darwin
00290 return 0;
00291 #else
00292 struct sched_param sched;
00293 int policy;
00294
00295 policy = sched_getscheduler(0);
00296 if(policy < 0)
00297 return false;
00298
00299 if (pthread_getschedparam(*hThread, &policy, &sched) != 0)
00300 return false;
00301
00302 priority = sched.sched_priority;
00303
00304 return priority;
00305 #endif
00306
00307 }
00308
00309 bool JThread::setPriority(int pri) {
00310
00311 if (hThread == NULL) {
00312 printf("SetPriority: No thread\n");
00313 return false;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 int policy;
00334 struct sched_param sched;
00335 memset(&sched, 0, sizeof(struct sched_param));
00336
00337 policy = SCHED_FIFO;
00338
00339 sched.sched_priority = convPriorityToOS(pri);
00340
00341 int res = pthread_setschedparam(*hThread, policy, &sched);
00342 if (res != 0) {
00343 if (res == EINVAL) {
00344
00345 }
00346 else if (res == ENOTSUP) {
00347
00348 }
00349 else if (res == EPERM) {
00350
00351 }
00352 else if (res == ESRCH) {
00353
00354 }
00355 return false;
00356 }
00357
00358 return true;
00359
00360
00361 }
00362
00363 int JThread::convPriorityToOS(int pri) {
00364 int val;
00365 if (pri == 0)
00366 val = 40;
00367 else if (pri >= 90)
00368 val = 60;
00369 else if (pri >= 80)
00370 val = 55;
00371 else if (pri >= 70)
00372 val = 40;
00373 else if (pri >= 60)
00374 val = 35;
00375 else if (pri >= 50)
00376 val = 30;
00377 else if (pri >= 40)
00378 val = 25;
00379 else if (pri >= 30)
00380 val = 20;
00381 else if (pri >= 20)
00382 val = 15;
00383 else if (pri >= 10)
00384 val = 10;
00385 else
00386 val = 5;
00387 return val;
00388 }
00389
00390 int JThread::convPriorityToInternal(int pri) {
00391 return pri;
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 bool JThread::waitThread(long ms) {
00409 usleep(ms * 1000);
00410 return true;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 JString JThread::osGetNameVersion() {
00499 JString ver = osGetVersion();
00500 if (ver.length() == 0)
00501 return osGetName();
00502 else
00503 return JString::format("%s %s", (char*) osGetName(), (char*) ver);
00504 }
00505
00506
00507 JString JThread::osGetName() {
00508
00509 if (OSName != NULL)
00510 return OSName;
00511
00512 #ifdef Darwin
00513 JString osName = runOSTextCommand("uname -s");
00514 #else
00515 JString osName = runOSTextCommand("uname -s");
00516 #endif // Darwin
00517
00518 if (osName.length() == 0)
00519 osName = "Unknown";
00520
00521 int len;
00522 OSName = osName.getCharCopy(len);
00523 return OSName;
00524 }
00525
00526 JString JThread::osGetVersion() {
00527
00528 if (OSVersion != NULL)
00529 return OSVersion;
00530
00531 #ifdef Darwin
00532 JString osVersion = runOSTextCommand("uname -r");
00533 #else
00534 JString osVersion = runOSTextCommand("uname -r");
00535 #endif // Darwin
00536
00537 if (osVersion.length() == 0)
00538 osVersion = "0";
00539
00540 int len;
00541 OSVersion = osVersion.getCharCopy(len);
00542 return OSVersion;
00543 }
00544
00545 JString JThread::osGetMachineArch() {
00546
00547 if (CPUArch != NULL)
00548 return CPUArch;
00549
00550 #ifdef Darwin
00551 JString cpuArch = runOSTextCommand("uname -p");
00552 #else
00553 JString cpuArch = runOSTextCommand("uname -p");
00554 #endif // Darwin
00555
00556 if (cpuArch.length() == 0)
00557 cpuArch = "Unknown";
00558
00559 int len;
00560 CPUArch = cpuArch.getCharCopy(len);
00561 return CPUArch;
00562 }
00563
00564
00565 double JThread::osGetTotalMemory() {
00566
00567 if (OSMemory > 0)
00568 return OSMemory;
00569
00570 #ifdef Darwin
00571 JString str = runOSTextCommand("sysctl hw.memsize");
00572 str = str.split(":").getLast();
00573 OSMemory = str.toDouble()/(1024*1024);
00574 #else
00575 JString str = runOSTextCommand("free | grep Mem | awk '{printf (\"%d\", $2/1000)}'");
00576 OSMemory = str.toDouble();
00577 #endif // Darwin
00578 return OSMemory;
00579 }
00580
00581 double JThread::osGetCPUSpeed() {
00582
00583 if (CPUSpeed > 0)
00584 return CPUSpeed;
00585
00586 #ifdef Darwin
00587 JString str = runOSTextCommand("sysctl hw.cpufrequency");
00588 str = str.split(":").getLast();
00589 CPUSpeed = str.toDouble()/1000000;
00590 #else
00591 JString str = runOSTextCommand("cat /proc/cpuinfo | grep 'cpu MHz' | head -1 | sed -e 's/^.*: //'");
00592 CPUSpeed = str.toDouble();
00593 #endif // Darwin
00594 return CPUSpeed;
00595 }
00596
00597 int JThread::osGetCPUCount() {
00598
00599 if (NumberOfCPUs > 0)
00600 return NumberOfCPUs;
00601
00602 #ifdef Darwin
00603 JString str = runOSTextCommand("sysctl hw.ncpu");
00604 str = str.split(":").getLast();
00605 #else
00606 JString str = runOSTextCommand("cat /proc/cpuinfo | grep processor | wc -l");
00607 #endif // Darwin
00608
00609 NumberOfCPUs = str.toInt();
00610 if (NumberOfCPUs <= 0)
00611 NumberOfCPUs = 1;
00612 return NumberOfCPUs;
00613 }
00614
00615 JString JThread::runOSTextCommand(JString cmd) {
00616
00617 fflush(stdin);
00618 fflush(stdout);
00619 FILE* runfile = popen(cmd, "r");
00620 if (runfile == NULL) return "";
00621
00622 char *buffer = new char[10000];
00623 int res = fread(buffer, 1, 10000, runfile);
00624 if (res <= 0) {
00625 delete [] buffer;
00626 pclose(runfile);
00627 return "";
00628 }
00629 for (int n=0; n<res; n++)
00630 if (buffer[n] < 32)
00631 buffer[n] = 0;
00632 buffer[res] = 0;
00633
00634 JString str = buffer;
00635 delete [] buffer;
00636 pclose(runfile);
00637 return str;
00638 }
00639
00640 int JThread::procMemUsage() {
00641
00642 #ifdef Darwin
00643 JString str = runOSTextCommand(JString::format("ps h -o rsz -p %d | tail -n 1", (int) getpid()));
00644 #else
00645 JString str = runOSTextCommand(JString::format("ps h -o rsz %d | tail -n 1", (int) getpid()));
00646
00647 #endif // Darwin
00648
00649 int c = str.toInt() * 1024;
00650 if (c <= 0)
00651 return 1;
00652 return c;
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 }
00712
00713 JString JThread::getComputerName() {
00714 int len = 1000;
00715 char buffer[1000];
00716 if (gethostname(buffer, len) == -1)
00717 return "";
00718 else
00719 return buffer;
00720 }
00721
00722
00723
00724 Collection JThread::getProgramTrace() {
00725 Collection col;
00726 #ifndef Darwin
00727 #ifdef _DEBUG
00728 void *array[200];
00729 size_t size;
00730 char **strings;
00731 size_t i;
00732
00733 size = backtrace(array, 200);
00734 strings = backtrace_symbols(array, size);
00735 for (i = 0; i < size; i++)
00736 col.add(strings[i]);
00737 free (strings);
00738 #endif // _DEBUG
00739 #endif // Darwin
00740 return col;
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 void* staticRunThread(void* arg) {
00767
00768 #ifndef Darwin
00769 sigset_t cancel;
00770 sigemptyset(&cancel);
00771 sigaddset(&cancel, SIGQUIT);
00772 pthread_sigmask(SIG_UNBLOCK, &cancel, NULL);
00773 #endif
00774
00775 JThread* thr = (JThread*) arg;
00776 thr->linuxThreadHasFinished = false;
00777
00778 thr->threadStartTime = JTime();
00779 thr->threadEndTime.setInvalid();
00780 thr->run();
00781 thr->threadEndTime = JTime();
00782
00783 thr->linuxThreadHasFinished = true;
00784 return NULL;
00785 }
00786
00787 }
00788
00789 #endif