sthread.cpp

00001 /* -*- mode:C++; c-basic-offset:4 -*-
00002    Shore-MT -- Multi-threaded port of the SHORE storage manager
00003    
00004                        Copyright (c) 2007-2009
00005       Data Intensive Applications and Systems Labaratory (DIAS)
00006                Ecole Polytechnique Federale de Lausanne
00007    
00008                          All Rights Reserved.
00009    
00010    Permission to use, copy, modify and distribute this software and
00011    its documentation is hereby granted, provided that both the
00012    copyright notice and this permission notice appear in all copies of
00013    the software, derivative works or modified versions, and any
00014    portions thereof, and that both notices appear in supporting
00015    documentation.
00016    
00017    This code is distributed in the hope that it will be useful, but
00018    WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
00020    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
00021    RESULTING FROM THE USE OF THIS SOFTWARE.
00022 */
00023 
00024 // -*- mode:c++; c-basic-offset:4 -*-
00025 /*<std-header orig-src='shore'>
00026 
00027  $Id: sthread.cpp,v 1.336 2012/01/02 21:52:27 nhall Exp $
00028 
00029 SHORE -- Scalable Heterogeneous Object REpository
00030 
00031 Copyright (c) 1994-99 Computer Sciences Department, University of
00032                       Wisconsin -- Madison
00033 All Rights Reserved.
00034 
00035 Permission to use, copy, modify and distribute this software and its
00036 documentation is hereby granted, provided that both the copyright
00037 notice and this permission notice appear in all copies of the
00038 software, derivative works or modified versions, and any portions
00039 thereof, and that both notices appear in supporting documentation.
00040 
00041 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00042 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00043 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00044 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00045 
00046 This software was developed with support by the Advanced Research
00047 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00048 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00049 Further funding for this work was provided by DARPA through
00050 Rome Research Laboratory Contract No. F30602-97-2-0247.
00051 
00052 */
00053 
00054 #include "w_defines.h"
00055 
00056 /*  -- do not edit anything above this line --   </std-header>*/
00057 
00058 
00059 /*
00060  *   NewThreads is Copyright 1992, 1993, 1994, 1995, 1996, 1997 by:
00061  *
00062  *    Josef Burger    <bolo@cs.wisc.edu>
00063  *    Dylan McNamee    <dylan@cse.ogi.edu>
00064  *    Ed Felten       <felten@cs.princeton.edu>
00065  *
00066  *   All Rights Reserved.
00067  *
00068  *   NewThreads may be freely used as long as credit is given
00069  *   to the above authors and the above copyright is maintained.
00070  */
00071 
00072 /*
00073  * The base thread functionality of Shore Threads is derived
00074  * from the NewThreads implementation wrapped up as c++ objects.
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 /* thread-local random number generator -- see rand48.h  */
00119 
00120 /**\var static __thread rand48 tls_rng
00121  * \brief A 48-bit pseudo-random number generator
00122  * \ingroup TLS
00123  * \details
00124  * Thread-safety is achieved by having one per thread.
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  * Class sthread_init_t
00143  *  Internal --- responsible for initialization
00144  *
00145  *********************************************************************/
00146 /**\brief Responsible for initialization of Shore threads
00147  *
00148  * A static instance initializes the package by calling its static method
00149  * \code
00150    do_init()
00151  * \endcode
00152  *
00153  * This is also called on every sthread fork() and by 
00154  * \code
00155     sthread_t::initialize_sthreads_package()
00156  * \endcode
00157  * which is called by the storage manager constructor.
00158  *
00159  * All this in lieu of using a Schwartz counter.
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 * /*file*/, int /*line*/) const
00179 {
00180 // NOTE: for now, I haven't found a way to get the current frame off
00181 // a pthread stack other than the current one (me()), so this is
00182 // not possible
00183     return true;
00184 }
00185 
00186 
00187 /* check all threads */
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 /* Give an estimate if the stack will overflow if a function with
00207    a stack frame of the requested size is called. */
00208 
00209 // For debugger breakpoint:
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 // In order of values:
00225     "STACK OVERFLOW frame (offset -%ld) %p bottom %p danger %p top %p stack_size %ld \n",
00226     // cast so it works for -m32 and -m64
00227      (long int) size, _stack_top, absolute_bottom, _danger, _start_frame, 
00228      (long int) _stack_size);
00229     } else {
00230     fprintf(stderr, 
00231 // In order of values:
00232     "STACK IN GUARD AREA bottom %p frame (offset -%ld) %p danger %p top %p stack_size %ld \n",
00233     // cast so it works for -m32 and -m64
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  *  Class static variable intialization
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  * sthread_t::cold_startup()
00262  *
00263  * Initialize system threads from cold-iron.  The main thread will run
00264  * on the stack startup() is called on.
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     // initialize the global RNG
00276     struct timeval now;
00277     gettimeofday(&now, NULL);
00278     // Set the seed for the clib random-number generator, which
00279     // we use to seed the per-thread RNG
00280     ::srand(now.tv_usec);
00281     
00282     /*
00283      * Boot the main thread onto the current (system) stack.
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     /* The main thread is different from all other threads. */
00296     purify_name_thread(me()->name());
00297 #endif
00298 
00299     return RCOK;
00300 }
00301 
00302 /*
00303  * sthread_t::shutdown()
00304  *
00305  * Shutdown the thread system.  Must be called from the context of
00306  * the main thread.
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 /**\cond skip */
00321 /*
00322  *  sthread_main_t::sthread_main_t()
00323  *
00324  * Create the main thread.  It is a placeholder for the
00325  * thread which uses the system stack.
00326  */
00327 
00328 sthread_main_t::sthread_main_t()
00329 : sthread_t(t_regular, "main_thread", 0)
00330 {
00331     /*
00332     fprintf(stderr, "sthread_main_t constructed, this %p\n", this);
00333     fflush(stderr);
00334     */
00335 }
00336 
00337 
00338 /*
00339  *  sthread_main_t::run()
00340  *
00341  *  This is never called.  It's an artifact of the thread architecture.
00342  *  It is a virtual function so that derived thread types put their guts here.
00343  */
00344 
00345 void sthread_main_t::run()
00346 {
00347 }
00348 
00349 /**\endcond skip */
00350 
00351 /*
00352  *  sthread_t::set_priority(priority)
00353  *
00354  *  Sets the priority of current thread.  The thread must not
00355  *  be in the ready Q.
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     // in this statement, <= is used to keep gcc -Wall quiet
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  *  sthread_t::sleep(timeout)
00380  *
00381  *  Sleep for timeout milliseconds.
00382  */
00383 
00384 void sthread_t::sleep(timeout_in_ms timeout, const char *reason)
00385 {
00386     reason = (reason && *reason) ? reason : "sleep";
00387 
00388     /* FRJ: even though we could just use the posix sleep() call,
00389        we'll stick to the sthreads way and block on a cond
00390        var. That way the sthreads debug stuff will keep
00391        working. Besides, we're here to waste time, right?
00392     */
00393     CRITICAL_SECTION(cs, _wait_lock);
00394     _sleeping = true;
00395     (void) _block(timeout, reason, this); // W_IGNORE
00396     _sleeping = false;
00397 }
00398 
00399 /*
00400  *  sthread_t::wakeup()
00401  *
00402  *  Cancel sleep
00403  */
00404 
00405 void sthread_t::wakeup()
00406 {
00407     CRITICAL_SECTION(cs, _wait_lock);
00408     if(_sleeping) _unblock(stOK);
00409 }
00410 
00411 
00412 /*
00413  *  Wait for this thread to end. This method returns when this thread
00414  *  ends.  Timeout is no longer available. 
00415  */
00416 
00417 w_rc_t
00418 sthread_t::join(timeout_in_ms /*timeout*/)
00419 {
00420     w_rc_t rc;
00421     {
00422         CRITICAL_SECTION(cs, _start_terminate_lock);
00423 
00424         /* A thread that hasn't been forked can't be wait()ed for.
00425            It's not a thread until it has been fork()ed. 
00426         */
00427         if (!_forked) {
00428             rc =  RC(stOS);
00429         } else 
00430         {
00431             cs.exit();
00432             /*
00433              *  Wait for thread to finish.
00434              */
00435             sthread_core_exit(_core, _terminated);
00436 
00437         }
00438     }
00439 
00440     return rc;
00441 }
00442 
00443 
00444 /*
00445  * sthread_t::fork()
00446  *
00447  * Turn the "chunk of memory" into a real-live thread.
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         /* can only fork a new thread */
00456         if (_forked)
00457             return RC(stOS);
00458 
00459         /* Add us to the list of threads, unless we are the main thread */
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             // happens at global constructor time
00470             CRITICAL_SECTION(cs_thread, _wait_lock);
00471             _status = t_running;
00472         } else    {
00473             // happens after main() called
00474             DO_PTHREAD( pthread_cond_signal(_start_cond) );
00475         }
00476     }
00477 
00478     return RCOK;
00479 }
00480 
00481 
00482 /*
00483  *  sthread_t::sthread_t(priority, name)
00484  *
00485  *  Create a thread.  Until it starts running, a created thread
00486  *  is just a memory object.
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++), // make it match the gdb threads #. Origin 1
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;  // not necessary, but might 
00516                                     // be useful for debugging
00517 
00518     /*
00519      *  Set a valid priority level
00520      */
00521     if (_priority > max_priority)
00522         _priority = max_priority;
00523     else if (_priority <= min_priority)
00524         _priority = min_priority;
00525 
00526     /*
00527      *  Initialize the core.
00528      */
00529     DO_PTHREAD(pthread_mutex_init(&_wait_lock, NULL));
00530     DO_PTHREAD(pthread_cond_init(&_wait_cond, NULL));
00531     
00532     /*
00533      * stash the procedure (sthread_t::_start)
00534      * and arg (this)
00535      * in the core structure, along with
00536      * status info.
00537      * and if this is not the _main_thread (running in
00538      * the system thread, i.e., in an already-running pthread)
00539      * then create a pthread for it and give it a starting function
00540      // TODO: should probably merge sthread_core_pthread.cpp in here
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  *  sthread_t::~sthread_t()
00552  *
00553  *  Destructor. Thread must have already exited before its object
00554  *  is destroyed.
00555  */
00556 
00557 sthread_t::~sthread_t()
00558 {
00559     /*
00560     fprintf(stderr, "sthread_t %s destructed, this %p core %p pthread %p\n", 
00561             name(), this, _core, (void *)myself()); 
00562     fflush(stderr);
00563     */
00564     {
00565     CRITICAL_SECTION(cs, _wait_lock);
00566     /* Valid states for destroying a thread are ...
00567        1) It was never started
00568        2) It ended.
00569        3) There is some braindamage in that that blocked threads
00570        can be deleted.  This is sick and wrong, and it
00571        can cause race conditions.  It is enabled for compatibility,
00572        and hopefully the warning messages will tell you if
00573        something is wrong. */
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; // clean up for valgrind
00596 
00597 }
00598 
00599 #ifndef PTHREAD_STACK_MIN
00600 // This SHOULD be defined in <limits.h> (included from w_defines.h)
00601 // but alas, I found that not to be the case on or solaris platform...
00602 // so here's a workaround.
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 /* A springboard from "C" function + argument into an object */
00623 void    sthread_t::__start(void *arg)
00624 {
00625     sthread_t* t = (sthread_t*) arg;
00626     me_lval() = t;
00627     t->_start_frame = &t; // used to gauge danger of stack overflow
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        // fprintf(stderr,"pthread stack size too small: %lld\n", (long long)sz);
00662 #ifndef PTHREAD_STACK_MIN_SUBSTITUTE 
00663 // How did I come up with this number?  It's from experimenting with
00664 // tests/thread1 on chianti, which seems not to be compliant in any way,
00665 // not giving me any way to find out what the pthreads stack size is.
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     // Lop off a few pages for a guard
00676     // though we're not actually mem-protecting these pages.
00677     // Rather, for debugging, we'll zero these pages, or a chunk of
00678     // them, and then we can check later to see if they got overwritten.
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  *  sthread_t::_start()
00691  *
00692  *  All *non-system* threads start and end here.
00693  */
00694 
00695 void sthread_t::_start()
00696 {
00697     tls_tricks::tls_manager::thread_init();
00698     w_assert1(me() == this);
00699  
00700     // assertions: will call stackoverflowed() if !ok and will return false
00701     w_assert1(isStackFrameOK(0));
00702     {
00703         CRITICAL_SECTION(cs, _start_terminate_lock);
00704         if(_forked) {
00705             // If the parent thread gets to fork() before
00706             // the child can get to _start(), then _forked
00707             // will be true. In this case, skip the condition wait.
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     /* threads should be named in the constructor, not
00719        in run() ... this is mostly useless if that happens */
00720     purify_name_thread(name());
00721 #endif
00722 
00723     { 
00724         // thread checker complains about this not being reentrant
00725         // so we'll protect it with a mutex.
00726         // We could use reentrant rand_r but then we need to seed it.
00727         // and the whole point here is to use rand() to seed each thread
00728         // differently.
00729         // to protect non-reentrant rand()
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         /* do not save sigmask */
00744         w_assert1(me() == this);
00745 #ifdef STHREAD_CXX_EXCEPTION
00746         // NOTE: this is not tested in SHORE-MT; it is old code.
00747         // TODO: exception-handling.
00748         
00749         /* Provide a "backstop" exception handler to catch uncaught
00750            exceptions in the thread.  This prevents them from going
00751            into never-never land. */
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     /* Returned from run(). Current thread is ending. */
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         // wake up any thread that joined on us
00788         tls_tricks::tls_manager::thread_fini();
00789         pthread_exit(0);
00790     }
00791     
00792     W_FATAL(stINTERNAL);    // never reached
00793 }
00794 
00795 
00796 
00797 /*********************************************************************
00798  *
00799  *  sthread_t::block(&lock, timeout, list, caller, id)
00800  *  sthread_t::_block(*lock, timeout, list, caller, id)
00801  *
00802  *  Block the current thread and puts it on list.
00803  *
00804  * NOTE: the caller is assumed to already hold the lock(first arg)
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,        // list for thread after blocking
00812     const char* const   caller,        // for debugging only
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 /*= WAIT_FOREVER*/)
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,        // list for thread after blocking
00831     const char* const   caller,        // for debugging only
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          *  Put on list
00841          */
00842         w_assert3(self->_link.member_of() == 0); // not in other list
00843         if (list)  {
00844             list->put_in_order(self);
00845         }
00846 
00847         if(lock) {
00848             // the caller expects us to unlock this
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(); // we timed out and removed ourself from the waitlist
00859         } else {
00860             CRITICAL_SECTION(cs, self->_wait_lock);
00861             self->_link.detach(); // we timed out and removed ourself from the waitlist
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         // find out how long we're supposed to wait...
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         ,        // for debugging only
00891     const void        *
00892         )
00893 {
00894 // ASSUMES WE ALREADY LOCKED self->_wait_lock
00895 
00896     /*
00897      *  Sanity checks
00898      */
00899     sthread_t* self = me();
00900     w_assert1(timeout != WAIT_IMMEDIATE);   // not 0 timeout
00901 
00902     // wait...
00903     status_t old_status = self->_status;
00904     self->_status = t_blocked;
00905 
00906     int error = 0;
00907     self->_unblock_flag = false;
00908     // NOTE: abstract timeouts, e.g., WAIT_FOREVER, are  < 0
00909     // absolute timeouts are > 0
00910     // WAIT_IMMEDIATE == 0; we asserted above that it's not immediate
00911  
00912  self->_rce = stOK;
00913 
00914     if(timeout > 0) {
00915         timespec when;
00916         timeout_to_timespec(timeout, when);
00917         // ta-ta for now
00918         // pthread_cond_timedwait should return ETIMEDOUT when the
00919         // timeout has passed, so we should drop out if timed out,
00920         // and it should return 0 if we were signalled.
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             // Break out if we were signalled
00926             if(!error) break;
00927         }
00928         
00929     } else {
00930         // wait forever... no other abstract timeout should get here
00931         w_assert1(timeout == sthread_t::WAIT_FOREVER);
00932         // wait until someone else unblocks us (sets _unblock_flag)
00933         // pthread_cond_wait should return 0 if no error, that is,
00934         // if we were signalled
00935         while(!error && !self->_unblock_flag)
00936                                      // condition          // mutex
00937             error = pthread_cond_wait(&self->_wait_cond, &self->_wait_lock);
00938     }
00939     // why did we wake up?
00940     switch(error) {
00941     case ETIMEDOUT:
00942         // FRJ: Not quite sure why this one thinks it's not being checked...
00943         // Should get here only from pthread_cond_timedwait
00944         w_assert1(timeout > 0);
00945 #if 1 || DEAD
00946         W_COERCE(self->_unblock(stTIMEOUT));
00947 #else
00948         // modified copy of _unblock(stTIMEOUT) below
00949         {
00950    // Don't change the error code unless it was not set
00951    // by an unblocker coincident with our timeout.
00952             if(!self->_rce) self->_rce = stTIMEOUT;
00953             self->_unblock_flag = true;
00954         }
00955 #endif
00956         // fall through
00957     case 0:
00958         /* somebody called unblock(). We don't need to lock because
00959          * locking only matters to make sure the thread doesn't
00960          * perform its initial block() after it is told to fork().
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  *  sthread_t::unblock(rc)
00975  *
00976  *  Unblock the thread with an error in rc.
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     /* Now that we hold both the list mutex (_wait_lock) 
00985        we can remove ourselves from the waitlist. 
00986     */
00987     _link.detach();
00988     return _unblock(e);
00989     
00990 }
00991 
00992 // this version assumes caller holds _lock
00993 w_rc_t
00994 sthread_t::_unblock(w_rc_t::errcode_t e)
00995 {
00996     _status = t_ready;
00997 
00998     /*
00999      *  Save rc (will be returned by block())
01000      */
01001     _rce = e;
01002     _unblock_flag = true;
01003 
01004     membar_producer(); // make sure the unblock_flag and _rce
01005     // are visible before the signal is.
01006     DO_PTHREAD(pthread_cond_signal(&_wait_cond));
01007     _status = t_running;
01008 
01009     return RCOK;
01010 }
01011 
01012 
01013 
01014 /*********************************************************************
01015  *
01016  *  sthread_t::yield()
01017  *  if do_select==true, we'll allow a select w/ 0 timeout
01018  *  to occur if the ready queue is empty
01019  *
01020  *  Give up CPU. Maintain ready status.
01021  *
01022  *  Used only in tests, nowhere in basic sm.
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 /* print all threads */
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 // We've put this into a huge critical section
01049 // to make it thread-safe, even though it's probably not necessary
01050 // when used in the debugger, which is the only place this is used...
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 /* XXX individual thread dump function... obsoleted by print method */
01066 void sthread_t::_dump(ostream &o) const
01067 {
01068     o << *this << endl;
01069 }
01070 
01071 /* XXX it is not a bug that you can sometime see >100% cpu utilization.
01072    Don't even think about hacking something to change it.  The %CPU
01073    is an *estimate* developed by statistics gathered by the process,
01074    not something solid given by the kernel. */
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     /* To be moved somewhere else once I put some other infrastructure
01102        into place.  Live with it in the meantime, the output is really
01103        useful for observing ad-hoc system performance. */
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     /* Try to provide some modicum of recent cpu use. This will eventually
01120        move into the class, once a "thread handler" arrives to take
01121        care of it. */
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  *  sthread_t::print(stream)
01177  *
01178  *  Print thread status to an stream
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  *  sthread_t::for_each_thread(ThreadFunc& f)
01212  *
01213  *  For each thread in the system call the function object f.
01214  *
01215  *********************************************************************/
01216 void sthread_t::for_each_thread(ThreadFunc& f)
01217 {
01218 // We've put this into a huge critical section
01219 // to make it thread-safe, even though it's probably not necessary
01220 // when used in the debugger, which is the only place this is used...
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", // DEAD
01237                       "WAIT_ALL", // DEAD
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         // wake it up
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         // block
01280         count = atomic_add_32_nv(&_active_count, -READER);
01281         {
01282             CRITICAL_SECTION(cs, _read_write_mutex);
01283             
01284             // nasty race: we could have fooled a writer into sleeping...
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     // only one writer allowed in at a time...
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     // any lurking writers are waiting on the cond var
01314     int count = atomic_add_32_nv(&_active_count, WRITER);
01315     w_assert1(count & WRITER);
01316 
01317     // drain readers
01318     while(count != WRITER) {
01319         DO_PTHREAD(pthread_cond_wait(&_write_cond, &_read_write_mutex));
01320         count = *&_active_count;
01321     }
01322 }
01323 
01324 /**\cond skip */
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     // can't have n2 or n3 without n1
01338     // can have n1,0,n3 or n1,n2,0
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         // only copy as much as will fit
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     // can't have n2 or n3 without n1
01382     // can have n1,0,n3 or n1,n2,0
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 /**\endcond skip */
01396 
01397 /**\cond skip */
01398 
01399 // if you really are a sthread_t return 0
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 /**\endcond skip */
01412 
01413 /*********************************************************************
01414  *
01415  *  dumpthreads()
01416  *  For debugging, but it's got to be
01417  *  present in servers compiled without debugging.
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      * Get limits on file sizes imposed by the operating
01438      * system and shell.
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      * Unfortunately, sometimes this comes out
01463      * negative, since r.rlim_cur is unsigned and
01464      * fileoff_t is signed (sigh).
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 /* XXX this doesn't work, neither does the one in sdisk, because
01473    the constructor order isn't guaranteed.  The only important
01474    use before main() runs is the one right above here. */
01475 
01476 
01477 /*********************************************************************
01478  *
01479  *  sthread_init_t::sthread_init_t()
01480  *
01481  *  Initialize the sthread environment. The first time this method
01482  *  is called, it sets up the environment 
01483  *
01484  *********************************************************************/
01485 #include "sthread_vtable_enum.h"
01486 
01487 // We'll have the ss_m constructor do this and just to be safe,
01488 // we'll have fork also do this init.
01489 // Cleanup is done in global destructors.
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     // This should not ever get initialized more than once
01500     if (sthread_init_t::initialized == 0) 
01501     {
01502         CRITICAL_SECTION(cs, init_mutex);
01503 
01504         // check again
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              *  Register error codes.
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  *  sthread_init_t::~sthread_init_t()
01535  *
01536  *  Destructor. Does not do much.
01537  *
01538  *********************************************************************/
01539 NORET
01540 sthread_init_t::~sthread_init_t()
01541 {
01542     CRITICAL_SECTION(cs, init_mutex);
01543 
01544     // This should not ever get initialized more than once
01545     // Could be that it never got initialized.
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         // Must delete the main thread before you delete the class list,
01553         // since it'll not be empty until main thread is gone.
01554         //
01555         /* note: me() is main thread */
01556         sthread_t::_main_thread->_status = sthread_t::t_defunct;
01557 
01558         delete sthread_t::_main_thread; // clean up for valgrind
01559         sthread_t::_main_thread = 0;
01560         
01561         delete sthread_t::_class_list; // clean up for valgrind
01562         sthread_t::_class_list = 0;
01563     }
01564 }
01565 
01566 pthread_t sthread_t::myself() { return _core->pthread; }
01567 

Generated on Mon Jan 2 15:13:57 2012 for Shore Storage Manager by  doxygen 1.4.7