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 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         
00173         
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 
00189 typedef void st_proc_t(void*);
00190 
00191 class sm_stats_info_t; 
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
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;      
00223         int      prev_pin_count; 
00224         timeout_in_ms lock_timeout;    
00225         bool    _in_sm;      
00226 #ifdef ARCH_LP64
00227         
00228 
00229 
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; 
00238 
00239         
00240         queue_based_lock_t::ext_qnode _me1;
00241         
00242         queue_based_lock_t::ext_qnode _me2;
00243         
00244         queue_based_lock_t::ext_qnode _me3;
00245 
00246 
00247 
00248 
00249 
00250         queue_based_lock_t::ext_qnode _1thread_xct_me;
00251 
00252 
00253 
00254 
00255         queue_based_lock_t::ext_qnode _1thread_log_me;
00256 
00257 
00258 
00259 
00260         queue_based_lock_t::ext_qnode _xct_t_me_node;
00261 
00262 
00263 
00264 
00265         queue_based_lock_t::ext_qnode _xlist_mutex_node;
00266 
00267 
00268 
00269 
00270         queue_based_block_lock_t::ext_qnode _log_me_node;
00271 
00272 
00273 
00274 
00275         typedef uint4_t        ordinal_number_t;
00276         ordinal_number_t __ordinal;
00277 
00278 
00279 
00280         int __metarecs;
00281         int __metarecs_in;
00282 
00283         
00284 
00285 
00286 
00287         double  _kc_buf_double[smlevel_0::page_sz/sizeof(double)]; 
00288         cvec_t  _kc_vec;
00289         
00290         char    _page_check_map[SM_PAGESIZE]; 
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), 
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; ;
00314             _me2._held = NULL; ;
00315             _me3._held = NULL; ;
00316             _1thread_xct_me._held = NULL; ;
00317             _1thread_log_me._held = NULL; ;
00318             _xct_t_me_node._held = NULL; ;
00319             _xlist_mutex_node._held = NULL; ;
00320             _log_me_node._held = NULL; ;
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(); 
00332     void               _initialize_fingerprint();
00333     void               _uninitialize_fingerprint();
00334     short              _fingerprint[FINGER_BITS]; 
00335     atomic_thread_map_t  _fingerprint_map; 
00336 
00337 public:
00338     const atomic_thread_map_t&  get_fingerprint_map() const
00339                             {   return _fingerprint_map; } 
00340 
00341 public:
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
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 
00363 
00364 
00365 
00366 
00367 
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     
00377     
00378     
00379     
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387     w_rc_t               join(timeout_in_ms timeout = WAIT_FOREVER);
00388 
00389     NORET                ~smthread_t();
00390 
00391 
00392     
00393     static void          init_fingerprint_map();
00394 
00395 
00396 
00397     virtual void         before_run();
00398 
00399 
00400     virtual void         run() = 0;
00401 
00402 
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 
00409 
00410 
00411 
00412 
00413     enum SmThreadTypes     {smThreadType = 1, smLastThreadType};
00414 
00415 
00416 
00417 
00418 
00419     virtual int            thread_type() { return smThreadType; }
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430     static void            for_each_smthread(SmthreadFunc& f);
00431     
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444     void             attach_xct(xct_t* x);
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456     void             detach_xct(xct_t* x);
00457 
00458 
00459     inline
00460     timeout_in_ms        lock_timeout() { 
00461                     return tcb().lock_timeout; 
00462                 }
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481     inline 
00482     void             lock_timeout(timeout_in_ms i) { 
00483                     tcb().lock_timeout = i;
00484                 }
00485 
00486 
00487     inline
00488     xct_t*             xct() { return tcb().xct; }
00489 
00490 
00491     inline
00492     xct_t*             xct() const { return tcb().xct; }
00493 
00494 
00495 
00496 
00497 
00498     static smthread_t*         me() { return (smthread_t*) sthread_t::me(); }
00499 
00500 
00501     inline sm_stats_info_t& TL_stats() { 
00502                                        return tcb().TL_stats(); }
00503 
00504 
00505     void add_from_TL_stats(sm_stats_info_t &w) const;
00506 
00507     
00508     
00509     
00510     
00511 #define GET_TSTAT(x) me()->TL_stats().sm.x
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 #define INC_TSTAT(x) me()->TL_stats().sm.x++
00520 
00521 
00522 
00523 
00524 
00525 #define INC_TSTAT_BFHT(x) me()->TL_stats().bfht.bf_htab #x++
00526 
00527 
00528 
00529 
00530 #define ADD_TSTAT(x,y) me()->TL_stats().sm.x += (y)
00531 
00532 
00533 
00534 
00535 #define SET_TSTAT(x,y) me()->TL_stats().sm.x = (y)
00536 
00537 
00538 
00539     
00540 
00541 
00542 
00543 
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 
00553 
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; 
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 
00576 
00577     
00578 
00579 
00580 
00581 
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     
00596 
00597     bool            generate_log_warnings()const{return _gen_log_warnings;}
00598     
00599 
00600     void            set_generate_log_warnings(bool b){_gen_log_warnings=b;}
00601 
00602 
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     
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 
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 
00650 
00651 
00652 
00653 
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 
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 
00720 
00721 #undef FUNC
00722 #define FUNC(fn)\
00723   do { char const* fname = __func__; \
00724     DBGTHRD(<< fname);} while(0)
00725 #endif 
00726 
00727 
00728 
00729 
00730 
00731 
00732 #endif