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