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