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 {
00505 if(!_start_terminate_lock || !_start_cond )
00506 W_FATAL(fcOUTOFMEMORY);
00507
00508 DO_PTHREAD(pthread_cond_init(_start_cond, NULL));
00509 DO_PTHREAD(pthread_mutex_init(_start_terminate_lock, NULL));
00510
00511 _core = new sthread_core_t;
00512 if (!_core)
00513 W_FATAL(fcOUTOFMEMORY);
00514 _core->sthread = (void *)this;
00515
00516
00517
00518
00519
00520 if (_priority > max_priority)
00521 _priority = max_priority;
00522 else if (_priority <= min_priority)
00523 _priority = min_priority;
00524
00525
00526
00527
00528 DO_PTHREAD(pthread_mutex_init(&_wait_lock, NULL));
00529 DO_PTHREAD(pthread_cond_init(&_wait_cond, NULL));
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 if (sthread_core_init(_core, __start, this, stack_size) == -1) {
00542 cerr << "sthread_t: cannot initialize thread core" << endl;
00543 W_FATAL(stINTERNAL);
00544 }
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 sthread_t::~sthread_t()
00557 {
00558
00559
00560
00561
00562
00563 {
00564 CRITICAL_SECTION(cs, _wait_lock);
00565
00566
00567
00568
00569
00570
00571
00572
00573 w_assert1(_status == t_virgin
00574 || _status == t_defunct
00575 || _status == t_blocked
00576 );
00577
00578 if (_link.member_of()) {
00579 W_FORM2(cerr,("sthread_t(%#lx): \"%s\": destroying a thread on a list!",
00580 (long)this, name()));
00581 }
00582 }
00583 sthread_core_exit(_core, _terminated);
00584
00585 delete _core;
00586 _core = 0;
00587
00588 DO_PTHREAD(pthread_cond_destroy(_start_cond));
00589 delete _start_cond;
00590 _start_cond = 0;
00591
00592 DO_PTHREAD(pthread_mutex_destroy(_start_terminate_lock));
00593 delete _start_terminate_lock;
00594 _start_terminate_lock = 0;
00595
00596 }
00597
00598 #ifndef PTHREAD_STACK_MIN
00599
00600
00601
00602 size_t get_pthread_stack_min()
00603 {
00604 static size_t gotit(0);
00605 if(!gotit) {
00606 gotit = sysconf(_SC_THREAD_STACK_MIN);
00607 if(!gotit) {
00608 const char *errmsg =
00609 "Platform does not appear to conform to POSIX 1003.1c-1995 re: limits";
00610
00611 W_FATAL_MSG(fcINTERNAL, << errmsg);
00612 }
00613 w_assert1(gotit > 0);
00614 }
00615 return gotit;
00616 }
00617 #endif
00618
00619
00620
00621
00622 void sthread_t::__start(void *arg)
00623 {
00624 sthread_t* t = (sthread_t*) arg;
00625 me_lval() = t;
00626 t->_start_frame = &t;
00627
00628 #ifndef PTHREAD_STACK_MIN
00629 size_t PTHREAD_STACK_MIN = get_pthread_stack_min();
00630 #endif
00631
00632 #if HAVE_PTHREAD_ATTR_GETSTACKSIZE
00633 pthread_attr_t attr;
00634 size_t sz=0;
00635 int e = pthread_attr_init(&attr);
00636 if(e) {
00637 fprintf(stderr,"Cannot init pthread_attr e=%d\n", e);
00638 ::exit(1);
00639 }
00640 else
00641 {
00642 e = pthread_attr_getstacksize( &attr, &sz);
00643 if(e || sz==0) {
00644 #if HAVE_PTHREAD_ATTR_GETSTACK
00645 void *voidp(NULL);
00646 e = pthread_attr_getstack( &attr, &voidp, &sz);
00647 if(e || sz == 0)
00648 #endif
00649 {
00650 #if W_DEBUG_LEVEL > 2
00651 fprintf(stderr,"Cannot get pthread stack size e=%d, sz=%lld\n",
00652 e, (long long)sz);
00653 #endif
00654 sz = PTHREAD_STACK_MIN;
00655 }
00656 }
00657 }
00658 #define GUARD 8192*4
00659 if(sz < GUARD) {
00660
00661 #ifndef PTHREAD_STACK_MIN_SUBSTITUTE
00662
00663
00664
00665 #define PTHREAD_STACK_MIN_SUBSTITUTE 0x100000
00666 #endif
00667 sz = PTHREAD_STACK_MIN_SUBSTITUTE;
00668 #if W_DEBUG_LEVEL > 2
00669 fprintf(stderr,"using %lld temporarily\n", (long long)sz);
00670 #endif
00671 }
00672 t->_stack_size = sz;
00673
00674
00675
00676
00677
00678 sz -= GUARD;
00679 t->_danger = (void *)((char *)t->_start_frame - sz);
00680
00681 #endif
00682 w_assert1(t->_danger < t->_start_frame);
00683 w_assert1(t->_stack_size > 0);
00684
00685 t->_start();
00686 }
00687
00688
00689
00690
00691
00692
00693
00694 void sthread_t::_start()
00695 {
00696 tls_tricks::tls_manager::thread_init();
00697 w_assert1(me() == this);
00698
00699
00700 w_assert1(isStackFrameOK(0));
00701 {
00702 CRITICAL_SECTION(cs, _start_terminate_lock);
00703 if(_forked) {
00704
00705
00706
00707 CRITICAL_SECTION(cs_thread, _wait_lock);
00708 _status = t_running;
00709 } else {
00710 DO_PTHREAD(pthread_cond_wait(_start_cond, _start_terminate_lock));
00711 CRITICAL_SECTION(cs_thread, _wait_lock);
00712 _status = t_running;
00713 }
00714 }
00715
00716 #if defined(PURIFY)
00717
00718
00719 purify_name_thread(name());
00720 #endif
00721
00722 {
00723
00724
00725
00726
00727
00728
00729 static queue_based_lock_t rand_mutex;
00730
00731 long seed1, seed2;
00732 {
00733 CRITICAL_SECTION(cs, rand_mutex);
00734 seed1 = ::rand();
00735 seed2 = ::rand();
00736 }
00737 tls_rng.seed( (seed1 << 24) ^ seed2);
00738 }
00739
00740
00741 {
00742
00743 w_assert1(me() == this);
00744 #ifdef STHREAD_CXX_EXCEPTION
00745
00746
00747
00748
00749
00750
00751 try {
00752 before_run();
00753 run();
00754 after_run();
00755 }
00756 catch (...) {
00757 cerr << endl
00758 << "sthread_t(id = " << id << " name = " << name()
00759 << "): run() threw an exception."
00760 << endl
00761 << endl;
00762 }
00763 #else
00764 before_run();
00765 run();
00766 after_run();
00767 #endif
00768 }
00769
00770
00771 {
00772 CRITICAL_SECTION(cs, _wait_lock);
00773 w_assert3(me() == this);
00774 _status = t_defunct;
00775 _link.detach();
00776 }
00777 {
00778 CRITICAL_SECTION(cs, _class_list_lock);
00779 _class_link.detach();
00780 }
00781
00782 w_assert3(this == me());
00783
00784 {
00785 w_assert1(_status == t_defunct);
00786
00787 tls_tricks::tls_manager::thread_fini();
00788 pthread_exit(0);
00789 }
00790
00791 W_FATAL(stINTERNAL);
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 w_rc_t
00807 sthread_t::block(
00808 pthread_mutex_t &lock,
00809 timeout_in_ms timeout,
00810 sthread_list_t* list,
00811 const char* const caller,
00812 const void * id)
00813 {
00814 w_rc_t::errcode_t rce = _block(&lock, timeout, list, caller, id);
00815 if(rce) return RC(rce);
00816 return RCOK;
00817 }
00818
00819 w_rc_t::errcode_t
00820 sthread_t::block(int4_t timeout )
00821 {
00822 return _block(NULL, timeout);
00823 }
00824
00825 w_rc_t::errcode_t
00826 sthread_t::_block(
00827 pthread_mutex_t *lock,
00828 timeout_in_ms timeout,
00829 sthread_list_t* list,
00830 const char* const caller,
00831 const void * id)
00832 {
00833 w_rc_t::errcode_t rce(stOK);
00834 sthread_t* self = me();
00835 {
00836 CRITICAL_SECTION(cs, self->_wait_lock);
00837
00838
00839
00840
00841 w_assert3(self->_link.member_of() == 0);
00842 if (list) {
00843 list->put_in_order(self);
00844 }
00845
00846 if(lock) {
00847
00848 DO_PTHREAD(pthread_mutex_unlock(lock));
00849 }
00850 rce = _block(timeout, caller, id);
00851 }
00852 if(rce == stTIMEOUT) {
00853 if(lock) {
00854 CRITICAL_SECTION(outer_cs, &lock);
00855
00856 CRITICAL_SECTION(cs, self->_wait_lock);
00857 self->_link.detach();
00858 } else {
00859 CRITICAL_SECTION(cs, self->_wait_lock);
00860 self->_link.detach();
00861 }
00862 }
00863
00864 return rce;
00865 }
00866
00867 void sthread_t::timeout_to_timespec(timeout_in_ms timeout, struct timespec &when)
00868 {
00869 w_assert1(timeout != WAIT_IMMEDIATE);
00870 w_assert1(timeout != sthread_t::WAIT_FOREVER);
00871 if(timeout > 0) {
00872 struct timeval now;
00873
00874
00875 gettimeofday(&now, NULL);
00876 when.tv_sec = now.tv_sec + timeout/1000;
00877 when.tv_nsec = now.tv_usec*1000 + 100000*(timeout%1000);
00878 if(when.tv_nsec >= 1000*1000*1000) {
00879 when.tv_sec++;
00880 when.tv_nsec -= 1000*1000*1000;
00881 }
00882 }
00883 }
00884
00885 w_rc_t::errcode_t
00886 sthread_t::_block(
00887 timeout_in_ms timeout,
00888 const char* const
00889 ,
00890 const void *
00891 )
00892 {
00893
00894
00895
00896
00897
00898 sthread_t* self = me();
00899 w_assert1(timeout != WAIT_IMMEDIATE);
00900
00901
00902
00903
00904 status_t old_status = self->_status;
00905 self->_status = t_blocked;
00906
00907 int error = 0;
00908 self->_unblock_flag = false;
00909 if(timeout > 0) {
00910 timespec when;
00911 timeout_to_timespec(timeout, when);
00912
00913
00914
00915
00916 while(!error && !self->_unblock_flag) {
00917 error = pthread_cond_timedwait(&self->_wait_cond,
00918 &self->_wait_lock, &when);
00919 w_assert1(error == ETIMEDOUT || error == 0);
00920
00921 if(!error) break;
00922 }
00923 }
00924 else {
00925
00926 w_assert1(timeout == sthread_t::WAIT_FOREVER);
00927
00928
00929
00930 while(!error && !self->_unblock_flag)
00931
00932 error = pthread_cond_wait(&self->_wait_cond, &self->_wait_lock);
00933 }
00934
00935 switch(error) {
00936 case ETIMEDOUT:
00937
00938 W_COERCE(self->_unblock(stTIMEOUT));
00939
00940 case 0:
00941
00942
00943
00944
00945 self->_status = old_status;
00946 return self->_rce;
00947 default:
00948 self->_status = old_status;
00949 return sthread_t::stOS;
00950 }
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 w_rc_t
00963 sthread_t::unblock(w_rc_t::errcode_t e)
00964 {
00965 CRITICAL_SECTION(cs, _wait_lock);
00966
00967
00968
00969
00970
00971
00972 _link.detach();
00973 return _unblock(e);
00974
00975 }
00976
00977
00978 w_rc_t
00979 sthread_t::_unblock(w_rc_t::errcode_t e)
00980 {
00981 _status = t_ready;
00982
00983
00984
00985
00986 if (e)
00987 _rce = e;
00988 else
00989 _rce = stOK;
00990
00991
00992
00993
00994 _unblock_flag = true;
00995 membar_producer();
00996 DO_PTHREAD(pthread_cond_signal(&_wait_cond));
00997 _status = t_running;
00998
00999 return RCOK;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015 void sthread_t::yield()
01016 {
01017 sthread_t* self = me();
01018 CRITICAL_SECTION(cs, self->_wait_lock);
01019 w_assert3(self->_status == t_running);
01020 self->_status = t_ready;
01021 cs.pause();
01022 sched_yield();
01023 cs.resume();
01024 self->_status = t_running;
01025 }
01026
01027
01028 void sthread_t::dumpall(const char *str, ostream &o)
01029 {
01030 if (str)
01031 o << str << ": " << endl;
01032
01033 dumpall(o);
01034 }
01035
01036 void sthread_t::dumpall(ostream &o)
01037 {
01038
01039
01040
01041 CRITICAL_SECTION(cs, _class_list_lock);
01042 w_list_i<sthread_t, queue_based_lock_t> i(*_class_list);
01043
01044 while (i.next()) {
01045 o << "******* ";
01046 if (me() == i.curr())
01047 o << " --->ME<---- ";
01048 o << endl;
01049
01050 i.curr()->_dump(o);
01051 }
01052 }
01053
01054
01055
01056 void sthread_t::_dump(ostream &o) const
01057 {
01058 o << *this << endl;
01059 }
01060
01061
01062
01063
01064
01065
01066 static void print_time(ostream &o, const sinterval_t &real,
01067 const sinterval_t &user, const sinterval_t &kernel)
01068 {
01069 sinterval_t total(user + kernel);
01070 double pcpu = ((double)total / (double)real) * 100.0;
01071 double pcpu2 = ((double)user / (double)real) * 100.0;
01072
01073 o << "\t" << "real: " << real
01074 << endl;
01075 o << "\tcpu:"
01076 << " kernel: " << kernel
01077 << " user: " << user
01078 << " total: " << total
01079 << endl;
01080 o << "\t%CPU:"
01081 << " " << setprecision(3) << pcpu
01082 << " %user: " << setprecision(2) << pcpu2;
01083 o
01084 << endl;
01085 }
01086
01087 void sthread_t::dump_stats(ostream &o)
01088 {
01089 o << me()->SthreadStats;
01090
01091
01092
01093
01094 struct rusage ru;
01095 int n;
01096
01097 stime_t now(stime_t::now());
01098 n = getrusage(RUSAGE_SELF, &ru);
01099 if (n == -1) {
01100 w_rc_t e = RC(fcOS);
01101 cerr << "getrusage() fails:" << endl << e << endl;
01102 return;
01103 }
01104
01105 sinterval_t real(now - boot_time);
01106 sinterval_t kernel(ru.ru_stime);
01107 sinterval_t user(ru.ru_utime);
01108
01109
01110
01111
01112 static sinterval_t last_real;
01113 static sinterval_t last_kernel;
01114 static sinterval_t last_user;
01115 static bool last_valid = false;
01116
01117 o << "TIME:" << endl;
01118 print_time(o, real, user, kernel);
01119 if (last_valid) {
01120 sinterval_t r(real - last_real);
01121 sinterval_t u(user - last_user);
01122 sinterval_t k(kernel - last_kernel);
01123 o << "RECENT:" << endl;
01124 print_time(o, r, u, k);
01125 }
01126 else
01127 last_valid = true;
01128
01129 last_kernel = kernel;
01130 last_user = user;
01131 last_real = real;
01132
01133 o << endl;
01134 }
01135
01136 void sthread_t::reset_stats()
01137 {
01138 me()->SthreadStats.clear();
01139 }
01140
01141
01142 const char *sthread_t::status_strings[] = {
01143 "defunct",
01144 "virgin",
01145 "ready",
01146 "running",
01147 "blocked",
01148 "boot"
01149 };
01150
01151 const char *sthread_t::priority_strings[]= {
01152 "idle_time",
01153 "fixed_low",
01154 "regular",
01155 "time_critical"
01156 };
01157
01158
01159 ostream& operator<<(ostream &o, const sthread_t &t)
01160 {
01161 return t.print(o);
01162 }
01163
01164
01165
01166
01167
01168
01169
01170 ostream &sthread_t::print(ostream &o) const
01171 {
01172 o << "thread id = " << id ;
01173
01174 if (name()) {
01175 o << ", name = " << name() ? name() : "anonymous";
01176 };
01177
01178 o
01179 << ", addr = " << (void *) this
01180 << ", core = " << (void *) _core << endl;
01181 o
01182 << "priority = " << sthread_t::priority_strings[priority()]
01183 << ", status = " << sthread_t::status_strings[status()];
01184 o << endl;
01185
01186 if (user)
01187 o << "user = " << user << endl;
01188
01189 if ((status() != t_defunct) && !isStackOK(__FILE__,__LINE__))
01190 {
01191 cerr << "*** warning: Thread stack overflow ***" << endl;
01192 }
01193
01194 return o;
01195 }
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206 void sthread_t::for_each_thread(ThreadFunc& f)
01207 {
01208
01209
01210
01211 CRITICAL_SECTION(cs, _class_list_lock);
01212 w_list_i<sthread_t, queue_based_lock_t> i(*_class_list);
01213
01214 while (i.next()) {
01215 f(*i.curr());
01216 }
01217 }
01218
01219 void print_timeout(ostream& o, const sthread_base_t::timeout_in_ms timeout)
01220 {
01221 if (timeout > 0) {
01222 o << timeout;
01223 } else if (timeout >= -5) {
01224 static const char* names[] = {"WAIT_IMMEDIATE",
01225 "WAIT_FOREVER",
01226 "WAIT_ANY",
01227 "WAIT_ALL",
01228 "WAIT_SPECIFIED_BY_THREAD",
01229 "WAIT_SPECIFIED_BY_XCT"};
01230 o << names[-timeout];
01231 } else {
01232 o << "UNKNOWN_TIMEOUT_VALUE(" << timeout << ")";
01233 }
01234 }
01235
01236 occ_rwlock::occ_rwlock()
01237 : _active_count(0)
01238 {
01239 _write_lock._lock = _read_lock._lock = this;
01240 DO_PTHREAD(pthread_mutex_init(&_read_write_mutex, NULL));
01241 DO_PTHREAD(pthread_cond_init(&_read_cond, NULL));
01242 DO_PTHREAD(pthread_cond_init(&_write_cond, NULL));
01243 }
01244
01245 occ_rwlock::~occ_rwlock()
01246 {
01247 DO_PTHREAD(pthread_mutex_destroy(&_read_write_mutex));
01248 DO_PTHREAD(pthread_cond_destroy(&_read_cond));
01249 DO_PTHREAD(pthread_cond_destroy(&_write_cond));
01250 _write_lock._lock = _read_lock._lock = NULL;
01251 }
01252
01253 void occ_rwlock::release_read()
01254 {
01255 membar_exit();
01256 w_assert1(READER <= (int) _active_count);
01257 unsigned count = atomic_add_32_nv(&_active_count, -READER);
01258 if(count == WRITER) {
01259
01260 CRITICAL_SECTION(cs, _read_write_mutex);
01261 DO_PTHREAD(pthread_cond_signal(&_write_cond));
01262 }
01263 }
01264
01265 void occ_rwlock::acquire_read()
01266 {
01267 int count = atomic_add_32_nv(&_active_count, READER);
01268 while(count & WRITER) {
01269
01270 count = atomic_add_32_nv(&_active_count, -READER);
01271 {
01272 CRITICAL_SECTION(cs, _read_write_mutex);
01273
01274
01275 if(count == WRITER)
01276 DO_PTHREAD(pthread_cond_signal(&_write_cond));
01277
01278 while(*&_active_count & WRITER) {
01279 DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex));
01280 }
01281 }
01282 count = atomic_add_32_nv(&_active_count, READER);
01283 }
01284 membar_enter();
01285 }
01286
01287 void occ_rwlock::release_write()
01288 {
01289 w_assert9(_active_count & WRITER);
01290 CRITICAL_SECTION(cs, _read_write_mutex);
01291 atomic_add_32(&_active_count, -WRITER);
01292 DO_PTHREAD(pthread_cond_broadcast(&_read_cond));
01293 }
01294
01295 void occ_rwlock::acquire_write()
01296 {
01297
01298 CRITICAL_SECTION(cs, _read_write_mutex);
01299 while(*&_active_count & WRITER) {
01300 DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex));
01301 }
01302
01303
01304 int count = atomic_add_32_nv(&_active_count, WRITER);
01305 w_assert1(count & WRITER);
01306
01307
01308 while(count != WRITER) {
01309 DO_PTHREAD(pthread_cond_wait(&_write_cond, &_read_write_mutex));
01310 count = *&_active_count;
01311 }
01312 }
01313
01314
01315
01316 sthread_name_t::sthread_name_t()
01317 {
01318 memset(_name, '\0', sizeof(_name));
01319 }
01320
01321 sthread_name_t::~sthread_name_t()
01322 {
01323 }
01324
01325 void
01326 sthread_name_t::rename(
01327
01328
01329 const char* n1,
01330 const char* n2,
01331 const char* n3)
01332 {
01333 const int sz = sizeof(_name) - 1;
01334 size_t len = 0;
01335 _name[0] = '\0';
01336 if (n1) {
01337 #if W_DEBUG_LEVEL > 2
01338 len = strlen(n1);
01339 if(n2) len += strlen(n2);
01340 if(n3) len += strlen(n3);
01341 len++;
01342 if(len>sizeof(_name)) {
01343 cerr << "WARNING-- name too long for sthread_named_t: "
01344 << n1 << n2 << n3;
01345 }
01346 #endif
01347
01348
01349 strncpy(_name, n1, sz);
01350 len = strlen(_name);
01351 if (n2 && (int)len < sz) {
01352 strncat(_name, n2, sz - len);
01353 len = strlen(_name);
01354 if (n3 && (int)len < sz)
01355 strncat(_name, n3, sz - len);
01356 }
01357
01358 _name[sz] = '\0';
01359 }
01360
01361 }
01362
01363 void
01364 sthread_named_base_t::unname()
01365 {
01366 rename(0,0,0);
01367 }
01368
01369 void
01370 sthread_named_base_t::rename(
01371
01372
01373 const char* n1,
01374 const char* n2,
01375 const char* n3)
01376 {
01377 _name.rename(n1,n2,n3);
01378 }
01379
01380 sthread_named_base_t::~sthread_named_base_t()
01381 {
01382 unname();
01383 }
01384
01385
01386
01387
01388
01389
01390 smthread_t* sthread_t::dynamic_cast_to_smthread()
01391 {
01392 return 0;
01393 }
01394
01395
01396 const smthread_t* sthread_t::dynamic_cast_to_const_smthread() const
01397 {
01398 return 0;
01399 }
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410 void dumpthreads()
01411 {
01412 sthread_t::dumpall("dumpthreads()", cerr);
01413 sthread_t::dump_io(cerr);
01414
01415 }
01416
01417 void threadstats()
01418 {
01419 sthread_t::dump_stats(cerr);
01420 }
01421
01422
01423
01424 static void get_large_file_size(w_base_t::int8_t &max_os_file_size)
01425 {
01426
01427
01428
01429
01430 os_rlimit_t r;
01431 int n;
01432
01433 n = os_getrlimit(RLIMIT_FSIZE, &r);
01434 if (n == -1) {
01435 w_rc_t e = RC(fcOS);
01436 cerr << "getrlimit(RLIMIT_FSIZE):" << endl << e << endl;
01437 W_COERCE(e);
01438 }
01439 if (r.rlim_cur < r.rlim_max) {
01440 r.rlim_cur = r.rlim_max;
01441 n = os_setrlimit(RLIMIT_FSIZE, &r);
01442 if (n == -1) {
01443 w_rc_t e = RC(fcOS);
01444 cerr << "setrlimit(RLIMIT_FSIZE, " << r.rlim_cur
01445 << "):" << endl << e << endl;
01446 cerr << e << endl;
01447 W_FATAL(fcINTERNAL);
01448 }
01449 }
01450 max_os_file_size = w_base_t::int8_t(r.rlim_cur);
01451
01452
01453
01454
01455
01456 if (max_os_file_size < 0) {
01457 max_os_file_size = w_base_t::uint8_t(r.rlim_cur) >> 1;
01458 w_assert1( max_os_file_size > 0);
01459 }
01460 }
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475 #include "sthread_vtable_enum.h"
01476
01477
01478
01479
01480 void sthread_t::initialize_sthreads_package()
01481 { sthread_init_t::do_init(); }
01482
01483 NORET
01484 sthread_init_t::sthread_init_t() { }
01485
01486 void
01487 sthread_init_t::do_init()
01488 {
01489
01490 if (sthread_init_t::initialized == 0)
01491 {
01492 CRITICAL_SECTION(cs, init_mutex);
01493
01494
01495 if (sthread_init_t::initialized == 0)
01496 {
01497 sthread_init_t::initialized ++;
01498
01499 get_large_file_size(sthread_t::max_os_file_size);
01500
01501
01502
01503
01504 if (! w_error_t::insert(
01505 "Threads Package",
01506 error_info,
01507 sizeof(error_info) / sizeof(error_info[0]))) {
01508
01509 cerr << "sthread_init_t::do_init: "
01510 << " cannot register error code" << endl;
01511
01512 W_FATAL(stINTERNAL);
01513 }
01514
01515 W_COERCE(sthread_t::cold_startup());
01516 }
01517 }
01518 }
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529 NORET
01530 sthread_init_t::~sthread_init_t()
01531 {
01532 CRITICAL_SECTION(cs, init_mutex);
01533
01534
01535
01536 w_assert1 (sthread_init_t::initialized <= 1) ;
01537 if (--sthread_init_t::initialized == 0)
01538 {
01539
01540 W_COERCE(sthread_t::shutdown());
01541
01542
01543
01544
01545
01546 sthread_t::_main_thread->_status = sthread_t::t_defunct;
01547
01548 delete sthread_t::_main_thread;
01549 sthread_t::_main_thread = 0;
01550
01551 delete sthread_t::_class_list;
01552 sthread_t::_class_list = 0;
01553 }
01554 }
01555
01556 pthread_t sthread_t::myself() { return _core->pthread; }
01557