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.105 2010/11/08 15:07:06 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 eliminating false-positives in the lock manager's deadlock 
00135  * detector while debugging something, look at the code 
00136  * in smthread_t::_initialize_fingerprint(), where you can 
00137  * enable some debugging code.
00138  * (There is no need to make them unique -- if there were, 
00139  * we'd use 1 bit per... -- but if you are debugging something you might
00140  * want to ensure or detect uniqueness for that purpose.)
00141  */
00142 class  atomic_thread_map_t : public sm_thread_map_t {
00143 private:
00144     mutable srwlock_t   _map_lock;
00145 public:
00146     bool has_reader() const {
00147         return _map_lock.has_reader();
00148     }
00149     bool has_writer() const {
00150         return _map_lock.has_writer();
00151     }
00152     void lock_for_read() const {
00153         _map_lock.acquire_read();
00154     }
00155     void lock_for_write() {
00156         _map_lock.acquire_write();
00157     }
00158     void unlock_reader() const{
00159         w_assert2(_map_lock.has_reader());
00160         _map_lock.release_read();
00161     }
00162     void unlock_writer() {
00163         w_assert2(_map_lock.has_writer());
00164         _map_lock.release_write();
00165     }
00166     atomic_thread_map_t () {
00167         w_assert1(_map_lock.has_reader() == false);
00168         w_assert1(_map_lock.has_writer() == false);
00169     }
00170     ~atomic_thread_map_t () { 
00171         w_assert1(_map_lock.has_reader() == false);
00172         w_assert1(_map_lock.has_writer() == false);
00173     }
00174 
00175     atomic_thread_map_t &operator=(const atomic_thread_map_t &other) {
00176         // Copy only the bitmap portion; do not touch the
00177         // _map_lock
00178 #if W_DEBUG_LEVEL > 0
00179         bool X=_map_lock.has_reader();
00180         bool Y=_map_lock.has_writer();
00181 #endif
00182         copy(other);
00183 #if W_DEBUG_LEVEL > 0
00184         w_assert1(_map_lock.has_reader() == X); 
00185         w_assert1(_map_lock.has_writer() == Y); 
00186 #endif
00187         return *this;
00188     }
00189 }; 
00190 
00191 
00192 /**\cond skip */
00193 typedef void st_proc_t(void*);
00194 
00195 class sm_stats_info_t; // forward
00196 /**\endcond skip */
00197 
00198 /**\brief Storage Manager thread.
00199  * \ingroup SSMINIT
00200  * \details
00201  * \attention
00202  * All threads that use storage manager functions must be of this type
00203  * or of type derived from this.
00204  *
00205  * Associated with an smthread_t is a POSIX thread (pthread_t).  
00206  * This class is in essence a wrapper around POSIX threads.  
00207  * The maximum number of threads a server can create depends on the
00208  * availability of resources internal to the pthread implementation,
00209  * (in addition to system-wide parameters), so it is not possible 
00210  * \e a \e priori to determine whether creation of a new thread will
00211  * succeed.  
00212  * Failure will result in a fatal error.
00213  *
00214  * The storage manager keeps its own thread-local state and provides for
00215  * a little more control over the starting of threads than does the
00216  * POSIX interface:  you can do meaningful work between the time the
00217  * thread is \e created and the time it starts to \e run.
00218  * The thread constructor creates the underlying pthread_t, which then
00219  * awaits permission (a pthread condition variable) 
00220  * to continue (signalled by smthread_t::fork).
00221  */
00222 class smthread_t : public sthread_t {
00223     friend class smthread_init_t;
00224     struct tcb_t {
00225         xct_t*   xct;
00226         int      pin_count;      // number of rsrc_m pins
00227         int      prev_pin_count; // previous # of rsrc_m pins
00228         timeout_in_ms lock_timeout;    // timeout to use for lock acquisitions
00229         bool    _in_sm;      // thread is in sm ss_m:: function
00230 #ifdef ARCH_LP64
00231         /* XXX Really want kc_buf aligned to the alignment of the most
00232            restrictive type. It would be except sizeof above bool == 8,
00233            and timeout_in_ms is 4 bytes. */
00234         fill1            _fill1;        
00235         fill2            _fill2;        
00236 #endif
00237 
00238         sdesc_cache_t     *_sdesc_cache;
00239         lockid_t          *_lock_hierarchy;
00240         xct_log_t*        _xct_log;
00241         sm_stats_info_t*  _TL_stats; // thread-local stats
00242 
00243         // for lock_head_t::my_lock::get_me
00244         queue_based_lock_t::ext_qnode _me1;
00245         // for DEF_LOCK_X_TYPE(2)
00246         queue_based_lock_t::ext_qnode _me2;
00247         // for DEF_LOCK_X_TYPE(3)
00248         queue_based_lock_t::ext_qnode _me3;
00249         // for histo.cpp histoid_me
00250         queue_based_lock_t::ext_qnode _histoid_me;
00251 
00252         /**\var queue_based_lock_t::ext_qnode _1thread_xct_me;
00253          * \brief Queue node for holding mutex to serialize access to xct 
00254          * structure.  Used in xct_impl.cpp
00255          */
00256         queue_based_lock_t::ext_qnode _1thread_xct_me;
00257         /**\var static __thread queue_based_lock_t::ext_qnode _1thread_log_me;
00258          * \brief Queue node for holding mutex to serialize access to log.
00259          * Used in xct_impl.cpp
00260          */
00261         queue_based_lock_t::ext_qnode _1thread_log_me;
00262         /**\var static __thread queue_based_lock_t::ext_qnode _xct_t_me_node;
00263          * \brief Queue node for holding mutex to prevent 
00264          * mutiple-thread/transaction where disallowed. Used in xct.cpp
00265          */
00266         queue_based_lock_t::ext_qnode _xct_t_me_node;
00267         /**\var static __thread queue_based_lock_t::ext_qnode _xlist_mutex_node;
00268          * \brief Queue node for holding mutex to serialize 
00269          * access transaction list. Used in xct.cpp
00270          */
00271         queue_based_lock_t::ext_qnode _xlist_mutex_node;
00272 
00273         /**\var static __thread queue_based_block_lock_t::ext_qnode _log_me_node;
00274          * \brief Queue node for holding partition lock.
00275          */
00276         queue_based_block_lock_t::ext_qnode _log_me_node;
00277 
00278         /**\var static __thread meta_header_t::ordinal_number_t __ordinal;
00279          * \brief Used in newsort.cpp
00280          */
00281         typedef uint4_t        ordinal_number_t;
00282         ordinal_number_t __ordinal;
00283         /**\var static __thread int __metarecs, __metarecs_in;
00284          * \brief Used in newsort.cpp
00285          */
00286         int __metarecs;
00287         int __metarecs_in;
00288 
00289         // force this to be 8-byte aligned:
00290         /**\var static __thread double _kc_buf_double[] 
00291          * \brief Used in lexify.cpp for scramble/unscramble scratch space.
00292          */
00293         double  _kc_buf_double[smlevel_0::page_sz/sizeof(double)]; // not initialized
00294         cvec_t  _kc_vec;
00295         // Used by page.cpp check()
00296         char    _page_check_map[SM_PAGESIZE]; // a little bigger than needed
00297 
00298         void    create_TL_stats();
00299         void    clear_TL_stats();
00300         void    destroy_TL_stats();
00301         inline sm_stats_info_t& TL_stats() { return *_TL_stats;}
00302         inline const sm_stats_info_t& TL_stats_const() const { 
00303                                                  return *_TL_stats; }
00304 
00305         tcb_t() : 
00306             xct(0), 
00307             pin_count(0), 
00308             prev_pin_count(0),
00309             lock_timeout(WAIT_FOREVER), // default for a thread
00310             _in_sm(false), 
00311             _sdesc_cache(0), 
00312             _lock_hierarchy(0), 
00313             _xct_log(0), 
00314             _TL_stats(0),
00315             __ordinal(0),
00316             __metarecs(0),
00317             __metarecs_in(0)
00318         { 
00319             QUEUE_EXT_QNODE_INITIALIZE(_me1);
00320             QUEUE_EXT_QNODE_INITIALIZE(_me2);
00321             QUEUE_EXT_QNODE_INITIALIZE(_me3);
00322             QUEUE_EXT_QNODE_INITIALIZE(_histoid_me);
00323             QUEUE_EXT_QNODE_INITIALIZE(_1thread_xct_me);
00324             QUEUE_EXT_QNODE_INITIALIZE(_1thread_log_me);
00325             QUEUE_EXT_QNODE_INITIALIZE(_xct_t_me_node);
00326             QUEUE_EXT_QNODE_INITIALIZE(_xlist_mutex_node);
00327 
00328             QUEUE_BLOCK_EXT_QNODE_INITIALIZE(_log_me_node);
00329             
00330             create_TL_stats();
00331         }
00332         ~tcb_t() { destroy_TL_stats(); }
00333     };
00334 
00335     tcb_t              _tcb;
00336     st_proc_t* const   _proc;
00337     void* const        _arg;
00338 
00339     bool               _try_initialize_fingerprint(); // true: failure false: ok
00340     void               _initialize_fingerprint();
00341     void               _uninitialize_fingerprint();
00342     short              _fingerprint[FINGER_BITS]; // dreadlocks
00343     atomic_thread_map_t  _fingerprint_map; // map containing only fingerprint
00344 
00345 public:
00346     const atomic_thread_map_t&  get_fingerprint_map() const
00347                             {   return _fingerprint_map; } 
00348 
00349 public:
00350 
00351     /**\brief Normal constructor for a storage manager client.
00352      * \details
00353      * @param[in] f Stored in thread for client's convenience, may
00354      * be used in run() method.
00355      * @param[in] arg Stored in thread for client's convenience, may
00356      * be used in run() method.
00357      * @param[in] priority Required, but not used in storage manager.
00358      * @param[in] name Optional thread name, used for debugging.
00359      * @param[in] lockto Timeout for lock waiting.  See timeout_in_ms.
00360      * @param[in] stack_size Best to use default.
00361      */
00362     NORET            smthread_t(
00363         st_proc_t*             f, 
00364         void*                  arg,
00365         priority_t             priority = t_regular,
00366         const char*            name = 0, 
00367         timeout_in_ms          lockto = WAIT_FOREVER,
00368         unsigned               stack_size = default_stack);
00369 
00370     /**\brief Normal constructor for a storage manager client.
00371      * \details
00372      * @param[in] priority Required, but not used in storage manager.
00373      * @param[in] name Optional thread name, used for debugging.
00374      * @param[in] lockto Timeout for lock waiting.  See timeout_in_ms.
00375      * @param[in] stack_size Best to use default.
00376      */
00377     NORET            smthread_t(
00378         priority_t             priority = t_regular,
00379         const char*            name = 0,
00380         timeout_in_ms          lockto = WAIT_FOREVER,
00381         unsigned               stack_size = default_stack
00382         );
00383 
00384     // This is helpful for debugging and besides, it returns a w_rc_t
00385     // so there is an opportunity to check for things like
00386     // no xcts attached, etc. and deliver this info to the client.
00387     
00388     /**\brief  Returns when this thread ends.
00389      * @param[in] timeout Not used.
00390      * \details
00391      * Errors:
00392      * -ePINACTIVE: if the thread ended while holding a pinned record.
00393      * -eINTRANS: if the thread ended while attached to a transaction.
00394      */
00395     w_rc_t               join(timeout_in_ms timeout = WAIT_FOREVER);
00396 
00397     NORET                ~smthread_t();
00398 
00399     /**\cond skip */
00400     /* public for debugging */
00401     static void          init_fingerprint_map();
00402     /**\endcond skip */
00403 
00404     /**\brief Called before run() is called. */
00405     virtual void         before_run();
00406 
00407     /**\brief Main work routine. */
00408     virtual void         run() = 0;
00409 
00410     /**\brief Call when run finishes, before join() returns */
00411     virtual void         after_run();
00412     
00413     virtual smthread_t*          dynamic_cast_to_smthread();
00414     virtual const smthread_t*    dynamic_cast_to_const_smthread() const;
00415 
00416     /**\brief RTTI
00417      * \details
00418      * Run-time type info: Derived threads are expected to
00419      * add thread types and override thread_type()
00420      */
00421     enum SmThreadTypes     {smThreadType = 1, smLastThreadType};
00422     /**\brief RTTI
00423      * \details
00424      * Run-time type info: Derived threads are expected to
00425      * add thread types and override thread_type()
00426      */
00427     virtual int            thread_type() { return smThreadType; }
00428 
00429     /**\brief Iterator over all smthreads. Thread-safe and so use carefully.
00430      * \details
00431      * @param[in] f Callback function.
00432      * For each smthread, this calls the callback function \a f.
00433      * Because this grabs a lock on the list of all shore threads, 
00434      * whether or not they are smthreads, this prevents new threads
00435      * from starting and old ones from finishing, so don't use with
00436      * long-running functions.
00437      */
00438     static void            for_each_smthread(SmthreadFunc& f);
00439     
00440     /**\cond skip
00441      **\brief Attach this thread to the given transaction.
00442      * \ingroup SSMXCT
00443      * @param[in] x Transaction to attach to the thread
00444      * \details
00445      * Attach this thread to the transaction \a x or, equivalently,
00446      * attach \a x to this thread.
00447      * \note "this" thread need not be the running thread.
00448      *
00449      * Only one transaction may be attached to a thread at any time.
00450      * More than one thread may attach to a transaction concurrently.
00451      */
00452     void             attach_xct(xct_t* x);
00453     /**\brief Detach this thread from the given transaction.
00454      * \ingroup SSMXCT
00455      * @param[in] x Transaction to detach from the thread.
00456      * \details
00457      * Detach this thread from the transaction \a x or, equivalently,
00458      * detach \a x from this thread.
00459      * \note "this" thread need not be the running thread.
00460      *
00461      * If the transaction is not attached, returns error.
00462      * \endcond skip
00463      */
00464     void             detach_xct(xct_t* x);
00465 
00466     /// get lock_timeout value
00467     inline
00468     timeout_in_ms        lock_timeout() { 
00469                     return tcb().lock_timeout; 
00470                 }
00471     /**\brief Set lock_timeout value
00472      * \details
00473      * You can give a value WAIT_FOREVER, WAIT_IMMEDIATE, or
00474      * a positive millisecond value. 
00475      * Every lock request made with WAIT_SPECIFIED_BY_THREAD will
00476      * use this value.
00477      *
00478      * A transaction can be given its own timeout on ss_m::begin_xct.
00479      * The transaction's lock timeout is used for every lock request
00480      * made with WAIT_SPECIFIED_BY_XCT. 
00481      * A transaction begun with WAIT_SPECIFIED_BY_THREAD will use
00482      * the thread's lock_timeout for the transaction timeout.
00483      *
00484      * All internal storage manager lock requests use WAIT_SPECIFIED_BY_XCT.
00485      * Since the transaction can defer to the per-thread timeout, the
00486      * client has control over which timeout to use by choosing the
00487      * value given at ss_m::begin_xct.
00488      */
00489     inline 
00490     void             lock_timeout(timeout_in_ms i) { 
00491                     tcb().lock_timeout = i;
00492                 }
00493 
00494     /// return xct this thread is running
00495     inline
00496     xct_t*             xct() { return tcb().xct; }
00497 
00498     /// return xct this thread is running
00499     inline
00500     xct_t*             xct() const { return tcb().xct; }
00501 
00502     /**\brief Return currently-running smthread. 
00503      * \details
00504      * \note Assumes all threads are smthreads
00505      */
00506     static smthread_t*         me() { return (smthread_t*) sthread_t::me(); }
00507 
00508     /// Return thread-local statistics collected for this thread.
00509     inline sm_stats_info_t& TL_stats() { 
00510                                        return tcb().TL_stats(); }
00511 
00512     /// Add thread-local stats into the given structure.
00513     void add_from_TL_stats(sm_stats_info_t &w) const;
00514 
00515     // NOTE: These macros don't have to be atomic since these thread stats
00516     // are stored in the smthread and collected when the smthread's tcb is
00517     // destroyed.
00518     
00519 #define GET_TSTAT(x) me()->TL_stats().sm.x
00520 /**\def GET_TSTAT(x) 
00521  *\brief Get per-thread statistic named x
00522 */
00523 
00524 /**\def INC_TSTAT(x) 
00525  *\brief Increment per-thread statistic named x by y
00526  */
00527 #define INC_TSTAT(x) me()->TL_stats().sm.x++
00528 
00529 
00530 /**\def INC_TSTAT_BFHT(x) 
00531  *\brief Increment per-thread statistic named x by y
00532  */
00533 #define INC_TSTAT_BFHT(x) me()->TL_stats().bfht.bf_htab #x++
00534 
00535 /**\def ADD_TSTAT(x,y) 
00536  *\brief Increment statistic named x by y
00537  */
00538 #define ADD_TSTAT(x,y) me()->TL_stats().sm.x += (y)
00539 
00540 /**\def SET_TSTAT(x,y) 
00541  *\brief Set per-thread statistic named x to y
00542  */
00543 #define SET_TSTAT(x,y) me()->TL_stats().sm.x = (y)
00544 
00545 
00546     /**\cond skip */
00547     /*
00548      *  These functions are used to verify than nothing is
00549      *  left pinned accidentally.  Call mark_pin_count before an
00550      *  operation and check_pin_count after it with the expected
00551      *  number of pins that should not have been realeased.
00552      */
00553     void             mark_pin_count();
00554     void             check_pin_count(int change);
00555     void             check_actual_pin_count(int actual) ;
00556     void             incr_pin_count(int amount) ;
00557     int              pin_count() ;
00558    
00559     /*
00560      *  These functions are used to verify that a thread
00561      *  is only in one ss_m::, scan::, or pin:: function at a time.
00562      */
00563     inline
00564     void             in_sm(bool in)    { tcb()._in_sm = in; }
00565     inline 
00566     bool             is_in_sm() const { return tcb()._in_sm; }
00567 
00568     void             new_xct(xct_t *);
00569     void             no_xct(xct_t *);
00570 
00571     inline
00572     xct_log_t*       xct_log() { return tcb()._xct_log; }
00573     inline
00574     lockid_t *       lock_hierarchy() { return tcb()._lock_hierarchy; }
00575 
00576     inline
00577     sdesc_cache_t *  tls_sdesc_cache() { return tcb()._sdesc_cache; }
00578 
00579     virtual void     _dump(ostream &) const; // to be over-ridden
00580     static int       collect(vtable_t&, bool names_too);
00581     virtual void     vtable_collect(vtable_row_t& t);
00582     static  void     vtable_collect_names(vtable_row_t& t);
00583     /**\endcond skip */
00584 
00585     /* thread-level block() and unblock aren't public or protected
00586        accessible.  
00587        These methods are used by the lock manager.
00588        Otherwise, ordinarly pthreads sychronization variables
00589        are used.
00590     */
00591     w_rc_t::errcode_t smthread_block(timeout_in_ms WAIT_FOREVER,
00592                       const char * const caller = 0,
00593                       const void * id = 0);
00594     w_rc_t            smthread_unblock(w_rc_t::errcode_t e);
00595 
00596 private:
00597     w_rc_t::errcode_t _smthread_block( timeout_in_ms WAIT_FOREVER,
00598                               const char * const why =0);
00599     w_rc_t           _smthread_unblock(w_rc_t::errcode_t e);
00600 public:
00601     void             prepare_to_block();
00602 
00603     /* \brief Find out if log warning checks are to be made. Default is true.
00604      */
00605     bool            generate_log_warnings()const{return _gen_log_warnings;}
00606     /* \brief Enable/disable log-space warning checks
00607      */
00608     void            set_generate_log_warnings(bool b){_gen_log_warnings=b;}
00609 
00610     /**\brief  TLS variables Exported to sm.
00611      */
00612     queue_based_lock_t::ext_qnode& get_histoid_me() { return tcb()._histoid_me; }
00613     queue_based_lock_t::ext_qnode& get_me3() { return tcb()._me3; }
00614     queue_based_lock_t::ext_qnode& get_me2() { return tcb()._me2; }
00615     queue_based_lock_t::ext_qnode& get_me1() { return tcb()._me1; }
00616     queue_based_block_lock_t::ext_qnode& get_log_me_node() { 
00617                                                return tcb()._log_me_node;}
00618     queue_based_lock_t::ext_qnode& get_xlist_mutex_node() { 
00619                                                return tcb()._xlist_mutex_node;}
00620     queue_based_lock_t::ext_qnode& get_1thread_log_me() {
00621                                                return tcb()._1thread_log_me;}
00622     queue_based_lock_t::ext_qnode& get_1thread_xct_me() {
00623                                                return tcb()._1thread_xct_me;}
00624     queue_based_lock_t::ext_qnode& get_xct_t_me_node() {
00625                                                return tcb()._xct_t_me_node;}
00626     tcb_t::ordinal_number_t &      get__ordinal()  { return tcb().__ordinal; }
00627     int&                           get___metarecs() { 
00628                                                return tcb().__metarecs; }
00629     int&                           get___metarecs_in() { 
00630                                                return tcb().__metarecs_in; }
00631     char *                         get_kc_buf()  { return (char *)&(tcb()._kc_buf_double[0]); }
00632     cvec_t*                        get_kc_vec()  { return &(tcb()._kc_vec); }
00633     char *                         get_page_check_map() {
00634                                          return &(tcb()._page_check_map[0]);  }
00635 private:
00636 
00637     /* sm-specif block / unblock implementation */
00638     volatile bool   _unblocked;
00639     bool            _waiting;
00640 
00641     bool            _gen_log_warnings;
00642 
00643     inline
00644     tcb_t           &tcb() { return _tcb; }
00645 
00646     inline
00647     const tcb_t     &tcb() const { return _tcb; }
00648 };
00649 
00650 /**\cond skip */
00651 class smthread_init_t {
00652 public:
00653     NORET            smthread_init_t();
00654     NORET            ~smthread_init_t();
00655 private:
00656     static int       count;
00657 };
00658 /**\endcond  skip */
00659 
00660 
00661 
00662 /**\cond skip */
00663 
00664 inline smthread_t* 
00665 me() 
00666 { 
00667     return smthread_t::me(); 
00668 }
00669 
00670 
00671 inline xct_t* 
00672 xct() 
00673 { 
00674     return me()->xct(); 
00675 }
00676 
00677 
00678 inline void 
00679 smthread_t::mark_pin_count()
00680 {    
00681     tcb().prev_pin_count = tcb().pin_count;
00682 }
00683 
00684 inline void 
00685 smthread_t::check_pin_count(int W_IFDEBUG4(change)) 
00686 {
00687 #if W_DEBUG_LEVEL > 3
00688     int diff = tcb().pin_count - tcb().prev_pin_count;
00689     if (change >= 0) {
00690         w_assert4(diff <= change);
00691     } else {
00692         w_assert4(diff >= change);
00693     }
00694 #endif 
00695 }
00696 
00697 inline void 
00698 smthread_t::check_actual_pin_count(int W_IFDEBUG3(actual)) 
00699 {
00700     w_assert3(tcb().pin_count == actual);
00701 }
00702 
00703 
00704 inline void 
00705 smthread_t::incr_pin_count(int amount) 
00706 {
00707     tcb().pin_count += amount; 
00708 }
00709 
00710 inline int 
00711 smthread_t::pin_count() 
00712 {
00713     return tcb().pin_count;
00714 }
00715 
00716 void
00717 DumpBlockedThreads(ostream& o);
00718 
00719 /*
00720  * redefine DBGTHRD to use our threads
00721  */
00722 #ifdef DBGTHRD
00723 #undef DBGTHRD
00724 #endif
00725 #define DBGTHRD(arg) DBG(<< " th." << smthread_t::me()->id << " " arg)
00726 #ifdef W_TRACE
00727 /* 
00728  * Redefine FUNC to print the thread id
00729  * (Be careful here that we are basing our printing on the
00730  * name given as an argument, not __func__, which would
00731  * give us the constructor func_helper::func_helper.)
00732  */
00733 class func_helper {
00734     static __thread int depth;
00735     bool entered;
00736     const char *file; 
00737     int line;
00738 public:
00739     func_helper(const char *name, 
00740             const char *f, int l) : entered(false), file(f), line(l) {
00741         if(_w_debug.flag_on(name,file)) {
00742         ++depth;
00743         entered=true;
00744         DBG2(<< " th." << smthread_t::me()->id << " " << name
00745                 << " " << depth << "-{", line,file);
00746         }
00747     }
00748     ~func_helper() {
00749         if(entered) {
00750             DBG2(<< " th." << smthread_t::me()->id << " " << depth << "-}",
00751                 line,file);
00752             depth--;
00753         }
00754     }
00755 };
00756 #undef FUNC
00757 #define FUNC(fn) func_helper local_func_helper(__func__, __FILE__, __LINE__);
00758 #endif /* W_TRACE */
00759 
00760 /**\endcond skip */
00761 
00762 
00763 /*<std-footer incl-file-exclusion='SMTHREAD_H'>  -- do not edit anything below this line -- */
00764 
00765 #endif          /*</std-footer>*/

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