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
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include "w_defines.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #include <w.h>
00078
00079 #include <w_debug.h>
00080 #include <w_stream.h>
00081 #include <cstdlib>
00082 #include <sched.h>
00083 #include <cstring>
00084
00085 #ifdef __SUNPRO_CC
00086 #include <sys/time.h>
00087 #else
00088 #include <ctime>
00089 #endif
00090
00091 #include <sys/wait.h>
00092 #include <new>
00093
00094 #include <sys/stat.h>
00095 #include <w_rusage.h>
00096 #include "tls.h"
00097
00098 #ifdef __GNUC__
00099 #pragma implementation "sthread.h"
00100 #endif
00101
00102 #include "sthread.h"
00103 #include "rand48.h"
00104 #include "sthread_stats.h"
00105 #include "stcore_pthread.h"
00106
00107 #ifdef PURIFY
00108 #include <purify.h>
00109 #endif
00110
00111 #ifdef EXPLICIT_TEMPLATE
00112 template class w_list_t<sthread_t, queue_based_lock_t>;
00113 template class w_list_i<sthread_t, queue_based_lock_t>;
00114 template class w_descend_list_t<sthread_t, queue_based_lock_t, sthread_t::priority_t>;
00115 template class w_keyed_list_t<sthread_t, queue_based_lock_t, sthread_t::priority_t>;
00116 #endif
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 static __thread rand48 tls_rng = RAND48_INITIALIZER;
00127
00128 int sthread_t::rand() { return tls_rng.rand(); }
00129 double sthread_t::drand() { return tls_rng.drand(); }
00130 int sthread_t::randn(int max) { return tls_rng.randn(max); }
00131
00132 class sthread_stats SthreadStats;
00133
00134 const
00135 #include "st_einfo_gen.h"
00136
00137 extern "C" void dumpthreads();
00138 extern "C" void threadstats();
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 class sthread_init_t : public sthread_base_t {
00163 public:
00164 NORET sthread_init_t();
00165 static void do_init();
00166 NORET ~sthread_init_t();
00167 private:
00168 static uint4_t initialized;
00169 static w_pthread_lock_t init_mutex;
00170 };
00171
00172 static sthread_init_t sthread_init;
00173
00174 w_base_t::uint4_t sthread_init_t::initialized = 0;
00175 w_pthread_lock_t sthread_init_t::init_mutex;
00176 w_base_t::int8_t sthread_t::max_os_file_size;
00177
00178 bool sthread_t::isStackOK(const char * , int ) const
00179 {
00180
00181
00182
00183 return true;
00184 }
00185
00186
00187
00188 void sthread_t::check_all_stacks(const char *file, int line)
00189 {
00190 w_list_i<sthread_t, queue_based_lock_t> i(*_class_list);
00191 unsigned corrupt = 0;
00192
00193 while (i.next()) {
00194 if (! i.curr()->isStackOK(file, line))
00195 corrupt++;
00196 }
00197
00198 if (corrupt > 0) {
00199 cerr << "sthread_t::check_all: " << corrupt
00200 << " thread stacks, dieing" << endl;
00201 W_FATAL(fcINTERNAL);
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210 extern "C" void stackoverflowed() {}
00211
00212 bool sthread_t::isStackFrameOK(size_t size)
00213 {
00214 bool ok;
00215 void *stack_top = &ok;
00216 void *_stack_top = &ok - size;
00217
00218 w_assert1(this->_danger < this->_start_frame);
00219 void *absolute_bottom = (void *)((char *)_start_frame - _stack_size);
00220
00221 if( stack_top < _danger) {
00222 if( stack_top <= absolute_bottom) {
00223 fprintf(stderr,
00224
00225 "STACK OVERFLOW frame (offset -%ld) %p bottom %p danger %p top %p stack_size %ld \n",
00226
00227 (long int) size, _stack_top, absolute_bottom, _danger, _start_frame,
00228 (long int) _stack_size);
00229 } else {
00230 fprintf(stderr,
00231
00232 "STACK IN GUARD AREA bottom %p frame (offset -%ld) %p danger %p top %p stack_size %ld \n",
00233
00234 absolute_bottom, (long int) size, _stack_top, _danger, _start_frame,
00235 (long int) _stack_size);
00236 }
00237 return false;
00238 }
00239
00240 return true;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 sthread_t* sthread_t::_main_thread = 0;
00253 const w_base_t::uint4_t MAIN_THREAD_ID(1);
00254 w_base_t::uint4_t sthread_t::_next_id = MAIN_THREAD_ID;
00255 sthread_list_t* sthread_t::_class_list = 0;
00256 queue_based_lock_t sthread_t::_class_list_lock;
00257
00258 stime_t sthread_t::boot_time = stime_t::now();
00259
00260
00261
00262
00263
00264
00265
00266
00267 w_rc_t sthread_t::cold_startup()
00268 {
00269
00270 _class_list = new sthread_list_t(W_LIST_ARG(sthread_t, _class_link),
00271 &_class_list_lock);
00272 if (_class_list == 0)
00273 W_FATAL(fcOUTOFMEMORY);
00274
00275
00276 struct timeval now;
00277 gettimeofday(&now, NULL);
00278
00279
00280 ::srand(now.tv_usec);
00281
00282
00283
00284
00285 sthread_main_t *main = new sthread_main_t;
00286 if (!main)
00287 W_FATAL(fcOUTOFMEMORY);
00288 me_lval() = _main_thread = main;
00289 W_COERCE( main->fork() );
00290
00291 if (me() != main)
00292 W_FATAL(stINTERNAL);
00293
00294 #if defined(PURIFY)
00295
00296 purify_name_thread(me()->name());
00297 #endif
00298
00299 return RCOK;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309 w_rc_t sthread_t::shutdown()
00310 {
00311 if (me() != _main_thread) {
00312 cerr << "sthread_t::shutdown(): not main thread!" << endl;
00313 return RC(stINTERNAL);
00314 }
00315
00316 return RCOK;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 sthread_main_t::sthread_main_t()
00329 : sthread_t(t_regular, "main_thread", 0)
00330 {
00331
00332
00333
00334
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 void sthread_main_t::run()
00346 {
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 w_rc_t sthread_t::set_priority(priority_t priority)
00359 {
00360 CRITICAL_SECTION(cs, _wait_lock);
00361 _priority = priority;
00362
00363
00364 if (_priority <= min_priority) _priority = min_priority;
00365 if (_priority > max_priority) _priority = max_priority;
00366
00367 if (_status == t_ready) {
00368 cerr << "sthread_t::set_priority() :- "
00369 << "cannot change priority of ready thread" << endl;
00370 W_FATAL(stINTERNAL);
00371 }
00372
00373 return RCOK;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 void sthread_t::sleep(timeout_in_ms timeout, const char *reason)
00385 {
00386 reason = (reason && *reason) ? reason : "sleep";
00387
00388
00389
00390
00391
00392
00393 CRITICAL_SECTION(cs, _wait_lock);
00394 _sleeping = true;
00395 (void) _block(timeout, reason, this);
00396 _sleeping = false;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405 void sthread_t::wakeup()
00406 {
00407 CRITICAL_SECTION(cs, _wait_lock);
00408 if(_sleeping) _unblock(stOK);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 w_rc_t
00418 sthread_t::join(timeout_in_ms )
00419 {
00420 w_rc_t rc;
00421 {
00422 CRITICAL_SECTION(cs, _start_terminate_lock);
00423
00424
00425
00426
00427 if (!_forked) {
00428 rc = RC(stOS);
00429 } else
00430 {
00431 cs.exit();
00432
00433
00434
00435 sthread_core_exit(_core, _terminated);
00436
00437 }
00438 }
00439
00440 return rc;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450 w_rc_t sthread_t::fork()
00451 {
00452 {
00453 sthread_init_t::do_init();
00454 CRITICAL_SECTION(cs, _start_terminate_lock);
00455
00456 if (_forked)
00457 return RC(stOS);
00458
00459
00460 if(this != _main_thread)
00461 {
00462 CRITICAL_SECTION(cs, _class_list_lock);
00463 _class_list->append(this);
00464 }
00465
00466
00467 _forked = true;
00468 if(this == _main_thread) {
00469
00470 CRITICAL_SECTION(cs_thread, _wait_lock);
00471 _status = t_running;
00472 } else {
00473
00474 DO_PTHREAD( pthread_cond_signal(_start_cond) );
00475 }
00476 }
00477
00478 return RCOK;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 sthread_t::sthread_t(priority_t pr,
00490 const char *nm,
00491 unsigned stack_size)
00492 : sthread_named_base_t(nm),
00493 user(0),
00494 id(_next_id++),
00495 _start_terminate_lock(new pthread_mutex_t),
00496 _start_cond(new pthread_cond_t),
00497 _sleeping(false),
00498 _forked(false),
00499 _terminated(false),
00500 _unblock_flag(false),
00501 _core(0),
00502 _status(t_virgin),
00503 _priority(pr),
00504 _rce(stOK)
00505 {
00506 if(!_start_terminate_lock || !_start_cond )
00507 W_FATAL(fcOUTOFMEMORY);
00508
00509 DO_PTHREAD(pthread_cond_init(_start_cond, NULL));
00510 DO_PTHREAD(pthread_mutex_init(_start_terminate_lock, NULL));
00511
00512 _core = new sthread_core_t;
00513 if (!_core)
00514 W_FATAL(fcOUTOFMEMORY);
00515 _core->sthread = (void *)this;
00516
00517
00518
00519
00520
00521 if (_priority > max_priority)
00522 _priority = max_priority;
00523 else if (_priority <= min_priority)
00524 _priority = min_priority;
00525
00526
00527
00528
00529 DO_PTHREAD(pthread_mutex_init(&_wait_lock, NULL));
00530 DO_PTHREAD(pthread_cond_init(&_wait_cond, NULL));
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 if (sthread_core_init(_core, __start, this, stack_size) == -1) {
00543 cerr << "sthread_t: cannot initialize thread core" << endl;
00544 W_FATAL(stINTERNAL);
00545 }
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 sthread_t::~sthread_t()
00558 {
00559
00560
00561
00562
00563
00564 {
00565 CRITICAL_SECTION(cs, _wait_lock);
00566
00567
00568
00569
00570
00571
00572
00573
00574 w_assert1(_status == t_virgin
00575 || _status == t_defunct
00576 || _status == t_blocked
00577 );
00578
00579 if (_link.member_of()) {
00580 W_FORM2(cerr,("sthread_t(%#lx): \"%s\": destroying a thread on a list!",
00581 (long)this, name()));
00582 }
00583 }
00584 sthread_core_exit(_core, _terminated);
00585
00586 delete _core;
00587 _core = 0;
00588
00589 DO_PTHREAD(pthread_cond_destroy(_start_cond));
00590 delete _start_cond;
00591 _start_cond = 0;
00592
00593 DO_PTHREAD(pthread_mutex_destroy(_start_terminate_lock));
00594 delete _start_terminate_lock;
00595 _start_terminate_lock = 0;
00596
00597 }
00598
00599 #ifndef PTHREAD_STACK_MIN
00600
00601
00602
00603 size_t get_pthread_stack_min()
00604 {
00605 static size_t gotit(0);
00606 if(!gotit) {
00607 gotit = sysconf(_SC_THREAD_STACK_MIN);
00608 if(!gotit) {
00609 const char *errmsg =
00610 "Platform does not appear to conform to POSIX 1003.1c-1995 re: limits";
00611
00612 W_FATAL_MSG(fcINTERNAL, << errmsg);
00613 }
00614 w_assert1(gotit > 0);
00615 }
00616 return gotit;
00617 }
00618 #endif
00619
00620
00621
00622
00623 void sthread_t::__start(void *arg)
00624 {
00625 sthread_t* t = (sthread_t*) arg;
00626 me_lval() = t;
00627 t->_start_frame = &t;
00628
00629 #ifndef PTHREAD_STACK_MIN
00630 size_t PTHREAD_STACK_MIN = get_pthread_stack_min();
00631 #endif
00632
00633 #if HAVE_PTHREAD_ATTR_GETSTACKSIZE
00634 pthread_attr_t attr;
00635 size_t sz=0;
00636 int e = pthread_attr_init(&attr);
00637 if(e) {
00638 fprintf(stderr,"Cannot init pthread_attr e=%d\n", e);
00639 ::exit(1);
00640 }
00641 else
00642 {
00643 e = pthread_attr_getstacksize( &attr, &sz);
00644 if(e || sz==0) {
00645 #if HAVE_PTHREAD_ATTR_GETSTACK
00646 void *voidp(NULL);
00647 e = pthread_attr_getstack( &attr, &voidp, &sz);
00648 if(e || sz == 0)
00649 #endif
00650 {
00651 #if W_DEBUG_LEVEL > 2
00652 fprintf(stderr,"Cannot get pthread stack size e=%d, sz=%lld\n",
00653 e, (long long)sz);
00654 #endif
00655 sz = PTHREAD_STACK_MIN;
00656 }
00657 }
00658 }
00659 #define GUARD 8192*4
00660 if(sz < GUARD) {
00661
00662 #ifndef PTHREAD_STACK_MIN_SUBSTITUTE
00663
00664
00665
00666 #define PTHREAD_STACK_MIN_SUBSTITUTE 0x100000
00667 #endif
00668 sz = PTHREAD_STACK_MIN_SUBSTITUTE;
00669 #if W_DEBUG_LEVEL > 2
00670 fprintf(stderr,"using %lld temporarily\n", (long long)sz);
00671 #endif
00672 }
00673 t->_stack_size = sz;
00674
00675
00676
00677
00678
00679 sz -= GUARD;
00680 t->_danger = (void *)((char *)t->_start_frame - sz);
00681
00682 #endif
00683 w_assert1(t->_danger < t->_start_frame);
00684 w_assert1(t->_stack_size > 0);
00685
00686 t->_start();
00687 }
00688
00689
00690
00691
00692
00693
00694
00695 void sthread_t::_start()
00696 {
00697 tls_tricks::tls_manager::thread_init();
00698 w_assert1(me() == this);
00699
00700
00701 w_assert1(isStackFrameOK(0));
00702 {
00703 CRITICAL_SECTION(cs, _start_terminate_lock);
00704 if(_forked) {
00705
00706
00707
00708 CRITICAL_SECTION(cs_thread, _wait_lock);
00709 _status = t_running;
00710 } else {
00711 DO_PTHREAD(pthread_cond_wait(_start_cond, _start_terminate_lock));
00712 CRITICAL_SECTION(cs_thread, _wait_lock);
00713 _status = t_running;
00714 }
00715 }
00716
00717 #if defined(PURIFY)
00718
00719
00720 purify_name_thread(name());
00721 #endif
00722
00723 {
00724
00725
00726
00727
00728
00729
00730 static queue_based_lock_t rand_mutex;
00731
00732 long seed1, seed2;
00733 {
00734 CRITICAL_SECTION(cs, rand_mutex);
00735 seed1 = ::rand();
00736 seed2 = ::rand();
00737 }
00738 tls_rng.seed( (seed1 << 24) ^ seed2);
00739 }
00740
00741
00742 {
00743
00744 w_assert1(me() == this);
00745 #ifdef STHREAD_CXX_EXCEPTION
00746
00747
00748
00749
00750
00751
00752 try {
00753 before_run();
00754 run();
00755 after_run();
00756 }
00757 catch (...) {
00758 cerr << endl
00759 << "sthread_t(id = " << id << " name = " << name()
00760 << "): run() threw an exception."
00761 << endl
00762 << endl;
00763 }
00764 #else
00765 before_run();
00766 run();
00767 after_run();
00768 #endif
00769 }
00770
00771
00772 {
00773 CRITICAL_SECTION(cswait, _wait_lock);
00774 w_assert3(me() == this);
00775 _status = t_defunct;
00776 _link.detach();
00777 }
00778 {
00779 CRITICAL_SECTION(csclass, _class_list_lock);
00780 _class_link.detach();
00781 }
00782
00783 w_assert3(this == me());
00784
00785 {
00786 w_assert1(_status == t_defunct);
00787
00788 tls_tricks::tls_manager::thread_fini();
00789 pthread_exit(0);
00790 }
00791
00792 W_FATAL(stINTERNAL);
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 w_rc_t
00808 sthread_t::block(
00809 pthread_mutex_t &lock,
00810 timeout_in_ms timeout,
00811 sthread_list_t* list,
00812 const char* const caller,
00813 const void * id)
00814 {
00815 w_rc_t::errcode_t rce = _block(&lock, timeout, list, caller, id);
00816 if(rce) return RC(rce);
00817 return RCOK;
00818 }
00819
00820 w_rc_t::errcode_t
00821 sthread_t::block(int4_t timeout )
00822 {
00823 return _block(NULL, timeout);
00824 }
00825
00826 w_rc_t::errcode_t
00827 sthread_t::_block(
00828 pthread_mutex_t *lock,
00829 timeout_in_ms timeout,
00830 sthread_list_t* list,
00831 const char* const caller,
00832 const void * id)
00833 {
00834 w_rc_t::errcode_t rce(stOK);
00835 sthread_t* self = me();
00836 {
00837 CRITICAL_SECTION(cs, self->_wait_lock);
00838
00839
00840
00841
00842 w_assert3(self->_link.member_of() == 0);
00843 if (list) {
00844 list->put_in_order(self);
00845 }
00846
00847 if(lock) {
00848
00849 DO_PTHREAD(pthread_mutex_unlock(lock));
00850 }
00851 rce = _block(timeout, caller, id);
00852 }
00853 if(rce == stTIMEOUT) {
00854 if(lock) {
00855 CRITICAL_SECTION(outer_cs, &lock);
00856
00857 CRITICAL_SECTION(cs, self->_wait_lock);
00858 self->_link.detach();
00859 } else {
00860 CRITICAL_SECTION(cs, self->_wait_lock);
00861 self->_link.detach();
00862 }
00863 }
00864
00865 return rce;
00866 }
00867
00868 void sthread_t::timeout_to_timespec(timeout_in_ms timeout, struct timespec &when)
00869 {
00870 w_assert1(timeout != WAIT_IMMEDIATE);
00871 w_assert1(timeout != sthread_t::WAIT_FOREVER);
00872 if(timeout > 0) {
00873 struct timeval now;
00874
00875
00876 gettimeofday(&now, NULL);
00877 when.tv_sec = now.tv_sec + timeout/1000;
00878 when.tv_nsec = now.tv_usec*1000 + 100000*(timeout%1000);
00879 if(when.tv_nsec >= 1000*1000*1000) {
00880 when.tv_sec++;
00881 when.tv_nsec -= 1000*1000*1000;
00882 }
00883 }
00884 }
00885
00886 w_rc_t::errcode_t
00887 sthread_t::_block(
00888 timeout_in_ms timeout,
00889 const char* const
00890 ,
00891 const void *
00892 )
00893 {
00894
00895
00896
00897
00898
00899 sthread_t* self = me();
00900 w_assert1(timeout != WAIT_IMMEDIATE);
00901
00902
00903 status_t old_status = self->_status;
00904 self->_status = t_blocked;
00905
00906 int error = 0;
00907 self->_unblock_flag = false;
00908
00909
00910
00911
00912 self->_rce = stOK;
00913
00914 if(timeout > 0) {
00915 timespec when;
00916 timeout_to_timespec(timeout, when);
00917
00918
00919
00920
00921 while(!error && !self->_unblock_flag) {
00922 error = pthread_cond_timedwait(&self->_wait_cond,
00923 &self->_wait_lock, &when);
00924 w_assert1(error == ETIMEDOUT || error == 0);
00925
00926 if(!error) break;
00927 }
00928
00929 } else {
00930
00931 w_assert1(timeout == sthread_t::WAIT_FOREVER);
00932
00933
00934
00935 while(!error && !self->_unblock_flag)
00936
00937 error = pthread_cond_wait(&self->_wait_cond, &self->_wait_lock);
00938 }
00939
00940 switch(error) {
00941 case ETIMEDOUT:
00942
00943
00944 w_assert1(timeout > 0);
00945 #if 1 || DEAD
00946 W_COERCE(self->_unblock(stTIMEOUT));
00947 #else
00948
00949 {
00950
00951
00952 if(!self->_rce) self->_rce = stTIMEOUT;
00953 self->_unblock_flag = true;
00954 }
00955 #endif
00956
00957 case 0:
00958
00959
00960
00961
00962 self->_status = old_status;
00963 return self->_rce;
00964 default:
00965 self->_status = old_status;
00966 return sthread_t::stOS;
00967 }
00968 }
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 w_rc_t
00980 sthread_t::unblock(w_rc_t::errcode_t e)
00981 {
00982 CRITICAL_SECTION(cs, _wait_lock);
00983
00984
00985
00986
00987 _link.detach();
00988 return _unblock(e);
00989
00990 }
00991
00992
00993 w_rc_t
00994 sthread_t::_unblock(w_rc_t::errcode_t e)
00995 {
00996 _status = t_ready;
00997
00998
00999
01000
01001 _rce = e;
01002 _unblock_flag = true;
01003
01004 membar_producer();
01005
01006 DO_PTHREAD(pthread_cond_signal(&_wait_cond));
01007 _status = t_running;
01008
01009 return RCOK;
01010 }
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025 void sthread_t::yield()
01026 {
01027 sthread_t* self = me();
01028 CRITICAL_SECTION(cs, self->_wait_lock);
01029 w_assert3(self->_status == t_running);
01030 self->_status = t_ready;
01031 cs.pause();
01032 sched_yield();
01033 cs.resume();
01034 self->_status = t_running;
01035 }
01036
01037
01038 void sthread_t::dumpall(const char *str, ostream &o)
01039 {
01040 if (str)
01041 o << str << ": " << endl;
01042
01043 dumpall(o);
01044 }
01045
01046 void sthread_t::dumpall(ostream &o)
01047 {
01048
01049
01050
01051 CRITICAL_SECTION(cs, _class_list_lock);
01052 w_list_i<sthread_t, queue_based_lock_t> i(*_class_list);
01053
01054 while (i.next()) {
01055 o << "******* ";
01056 if (me() == i.curr())
01057 o << " --->ME<---- ";
01058 o << endl;
01059
01060 i.curr()->_dump(o);
01061 }
01062 }
01063
01064
01065
01066 void sthread_t::_dump(ostream &o) const
01067 {
01068 o << *this << endl;
01069 }
01070
01071
01072
01073
01074
01075
01076 static void print_time(ostream &o, const sinterval_t &real,
01077 const sinterval_t &user, const sinterval_t &kernel)
01078 {
01079 sinterval_t total(user + kernel);
01080 double pcpu = ((double)total / (double)real) * 100.0;
01081 double pcpu2 = ((double)user / (double)real) * 100.0;
01082
01083 o << "\t" << "real: " << real
01084 << endl;
01085 o << "\tcpu:"
01086 << " kernel: " << kernel
01087 << " user: " << user
01088 << " total: " << total
01089 << endl;
01090 o << "\t%CPU:"
01091 << " " << setprecision(3) << pcpu
01092 << " %user: " << setprecision(2) << pcpu2;
01093 o
01094 << endl;
01095 }
01096
01097 void sthread_t::dump_stats(ostream &o)
01098 {
01099 o << me()->SthreadStats;
01100
01101
01102
01103
01104 struct rusage ru;
01105 int n;
01106
01107 stime_t now(stime_t::now());
01108 n = getrusage(RUSAGE_SELF, &ru);
01109 if (n == -1) {
01110 w_rc_t e = RC(fcOS);
01111 cerr << "getrusage() fails:" << endl << e << endl;
01112 return;
01113 }
01114
01115 sinterval_t real(now - boot_time);
01116 sinterval_t kernel(ru.ru_stime);
01117 sinterval_t user(ru.ru_utime);
01118
01119
01120
01121
01122 static sinterval_t last_real;
01123 static sinterval_t last_kernel;
01124 static sinterval_t last_user;
01125 static bool last_valid = false;
01126
01127 o << "TIME:" << endl;
01128 print_time(o, real, user, kernel);
01129 if (last_valid) {
01130 sinterval_t r(real - last_real);
01131 sinterval_t u(user - last_user);
01132 sinterval_t k(kernel - last_kernel);
01133 o << "RECENT:" << endl;
01134 print_time(o, r, u, k);
01135 }
01136 else
01137 last_valid = true;
01138
01139 last_kernel = kernel;
01140 last_user = user;
01141 last_real = real;
01142
01143 o << endl;
01144 }
01145
01146 void sthread_t::reset_stats()
01147 {
01148 me()->SthreadStats.clear();
01149 }
01150
01151
01152 const char *sthread_t::status_strings[] = {
01153 "defunct",
01154 "virgin",
01155 "ready",
01156 "running",
01157 "blocked",
01158 "boot"
01159 };
01160
01161 const char *sthread_t::priority_strings[]= {
01162 "idle_time",
01163 "fixed_low",
01164 "regular",
01165 "time_critical"
01166 };
01167
01168
01169 ostream& operator<<(ostream &o, const sthread_t &t)
01170 {
01171 return t.print(o);
01172 }
01173
01174
01175
01176
01177
01178
01179
01180 ostream &sthread_t::print(ostream &o) const
01181 {
01182 o << "thread id = " << id ;
01183
01184 if (name()) {
01185 o << ", name = " << name() ? name() : "anonymous";
01186 };
01187
01188 o
01189 << ", addr = " << (void *) this
01190 << ", core = " << (void *) _core << endl;
01191 o
01192 << "priority = " << sthread_t::priority_strings[priority()]
01193 << ", status = " << sthread_t::status_strings[status()];
01194 o << endl;
01195
01196 if (user)
01197 o << "user = " << user << endl;
01198
01199 if ((status() != t_defunct) && !isStackOK(__FILE__,__LINE__))
01200 {
01201 cerr << "*** warning: Thread stack overflow ***" << endl;
01202 }
01203
01204 return o;
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 void sthread_t::for_each_thread(ThreadFunc& f)
01217 {
01218
01219
01220
01221 CRITICAL_SECTION(cs, _class_list_lock);
01222 w_list_i<sthread_t, queue_based_lock_t> i(*_class_list);
01223
01224 while (i.next()) {
01225 f(*i.curr());
01226 }
01227 }
01228
01229 void print_timeout(ostream& o, const sthread_base_t::timeout_in_ms timeout)
01230 {
01231 if (timeout > 0) {
01232 o << timeout;
01233 } else if (timeout >= -5) {
01234 static const char* names[] = {"WAIT_IMMEDIATE",
01235 "WAIT_FOREVER",
01236 "WAIT_ANY",
01237 "WAIT_ALL",
01238 "WAIT_SPECIFIED_BY_THREAD",
01239 "WAIT_SPECIFIED_BY_XCT"};
01240 o << names[-timeout];
01241 } else {
01242 o << "UNKNOWN_TIMEOUT_VALUE(" << timeout << ")";
01243 }
01244 }
01245
01246 occ_rwlock::occ_rwlock()
01247 : _active_count(0)
01248 {
01249 _write_lock._lock = _read_lock._lock = this;
01250 DO_PTHREAD(pthread_mutex_init(&_read_write_mutex, NULL));
01251 DO_PTHREAD(pthread_cond_init(&_read_cond, NULL));
01252 DO_PTHREAD(pthread_cond_init(&_write_cond, NULL));
01253 }
01254
01255 occ_rwlock::~occ_rwlock()
01256 {
01257 DO_PTHREAD(pthread_mutex_destroy(&_read_write_mutex));
01258 DO_PTHREAD(pthread_cond_destroy(&_read_cond));
01259 DO_PTHREAD(pthread_cond_destroy(&_write_cond));
01260 _write_lock._lock = _read_lock._lock = NULL;
01261 }
01262
01263 void occ_rwlock::release_read()
01264 {
01265 membar_exit();
01266 w_assert1(READER <= (int) _active_count);
01267 unsigned count = atomic_add_32_nv(&_active_count, -READER);
01268 if(count == WRITER) {
01269
01270 CRITICAL_SECTION(cs, _read_write_mutex);
01271 DO_PTHREAD(pthread_cond_signal(&_write_cond));
01272 }
01273 }
01274
01275 void occ_rwlock::acquire_read()
01276 {
01277 int count = atomic_add_32_nv(&_active_count, READER);
01278 while(count & WRITER) {
01279
01280 count = atomic_add_32_nv(&_active_count, -READER);
01281 {
01282 CRITICAL_SECTION(cs, _read_write_mutex);
01283
01284
01285 if(count == WRITER)
01286 DO_PTHREAD(pthread_cond_signal(&_write_cond));
01287
01288 while(*&_active_count & WRITER) {
01289 DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex));
01290 }
01291 }
01292 count = atomic_add_32_nv(&_active_count, READER);
01293 }
01294 membar_enter();
01295 }
01296
01297 void occ_rwlock::release_write()
01298 {
01299 w_assert9(_active_count & WRITER);
01300 CRITICAL_SECTION(cs, _read_write_mutex);
01301 atomic_add_32(&_active_count, -WRITER);
01302 DO_PTHREAD(pthread_cond_broadcast(&_read_cond));
01303 }
01304
01305 void occ_rwlock::acquire_write()
01306 {
01307
01308 CRITICAL_SECTION(cs, _read_write_mutex);
01309 while(*&_active_count & WRITER) {
01310 DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex));
01311 }
01312
01313
01314 int count = atomic_add_32_nv(&_active_count, WRITER);
01315 w_assert1(count & WRITER);
01316
01317
01318 while(count != WRITER) {
01319 DO_PTHREAD(pthread_cond_wait(&_write_cond, &_read_write_mutex));
01320 count = *&_active_count;
01321 }
01322 }
01323
01324
01325
01326 sthread_name_t::sthread_name_t()
01327 {
01328 memset(_name, '\0', sizeof(_name));
01329 }
01330
01331 sthread_name_t::~sthread_name_t()
01332 {
01333 }
01334
01335 void
01336 sthread_name_t::rename(
01337
01338
01339 const char* n1,
01340 const char* n2,
01341 const char* n3)
01342 {
01343 const int sz = sizeof(_name) - 1;
01344 size_t len = 0;
01345 _name[0] = '\0';
01346 if (n1) {
01347 #if W_DEBUG_LEVEL > 2
01348 len = strlen(n1);
01349 if(n2) len += strlen(n2);
01350 if(n3) len += strlen(n3);
01351 len++;
01352 if(len>sizeof(_name)) {
01353 cerr << "WARNING-- name too long for sthread_named_t: "
01354 << n1 << n2 << n3;
01355 }
01356 #endif
01357
01358
01359 strncpy(_name, n1, sz);
01360 len = strlen(_name);
01361 if (n2 && (int)len < sz) {
01362 strncat(_name, n2, sz - len);
01363 len = strlen(_name);
01364 if (n3 && (int)len < sz)
01365 strncat(_name, n3, sz - len);
01366 }
01367
01368 _name[sz] = '\0';
01369 }
01370
01371 }
01372
01373 void
01374 sthread_named_base_t::unname()
01375 {
01376 rename(0,0,0);
01377 }
01378
01379 void
01380 sthread_named_base_t::rename(
01381
01382
01383 const char* n1,
01384 const char* n2,
01385 const char* n3)
01386 {
01387 _name.rename(n1,n2,n3);
01388 }
01389
01390 sthread_named_base_t::~sthread_named_base_t()
01391 {
01392 unname();
01393 }
01394
01395
01396
01397
01398
01399
01400 smthread_t* sthread_t::dynamic_cast_to_smthread()
01401 {
01402 return 0;
01403 }
01404
01405
01406 const smthread_t* sthread_t::dynamic_cast_to_const_smthread() const
01407 {
01408 return 0;
01409 }
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 void dumpthreads()
01421 {
01422 sthread_t::dumpall("dumpthreads()", cerr);
01423 sthread_t::dump_io(cerr);
01424
01425 }
01426
01427 void threadstats()
01428 {
01429 sthread_t::dump_stats(cerr);
01430 }
01431
01432
01433
01434 static void get_large_file_size(w_base_t::int8_t &max_os_file_size)
01435 {
01436
01437
01438
01439
01440 os_rlimit_t r;
01441 int n;
01442
01443 n = os_getrlimit(RLIMIT_FSIZE, &r);
01444 if (n == -1) {
01445 w_rc_t e = RC(fcOS);
01446 cerr << "getrlimit(RLIMIT_FSIZE):" << endl << e << endl;
01447 W_COERCE(e);
01448 }
01449 if (r.rlim_cur < r.rlim_max) {
01450 r.rlim_cur = r.rlim_max;
01451 n = os_setrlimit(RLIMIT_FSIZE, &r);
01452 if (n == -1) {
01453 w_rc_t e = RC(fcOS);
01454 cerr << "setrlimit(RLIMIT_FSIZE, " << r.rlim_cur
01455 << "):" << endl << e << endl;
01456 cerr << e << endl;
01457 W_FATAL(fcINTERNAL);
01458 }
01459 }
01460 max_os_file_size = w_base_t::int8_t(r.rlim_cur);
01461
01462
01463
01464
01465
01466 if (max_os_file_size < 0) {
01467 max_os_file_size = w_base_t::uint8_t(r.rlim_cur) >> 1;
01468 w_assert1( max_os_file_size > 0);
01469 }
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485 #include "sthread_vtable_enum.h"
01486
01487
01488
01489
01490 void sthread_t::initialize_sthreads_package()
01491 { sthread_init_t::do_init(); }
01492
01493 NORET
01494 sthread_init_t::sthread_init_t() { }
01495
01496 void
01497 sthread_init_t::do_init()
01498 {
01499
01500 if (sthread_init_t::initialized == 0)
01501 {
01502 CRITICAL_SECTION(cs, init_mutex);
01503
01504
01505 if (sthread_init_t::initialized == 0)
01506 {
01507 sthread_init_t::initialized ++;
01508
01509 get_large_file_size(sthread_t::max_os_file_size);
01510
01511
01512
01513
01514 if (! w_error_t::insert(
01515 "Threads Package",
01516 error_info,
01517 sizeof(error_info) / sizeof(error_info[0]))) {
01518
01519 cerr << "sthread_init_t::do_init: "
01520 << " cannot register error code" << endl;
01521
01522 W_FATAL(stINTERNAL);
01523 }
01524
01525 W_COERCE(sthread_t::cold_startup());
01526 }
01527 }
01528 }
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539 NORET
01540 sthread_init_t::~sthread_init_t()
01541 {
01542 CRITICAL_SECTION(cs, init_mutex);
01543
01544
01545
01546 w_assert1 (sthread_init_t::initialized <= 1) ;
01547 if (--sthread_init_t::initialized == 0)
01548 {
01549
01550 W_COERCE(sthread_t::shutdown());
01551
01552
01553
01554
01555
01556 sthread_t::_main_thread->_status = sthread_t::t_defunct;
01557
01558 delete sthread_t::_main_thread;
01559 sthread_t::_main_thread = 0;
01560
01561 delete sthread_t::_class_list;
01562 sthread_t::_class_list = 0;
01563 }
01564 }
01565
01566 pthread_t sthread_t::myself() { return _core->pthread; }
01567