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.333 2010/12/08 17:37:50 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 {
00505     if(!_start_terminate_lock || !_start_cond )
00506         W_FATAL(fcOUTOFMEMORY);
00507 
00508     DO_PTHREAD(pthread_cond_init(_start_cond, NULL));
00509     DO_PTHREAD(pthread_mutex_init(_start_terminate_lock, NULL));
00510     
00511     _core = new sthread_core_t;
00512     if (!_core)
00513         W_FATAL(fcOUTOFMEMORY);
00514     _core->sthread = (void *)this;  // not necessary, but might 
00515                                     // be useful for debugging
00516 
00517     /*
00518      *  Set a valid priority level
00519      */
00520     if (_priority > max_priority)
00521         _priority = max_priority;
00522     else if (_priority <= min_priority)
00523         _priority = min_priority;
00524 
00525     /*
00526      *  Initialize the core.
00527      */
00528     DO_PTHREAD(pthread_mutex_init(&_wait_lock, NULL));
00529     DO_PTHREAD(pthread_cond_init(&_wait_cond, NULL));
00530     
00531     /*
00532      * stash the procedure (sthread_t::_start)
00533      * and arg (this)
00534      * in the core structure, along with
00535      * status info.
00536      * and if this is not the _main_thread (running in
00537      * the system thread, i.e., in an already-running pthread)
00538      * then create a pthread for it and give it a starting function
00539      // TODO: should probably merge sthread_core_pthread.cpp in here
00540      */
00541     if (sthread_core_init(_core, __start, this, stack_size) == -1) {
00542         cerr << "sthread_t: cannot initialize thread core" << endl;
00543         W_FATAL(stINTERNAL);
00544     }
00545 }
00546 
00547 
00548 
00549 /*
00550  *  sthread_t::~sthread_t()
00551  *
00552  *  Destructor. Thread must have already exited before its object
00553  *  is destroyed.
00554  */
00555 
00556 sthread_t::~sthread_t()
00557 {
00558     /*
00559     fprintf(stderr, "sthread_t %s destructed, this %p core %p pthread %p\n", 
00560             name(), this, _core, (void *)myself()); 
00561     fflush(stderr);
00562     */
00563     {
00564     CRITICAL_SECTION(cs, _wait_lock);
00565     /* Valid states for destroying a thread are ...
00566        1) It was never started
00567        2) It ended.
00568        3) There is some braindamage in that that blocked threads
00569        can be deleted.  This is sick and wrong, and it
00570        can cause race conditions.  It is enabled for compatibility,
00571        and hopefully the warning messages will tell you if
00572        something is wrong. */
00573     w_assert1(_status == t_virgin
00574           || _status == t_defunct
00575           || _status == t_blocked
00576                   );
00577 
00578     if (_link.member_of()) {
00579         W_FORM2(cerr,("sthread_t(%#lx): \"%s\": destroying a thread on a list!",
00580               (long)this, name()));
00581     }
00582     }
00583     sthread_core_exit(_core, _terminated);
00584 
00585     delete _core;
00586     _core = 0;
00587 
00588     DO_PTHREAD(pthread_cond_destroy(_start_cond));
00589     delete _start_cond;
00590     _start_cond = 0;
00591 
00592     DO_PTHREAD(pthread_mutex_destroy(_start_terminate_lock));
00593     delete _start_terminate_lock;
00594     _start_terminate_lock = 0; // clean up for valgrind
00595 
00596 }
00597 
00598 #ifndef PTHREAD_STACK_MIN
00599 // This SHOULD be defined in <limits.h> (included from w_defines.h)
00600 // but alas, I found that not to be the case on or solaris platform...
00601 // so here's a workaround.
00602 size_t get_pthread_stack_min()
00603 {
00604    static size_t gotit(0);
00605    if(!gotit) {
00606       gotit = sysconf(_SC_THREAD_STACK_MIN);
00607       if(!gotit) {
00608           const char *errmsg =
00609          "Platform does not appear to conform to POSIX 1003.1c-1995 re: limits";
00610 
00611           W_FATAL_MSG(fcINTERNAL, << errmsg);
00612       }
00613       w_assert1(gotit > 0);
00614    }
00615    return gotit;
00616 }
00617 #endif
00618 
00619 
00620 
00621 /* A springboard from "C" function + argument into an object */
00622 void    sthread_t::__start(void *arg)
00623 {
00624     sthread_t* t = (sthread_t*) arg;
00625     me_lval() = t;
00626     t->_start_frame = &t; // used to gauge danger of stack overflow
00627 
00628 #ifndef PTHREAD_STACK_MIN
00629     size_t PTHREAD_STACK_MIN = get_pthread_stack_min();
00630 #endif
00631 
00632 #if HAVE_PTHREAD_ATTR_GETSTACKSIZE
00633     pthread_attr_t attr;
00634     size_t         sz=0;
00635     int e = pthread_attr_init(&attr);
00636     if(e) {
00637         fprintf(stderr,"Cannot init pthread_attr e=%d\n", e);
00638         ::exit(1);
00639     }
00640     else 
00641     {
00642         e = pthread_attr_getstacksize( &attr, &sz);
00643         if(e || sz==0) {
00644 #if HAVE_PTHREAD_ATTR_GETSTACK
00645             void *voidp(NULL);
00646             e = pthread_attr_getstack( &attr, &voidp, &sz);
00647             if(e || sz == 0) 
00648 #endif
00649             {
00650 #if W_DEBUG_LEVEL > 2
00651                 fprintf(stderr,"Cannot get pthread stack size e=%d, sz=%lld\n", 
00652                 e, (long long)sz);
00653 #endif
00654                 sz = PTHREAD_STACK_MIN;
00655             } 
00656         }
00657     }
00658 #define GUARD 8192*4
00659     if(sz <  GUARD) {
00660        // fprintf(stderr,"pthread stack size too small: %lld\n", (long long)sz);
00661 #ifndef PTHREAD_STACK_MIN_SUBSTITUTE 
00662 // How did I come up with this number?  It's from experimenting with
00663 // tests/thread1 on chianti, which seems not to be compliant in any way,
00664 // not giving me any way to find out what the pthreads stack size is.
00665 #define PTHREAD_STACK_MIN_SUBSTITUTE 0x100000
00666 #endif
00667        sz = PTHREAD_STACK_MIN_SUBSTITUTE;
00668 #if W_DEBUG_LEVEL > 2
00669        fprintf(stderr,"using  %lld temporarily\n", (long long)sz);
00670 #endif
00671     }
00672     t->_stack_size = sz;
00673 
00674     // Lop off a few pages for a guard
00675     // though we're not actually mem-protecting these pages.
00676     // Rather, for debugging, we'll zero these pages, or a chunk of
00677     // them, and then we can check later to see if they got overwritten.
00678     sz -= GUARD;
00679     t->_danger = (void *)((char *)t->_start_frame - sz);
00680 
00681 #endif
00682     w_assert1(t->_danger < t->_start_frame);
00683     w_assert1(t->_stack_size > 0);
00684 
00685     t->_start();
00686 }
00687 
00688 /*
00689  *  sthread_t::_start()
00690  *
00691  *  All *non-system* threads start and end here.
00692  */
00693 
00694 void sthread_t::_start()
00695 {
00696     tls_tricks::tls_manager::thread_init();
00697     w_assert1(me() == this);
00698  
00699     // assertions: will call stackoverflowed() if !ok and will return false
00700     w_assert1(isStackFrameOK(0));
00701     {
00702         CRITICAL_SECTION(cs, _start_terminate_lock);
00703         if(_forked) {
00704             // If the parent thread gets to fork() before
00705             // the child can get to _start(), then _forked
00706             // will be true. In this case, skip the condition wait.
00707             CRITICAL_SECTION(cs_thread, _wait_lock);
00708             _status = t_running;
00709         } else {
00710             DO_PTHREAD(pthread_cond_wait(_start_cond, _start_terminate_lock));
00711             CRITICAL_SECTION(cs_thread, _wait_lock);
00712             _status = t_running;
00713         }
00714     }
00715 
00716 #if defined(PURIFY)
00717     /* threads should be named in the constructor, not
00718        in run() ... this is mostly useless if that happens */
00719     purify_name_thread(name());
00720 #endif
00721 
00722     { 
00723         // thread checker complains about this not being reentrant
00724         // so we'll protect it with a mutex.
00725         // We could use reentrant rand_r but then we need to seed it.
00726         // and the whole point here is to use rand() to seed each thread
00727         // differently.
00728         // to protect non-reentrant rand()
00729         static queue_based_lock_t rand_mutex;
00730 
00731         long seed1, seed2;
00732         {
00733             CRITICAL_SECTION(cs, rand_mutex);
00734             seed1 = ::rand();
00735             seed2 = ::rand();
00736         }
00737         tls_rng.seed( (seed1 << 24) ^ seed2);
00738     }
00739      
00740     
00741     {
00742         /* do not save sigmask */
00743         w_assert1(me() == this);
00744 #ifdef STHREAD_CXX_EXCEPTION
00745         // NOTE: this is not tested in SHORE-MT; it is old code.
00746         // TODO: exception-handling.
00747         
00748         /* Provide a "backstop" exception handler to catch uncaught
00749            exceptions in the thread.  This prevents them from going
00750            into never-never land. */
00751         try {
00752             before_run();
00753             run();
00754             after_run();
00755         }
00756         catch (...) {
00757             cerr << endl
00758                  << "sthread_t(id = " << id << "  name = " << name()
00759                  << "): run() threw an exception."
00760                  << endl
00761                  << endl;
00762         }
00763 #else
00764         before_run();
00765         run();
00766         after_run();
00767 #endif
00768     }
00769 
00770     /* Returned from run(). Current thread is ending. */
00771     {
00772         CRITICAL_SECTION(cs, _wait_lock);
00773         w_assert3(me() == this);
00774         _status = t_defunct;
00775         _link.detach();
00776     }
00777     {
00778         CRITICAL_SECTION(cs, _class_list_lock);
00779         _class_link.detach();
00780     }
00781 
00782     w_assert3(this == me());
00783 
00784     {
00785         w_assert1(_status == t_defunct);
00786         // wake up any thread that joined on us
00787         tls_tricks::tls_manager::thread_fini();
00788         pthread_exit(0);
00789     }
00790     
00791     W_FATAL(stINTERNAL);    // never reached
00792 }
00793 
00794 
00795 
00796 /*********************************************************************
00797  *
00798  *  sthread_t::block(&lock, timeout, list, caller, id)
00799  *  sthread_t::_block(*lock, timeout, list, caller, id)
00800  *
00801  *  Block the current thread and puts it on list.
00802  *
00803  * NOTE: the caller is assumed to already hold the lock(first arg)
00804  *
00805  *********************************************************************/
00806 w_rc_t
00807 sthread_t::block(
00808     pthread_mutex_t     &lock,
00809     timeout_in_ms       timeout,
00810     sthread_list_t*     list,        // list for thread after blocking
00811     const char* const   caller,        // for debugging only
00812     const void *        id)
00813 {
00814     w_rc_t::errcode_t rce = _block(&lock, timeout, list, caller, id);
00815     if(rce) return RC(rce);
00816     return RCOK;
00817 }
00818 
00819 w_rc_t::errcode_t        
00820 sthread_t::block(int4_t timeout /*= WAIT_FOREVER*/)
00821 {
00822     return  _block(NULL, timeout);
00823 }
00824 
00825 w_rc_t::errcode_t
00826 sthread_t::_block(
00827     pthread_mutex_t     *lock,
00828     timeout_in_ms       timeout,
00829     sthread_list_t*     list,        // list for thread after blocking
00830     const char* const   caller,        // for debugging only
00831     const void *        id)
00832 {
00833     w_rc_t::errcode_t rce(stOK);
00834     sthread_t* self = me();
00835     {
00836         CRITICAL_SECTION(cs, self->_wait_lock);
00837         
00838         /*
00839          *  Put on list
00840          */
00841         w_assert3(self->_link.member_of() == 0); // not in other list
00842         if (list)  {
00843             list->put_in_order(self);
00844         }
00845 
00846         if(lock) {
00847             // the caller expects us to unlock this
00848             DO_PTHREAD(pthread_mutex_unlock(lock));
00849         }
00850         rce = _block(timeout, caller, id);
00851     }
00852     if(rce == stTIMEOUT) {
00853         if(lock) {
00854             CRITICAL_SECTION(outer_cs, &lock);
00855 
00856             CRITICAL_SECTION(cs, self->_wait_lock);
00857             self->_link.detach(); // we timed out and removed ourself from the waitlist
00858         } else {
00859             CRITICAL_SECTION(cs, self->_wait_lock);
00860             self->_link.detach(); // we timed out and removed ourself from the waitlist
00861         }
00862     }
00863     
00864     return rce;
00865 }
00866 
00867 void sthread_t::timeout_to_timespec(timeout_in_ms timeout, struct timespec &when)
00868 {
00869     w_assert1(timeout != WAIT_IMMEDIATE); 
00870     w_assert1(timeout != sthread_t::WAIT_FOREVER);
00871     if(timeout > 0) {
00872         struct timeval now;
00873 
00874         // find out how long we're supposed to wait...
00875         gettimeofday(&now, NULL);
00876         when.tv_sec = now.tv_sec + timeout/1000;
00877         when.tv_nsec = now.tv_usec*1000 + 100000*(timeout%1000);
00878         if(when.tv_nsec >= 1000*1000*1000) {
00879             when.tv_sec++;
00880             when.tv_nsec -= 1000*1000*1000;
00881         }
00882     }
00883 }
00884 
00885 w_rc_t::errcode_t
00886 sthread_t::_block(
00887     timeout_in_ms    timeout,
00888     const char* const    
00889         ,        // for debugging only
00890     const void        *
00891         )
00892 {
00893 // ASSUMES WE ALREADY LOCKED self->_wait_lock
00894 
00895     /*
00896      *  Sanity checks
00897      */
00898     sthread_t* self = me();
00899     w_assert1(timeout != WAIT_IMMEDIATE);   // not 0 timeout
00900 
00901     
00902 
00903     // wait...
00904     status_t old_status = self->_status;
00905     self->_status = t_blocked;
00906 
00907     int error = 0;
00908     self->_unblock_flag = false;
00909     if(timeout > 0) {
00910         timespec when;
00911         timeout_to_timespec(timeout, when);
00912         // ta-ta for now
00913         // pthread_cond_timedwait should return ETIMEDOUT when the
00914         // timeout has passed, so we should drop out if timed out,
00915         // and it should return 0 if we were signalled.
00916         while(!error && !self->_unblock_flag)  {
00917             error = pthread_cond_timedwait(&self->_wait_cond, 
00918                     &self->_wait_lock, &when);
00919             w_assert1(error == ETIMEDOUT || error == 0);
00920             // Break out if we were signalled
00921             if(!error) break;
00922         }
00923     }
00924     else {
00925         // wait forever... no other abstract timeout should have gotten here
00926         w_assert1(timeout == sthread_t::WAIT_FOREVER);
00927         // wait until someone else unblocks us (sets _unblock_flag)
00928         // pthread_cond_wait should return 0 if no error, that is,
00929         // if we were signalled
00930         while(!error && !self->_unblock_flag)
00931                                      // condition          // mutex
00932             error = pthread_cond_wait(&self->_wait_cond, &self->_wait_lock);
00933     }
00934     // why did we wake up?
00935     switch(error) {
00936     case ETIMEDOUT:
00937         // FRJ: Not quite sure why this one thinks it's not being checked...
00938         W_COERCE(self->_unblock(stTIMEOUT));
00939         // fall through
00940     case 0:
00941         /* somebody called unblock(). We don't need to lock because
00942          * locking only matters to make sure the thread doesn't
00943          * perform its initial block() after it is told to fork().
00944          */
00945         self->_status = old_status;
00946         return self->_rce;
00947     default:
00948         self->_status = old_status;
00949         return sthread_t::stOS;
00950     }
00951 }
00952 
00953 
00954 
00955 /*********************************************************************
00956  *
00957  *  sthread_t::unblock(rc)
00958  *
00959  *  Unblock the thread with an error in rc.
00960  *
00961  *********************************************************************/
00962 w_rc_t
00963 sthread_t::unblock(w_rc_t::errcode_t e) 
00964 {
00965     CRITICAL_SECTION(cs, _wait_lock);
00966 
00967     /* Now that we hold both the list mutex (our caller did that) and
00968        the thread mutex, we can remove ourselves from the waitlist. To
00969        be honest, the list lock might be enough by itself, but we have
00970        to grab both locks anyway, so we may as well be doubly sure.
00971     */
00972     _link.detach();
00973     return _unblock(e);
00974     
00975 }
00976 
00977 // this version assumes caller holds _lock
00978 w_rc_t
00979 sthread_t::_unblock(w_rc_t::errcode_t e)
00980 {
00981     _status = t_ready;
00982 
00983     /*
00984      *  Save rc (will be returned by block())
00985      */
00986     if (e)
00987         _rce = e;
00988     else
00989         _rce = stOK;
00990 
00991     /*
00992      *  Thread is again ready.
00993      */
00994     _unblock_flag = true;
00995     membar_producer(); // make sure the unblock_flag is visible
00996     DO_PTHREAD(pthread_cond_signal(&_wait_cond));
00997     _status = t_running;
00998 
00999     return RCOK;
01000 }
01001 
01002 
01003 
01004 /*********************************************************************
01005  *
01006  *  sthread_t::yield()
01007  *  if do_select==true, we'll allow a select w/ 0 timeout
01008  *  to occur if the ready queue is empty
01009  *
01010  *  Give up CPU. Maintain ready status.
01011  *
01012  *  Used only in tests, nowhere in basic sm.
01013  *
01014  *********************************************************************/
01015 void sthread_t::yield()
01016 {
01017     sthread_t* self = me();
01018     CRITICAL_SECTION(cs, self->_wait_lock);
01019     w_assert3(self->_status == t_running);
01020     self->_status = t_ready;
01021     cs.pause();
01022     sched_yield();
01023     cs.resume();
01024     self->_status = t_running;
01025 }
01026 
01027 /* print all threads */
01028 void sthread_t::dumpall(const char *str, ostream &o)
01029 {
01030     if (str)
01031         o << str << ": " << endl;
01032 
01033     dumpall(o);
01034 }
01035 
01036 void sthread_t::dumpall(ostream &o)
01037 {
01038 // We've put this into a huge critical section
01039 // to make it thread-safe, even though it's probably not necessary
01040 // when used in the debugger, which is the only place this is used...
01041     CRITICAL_SECTION(cs, _class_list_lock);
01042     w_list_i<sthread_t, queue_based_lock_t> i(*_class_list);
01043 
01044     while (i.next())  {
01045         o << "******* ";
01046         if (me() == i.curr())
01047             o << " --->ME<---- ";
01048         o << endl;
01049 
01050         i.curr()->_dump(o);
01051     }
01052 }
01053 
01054 
01055 /* XXX individual thread dump function... obsoleted by print method */
01056 void sthread_t::_dump(ostream &o) const
01057 {
01058     o << *this << endl;
01059 }
01060 
01061 /* XXX it is not a bug that you can sometime see >100% cpu utilization.
01062    Don't even think about hacking something to change it.  The %CPU
01063    is an *estimate* developed by statistics gathered by the process,
01064    not something solid given by the kernel. */
01065 
01066 static void print_time(ostream &o, const sinterval_t &real,
01067                const sinterval_t &user, const sinterval_t &kernel)
01068 {
01069     sinterval_t    total(user + kernel);
01070     double    pcpu = ((double)total / (double)real) * 100.0;
01071     double     pcpu2 = ((double)user / (double)real) * 100.0;
01072 
01073     o << "\t" << "real: " << real
01074         << endl;
01075     o << "\tcpu:"
01076         << "  kernel: " << kernel
01077         << "  user: " << user
01078         << "  total: " << total
01079         << endl;
01080     o << "\t%CPU:"
01081         << " " << setprecision(3) << pcpu
01082         << "  %user: " << setprecision(2) << pcpu2;
01083         o 
01084         << endl;
01085 }
01086 
01087 void sthread_t::dump_stats(ostream &o)
01088 {
01089     o << me()->SthreadStats;
01090 
01091     /* To be moved somewhere else once I put some other infrastructure
01092        into place.  Live with it in the meantime, the output is really
01093        useful for observing ad-hoc system performance. */
01094     struct    rusage    ru;
01095     int                 n;
01096 
01097     stime_t    now(stime_t::now());
01098     n = getrusage(RUSAGE_SELF, &ru);
01099     if (n == -1) {
01100         w_rc_t    e = RC(fcOS);
01101         cerr << "getrusage() fails:" << endl << e << endl;
01102         return;
01103     }
01104 
01105     sinterval_t    real(now - boot_time);
01106     sinterval_t    kernel(ru.ru_stime);
01107     sinterval_t    user(ru.ru_utime);
01108 
01109     /* Try to provide some modicum of recent cpu use. This will eventually
01110        move into the class, once a "thread handler" arrives to take
01111        care of it. */
01112     static    sinterval_t    last_real;
01113     static    sinterval_t    last_kernel;
01114     static    sinterval_t    last_user;
01115     static    bool last_valid = false;
01116 
01117     o << "TIME:" << endl;
01118     print_time(o, real, user, kernel);
01119     if (last_valid) {
01120         sinterval_t    r(real - last_real);
01121         sinterval_t    u(user - last_user);
01122         sinterval_t    k(kernel - last_kernel);
01123         o << "RECENT:" << endl;
01124         print_time(o, r, u, k);
01125     }
01126     else
01127         last_valid = true;
01128 
01129     last_kernel = kernel;
01130     last_user = user;
01131     last_real = real;
01132 
01133     o << endl;
01134 }
01135 
01136 void sthread_t::reset_stats()
01137 {
01138     me()->SthreadStats.clear();
01139 }
01140 
01141 
01142 const char *sthread_t::status_strings[] = {
01143     "defunct",
01144     "virgin",
01145     "ready",
01146     "running",
01147     "blocked",
01148     "boot"
01149 };
01150 
01151 const char *sthread_t::priority_strings[]= {
01152     "idle_time",
01153     "fixed_low",
01154     "regular",
01155     "time_critical"
01156 };
01157 
01158 
01159 ostream& operator<<(ostream &o, const sthread_t &t)
01160 {
01161     return t.print(o);
01162 }
01163 
01164 
01165 /*
01166  *  sthread_t::print(stream)
01167  *
01168  *  Print thread status to an stream
01169  */
01170 ostream &sthread_t::print(ostream &o) const
01171 {
01172     o << "thread id = " << id ;
01173 
01174     if (name()) {
01175         o << ", name = " << name() ? name() : "anonymous";
01176     };
01177 
01178     o
01179     << ", addr = " <<  (void *) this
01180     << ", core = " <<  (void *) _core << endl;
01181     o
01182     << "priority = " << sthread_t::priority_strings[priority()]
01183     << ", status = " << sthread_t::status_strings[status()];
01184     o << endl;
01185 
01186     if (user)
01187         o << "user = " << user << endl;
01188 
01189     if ((status() != t_defunct)  && !isStackOK(__FILE__,__LINE__))
01190     {
01191         cerr << "***  warning:  Thread stack overflow  ***" << endl;
01192     }
01193 
01194     return o;
01195 }
01196 
01197 
01198 
01199 /*********************************************************************
01200  *
01201  *  sthread_t::for_each_thread(ThreadFunc& f)
01202  *
01203  *  For each thread in the system call the function object f.
01204  *
01205  *********************************************************************/
01206 void sthread_t::for_each_thread(ThreadFunc& f)
01207 {
01208 // We've put this into a huge critical section
01209 // to make it thread-safe, even though it's probably not necessary
01210 // when used in the debugger, which is the only place this is used...
01211     CRITICAL_SECTION(cs, _class_list_lock);
01212     w_list_i<sthread_t, queue_based_lock_t> i(*_class_list);
01213 
01214     while (i.next())  {
01215         f(*i.curr());
01216     }
01217 }
01218 
01219 void print_timeout(ostream& o, const sthread_base_t::timeout_in_ms timeout)
01220 {
01221     if (timeout > 0)  {
01222     o << timeout;
01223     }  else if (timeout >= -5)  {
01224     static const char* names[] = {"WAIT_IMMEDIATE",
01225                       "WAIT_FOREVER",
01226                       "WAIT_ANY", // DEAD
01227                       "WAIT_ALL", // DEAD
01228                       "WAIT_SPECIFIED_BY_THREAD",
01229                       "WAIT_SPECIFIED_BY_XCT"};
01230     o << names[-timeout];
01231     }  else  {
01232     o << "UNKNOWN_TIMEOUT_VALUE(" << timeout << ")";
01233     }
01234 }
01235 
01236 occ_rwlock::occ_rwlock()
01237     : _active_count(0)
01238 {
01239     _write_lock._lock = _read_lock._lock = this;
01240     DO_PTHREAD(pthread_mutex_init(&_read_write_mutex, NULL));
01241     DO_PTHREAD(pthread_cond_init(&_read_cond, NULL));
01242     DO_PTHREAD(pthread_cond_init(&_write_cond, NULL));
01243 }
01244 
01245 occ_rwlock::~occ_rwlock()
01246 {
01247     DO_PTHREAD(pthread_mutex_destroy(&_read_write_mutex));
01248     DO_PTHREAD(pthread_cond_destroy(&_read_cond));
01249     DO_PTHREAD(pthread_cond_destroy(&_write_cond));
01250     _write_lock._lock = _read_lock._lock = NULL;
01251 }
01252 
01253 void occ_rwlock::release_read()
01254 {
01255     membar_exit();
01256     w_assert1(READER <= (int) _active_count);
01257     unsigned count = atomic_add_32_nv(&_active_count, -READER);
01258     if(count == WRITER) {
01259         // wake it up
01260         CRITICAL_SECTION(cs, _read_write_mutex);
01261         DO_PTHREAD(pthread_cond_signal(&_write_cond));
01262     }
01263 }
01264 
01265 void occ_rwlock::acquire_read()
01266 {
01267     int count = atomic_add_32_nv(&_active_count, READER);
01268     while(count & WRITER) {
01269         // block
01270         count = atomic_add_32_nv(&_active_count, -READER);
01271         {
01272             CRITICAL_SECTION(cs, _read_write_mutex);
01273             
01274             // nasty race: we could have fooled a writer into sleeping...
01275             if(count == WRITER)
01276                 DO_PTHREAD(pthread_cond_signal(&_write_cond));
01277             
01278             while(*&_active_count & WRITER) {
01279                 DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex));
01280             }
01281         }
01282         count = atomic_add_32_nv(&_active_count, READER);
01283     }
01284     membar_enter();
01285 }
01286 
01287 void occ_rwlock::release_write()
01288 {
01289     w_assert9(_active_count & WRITER);
01290     CRITICAL_SECTION(cs, _read_write_mutex);
01291     atomic_add_32(&_active_count, -WRITER);
01292     DO_PTHREAD(pthread_cond_broadcast(&_read_cond));
01293 }
01294 
01295 void occ_rwlock::acquire_write()
01296 {
01297     // only one writer allowed in at a time...
01298     CRITICAL_SECTION(cs, _read_write_mutex);    
01299     while(*&_active_count & WRITER) {
01300         DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex));
01301     }
01302     
01303     // any lurking writers are waiting on the cond var
01304     int count = atomic_add_32_nv(&_active_count, WRITER);
01305     w_assert1(count & WRITER);
01306 
01307     // drain readers
01308     while(count != WRITER) {
01309         DO_PTHREAD(pthread_cond_wait(&_write_cond, &_read_write_mutex));
01310         count = *&_active_count;
01311     }
01312 }
01313 
01314 /**\cond skip */
01315 
01316 sthread_name_t::sthread_name_t()
01317 {
01318     memset(_name, '\0', sizeof(_name));
01319 }
01320 
01321 sthread_name_t::~sthread_name_t()
01322 {
01323 }
01324 
01325 void
01326 sthread_name_t::rename(
01327     // can't have n2 or n3 without n1
01328     // can have n1,0,n3 or n1,n2,0
01329     const char*        n1,
01330     const char*        n2,
01331     const char*        n3)
01332 {
01333     const int sz = sizeof(_name) - 1;
01334     size_t len = 0;
01335     _name[0] = '\0';
01336     if (n1)  {
01337 #if W_DEBUG_LEVEL > 2
01338         len = strlen(n1);
01339         if(n2) len += strlen(n2);
01340         if(n3) len += strlen(n3);
01341         len++;
01342         if(len>sizeof(_name)) {
01343             cerr << "WARNING-- name too long for sthread_named_t: "
01344                 << n1 << n2 << n3;
01345         }
01346 #endif
01347 
01348         // only copy as much as will fit
01349         strncpy(_name, n1, sz);
01350         len = strlen(_name);
01351         if (n2 && (int)len < sz)  {
01352             strncat(_name, n2, sz - len);
01353             len = strlen(_name);
01354             if (n3 && (int)len < sz)
01355                 strncat(_name, n3, sz - len);
01356         }
01357 
01358         _name[sz] = '\0';
01359     }
01360 
01361 }
01362 
01363 void
01364 sthread_named_base_t::unname()
01365 {
01366     rename(0,0,0);
01367 }
01368 
01369 void
01370 sthread_named_base_t::rename(
01371     // can't have n2 or n3 without n1
01372     // can have n1,0,n3 or n1,n2,0
01373     const char*        n1,
01374     const char*        n2,
01375     const char*        n3)
01376 {
01377     _name.rename(n1,n2,n3);
01378 }
01379 
01380 sthread_named_base_t::~sthread_named_base_t()
01381 {
01382     unname();
01383 }
01384 
01385 /**\endcond skip */
01386 
01387 /**\cond skip */
01388 
01389 // if you really are a sthread_t return 0
01390 smthread_t* sthread_t::dynamic_cast_to_smthread()
01391 {
01392     return 0;
01393 }
01394 
01395 
01396 const smthread_t* sthread_t::dynamic_cast_to_const_smthread() const
01397 {
01398     return 0;
01399 }
01400 
01401 /**\endcond skip */
01402 
01403 /*********************************************************************
01404  *
01405  *  dumpthreads()
01406  *  For debugging, but it's got to be
01407  *  present in servers compiled without debugging.
01408  *
01409  *********************************************************************/
01410 void dumpthreads()
01411 {
01412     sthread_t::dumpall("dumpthreads()", cerr);
01413     sthread_t::dump_io(cerr);
01414 
01415 }
01416 
01417 void threadstats()
01418 {
01419     sthread_t::dump_stats(cerr);
01420 }
01421 
01422 
01423 
01424 static    void    get_large_file_size(w_base_t::int8_t &max_os_file_size)
01425 {
01426     /*
01427      * Get limits on file sizes imposed by the operating
01428      * system and shell.
01429      */
01430     os_rlimit_t    r;
01431     int        n;
01432 
01433     n = os_getrlimit(RLIMIT_FSIZE, &r);
01434     if (n == -1) {
01435         w_rc_t e = RC(fcOS);
01436         cerr << "getrlimit(RLIMIT_FSIZE):" << endl << e << endl;
01437         W_COERCE(e);
01438     }
01439     if (r.rlim_cur < r.rlim_max) {
01440         r.rlim_cur = r.rlim_max;
01441         n = os_setrlimit(RLIMIT_FSIZE, &r);
01442         if (n == -1) {
01443             w_rc_t e = RC(fcOS);
01444             cerr << "setrlimit(RLIMIT_FSIZE, " << r.rlim_cur
01445                 << "):" << endl << e << endl;
01446                 cerr << e << endl;
01447             W_FATAL(fcINTERNAL);
01448         }
01449     }
01450     max_os_file_size = w_base_t::int8_t(r.rlim_cur);
01451     /*
01452      * Unfortunately, sometimes this comes out
01453      * negative, since r.rlim_cur is unsigned and
01454      * fileoff_t is signed (sigh).
01455      */
01456     if (max_os_file_size < 0) {
01457         max_os_file_size = w_base_t::uint8_t(r.rlim_cur) >> 1;
01458         w_assert1( max_os_file_size > 0);
01459     }
01460 }
01461 
01462 /* XXX this doesn't work, neither does the one in sdisk, because
01463    the constructor order isn't guaranteed.  The only important
01464    use before main() runs is the one right above here. */
01465 
01466 
01467 /*********************************************************************
01468  *
01469  *  sthread_init_t::sthread_init_t()
01470  *
01471  *  Initialize the sthread environment. The first time this method
01472  *  is called, it sets up the environment 
01473  *
01474  *********************************************************************/
01475 #include "sthread_vtable_enum.h"
01476 
01477 // We'll have the ss_m constructor do this and just to be safe,
01478 // we'll have fork also do this init.
01479 // Cleanup is done in global destructors.
01480 void  sthread_t::initialize_sthreads_package()
01481 {   sthread_init_t::do_init(); }
01482 
01483 NORET            
01484 sthread_init_t::sthread_init_t() { }
01485 
01486 void
01487 sthread_init_t::do_init()
01488 {
01489     // This should not ever get initialized more than once
01490     if (sthread_init_t::initialized == 0) 
01491     {
01492         CRITICAL_SECTION(cs, init_mutex);
01493 
01494         // check again
01495         if (sthread_init_t::initialized == 0) 
01496         {
01497             sthread_init_t::initialized ++;
01498 
01499             get_large_file_size(sthread_t::max_os_file_size);
01500 
01501             /*
01502              *  Register error codes.
01503              */
01504             if (! w_error_t::insert(
01505                 "Threads Package",
01506                 error_info,
01507                 sizeof(error_info) / sizeof(error_info[0])))   {
01508 
01509                     cerr << "sthread_init_t::do_init: "
01510                      << " cannot register error code" << endl;
01511 
01512                     W_FATAL(stINTERNAL);
01513                 }
01514 
01515                 W_COERCE(sthread_t::cold_startup());
01516         }
01517     }
01518 }
01519 
01520 
01521 
01522 /*********************************************************************
01523  *
01524  *  sthread_init_t::~sthread_init_t()
01525  *
01526  *  Destructor. Does not do much.
01527  *
01528  *********************************************************************/
01529 NORET
01530 sthread_init_t::~sthread_init_t()
01531 {
01532     CRITICAL_SECTION(cs, init_mutex);
01533 
01534     // This should not ever get initialized more than once
01535     // Could be that it never got initialized.
01536     w_assert1 (sthread_init_t::initialized <= 1)  ;
01537     if (--sthread_init_t::initialized == 0) 
01538     {
01539 
01540         W_COERCE(sthread_t::shutdown());
01541 
01542         // Must delete the main thread before you delete the class list,
01543         // since it'll not be empty until main thread is gone.
01544         //
01545         /* note: me() is main thread */
01546         sthread_t::_main_thread->_status = sthread_t::t_defunct;
01547 
01548         delete sthread_t::_main_thread; // clean up for valgrind
01549         sthread_t::_main_thread = 0;
01550         
01551         delete sthread_t::_class_list; // clean up for valgrind
01552         sthread_t::_class_list = 0;
01553     }
01554 }
01555 
01556 pthread_t sthread_t::myself() { return _core->pthread; }
01557 

Generated on Thu Dec 9 08:42:27 2010 for Shore Storage Manager by  doxygen 1.4.7