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