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

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