smthread.h

Go to the documentation of this file.
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 /*<std-header orig-src='shore' incl-file-exclusion='SMTHREAD_H'>
00025 
00026  $Id: smthread.h,v 1.102 2010/07/07 21:43:46 nhall Exp $
00027 
00028 SHORE -- Scalable Heterogeneous Object REpository
00029 
00030 Copyright (c) 1994-99 Computer Sciences Department, University of
00031                       Wisconsin -- Madison
00032 All Rights Reserved.
00033 
00034 Permission to use, copy, modify and distribute this software and its
00035 documentation is hereby granted, provided that both the copyright
00036 notice and this permission notice appear in all copies of the
00037 software, derivative works or modified versions, and any portions
00038 thereof, and that both notices appear in supporting documentation.
00039 
00040 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00041 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00042 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00043 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00044 
00045 This software was developed with support by the Advanced Research
00046 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00047 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00048 Further funding for this work was provided by DARPA through
00049 Rome Research Laboratory Contract No. F30602-97-2-0247.
00050 
00051 */
00052 
00053 #ifndef SMTHREAD_H
00054 #define SMTHREAD_H
00055 
00056 #include "w_defines.h"
00057 
00058 /*  -- do not edit anything above this line --   </std-header>*/
00059 
00060 /**\file smthread.h
00061  * \ingroup MACROS
00062  */
00063 
00064 #ifndef W_H
00065 #include <w.h>
00066 #endif
00067 #ifndef SM_BASE_H
00068 #include <sm_base.h>
00069 #endif
00070 #ifndef STHREAD_H
00071 #include <sthread.h>
00072 #endif
00073 #include <w_bitvector.h>
00074 
00075 /**\enum special_timeout_in_ms_t
00076  * \brief Special values for timeout_in_ms.
00077  * \details
00078  * - WAIT_FOREVER : no timeout
00079  * - WAIT_IMMEDIATE : do not block
00080  * - WAIT_SPECIFIED_BY_XCT : use the per-transaction custom timeout value
00081  * - WAIT_SPECIFIED_BY_THREAD : use the per-smthread custom timeout value
00082  *
00083  * To set the smthread_t's timeout, use smthread_t::lock_timeout.
00084  */
00085 enum special_timeout_in_ms_t {
00086     WAIT_FOREVER = sthread_t::WAIT_FOREVER,
00087     WAIT_IMMEDIATE = sthread_t::WAIT_IMMEDIATE,
00088     WAIT_SPECIFIED_BY_XCT = sthread_t::WAIT_SPECIFIED_BY_XCT,
00089     WAIT_SPECIFIED_BY_THREAD = sthread_t::WAIT_SPECIFIED_BY_THREAD
00090 };
00091 
00092 typedef sthread_t::timeout_in_ms timeout_in_ms;
00093 
00094 class xct_t;
00095 class xct_log_t;
00096 class sdesc_cache_t;
00097 class lockid_t;
00098 
00099 #ifdef __GNUG__
00100 #pragma interface
00101 #endif
00102 
00103 class smthread_t;
00104 
00105 /**\brief Callback class use with smthread::for_each_smthread()
00106  * \details
00107  * Derive your per-smthread processing function (callback) from this.
00108  */
00109 class SmthreadFunc {
00110 public:
00111     virtual ~SmthreadFunc();
00112     
00113     virtual void operator()(const smthread_t& smthread) = 0;
00114 };
00115 
00116 
00117 /**\cond skip */
00118 enum { FINGER_BITS=3 };
00119 typedef w_bitvector_t<256>    sm_thread_map_t;
00120 /**\endcond skip */
00121 
00122 /**\brief Fingerprint for this smthread.
00123  * \details
00124  * Each smthread_t has a fingerprint. This is used by the
00125  * deadlock detector.  The fingerprint is a bitmap; each thread's
00126  * bitmap is unique, the deadlock detector ORs fingerprints together
00127  * to make a "digest" of the waits-for-map.
00128  * Rather than have fingerprints associated with transactions, we
00129  * associate them with threads.
00130  *
00131  * This class provides synchronization (protection) for updating the map.
00132  *
00133  * \note: If you want to be sure the fingerprints are unique, for the 
00134  * purpose of minimizing false-positives in the lock manager's deadlock 
00135  * detector, look at the code in smthread_t::_initialize_fingerprint(),
00136  * where you can enable some debugging code.
00137  */
00138 class  atomic_thread_map_t : public sm_thread_map_t {
00139 private:
00140     mutable srwlock_t   _map_lock;
00141 public:
00142     bool has_reader() const {
00143         return _map_lock.has_reader();
00144     }
00145     bool has_writer() const {
00146         return _map_lock.has_writer();
00147     }
00148     void lock_for_read() const {
00149         _map_lock.acquire_read();
00150     }
00151     void lock_for_write() {
00152         _map_lock.acquire_write();
00153     }
00154     void unlock_reader() const{
00155         w_assert2(_map_lock.has_reader());
00156         _map_lock.release_read();
00157     }
00158     void unlock_writer() {
00159         w_assert2(_map_lock.has_writer());
00160         _map_lock.release_write();
00161     }
00162     atomic_thread_map_t () {
00163         w_assert1(_map_lock.has_reader() == false);
00164         w_assert1(_map_lock.has_writer() == false);
00165     }
00166     ~atomic_thread_map_t () { 
00167         w_assert1(_map_lock.has_reader() == false);
00168         w_assert1(_map_lock.has_writer() == false);
00169     }
00170 
00171     atomic_thread_map_t &operator=(const atomic_thread_map_t &other) {
00172         // Copy only the bitmap portion; do not touch the
00173         // _map_lock
00174 #if W_DEBUG_LEVEL > 0
00175         bool X=_map_lock.has_reader();
00176         bool Y=_map_lock.has_writer();
00177 #endif
00178         copy(other);
00179 #if W_DEBUG_LEVEL > 0
00180         w_assert1(_map_lock.has_reader() == X); 
00181         w_assert1(_map_lock.has_writer() == Y); 
00182 #endif
00183         return *this;
00184     }
00185 }; 
00186 
00187 
00188 /**\cond skip */
00189 typedef void st_proc_t(void*);
00190 
00191 class sm_stats_info_t; // forward
00192 /**\endcond skip */
00193 
00194 /**\brief Storage Manager thread.
00195  * \ingroup SSMINIT
00196  * \details
00197  * \attention
00198  * All threads that use storage manager functions must be of this type
00199  * or of type derived from this.
00200  *
00201  * Associated with an smthread_t is a POSIX thread (pthread_t).  
00202  * This class is in essence a wrapper around POSIX threads.  
00203  * The maximum number of threads a server can create depends on the
00204  * availability of resources internal to the pthread implementation,
00205  * (in addition to system-wide parameters), so it is not possible 
00206  * \e a \e priori to determine whether creation of a new thread will
00207  * succeed.  
00208  * Failure will result in a fatal error.
00209  *
00210  * The storage manager keeps its own thread-local state and provides for
00211  * a little more control over the starting of threads than does the
00212  * POSIX interface:  you can do meaningful work between the time the
00213  * thread is \e created and the time it starts to \e run.
00214  * The thread constructor creates the underlying pthread_t, which then
00215  * awaits permission (a pthread condition variable) 
00216  * to continue (signalled by smthread_t::fork).
00217  */
00218 class smthread_t : public sthread_t {
00219     friend class smthread_init_t;
00220     struct tcb_t {
00221         xct_t*   xct;
00222         int      pin_count;      // number of rsrc_m pins
00223         int      prev_pin_count; // previous # of rsrc_m pins
00224         timeout_in_ms lock_timeout;    // timeout to use for lock acquisitions
00225         bool    _in_sm;      // thread is in sm ss_m:: function
00226 #ifdef ARCH_LP64
00227         /* XXX Really want kc_buf aligned to the alignment of the most
00228            restrictive type. It would be except sizeof above bool == 8,
00229            and timeout_in_ms is 4 bytes. */
00230         fill1            _fill1;        
00231         fill2            _fill2;        
00232 #endif
00233 
00234         sdesc_cache_t     *_sdesc_cache;
00235         lockid_t          *_lock_hierarchy;
00236         xct_log_t*        _xct_log;
00237         sm_stats_info_t*  _TL_stats; // thread-local stats
00238 
00239         // for lock_head_t::my_lock::get_me
00240         queue_based_lock_t::ext_qnode _me1;
00241         // for DEF_LOCK_X_TYPE(2)
00242         queue_based_lock_t::ext_qnode _me2;
00243         // for DEF_LOCK_X_TYPE(3)
00244         queue_based_lock_t::ext_qnode _me3;
00245 
00246         /**\var queue_based_lock_t::ext_qnode _1thread_xct_me;
00247          * \brief Queue node for holding mutex to serialize access to xct 
00248          * structure.  Used in xct_impl.cpp
00249          */
00250         queue_based_lock_t::ext_qnode _1thread_xct_me;
00251         /**\var static __thread queue_based_lock_t::ext_qnode _1thread_log_me;
00252          * \brief Queue node for holding mutex to serialize access to log.
00253          * Used in xct_impl.cpp
00254          */
00255         queue_based_lock_t::ext_qnode _1thread_log_me;
00256         /**\var static __thread queue_based_lock_t::ext_qnode _xct_t_me_node;
00257          * \brief Queue node for holding mutex to prevent 
00258          * mutiple-thread/transaction where disallowed. Used in xct.cpp
00259          */
00260         queue_based_lock_t::ext_qnode _xct_t_me_node;
00261         /**\var static __thread queue_based_lock_t::ext_qnode _xlist_mutex_node;
00262          * \brief Queue node for holding mutex to serialize 
00263          * access transaction list. Used in xct.cpp
00264          */
00265         queue_based_lock_t::ext_qnode _xlist_mutex_node;
00266 
00267         /**\var static __thread queue_based_block_lock_t::ext_qnode _log_me_node;
00268          * \brief Queue node for holding partition lock.
00269          */
00270         queue_based_block_lock_t::ext_qnode _log_me_node;
00271 
00272         /**\var static __thread meta_header_t::ordinal_number_t __ordinal;
00273          * \brief Used in newsort.cpp
00274          */
00275         typedef uint4_t        ordinal_number_t;
00276         ordinal_number_t __ordinal;
00277         /**\var static __thread int __metarecs, __metarecs_in;
00278          * \brief Used in newsort.cpp
00279          */
00280         int __metarecs;
00281         int __metarecs_in;
00282 
00283         // force this to be 8-byte aligned:
00284         /**\var static __thread double _kc_buf_double[] 
00285          * \brief Used in lexify.cpp for scramble/unscramble scratch space.
00286          */
00287         double  _kc_buf_double[smlevel_0::page_sz/sizeof(double)]; // not initialized
00288         cvec_t  _kc_vec;
00289         // Used by page.cpp check()
00290         char    _page_check_map[SM_PAGESIZE]; // a little bigger than needed
00291 
00292         void    create_TL_stats();
00293         void    clear_TL_stats();
00294         void    destroy_TL_stats();
00295         inline sm_stats_info_t& TL_stats() { return *_TL_stats;}
00296         inline const sm_stats_info_t& TL_stats_const() const { 
00297                                                  return *_TL_stats; }
00298 
00299         tcb_t() : 
00300             xct(0), 
00301             pin_count(0), 
00302             prev_pin_count(0),
00303             lock_timeout(WAIT_FOREVER), // default for a thread
00304             _in_sm(false), 
00305             _sdesc_cache(0), 
00306             _lock_hierarchy(0), 
00307             _xct_log(0), 
00308             _TL_stats(0),
00309             __ordinal(0),
00310             __metarecs(0),
00311             __metarecs_in(0)
00312         { 
00313             _me1._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00314             _me2._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00315             _me3._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00316             _1thread_xct_me._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00317             _1thread_log_me._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00318             _xct_t_me_node._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00319             _xlist_mutex_node._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00320             _log_me_node._held = NULL; /*EXT_QNODE_INITIALIZER*/;
00321 
00322             create_TL_stats();
00323         }
00324         ~tcb_t() { destroy_TL_stats(); }
00325     };
00326 
00327     tcb_t              _tcb;
00328     st_proc_t* const   _proc;
00329     void* const        _arg;
00330 
00331     bool               _try_initialize_fingerprint(); // true: failure false: ok
00332     void               _initialize_fingerprint();
00333     void               _uninitialize_fingerprint();
00334     short              _fingerprint[FINGER_BITS]; // dreadlocks
00335     atomic_thread_map_t  _fingerprint_map; // map containing only fingerprint
00336 
00337 public:
00338     const atomic_thread_map_t&  get_fingerprint_map() const
00339                             {   return _fingerprint_map; } 
00340 
00341 public:
00342 
00343     /**\brief Normal constructor for a storage manager client.
00344      * \details
00345      * @param[in] f Stored in thread for client's convenience, may
00346      * be used in run() method.
00347      * @param[in] arg Stored in thread for client's convenience, may
00348      * be used in run() method.
00349      * @param[in] priority Required, but not used in storage manager.
00350      * @param[in] name Optional thread name, used for debugging.
00351      * @param[in] lockto Timeout for lock waiting.  See timeout_in_ms.
00352      * @param[in] stack_size Best to use default.
00353      */
00354     NORET            smthread_t(
00355         st_proc_t*             f, 
00356         void*                  arg,
00357         priority_t             priority = t_regular,
00358         const char*            name = 0, 
00359         timeout_in_ms          lockto = WAIT_FOREVER,
00360         unsigned               stack_size = default_stack);
00361 
00362     /**\brief Normal constructor for a storage manager client.
00363      * \details
00364      * @param[in] priority Required, but not used in storage manager.
00365      * @param[in] name Optional thread name, used for debugging.
00366      * @param[in] lockto Timeout for lock waiting.  See timeout_in_ms.
00367      * @param[in] stack_size Best to use default.
00368      */
00369     NORET            smthread_t(
00370         priority_t             priority = t_regular,
00371         const char*            name = 0,
00372         timeout_in_ms          lockto = WAIT_FOREVER,
00373         unsigned               stack_size = default_stack
00374         );
00375 
00376     // This is helpful for debugging and besides, it returns a w_rc_t
00377     // so there is an opportunity to check for things like
00378     // no xcts attached, etc. and deliver this info to the client.
00379     
00380     /**\brief  Returns when this thread ends.
00381      * @param[in] timeout Not used.
00382      * \details
00383      * Errors:
00384      * -ePINACTIVE: if the thread ended while holding a pinned record.
00385      * -eINTRANS: if the thread ended while attached to a transaction.
00386      */
00387     w_rc_t               join(timeout_in_ms timeout = WAIT_FOREVER);
00388 
00389     NORET                ~smthread_t();
00390 
00391     /**\cond skip */
00392     /* public for debugging */
00393     static void          init_fingerprint_map();
00394     /**\endcond skip */
00395 
00396     /**\brief Called before run() is called. */
00397     virtual void         before_run();
00398 
00399     /**\brief Main work routine. */
00400     virtual void         run() = 0;
00401 
00402     /**\brief Call when run finishes, before join() returns */
00403     virtual void         after_run();
00404     
00405     virtual smthread_t*          dynamic_cast_to_smthread();
00406     virtual const smthread_t*    dynamic_cast_to_const_smthread() const;
00407 
00408     /**\brief RTTI
00409      * \details
00410      * Run-time type info: Derived threads are expected to
00411      * add thread types and override thread_type()
00412      */
00413     enum SmThreadTypes     {smThreadType = 1, smLastThreadType};
00414     /**\brief RTTI
00415      * \details
00416      * Run-time type info: Derived threads are expected to
00417      * add thread types and override thread_type()
00418      */
00419     virtual int            thread_type() { return smThreadType; }
00420 
00421     /**\brief Iterator over all smthreads. Thread-safe and so use carefully.
00422      * \details
00423      * @param[in] f Callback function.
00424      * For each smthread, this calls the callback function \a f.
00425      * Because this grabs a lock on the list of all shore threads, 
00426      * whether or not they are smthreads, this prevents new threads
00427      * from starting and old ones from finishing, so don't use with
00428      * long-running functions.
00429      */
00430     static void            for_each_smthread(SmthreadFunc& f);
00431     
00432     /**\cond skip
00433      **\brief Attach this thread to the given transaction.
00434      * \ingroup SSMXCT
00435      * @param[in] x Transaction to attach to the thread
00436      * \details
00437      * Attach this thread to the transaction \a x or, equivalently,
00438      * attach \a x to this thread.
00439      * \note "this" thread need not be the running thread.
00440      *
00441      * Only one transaction may be attached to a thread at any time.
00442      * More than one thread may attach to a transaction concurrently.
00443      */
00444     void             attach_xct(xct_t* x);
00445     /**\brief Detach this thread from the given transaction.
00446      * \ingroup SSMXCT
00447      * @param[in] x Transaction to detach from the thread.
00448      * \details
00449      * Detach this thread from the transaction \a x or, equivalently,
00450      * detach \a x from this thread.
00451      * \note "this" thread need not be the running thread.
00452      *
00453      * If the transaction is not attached, returns error.
00454      * \endcond skip
00455      */
00456     void             detach_xct(xct_t* x);
00457 
00458     /// get lock_timeout value
00459     inline
00460     timeout_in_ms        lock_timeout() { 
00461                     return tcb().lock_timeout; 
00462                 }
00463     /**\brief Set lock_timeout value
00464      * \details
00465      * You can give a value WAIT_FOREVER, WAIT_IMMEDIATE, or
00466      * a positive millisecond value. 
00467      * Every lock request made with WAIT_SPECIFIED_BY_THREAD will
00468      * use this value.
00469      *
00470      * A transaction can be given its own timeout on ss_m::begin_xct.
00471      * The transaction's lock timeout is used for every lock request
00472      * made with WAIT_SPECIFIED_BY_XCT. 
00473      * A transaction begun with WAIT_SPECIFIED_BY_THREAD will use
00474      * the thread's lock_timeout for the transaction timeout.
00475      *
00476      * All internal storage manager lock requests use WAIT_SPECIFIED_BY_XCT.
00477      * Since the transaction can defer to the per-thread timeout, the
00478      * client has control over which timeout to use by choosing the
00479      * value given at ss_m::begin_xct.
00480      */
00481     inline 
00482     void             lock_timeout(timeout_in_ms i) { 
00483                     tcb().lock_timeout = i;
00484                 }
00485 
00486     /// return xct this thread is running
00487     inline
00488     xct_t*             xct() { return tcb().xct; }
00489 
00490     /// return xct this thread is running
00491     inline
00492     xct_t*             xct() const { return tcb().xct; }
00493 
00494     /**\brief Return currently-running smthread. 
00495      * \details
00496      * \note Assumes all threads are smthreads
00497      */
00498     static smthread_t*         me() { return (smthread_t*) sthread_t::me(); }
00499 
00500     /// Return thread-local statistics collected for this thread.
00501     inline sm_stats_info_t& TL_stats() { 
00502                                        return tcb().TL_stats(); }
00503 
00504     /// Add thread-local stats into the given structure.
00505     void add_from_TL_stats(sm_stats_info_t &w) const;
00506 
00507     // NOTE: These macros don't have to be atomic since these thread stats
00508     // are stored in the smthread and collected when the smthread's tcb is
00509     // destroyed.
00510     
00511 #define GET_TSTAT(x) me()->TL_stats().sm.x
00512 /**\def GET_TSTAT(x) 
00513  *\brief Get per-thread statistic named x
00514 */
00515 
00516 /**\def INC_TSTAT(x) 
00517  *\brief Increment per-thread statistic named x by y
00518  */
00519 #define INC_TSTAT(x) me()->TL_stats().sm.x++
00520 
00521 
00522 /**\def INC_TSTAT_BFHT(x) 
00523  *\brief Increment per-thread statistic named x by y
00524  */
00525 #define INC_TSTAT_BFHT(x) me()->TL_stats().bfht.bf_htab #x++
00526 
00527 /**\def ADD_TSTAT(x,y) 
00528  *\brief Increment statistic named x by y
00529  */
00530 #define ADD_TSTAT(x,y) me()->TL_stats().sm.x += (y)
00531 
00532 /**\def SET_TSTAT(x,y) 
00533  *\brief Set per-thread statistic named x to y
00534  */
00535 #define SET_TSTAT(x,y) me()->TL_stats().sm.x = (y)
00536 
00537 
00538     /**\cond skip */
00539     /*
00540      *  These functions are used to verify than nothing is
00541      *  left pinned accidentally.  Call mark_pin_count before an
00542      *  operation and check_pin_count after it with the expected
00543      *  number of pins that should not have been realeased.
00544      */
00545     void             mark_pin_count();
00546     void             check_pin_count(int change);
00547     void             check_actual_pin_count(int actual) ;
00548     void             incr_pin_count(int amount) ;
00549     int              pin_count() ;
00550    
00551     /*
00552      *  These functions are used to verify that a thread
00553      *  is only in one ss_m::, scan::, or pin:: function at a time.
00554      */
00555     inline
00556     void             in_sm(bool in)    { tcb()._in_sm = in; }
00557     inline 
00558     bool             is_in_sm() const { return tcb()._in_sm; }
00559 
00560     void             new_xct(xct_t *);
00561     void             no_xct(xct_t *);
00562 
00563     inline
00564     xct_log_t*       xct_log() { return tcb()._xct_log; }
00565     inline
00566     lockid_t *       lock_hierarchy() { return tcb()._lock_hierarchy; }
00567 
00568     inline
00569     sdesc_cache_t *  tls_sdesc_cache() { return tcb()._sdesc_cache; }
00570 
00571     virtual void     _dump(ostream &) const; // to be over-ridden
00572     static int       collect(vtable_t&, bool names_too);
00573     virtual void     vtable_collect(vtable_row_t& t);
00574     static  void     vtable_collect_names(vtable_row_t& t);
00575     /**\endcond skip */
00576 
00577     /* thread-level block() and unblock aren't public or protected
00578        accessible.  
00579        These methods are used by the lock manager.
00580        Otherwise, ordinarly pthreads sychronization variables
00581        are used.
00582     */
00583     w_rc_t::errcode_t smthread_block(timeout_in_ms WAIT_FOREVER,
00584                       const char * const caller = 0,
00585                       const void * id = 0);
00586     w_rc_t            smthread_unblock(w_rc_t::errcode_t e);
00587 
00588 private:
00589     w_rc_t::errcode_t _smthread_block( timeout_in_ms WAIT_FOREVER,
00590                               const char * const why =0);
00591     w_rc_t           _smthread_unblock(w_rc_t::errcode_t e);
00592 public:
00593     void             prepare_to_block();
00594 
00595     /* \brief Find out if log warning checks are to be made. Default is true.
00596      */
00597     bool            generate_log_warnings()const{return _gen_log_warnings;}
00598     /* \brief Enable/disable log-space warning checks
00599      */
00600     void            set_generate_log_warnings(bool b){_gen_log_warnings=b;}
00601 
00602     /**\brief  TLS variables Exported to sm.
00603      */
00604     queue_based_lock_t::ext_qnode& get_me3() { return tcb()._me3; }
00605     queue_based_lock_t::ext_qnode& get_me2() { return tcb()._me2; }
00606     queue_based_lock_t::ext_qnode& get_me1() { return tcb()._me1; }
00607     queue_based_lock_t::ext_qnode& get_log_me_node() { 
00608                                                return tcb()._log_me_node;}
00609     queue_based_lock_t::ext_qnode& get_xlist_mutex_node() { 
00610                                                return tcb()._xlist_mutex_node;}
00611     queue_based_lock_t::ext_qnode& get_1thread_log_me() {
00612                                                return tcb()._1thread_log_me;}
00613     queue_based_lock_t::ext_qnode& get_1thread_xct_me() {
00614                                                return tcb()._1thread_xct_me;}
00615     queue_based_lock_t::ext_qnode& get_xct_t_me_node() {
00616                                                return tcb()._xct_t_me_node;}
00617     tcb_t::ordinal_number_t &      get__ordinal()  { return tcb().__ordinal; }
00618     int&                           get___metarecs() { 
00619                                                return tcb().__metarecs; }
00620     int&                           get___metarecs_in() { 
00621                                                return tcb().__metarecs_in; }
00622     char *                         get_kc_buf()  { return (char *)&(tcb()._kc_buf_double[0]); }
00623     cvec_t*                        get_kc_vec()  { return &(tcb()._kc_vec); }
00624     char *                         get_page_check_map() {
00625                                          return &(tcb()._page_check_map[0]);  }
00626 private:
00627 
00628     /* sm-specif block / unblock implementation */
00629     volatile bool   _unblocked;
00630     bool            _waiting;
00631 
00632     bool            _gen_log_warnings;
00633 
00634     inline
00635     tcb_t           &tcb() { return _tcb; }
00636 
00637     inline
00638     const tcb_t     &tcb() const { return _tcb; }
00639 };
00640 
00641 /**\cond skip */
00642 class smthread_init_t {
00643 public:
00644     NORET            smthread_init_t();
00645     NORET            ~smthread_init_t();
00646 private:
00647     static int       count;
00648 };
00649 /**\endcond  skip */
00650 
00651 
00652 
00653 /**\cond skip */
00654 
00655 inline smthread_t* 
00656 me() 
00657 { 
00658     return smthread_t::me(); 
00659 }
00660 
00661 
00662 inline xct_t* 
00663 xct() 
00664 { 
00665     return me()->xct(); 
00666 }
00667 
00668 
00669 inline void 
00670 smthread_t::mark_pin_count()
00671 {    
00672     tcb().prev_pin_count = tcb().pin_count;
00673 }
00674 
00675 inline void 
00676 smthread_t::check_pin_count(int W_IFDEBUG4(change)) 
00677 {
00678 #if W_DEBUG_LEVEL > 3
00679     int diff = tcb().pin_count - tcb().prev_pin_count;
00680     if (change >= 0) {
00681         w_assert4(diff <= change);
00682     } else {
00683         w_assert4(diff >= change);
00684     }
00685 #endif 
00686 }
00687 
00688 inline void 
00689 smthread_t::check_actual_pin_count(int W_IFDEBUG3(actual)) 
00690 {
00691     w_assert3(tcb().pin_count == actual);
00692 }
00693 
00694 
00695 inline void 
00696 smthread_t::incr_pin_count(int amount) 
00697 {
00698     tcb().pin_count += amount; 
00699 }
00700 
00701 inline int 
00702 smthread_t::pin_count() 
00703 {
00704     return tcb().pin_count;
00705 }
00706 
00707 void
00708 DumpBlockedThreads(ostream& o);
00709 
00710 /*
00711  * redefine DBGTHRD to use our threads
00712  */
00713 #ifdef DBGTHRD
00714 #undef DBGTHRD
00715 #endif
00716 #define DBGTHRD(arg) DBG(<< " th." << smthread_t::me()->id << " " arg)
00717 #ifdef W_TRACE
00718 /* 
00719  * redefine FUNC to print the thread id
00720  */
00721 #undef FUNC
00722 #define FUNC(fn)\
00723   do { char const* fname = __func__; \
00724     DBGTHRD(<< fname);} while(0)
00725 #endif /* W_TRACE */
00726 
00727 /**\endcond skip */
00728 
00729 
00730 /*<std-footer incl-file-exclusion='SMTHREAD_H'>  -- do not edit anything below this line -- */
00731 
00732 #endif          /*</std-footer>*/

Generated on Wed Jul 7 17:22:32 2010 for Shore Storage Manager by  doxygen 1.4.7