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

Generated on Mon Nov 8 11:12:38 2010 for Shore Storage Manager by  doxygen 1.4.7