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