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 
00054 
00055 
00056 #include "mtm_i.h"
00057 #include "useraction.h"
00058 #include "mode/pwb-common/pwb_i.h"
00059 #include "mode/common/rwset.h"
00060 #include "cm.h" 
00061 
00062 
00063 
00064 
00065 static inline 
00066 bool
00067 pwb_trycommit (mtm_tx_t *tx, int enable_isolation)
00068 {
00069         assert((tx->mode == MTM_MODE_pwbnl && !enable_isolation) || 
00070                (tx->mode == MTM_MODE_pwbetl && enable_isolation));
00071 
00072         mode_data_t *modedata = (mode_data_t *) tx->modedata[tx->mode];
00073         w_entry_t   *w;
00074         mtm_word_t  t;
00075         int         i;
00076 #ifdef READ_LOCKED_DATA
00077         mtm_word_t  id;
00078 #endif 
00079 
00080         PRINT_DEBUG("==> mtm_commit(%p[%lu-%lu] nest_level:%d-->%d)\n", tx, 
00081                     (unsigned long)modedata->start, (unsigned long)modedata->end, tx->nesting, tx->nesting-1);
00082 
00083         
00084         assert(tx->status == TX_ACTIVE);
00085 
00086         
00087         if (--tx->nesting > 0) {
00088                 return true;
00089         }       
00090 
00091         if (modedata->w_set.nb_entries > 0) {
00092                 
00093 
00094                 
00095                 t = FETCH_INC_CLOCK + 1;
00096                 if (t >= VERSION_MAX) {
00097 #ifdef ROLLOVER_CLOCK
00098                         
00099 #ifdef _M_STATS_BUILD
00100                         m_stats_statset_increment(mtm_statsmgr, tx->statset, XACT, aborts, 1);
00101 #endif                                  
00102 # ifdef INTERNAL_STATS
00103                         tx->aborts_rollover++;
00104 # endif 
00105                         return false;
00106 #else 
00107                         fprintf(stderr, "Exceeded maximum version number: 0x%lx\n", (unsigned long)t);
00108                         exit(1);
00109 #endif 
00110                 }
00111 
00112                 
00113                 if (enable_isolation) {
00114                         if (modedata->start != t - 1 && !mtm_validate(tx, modedata)) {
00115                                 
00116                                 
00117                                 cm_visible_read(tx);
00118 #ifdef _M_STATS_BUILD
00119                                 m_stats_statset_increment(mtm_statsmgr, tx->statset, XACT, aborts, 1);
00120 #endif                                  
00121 #ifdef INTERNAL_STATS
00122                                 tx->aborts_validate_commit++;
00123 #endif 
00124                                 return false;
00125                         }
00126                 }
00127 
00128 # ifdef READ_LOCKED_DATA
00129                 
00130                 id = tx->id;
00131                 assert(id % 2 == 0);
00132                 ATOMIC_STORE_REL(&tx->id, id + 1);
00133 # endif 
00134 
00135                 
00136                 M_TMLOG_COMMIT(tx->pcm_storeset, modedata->ptmlog, t);
00137 
00138                 
00139                 PCM_WB_FENCE(tx->pcm_storeset);
00140 
00141                 
00142                 
00143 
00144                 w = modedata->w_set.entries;
00145                 int wbflush_cnt=0;
00146                 for (i = modedata->w_set.nb_entries; i > 0; i--, w++) {
00147                         MTM_DEBUG_PRINT("==> write(t=%p[%lu-%lu],a=%p,d=%p-%d,m=%llx,v=%d)\n", tx,
00148                                         (unsigned long)modedata->start, (unsigned long)modedata->end,
00149                                         w->addr, (void *)w->value, (int)w->value, (unsigned long long) w->mask, (int)w->version);
00150                         
00151                         if (w->mask != 0) {
00152                                 PCM_WB_STORE_ALIGNED_MASKED(tx->pcm_storeset, w->addr, w->value, w->mask);
00153                         }       
00154 # ifdef SYNC_TRUNCATION
00155                         
00156                         if (w->next_cache_neighbor == NULL) {
00157                                 
00158 
00159 
00160 
00161 
00162 
00163                                 if (enable_isolation) {
00164                                         if (((uintptr_t) w->addr >= PSEGMENT_RESERVED_REGION_START &&
00165                                                  (uintptr_t) w->addr < (PSEGMENT_RESERVED_REGION_START + PSEGMENT_RESERVED_REGION_SIZE)))
00166                                         {
00167                                                 
00168                                                 PCM_WB_FLUSH(tx->pcm_storeset, w->addr);
00169                                                 wbflush_cnt++;
00170                                         }
00171                                 } else {
00172                                         PCM_WB_FLUSH(tx->pcm_storeset, w->addr);
00173                                         wbflush_cnt++;
00174                                 }
00175                         }       
00176 # endif
00177                         
00178                         if (w->next == NULL) {
00179                                 ATOMIC_STORE_REL(w->lock, LOCK_SET_TIMESTAMP(t));
00180                         }       
00181                 }
00182                 
00183 #ifdef _M_STATS_BUILD
00184                 m_stats_statset_increment(mtm_statsmgr, tx->statset, XACT, wbflush, wbflush_cnt);
00185 #endif          
00186                 
00187                 
00188 # ifdef READ_LOCKED_DATA
00189                 
00190                 ATOMIC_STORE_REL(&tx->id, id + 2);
00191 # endif 
00192 
00193 # ifdef SYNC_TRUNCATION
00194                         M_TMLOG_TRUNCATE_SYNC(tx->pcm_storeset, modedata->ptmlog);
00195 # endif
00196         }
00197 
00198 #ifdef _M_STATS_BUILD   
00199         m_stats_threadstat_aggregate(tx->threadstat, tx->statset);
00200         assert(m_stats_statset_destroy(&tx->statset) == M_R_SUCCESS);
00201 #endif  
00202 
00203         cm_reset(tx);
00204         return true;
00205 }
00206 
00207 
00208 
00209 
00210 
00211 static inline 
00212 void 
00213 pwb_rollback(mtm_tx_t *tx)
00214 {
00215         assert(tx->mode == MTM_MODE_pwbnl || MTM_MODE_pwbetl);
00216         mode_data_t   *modedata = (mode_data_t *) tx->modedata[tx->mode];
00217         w_entry_t     *w;
00218         int           i;
00219 #ifdef READ_LOCKED_DATA
00220         mtm_word_t    id;
00221 #endif 
00222 
00223         MTM_DEBUG_PRINT("==> pwb_rollback(%p[%lu-%lu])\n", tx,
00224                         (unsigned long)modedata->start,
00225                         (unsigned long)modedata->end);
00226 
00227         
00228         assert(tx->status == TX_ACTIVE);
00229 
00230         
00231         M_TMLOG_ABORT(tx->pcm_storeset, modedata->ptmlog, 0);
00232 # ifdef SYNC_TRUNCATION
00233         M_TMLOG_TRUNCATE_SYNC(tx->pcm_storeset, modedata->ptmlog);
00234 # endif
00235 
00236         
00237         i = modedata->w_set.nb_entries;
00238         if (i > 0) {
00239 # ifdef READ_LOCKED_DATA
00240                 
00241                 id = tx->id;
00242                 assert(id % 2 == 0);
00243                 ATOMIC_STORE_REL(&tx->id, id + 1);
00244 # endif 
00245                 w = modedata->w_set.entries;
00246                 for (; i > 0; i--, w++) {
00247                         if (w->next == NULL) {
00248                                 
00249                                 ATOMIC_STORE(w->lock, LOCK_SET_TIMESTAMP(w->version));
00250                         }
00251                         PRINT_DEBUG2("==> discard(t=%p[%lu-%lu],a=%p,d=%p-%lu,v=%lu)\n", tx,
00252                                      (unsigned long)modedata->start, 
00253                                      (unsigned long)modedata->end,
00254                                      w->addr, 
00255                                      (void *)w->value, 
00256                                      (unsigned long)w->value,
00257                                      (unsigned long)w->version);
00258                 }
00259                 
00260                 ATOMIC_MB_WRITE;
00261 # ifdef READ_LOCKED_DATA
00262                 
00263                 ATOMIC_STORE_REL(&tx->id, id + 2);
00264 # endif 
00265         }
00266 
00267         tx->retries++;
00268 #ifdef INTERNAL_STATS
00269         tx->aborts++;
00270         if (tx->max_retries < tx->retries) {
00271                 tx->max_retries = tx->retries;
00272         }       
00273 #endif 
00274 
00275         
00276         tx->status = TX_ABORTED;
00277 
00278         
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289         tx->nesting = 0;
00290 
00291 }
00292 
00293 
00294 static void
00295 rollback_transaction (mtm_tx_t *tx)
00296 {
00297         pwb_rollback (tx);
00298         switch (tx->mode) {
00299                 case MTM_MODE_pwbnl:
00300 #if (defined(ALLOW_ABORTS))
00301                         mtm_local_rollback (tx);
00302 #endif
00303                         break;
00304                 case MTM_MODE_pwbetl:
00305                         mtm_local_rollback (tx);
00306                         break;
00307                 default:
00308                         assert(0);
00309         }
00310         mtm_useraction_list_run (tx->undo_action_list, 1);
00311 
00312         
00313         
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 }
00322 
00323 
00324 static inline
00325 void pwb_prepare_transaction(mtm_tx_t *tx)
00326 {
00327         assert(tx->mode == MTM_MODE_pwbnl || MTM_MODE_pwbetl);
00328         mode_data_t *modedata = (mode_data_t *) tx->modedata[tx->mode];
00329 
00330 start:
00331         
00332         modedata->start = modedata->end = GET_CLOCK; 
00333         
00334         tx->can_extend = 1;
00335 #ifdef ROLLOVER_CLOCK
00336         if (modedata->start >= VERSION_MAX) {
00337                 
00338                 mtm_overflow(tx);
00339                 goto start;
00340         }
00341 #endif 
00342         
00343         
00344         
00345 
00346 
00347            
00348         assert(modedata->w_set.reallocate == 0);
00349         
00350         modedata->w_set.nb_entries = 0;
00351         modedata->r_set.nb_entries = 0;
00352         mtm_useraction_clear (tx->commit_action_list);
00353         mtm_useraction_clear (tx->undo_action_list);
00354 
00355         M_TMLOG_BEGIN(modedata->ptmlog);
00356 
00357 #ifdef EPOCH_GC
00358         gc_set_epoch(modedata->start);
00359 #endif 
00360 
00361         tx->nesting = 1;
00362         tx->status = TX_ACTIVE; 
00363                                 
00364                                                       
00365 
00366 }
00367 
00368 static inline
00369 uint32_t
00370 beginTransaction_internal (mtm_tx_t *tx, 
00371                            uint32_t prop, 
00372                            _ITM_srcLocation *srcloc,
00373                            int enable_isolation)
00374 {
00375         assert(tx->mode == MTM_MODE_pwbnl || MTM_MODE_pwbetl);
00376 
00377         MTM_DEBUG_PRINT("==> mtm_pwb_beginTransaction(%p) nest_level: %d-->%d\n", tx,
00378                         tx->nesting, tx->nesting+1);
00379 
00380         
00381         if (tx->nesting++ > 0) {
00382                 return a_runInstrumentedCode | a_saveLiveVariables;
00383         }       
00384 
00385         tx->jb = tx->tmp_jb;
00386         tx->prop = prop;
00387 
00388         
00389         pwb_prepare_transaction(tx);
00390 
00391 #ifdef _M_STATS_BUILD   
00392         assert(m_stats_statset_create(&tx->statset) == M_R_SUCCESS);
00393         assert(m_stats_statset_init(tx->statset, srcloc->psource) == M_R_SUCCESS);
00394 #endif  
00395 
00396         if ((prop & pr_doesGoIrrevocable) || !(prop & pr_instrumentedCode))
00397         {
00398                 
00399                 return (prop & pr_uninstrumentedCode
00400                         ? a_runUninstrumentedCode : a_runInstrumentedCode);
00401         }
00402 
00403         if (enable_isolation) {
00404                 
00405         }
00406 
00407         return a_runInstrumentedCode | a_saveLiveVariables;
00408 }
00409 
00410 
00411 static 
00412 bool
00413 trycommit_transaction (mtm_tx_t *tx, int enable_isolation)
00414 {
00415         if (pwb_trycommit(tx, enable_isolation)) {
00416                 if (tx->nesting > 0) {
00417                         return true;
00418                 }
00419                 switch (tx->mode) {
00420                         case MTM_MODE_pwbnl:
00421 #if (defined(ALLOW_ABORTS))
00422                                 mtm_local_commit (tx);
00423 #endif
00424                                 break;
00425                         case MTM_MODE_pwbetl:
00426                                 mtm_local_commit (tx);
00427                                 break;
00428                         default:
00429                                 assert(0);
00430                 }
00431 
00432                 mtm_useraction_list_run (tx->commit_action_list, 0);
00433 
00434                 
00435                 tx->status = TX_COMMITTED;
00436                 return true;
00437         }
00438         return false;
00439 }