src/core/sentinel.c

Go to the documentation of this file.
00001 
00092 #include <sys/types.h>
00093 #include <sys/stat.h>
00094 #include <pthread.h>
00095 #include <unistd.h>
00096 #include <stddef.h>
00097 #include <misc/result.h>
00098 #include <misc/pool.h>
00099 #include <misc/malloc.h>
00100 #include <misc/debug.h>
00101 #include <misc/mutex.h>
00102 #include <core/config.h>
00103 #include <core/sentinel.h>
00104 #include <core/tx.h>
00105 #include <core/txdesc.h>
00106 
00107 #define TXC_SENTINEL_NOOWNER                0x0
00108 
00110 struct txc_sentinel_s {
00111         txc_mutex_t       sentinel_mutex;  
00112         txc_mutex_t       synch_mutex;     
00113         int               id;              
00114         int               refcnt;          
00115         txc_tx_t          *owner;          
00116         txc_sentinelmgr_t *manager;        
00117 };
00118 
00120 struct txc_sentinel_list_entry_s {
00121         txc_sentinel_t *sentinel;          
00122         txc_result_t   status;             
00123 };
00124 
00126 struct txc_sentinel_list_s {
00127         txc_sentinel_list_entry_t *entries;      
00128         unsigned int              num_entries;   
00129         unsigned int              size;          
00130         txc_sentinelmgr_t         *manager;      
00131 };
00132 
00133 
00135 struct txc_sentinelmgr_s {
00136         txc_mutex_t mutex;
00137         txc_pool_t  *pool_sentinel;
00138 };
00139 
00140 
00141 static inline void sentinel_list_print(txc_sentinel_list_t *sentinel_list, char *heading);
00142 static inline txc_result_t enlist_sentinel(txc_sentinel_list_t *sentinel_list, txc_sentinel_t *sentinel, txc_result_t status);
00143 static inline void backoff(txc_tx_t *txd);
00144 
00145 
00146 txc_sentinelmgr_t *txc_g_sentinelmgr;
00147 
00148 
00157 txc_result_t
00158 txc_sentinelmgr_create(txc_sentinelmgr_t **sentinelmgrp) 
00159 {
00160         txc_result_t      result;
00161         txc_pool_object_t *pool_object;
00162         txc_sentinel_t    *sentinel;
00163         int               i;
00164 
00165         *sentinelmgrp = (txc_sentinelmgr_t *) MALLOC(sizeof(txc_sentinelmgr_t));
00166         if (*sentinelmgrp == NULL) {
00167                 return TXC_R_NOMEMORY;
00168         }
00169 
00170         if ((result = txc_pool_create(&((*sentinelmgrp)->pool_sentinel), 
00171                                       sizeof(txc_sentinel_t),
00172                                       TXC_SENTINEL_NUM, 
00173                                   NULL)) != TXC_R_SUCCESS) 
00174         {
00175                 FREE(*sentinelmgrp);
00176                 return result;
00177         }
00178         TXC_MUTEX_INIT(&((*sentinelmgrp)->mutex), NULL);
00179         for (i = 0,
00180              pool_object = txc_pool_object_first((*sentinelmgrp)->pool_sentinel,
00181                                                  TXC_POOL_OBJECT_ALLOCATED & 
00182                                                  TXC_POOL_OBJECT_FREE);
00183              pool_object != NULL;
00184                  i++, pool_object = txc_pool_object_next(pool_object))
00185         {
00186                 sentinel = (txc_sentinel_t *) txc_pool_object_of(pool_object);
00187                 TXC_MUTEX_INIT(&sentinel->synch_mutex, NULL);
00188                 TXC_MUTEX_INIT(&sentinel->sentinel_mutex, NULL);
00189                 sentinel->id = i;
00190                 sentinel->manager = *sentinelmgrp;
00191                 sentinel->owner = TXC_SENTINEL_NOOWNER;  
00192         }
00193         
00194         return TXC_R_SUCCESS;
00195 }
00196 
00197 
00205 void
00206 txc_sentinelmgr_destroy(txc_sentinelmgr_t **sentinelmgrp)
00207 {
00208         txc_pool_destroy(&((*sentinelmgrp)->pool_sentinel));
00209         FREE(*sentinelmgrp);
00210         *sentinelmgrp = NULL;
00211 }
00212 
00213 
00214 txc_result_t
00215 txc_sentinel_create(txc_sentinelmgr_t *sentinelmgr, txc_sentinel_t **sentinelp) 
00216 {
00217         txc_result_t   result;
00218         txc_sentinel_t *sentinel;
00219 
00220         if ((result = txc_pool_object_alloc(sentinelmgr->pool_sentinel, 
00221                                             (void **) &sentinel, 1)) 
00222             != TXC_R_SUCCESS) 
00223         {
00224                 TXC_INTERNALERROR("Could not create sentinel object\n");
00225                 return result;
00226         }
00227 
00228         sentinel->owner = TXC_SENTINEL_NOOWNER;
00229         sentinel->refcnt = 1;
00230         *sentinelp = sentinel;
00231 
00232         return TXC_R_SUCCESS;
00233 }
00234 
00235 
00236 static inline
00237 void 
00238 sentinel_destroy(txc_sentinel_t *sentinel) 
00239 {
00240         txc_sentinel_t **sentinelp = &sentinel;
00241 
00242         txc_pool_object_free(sentinel->manager->pool_sentinel, 
00243                              (void **) sentinelp, 1);
00244 }
00245 
00251 void 
00252 txc_sentinel_destroy(txc_sentinel_t *sentinel) 
00253 {
00254         TXC_ASSERT(sentinel != NULL);
00255         TXC_MUTEX_LOCK(&sentinel->synch_mutex);
00256         sentinel_destroy(sentinel);
00257         TXC_MUTEX_UNLOCK(&sentinel->synch_mutex);
00258 }
00259 
00260 
00261 static 
00262 void
00263 sentinel_attach(txc_sentinel_t *sentinel)
00264 {
00265         sentinel->refcnt++;
00266 }
00267 
00268 
00269 /*
00270  * Assumes lock sentinel->synch_mutex is held by the caller.
00271  */
00272 static
00273 txc_result_t 
00274 sentinel_detach(txc_sentinel_t *sentinel)
00275 {
00276         if (--sentinel->refcnt==0) {
00277                 sentinel_destroy(sentinel);     
00278         }
00279         return TXC_R_SUCCESS;
00280 }
00281 
00282 
00293 txc_result_t
00294 txc_sentinel_detach(txc_sentinel_t *sentinel)
00295 {
00296         txc_result_t ret;
00297 
00298         TXC_MUTEX_LOCK(&sentinel->synch_mutex);
00299         ret = sentinel_detach(sentinel);
00300         TXC_MUTEX_UNLOCK(&sentinel->synch_mutex);
00301         return ret;
00302 }
00303 
00304 
00315 static inline
00316 void
00317 sentinel_list_acquire(txc_tx_t *txd, txc_sentinel_list_t *list_acquire)
00318 {
00319         txc_sentinel_list_entry_t *entry;
00320         int                       i;
00321 
00322         TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, "SENTINEL LIST: ACQUIRE SENTINELS\n");
00323         sentinel_list_print(list_acquire, "SENTINEL_LIST_ACQUIRE");
00324         for (i=0; i<list_acquire->num_entries; i++) {
00325                 entry = &list_acquire->entries[i];
00326                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00327                                 "ACQUIRE SENTINEL %3d: MAY BLOCK\n",
00328                                 entry->sentinel->id);
00329                 TXC_MUTEX_LOCK(&(entry->sentinel->sentinel_mutex));
00330                 entry->sentinel->owner = txd;
00331                 enlist_sentinel(txd->sentinel_list, entry->sentinel, 
00332                                 TXC_SENTINEL_ACQUIRED | 
00333                                                 TXC_SENTINEL_ACQUIREONRETRY);
00334 
00335                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00336                                 "ACQUIRE SENTINEL %3d: SUCCESS\n",
00337                                 entry->sentinel->id);
00338         }
00339 }
00340 
00341 
00351 static
00352 void
00353 sentinel_list_release(txc_sentinel_list_t *sentinel_list, int transaction_completion)
00354 {
00355         txc_sentinel_list_entry_t *entry;
00356         int                       i;
00357 
00358         TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, "SENTINEL LIST: RELEASE SENTINELS\n");
00359         for (i=0; i<sentinel_list->num_entries; i++) {
00360                 entry = &sentinel_list->entries[i];
00361                 TXC_MUTEX_LOCK(&(entry->sentinel->synch_mutex));
00362                 if (entry->status & TXC_SENTINEL_ACQUIRED) {
00363                         entry->sentinel->owner = TXC_SENTINEL_NOOWNER;
00364                         TXC_MUTEX_UNLOCK(&(entry->sentinel->sentinel_mutex));
00365                         TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00366                                         "RELEASE SENTINEL %3d: SUCCESS\n",
00367                                         entry->sentinel->id);
00368                 }
00374                 if (transaction_completion) {
00375                         /* 
00376                          * sentinel_detach will destroy the sentinel if after the
00377                          * detach operation (sentinel->refcnt == 0) 
00378                          */
00379                         sentinel_detach(entry->sentinel);
00380                 } else {
00381                         if (!(entry->status & TXC_SENTINEL_ACQUIREONRETRY)) {
00382                                 sentinel_detach(entry->sentinel);
00383                         }
00384                 }
00385                 TXC_MUTEX_UNLOCK(&(entry->sentinel->synch_mutex));
00386         }
00387 }
00388 
00389 
00390 static 
00391 void
00392 sentinel_list_sort(txc_sentinel_list_t *sentinel_list) 
00393 {
00394         int                       i;
00395         int                       n = sentinel_list->num_entries;
00396         txc_sentinel_list_entry_t entry_temp;
00397         unsigned int              swapped;
00398 
00399         TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, "SENTINEL LIST: SORT\n");
00400         do {
00401                 swapped = 0;
00402                 for (i = 0; i<n-1; i++) {
00403                         if (sentinel_list->entries[i].sentinel->id >
00404                             sentinel_list->entries[i+1].sentinel->id) 
00405                         {
00406                                 entry_temp = sentinel_list->entries[i+1];
00407                                 sentinel_list->entries[i+1] = sentinel_list->entries[i];
00408                                 sentinel_list->entries[i] = entry_temp;
00409                                 swapped = 1;
00410                         }
00411                 }
00412                 n = n-1;
00413         } while (swapped);
00414 }
00415 
00416 
00417 
00418 static inline
00419 void
00420 sentinelmgr_transaction_on_complete(txc_tx_t *txd)
00421 {
00422 #ifdef _TXC_DEBUG_BUILD
00423         sentinel_list_print(txd->sentinel_list, "TRANSACTION ON COMPLETE");
00424         sentinel_list_print(txd->sentinel_list, "SENTINEL LIST (MAIN LIST)");
00425 #endif
00426         sentinel_list_release(txd->sentinel_list, 1);
00427         txc_sentinel_list_init(txd->sentinel_list);
00428         txd->sentinelmgr_undo_action_registered = 0;                                                      
00429         txd->sentinelmgr_commit_action_registered = 0;                                                    
00430 }
00431 
00432 
00433 static 
00434 void
00435 sentinelmgr_transaction_before_retry(txc_tx_t *txd)
00436 {
00437         int                       i;
00438         txc_sentinel_list_entry_t *entry;
00439 
00440 #ifdef _TXC_DEBUG_BUILD
00441         sentinel_list_print(txd->sentinel_list, "TRANSACTION BEFORE RETRY");
00442         sentinel_list_print(txd->sentinel_list, "SENTINEL_LIST (MAIN LIST)");
00443 #endif
00444         txd->sentinel_list_preacquire->num_entries = 0;
00445         for (i=0; i<txd->sentinel_list->num_entries; i++) {
00446                 entry = &txd->sentinel_list->entries[i];
00447                 if (entry->status & TXC_SENTINEL_ACQUIREONRETRY) {
00448                         enlist_sentinel(txd->sentinel_list_preacquire, 
00449                                         entry->sentinel, 
00450                                         0 & ~TXC_SENTINEL_ACQUIRED);
00451                 }
00452         }
00453         sentinel_list_sort(txd->sentinel_list_preacquire);
00454         /* 
00455          * Ask sentinel_list_release to release all the sentinels but only drop 
00456          * the references to sentinels that we won't reacquire after transaction 
00457          * restarts. This is because we continue logically referencing sentinels 
00458          * we'll acquire after transaction restarts. 
00459          */
00460         sentinel_list_release(txd->sentinel_list, 0);
00461 #ifdef _TXC_DEBUG_BUILD
00462         sentinel_list_print(txd->sentinel_list_preacquire, 
00463                             "SENTINEL LIST (PREACQUIRE LIST)");
00464 #endif  
00465         txc_sentinel_list_init(txd->sentinel_list);
00466         txd->sentinelmgr_undo_action_registered = 0;                                                      
00467         txd->sentinelmgr_commit_action_registered = 0;
00468         backoff(txd);
00469         sentinel_list_acquire(txd, txd->sentinel_list_preacquire);
00470 }
00471 
00472 
00473 static
00474 void 
00475 sentinelmgr_commit_action(void *args, int *result)
00476 {
00477         txc_tx_t *txd = (txc_tx_t *) args;
00478         sentinelmgr_transaction_on_complete(txd);
00479 
00480         if (result) {
00481                 *result = 0;
00482         }
00483 }
00484 
00485 
00486 static 
00487 void 
00488 sentinelmgr_undo_action(void *args, int *result)
00489 {
00490         txc_tx_t *txd = (txc_tx_t *) args;
00491 
00492         switch (txd->abort_reason) {
00493                 case TXC_ABORTREASON_USERABORT:
00494                         sentinelmgr_transaction_on_complete(txd);
00495                         break;
00496                 case TXC_ABORTREASON_TMCONFLICT:
00497                 case TXC_ABORTREASON_USERRETRY:
00498                 case TXC_ABORTREASON_INCONSISTENCY:
00499                 case TXC_ABORTREASON_BUSYSENTINEL:
00500                 case TXC_ABORTREASON_BUSYTXLOCK:
00501                         sentinelmgr_transaction_before_retry(txd);
00502                         break;
00503                 default:
00504                         TXC_INTERNALERROR("Unknown abort reason\n");
00505                         /* never returns here */
00506         }
00507 
00508         if (result) {
00509                 *result = 0;
00510         }
00511 }
00512 
00513 
00514 static inline
00515 void
00516 register_sentinelmgr_commit_action(txc_tx_t *txd)
00517 {
00518         if (txd->sentinelmgr_commit_action_registered == 0) {
00519                 txc_tx_register_commit_action(txd, 
00520                                               sentinelmgr_commit_action, 
00521                                               (void *) txd,
00522                                               NULL,
00523                                           TXC_SENTINELMGR_COMMIT_ACTION_ORDER);
00524                 txd->sentinelmgr_commit_action_registered = 1;                                                    
00525         }
00526 }
00527 
00528 
00529 static inline
00530 void
00531 register_sentinelmgr_undo_action(txc_tx_t *txd)
00532 {
00533         if (txd->sentinelmgr_undo_action_registered == 0) {
00534                 txc_tx_register_undo_action(txd, 
00535                                               sentinelmgr_undo_action,
00536                                               (void *) txd,
00537                                               NULL,
00538                                           TXC_SENTINELMGR_UNDO_ACTION_ORDER);
00539                 txd->sentinelmgr_undo_action_registered = 1;                                                      
00540         }
00541 }
00542 
00543 
00544 void
00545 txc_sentinel_register_sentinelmgr_commit_action(txc_tx_t *txd)
00546 {
00547         register_sentinelmgr_commit_action(txd);
00548 }
00549 
00550 
00551 void
00552 txc_sentinel_register_sentinelmgr_undo_action(txc_tx_t *txd)
00553 {
00554         register_sentinelmgr_undo_action(txd);
00555 }
00556 
00557 
00558 void
00559 txc_sentinel_transaction_postbegin(txc_tx_t *txd)
00560 {
00561         /* 
00562          * If we have preacquired sentinels then we need to register commit and
00563          * undo actions so that we release the sentinels when the transaction
00564          * commits/aborts/retries.
00565          */
00566         if (txd->sentinel_list->num_entries) {  
00567                 register_sentinelmgr_commit_action(txd);
00568                 register_sentinelmgr_undo_action(txd);
00569         }       
00570 }
00571 
00572 
00573 static inline
00574 txc_result_t
00575 allocate_sentinel_list_entries(txc_sentinel_list_t *la, int extend)
00576 {
00577         if (extend) {
00578                 /* Extend action list */
00579                 la->size *= 2;
00580                 if ((la->entries = 
00581                      (txc_sentinel_list_entry_t *) REALLOC (la->entries, 
00582                                                              la->size * sizeof(txc_sentinel_list_entry_t)))
00583                     == NULL)
00584                 {
00585                         return TXC_R_NOMEMORY;
00586                 }
00587         } else {
00588                 /* Allocate action list */
00589                 if ((la->entries = 
00590                      (txc_sentinel_list_entry_t *) MALLOC (la->size * sizeof(txc_sentinel_list_entry_t)))
00591                     == NULL)
00592                 {
00593                         return TXC_R_NOMEMORY;
00594                 }       
00595         }
00596         return TXC_R_SUCCESS;
00597 }
00598 
00599 
00600 static inline
00601 txc_result_t
00602 deallocate_sentinel_list_entries(txc_sentinel_list_t *la)
00603 {
00604         FREE(la->entries);
00605         return TXC_R_SUCCESS;
00606 }
00607 
00608 
00617 txc_result_t
00618 txc_sentinel_list_create(txc_sentinelmgr_t *sentinelmgr, 
00619                          txc_sentinel_list_t **sentinel_list)
00620 {
00621         txc_result_t result;
00622 
00623         if ((*sentinel_list = (txc_sentinel_list_t *) MALLOC(sizeof(txc_sentinel_list_t)))
00624             == NULL) 
00625         {
00626                 return TXC_R_NOMEMORY;
00627         }
00628 
00629         (*sentinel_list)->manager = sentinelmgr;
00630         (*sentinel_list)->num_entries = 0;
00631         (*sentinel_list)->size = TXC_SENTINEL_LIST_SIZE;
00632 
00633         if ((result = allocate_sentinel_list_entries(*sentinel_list, 0)) 
00634             != TXC_R_SUCCESS) 
00635         {
00636                 FREE(*sentinel_list);
00637                 return result;
00638         }
00639 
00640         return TXC_R_SUCCESS;
00641 }
00642 
00650 txc_result_t
00651 txc_sentinel_list_init(txc_sentinel_list_t *sentinel_list)
00652 {
00653         sentinel_list->num_entries = 0;
00654 
00655         return TXC_R_SUCCESS;
00656 }
00657 
00668 txc_result_t
00669 txc_sentinel_list_destroy(txc_sentinel_list_t **sentinel_list) 
00670 {
00671         txc_result_t result;
00672 
00673         if ((result = deallocate_sentinel_list_entries(*sentinel_list))
00674             != TXC_R_SUCCESS)
00675         {
00676                 return result;
00677         }       
00678         FREE(*sentinel_list);
00679         *sentinel_list = NULL;
00680         return TXC_R_SUCCESS;
00681 }
00682 
00683 
00694 static inline 
00695 txc_result_t
00696 enlist_sentinel(txc_sentinel_list_t *sentinel_list, 
00697                 txc_sentinel_t *sentinel, 
00698                 txc_result_t status)
00699 {
00700         txc_result_t ret;
00701 
00702         if (sentinel_list->num_entries == sentinel_list->size) {
00703                 if ((ret = allocate_sentinel_list_entries(sentinel_list, 1)) 
00704                     != TXC_R_SUCCESS) 
00705                 {
00706                         return ret;
00707                 }       
00708         }
00709 
00710         sentinel_list->entries[sentinel_list->num_entries].sentinel = sentinel;
00711         sentinel_list->entries[sentinel_list->num_entries].status = status;
00712         sentinel_list->num_entries++; 
00713 
00714         return TXC_R_SUCCESS;
00715 }
00716 
00717 
00729 txc_result_t 
00730 txc_sentinel_enlist(txc_tx_t *txd, txc_sentinel_t *sentinel, int flags) 
00731 {
00732         int acquire_on_retry;
00733 
00734         acquire_on_retry = (flags & TXC_SENTINEL_ACQUIREONRETRY) > 0 ? 
00735                            TXC_SENTINEL_ACQUIREONRETRY : 0;
00736 
00737         TXC_MUTEX_LOCK(&sentinel->synch_mutex);
00738         sentinel_attach(sentinel);
00739         TXC_MUTEX_UNLOCK(&sentinel->synch_mutex);
00740         enlist_sentinel(txd->sentinel_list, sentinel, acquire_on_retry);
00741         return TXC_R_SUCCESS;
00742 }
00743 
00744 
00758 txc_result_t 
00759 txc_sentinel_tryacquire(txc_tx_t *txd, txc_sentinel_t *sentinel, int flags) 
00760 {
00761         int          ret;
00762         int          num_spin_retries;
00763         int          acquire_on_retry;
00764         txc_result_t result;
00765 
00766         TXC_ASSERT(sentinel != NULL);
00767         TXC_ASSERT(txd != NULL);
00768         acquire_on_retry = (flags & TXC_SENTINEL_ACQUIREONRETRY) > 0 ? 
00769                            TXC_SENTINEL_ACQUIREONRETRY : 0;
00770 
00771 
00772         if (sentinel->owner != txd) {
00773                 switch (txc_tx_get_xactstate(txd)) {
00774                         case TXC_XACTSTATE_NONTRANSACTIONAL:
00775                                 TXC_INTERNALERROR("Acquiring a sentinel outside of a transaction not supported\n");
00776                                 /* never gets here */
00777                         case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00778                                 /* 
00779                                  * Do not need to acquire any sentinels. 
00780                                  * Irrevocable global lock already provides atomicity & isolation. 
00781                                  */
00782                                 result = TXC_R_SUCCESS;
00783                                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00784                                                 "ACQUIRE SENTINEL %3d: SUCCESS (GLOCK)\n",
00785                                                 sentinel->id);
00786                                 break;
00787                         case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00788                                 register_sentinelmgr_undo_action(txd);
00789                                 register_sentinelmgr_commit_action(txd);
00790                                 num_spin_retries = txc_runtime_settings.sentinel_max_spin_retries;
00791                                 do {
00792                                         ret = TXC_MUTEX_TRYLOCK(&sentinel->sentinel_mutex);
00793                                 } while (--num_spin_retries >= 0 && ret != 0);
00794                                 if (ret == 0) {
00795                                         TXC_MUTEX_LOCK(&sentinel->synch_mutex);
00796                                         sentinel_attach(sentinel);
00797                                         TXC_MUTEX_UNLOCK(&sentinel->synch_mutex);
00798                                         sentinel->owner = txd;
00799                                         enlist_sentinel(txd->sentinel_list, sentinel, 
00800                                                         TXC_SENTINEL_ACQUIRED | 
00801                                                         acquire_on_retry);
00802                                         TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00803                                                         "ACQUIRE SENTINEL %3d: SUCCESS\n",
00804                                                         sentinel->id);
00805                                         result = TXC_R_SUCCESS;
00806                                 } else {
00807                                         TXC_MUTEX_LOCK(&sentinel->synch_mutex);
00808                                         sentinel_attach(sentinel);
00809                                         TXC_MUTEX_UNLOCK(&sentinel->synch_mutex);
00810                                         enlist_sentinel(txd->sentinel_list, sentinel, 
00811                                                         acquire_on_retry);
00812                                         TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00813                                                         "ACQUIRE SENTINEL %3d: BUSY\n",
00814                                                         sentinel->id);
00815                                         result = TXC_R_BUSYSENTINEL;
00816                                 }
00817                                 break;
00818                         default:
00819                                 TXC_INTERNALERROR("Unknown transaction state\n");
00820                 }
00821         } else {
00822 #ifdef _TXC_DEBUG_BUILD
00823                 TXC_ASSERT(txc_sentinel_owner(sentinel) == txd);
00824                 TXC_ASSERT(txc_sentinel_is_enlisted(txd, sentinel) == TXC_R_SUCCESS);
00825                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00826                                 "ACQUIRE SENTINEL %3d: SUCCESS (HAVE IT)\n",
00827                                 sentinel->id);  
00828 #endif                                                                                                  
00829         }
00830         return result;
00831 }
00832 
00833 
00834 static inline
00835 void
00836 backoff(txc_tx_t *txd)
00837 {
00838         useconds_t wait_time;
00839 
00840         if (txc_runtime_settings.sentinel_max_backoff_time>0) {
00841                 wait_time = (useconds_t) txc_tx_get_forced_retries(txd) * 32;
00842                 if (wait_time < txc_runtime_settings.sentinel_max_backoff_time) {
00843                         usleep(wait_time);
00844                 } else {
00845                         usleep(txc_runtime_settings.sentinel_max_backoff_time);
00846                 }
00847         }
00848 }
00849 
00850 
00851 /*
00852  ****************************************************************************
00853  ***                      DEBUGGING SUPPORT ROUTINES                      ***
00854  ****************************************************************************
00855  */
00856 
00857 
00858 static inline
00859 void
00860 sentinel_print(void *addr)
00861 {
00862         txc_sentinel_t *sentinel = (txc_sentinel_t *) addr;
00863 
00864         fprintf(TXC_DEBUG_OUT, "SENTINEL %3d: owner = %p (TID = %u)\n", 
00865                 sentinel->id, 
00866                 sentinel->owner,
00867                 sentinel->owner->tid);
00868 
00869 }
00870 
00871 static inline
00872 void
00873 sentinel_list_print(txc_sentinel_list_t *sentinel_list, char *heading)
00874 {
00875         int                       i;
00876         txc_sentinel_list_entry_t *entry;
00877         txc_sentinel_t            *sentinel;
00878 
00879         if (TXC_DEBUG_SENTINEL) {
00880                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, "%s\n", heading);
00881                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, "====================================\n");
00882                 for (i=0; i<sentinel_list->num_entries; i++) {
00883                         entry = &sentinel_list->entries[i];
00884                         sentinel = entry->sentinel;
00885                         TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, 
00886                                         "SENTINEL %3d: owner = %p (TID = %d) entry_status = %x\n", 
00887                                         sentinel->id, 
00888                                         sentinel->owner,
00889                                         (sentinel->owner == NULL) ? -1 : sentinel->owner->tid,
00890                                         entry->status);
00891                 }
00892         }
00893 }
00894 
00895 
00896 void 
00897 txc_sentinelmgr_print_pools(txc_sentinelmgr_t *sentinelmgr) {
00898         if (TXC_DEBUG_SENTINEL) {
00899                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, "SENTINEL POOL\n");
00900                 TXC_DEBUG_PRINT(TXC_DEBUG_SENTINEL, "====================================\n");
00901                 txc_pool_print(sentinelmgr->pool_sentinel, sentinel_print, 0);
00902         }
00903 }
00904 
00905 
00906 txc_tx_t * 
00907 txc_sentinel_owner(txc_sentinel_t *sentinel)
00908 {
00909         return sentinel->owner;
00910 }
00911 
00912 
00913 txc_result_t 
00914 txc_sentinel_is_enlisted(txc_tx_t *txd, txc_sentinel_t *sentinel)
00915 {
00916         int            i;
00917         txc_sentinel_t *sentinel_iter;
00918 
00919         /* 
00920          * Sentinel must be found in the list of acquired sentinels and the
00921          * sentinel's owner field be the descriptor txd.
00922          */
00923         for (i=0; i<txd->sentinel_list->num_entries; i++) {
00924                 sentinel_iter = txd->sentinel_list->entries[i].sentinel;
00925                 if (sentinel_iter == sentinel) {
00926                         return TXC_R_SUCCESS;
00927                 }
00928         }
00929         return TXC_R_FAILURE;
00930 }

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7