00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 #ifndef SMTHREAD_H
00054 #define SMTHREAD_H
00055 
00056 #include "w_defines.h"
00057 
00058 
00059 
00060 
00061 
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 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
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 
00106 
00107 
00108 
00109 class SmthreadFunc {
00110 public:
00111     virtual ~SmthreadFunc();
00112     
00113     virtual void operator()(const smthread_t& smthread) = 0;
00114 };
00115 
00116 
00117 
00118 enum { FINGER_BITS=3 };
00119 typedef w_bitvector_t<256>    sm_thread_map_t;
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
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         
00177         
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 
00193 typedef void st_proc_t(void*);
00194 
00195 class sm_stats_info_t; 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
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;      
00227         int      prev_pin_count; 
00228         timeout_in_ms lock_timeout;    
00229         bool    _in_sm;      
00230         bool    _is_update_thread;
00231 #ifdef ARCH_LP64
00232         
00233 
00234 
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; 
00243 
00244         
00245         queue_based_lock_t::ext_qnode _me1;
00246         
00247         queue_based_lock_t::ext_qnode _me2;
00248         
00249         queue_based_lock_t::ext_qnode _me3;
00250         
00251         queue_based_lock_t::ext_qnode _histoid_me;
00252 
00253 
00254 
00255 
00256 
00257         queue_based_lock_t::ext_qnode _1thread_xct_me;
00258 
00259 
00260 
00261 
00262         queue_based_lock_t::ext_qnode _xct_t_me_node;
00263 
00264 
00265 
00266 
00267         queue_based_lock_t::ext_qnode _xlist_mutex_node;
00268 
00269 
00270 
00271 
00272         queue_based_block_lock_t::ext_qnode _log_me_node;
00273 
00274 
00275 
00276 
00277         typedef uint4_t        ordinal_number_t;
00278         ordinal_number_t __ordinal;
00279 
00280 
00281 
00282         int __metarecs;
00283         int __metarecs_in;
00284 
00285         
00286 
00287 
00288 
00289         double  _kc_buf_double[smlevel_0::page_sz/sizeof(double)]; 
00290         cvec_t  _kc_vec;
00291         
00292         char    _page_check_map[SM_PAGESIZE]; 
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), 
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(); 
00336     void               _initialize_fingerprint();
00337     void               _uninitialize_fingerprint();
00338     short              _fingerprint[FINGER_BITS]; 
00339     atomic_thread_map_t  _fingerprint_map; 
00340 
00341 public:
00342     const atomic_thread_map_t&  get_fingerprint_map() const
00343                             {   return _fingerprint_map; } 
00344 
00345 public:
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
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 
00367 
00368 
00369 
00370 
00371 
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     
00381     
00382     
00383     
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391     w_rc_t               join(timeout_in_ms timeout = WAIT_FOREVER);
00392 
00393     NORET                ~smthread_t();
00394 
00395 
00396     
00397     static void          init_fingerprint_map();
00398 
00399 
00400 
00401     virtual void         before_run();
00402 
00403 
00404     virtual void         run() = 0;
00405 
00406 
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 
00413 
00414 
00415 
00416 
00417     enum SmThreadTypes     {smThreadType = 1, smLastThreadType};
00418 
00419 
00420 
00421 
00422 
00423     virtual int            thread_type() { return smThreadType; }
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434     static void            for_each_smthread(SmthreadFunc& f);
00435     
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448     void             attach_xct(xct_t* x);
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460     void             detach_xct(xct_t* x);
00461 
00462 
00463     inline
00464     timeout_in_ms        lock_timeout() { 
00465                     return tcb().lock_timeout; 
00466                 }
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485     inline 
00486     void             lock_timeout(timeout_in_ms i) { 
00487                     tcb().lock_timeout = i;
00488                 }
00489 
00490 
00491     inline
00492     xct_t*             xct() { return tcb().xct; }
00493 
00494 
00495     inline
00496     xct_t*             xct() const { return tcb().xct; }
00497 
00498 
00499 
00500 
00501 
00502     static smthread_t*         me() { return (smthread_t*) sthread_t::me(); }
00503 
00504 
00505     inline sm_stats_info_t& TL_stats() { 
00506                                        return tcb().TL_stats(); }
00507 
00508 
00509     void add_from_TL_stats(sm_stats_info_t &w) const;
00510 
00511     
00512     
00513     
00514     
00515 #define GET_TSTAT(x) me()->TL_stats().sm.x
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 #define INC_TSTAT(x) me()->TL_stats().sm.x++
00524 
00525 
00526 
00527 
00528 #define ADD_TSTAT(x,y) me()->TL_stats().sm.x += (y)
00529 
00530 
00531 
00532 
00533 #define SET_TSTAT(x,y) me()->TL_stats().sm.x = (y)
00534 
00535 
00536 
00537     
00538 
00539 
00540 
00541 
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 
00551 
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; 
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 
00580 
00581     
00582 
00583 
00584 
00585 
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     
00600 
00601     bool            generate_log_warnings()const{return _gen_log_warnings;}
00602     
00603 
00604     void            set_generate_log_warnings(bool b){_gen_log_warnings=b;}
00605 
00606 
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     
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 
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 
00653 
00654 
00655 
00656 
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 
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 
00723 
00724 
00725 
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 
00753 
00754 
00755 
00756 
00757 
00758 
00759 #endif