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 #ifdef ARCH_LP64
00231
00232
00233
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;
00242
00243
00244 queue_based_lock_t::ext_qnode _me1;
00245
00246 queue_based_lock_t::ext_qnode _me2;
00247
00248 queue_based_lock_t::ext_qnode _me3;
00249
00250 queue_based_lock_t::ext_qnode _histoid_me;
00251
00252
00253
00254
00255
00256 queue_based_lock_t::ext_qnode _1thread_xct_me;
00257
00258
00259
00260
00261 queue_based_lock_t::ext_qnode _1thread_log_me;
00262
00263
00264
00265
00266 queue_based_lock_t::ext_qnode _xct_t_me_node;
00267
00268
00269
00270
00271 queue_based_lock_t::ext_qnode _xlist_mutex_node;
00272
00273
00274
00275
00276 queue_based_block_lock_t::ext_qnode _log_me_node;
00277
00278
00279
00280
00281 typedef uint4_t ordinal_number_t;
00282 ordinal_number_t __ordinal;
00283
00284
00285
00286 int __metarecs;
00287 int __metarecs_in;
00288
00289
00290
00291
00292
00293 double _kc_buf_double[smlevel_0::page_sz/sizeof(double)];
00294 cvec_t _kc_vec;
00295
00296 char _page_check_map[SM_PAGESIZE];
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),
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();
00340 void _initialize_fingerprint();
00341 void _uninitialize_fingerprint();
00342 short _fingerprint[FINGER_BITS];
00343 atomic_thread_map_t _fingerprint_map;
00344
00345 public:
00346 const atomic_thread_map_t& get_fingerprint_map() const
00347 { return _fingerprint_map; }
00348
00349 public:
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
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
00371
00372
00373
00374
00375
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
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 w_rc_t join(timeout_in_ms timeout = WAIT_FOREVER);
00396
00397 NORET ~smthread_t();
00398
00399
00400
00401 static void init_fingerprint_map();
00402
00403
00404
00405 virtual void before_run();
00406
00407
00408 virtual void run() = 0;
00409
00410
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
00417
00418
00419
00420
00421 enum SmThreadTypes {smThreadType = 1, smLastThreadType};
00422
00423
00424
00425
00426
00427 virtual int thread_type() { return smThreadType; }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 static void for_each_smthread(SmthreadFunc& f);
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 void attach_xct(xct_t* x);
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 void detach_xct(xct_t* x);
00465
00466
00467 inline
00468 timeout_in_ms lock_timeout() {
00469 return tcb().lock_timeout;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 inline
00490 void lock_timeout(timeout_in_ms i) {
00491 tcb().lock_timeout = i;
00492 }
00493
00494
00495 inline
00496 xct_t* xct() { return tcb().xct; }
00497
00498
00499 inline
00500 xct_t* xct() const { return tcb().xct; }
00501
00502
00503
00504
00505
00506 static smthread_t* me() { return (smthread_t*) sthread_t::me(); }
00507
00508
00509 inline sm_stats_info_t& TL_stats() {
00510 return tcb().TL_stats(); }
00511
00512
00513 void add_from_TL_stats(sm_stats_info_t &w) const;
00514
00515
00516
00517
00518
00519 #define GET_TSTAT(x) me()->TL_stats().sm.x
00520
00521
00522
00523
00524
00525
00526
00527 #define INC_TSTAT(x) me()->TL_stats().sm.x++
00528
00529
00530
00531
00532
00533 #define INC_TSTAT_BFHT(x) me()->TL_stats().bfht.bf_htab #x++
00534
00535
00536
00537
00538 #define ADD_TSTAT(x,y) me()->TL_stats().sm.x += (y)
00539
00540
00541
00542
00543 #define SET_TSTAT(x,y) me()->TL_stats().sm.x = (y)
00544
00545
00546
00547
00548
00549
00550
00551
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
00561
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;
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
00584
00585
00586
00587
00588
00589
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
00604
00605 bool generate_log_warnings()const{return _gen_log_warnings;}
00606
00607
00608 void set_generate_log_warnings(bool b){_gen_log_warnings=b;}
00609
00610
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
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
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
00659
00660
00661
00662
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
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
00729
00730
00731
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
00759
00760
00761
00762
00763
00764
00765 #endif