usermode/library/mtm/src/mode/common/rwset.h

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2011 Computer Sciences Department, 
00003     University of Wisconsin -- Madison
00004 
00005     ----------------------------------------------------------------------
00006 
00007     This file is part of Mnemosyne: Lightweight Persistent Memory, 
00008     originally developed at the University of Wisconsin -- Madison.
00009 
00010     Mnemosyne was originally developed primarily by Haris Volos
00011     with contributions from Andres Jaan Tack.
00012 
00013     ----------------------------------------------------------------------
00014 
00015     Mnemosyne is free software; you can redistribute it and/or
00016     modify it under the terms of the GNU General Public License
00017     as published by the Free Software Foundation, version 2
00018     of the License.
00019  
00020     Mnemosyne is distributed in the hope that it will be useful,
00021     but WITHOUT ANY WARRANTY; without even the implied warranty of
00022     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023     GNU General Public License for more details.
00024 
00025     You should have received a copy of the GNU General Public License
00026     along with this program; if not, write to the Free Software
00027     Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00028     Boston, MA  02110-1301, USA.
00029 
00030 ### END HEADER ###
00031 */
00032 
00040 /*
00041  * Source code is partially derived from TinySTM (license is attached)
00042  *
00043  *
00044  * Author(s):
00045  *   Pascal Felber <pascal.felber@unine.ch>
00046  * Description:
00047  *   STM functions.
00048  *
00049  * Copyright (c) 2007-2009.
00050  *
00051  * This program is free software; you can redistribute it and/or
00052  * modify it under the terms of the GNU General Public License
00053  * as published by the Free Software Foundation, version 2
00054  * of the License.
00055  *
00056  * This program is distributed in the hope that it will be useful,
00057  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00058  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00059  * GNU General Public License for more details.
00060  */
00061 
00062 #ifndef _RWSET_H
00063 #define _RWSET_H
00064 
00065 /*
00066  * Check if stripe has been read previously.
00067  */
00068 static inline 
00069 r_entry_t *
00070 mtm_has_read(mtm_tx_t *tx, mode_data_t *modedata, volatile mtm_word_t *lock)
00071 {
00072         r_entry_t   *r;
00073         int         i;
00074 
00075         PRINT_DEBUG("==> mtm_has_read(%p[%lu-%lu],%p)\n", tx, 
00076                     (unsigned long)modedata->start, (unsigned long)modedata->end, lock);
00077 
00078         /* Check status */
00079         assert(tx->status == TX_ACTIVE);
00080 
00081         /* Look for read */
00082         r = modedata->r_set.entries;
00083         for (i = modedata->r_set.nb_entries; i > 0; i--, r++) {
00084                 if (r->lock == lock) {
00085                         /* Return first match*/
00086                         return r;
00087                 }
00088         }
00089         return NULL;
00090 }
00091 
00092 
00093 /*
00094  * Validate read set (check if all read addresses are still valid now).
00095  */
00096 static inline 
00097 int 
00098 mtm_validate(mtm_tx_t *tx, mode_data_t *modedata)
00099 {
00100         r_entry_t  *r;
00101         int        i;
00102         mtm_word_t l;
00103 
00104         PRINT_DEBUG("==> mtm_validate(%p[%lu-%lu])\n", tx, 
00105                     (unsigned long)modedata->start, (unsigned long)modedata->end);
00106 
00107         /* Check status */
00108         assert(tx->status == TX_ACTIVE);
00109 
00110         /* Validate reads */
00111         r = modedata->r_set.entries;
00112         for (i = modedata->r_set.nb_entries; i > 0; i--, r++) {
00113                 /* Read lock */
00114                 l = ATOMIC_LOAD(r->lock);
00115                 /* Unlocked and still the same version? */
00116                 if (LOCK_GET_OWNED(l)) {
00117                         /* Do we own the lock? */
00118 #if DESIGN == WRITE_THROUGH
00119                         if ((mtm_tx_t *)LOCK_GET_ADDR(l) != tx)
00120 #else /* DESIGN != WRITE_THROUGH */
00121                         w_entry_t *w = (w_entry_t *)LOCK_GET_ADDR(l);
00122                         /* Simply check if address falls inside our write set (avoids non-faulting load) */
00123                         if (!(modedata->w_set.entries <= w && 
00124                             w < modedata->w_set.entries + modedata->w_set.nb_entries))
00125 #endif /* DESIGN != WRITE_THROUGH */
00126                         {
00127                                 /* Locked by another transaction: cannot validate */
00128                                 return 0;
00129                         }
00130                         /* We own the lock: OK */
00131                 } else {
00132                         if (LOCK_GET_TIMESTAMP(l) != r->version) {
00133                                 /* Other version: cannot validate */
00134                                 return 0;
00135                         }
00136                         /* Same version: OK */
00137                 }
00138         }
00139         return 1;
00140 }
00141 
00142 
00143 /*
00144  * (Re)allocate read set entries.
00145  */
00146 static inline 
00147 void 
00148 mtm_allocate_rs_entries(mtm_tx_t *tx, mode_data_t *data, int extend)
00149 {
00150         if (extend) {
00151                 /* Extend read set */
00152                 data->r_set.size *= 2;
00153                 PRINT_DEBUG2("==> reallocate read set (%p[%lu-%lu],%d)\n", tx, 
00154                              (unsigned long)data->start, 
00155                              (unsigned long)data->end, 
00156                              data->r_set.size);
00157                 if ((data->r_set.entries = 
00158                      (r_entry_t *)realloc(data->r_set.entries, 
00159                                           data->r_set.size * sizeof(r_entry_t))) == NULL) 
00160                 {
00161                         perror("realloc");
00162                         exit(1);
00163                 }
00164         } else {
00165                 /* Allocate read set */
00166                 if ((data->r_set.entries = 
00167                      (r_entry_t *)malloc(data->r_set.size * sizeof(r_entry_t))) == NULL) 
00168                 {
00169                         perror("malloc");
00170                         exit(1);
00171                 }
00172         }
00173 }
00174 
00175 
00176 /*
00177  * (Re)allocate write set entries.
00178  */
00179 static inline 
00180 void 
00181 mtm_allocate_ws_entries(mtm_tx_t *tx, mode_data_t *data, int extend)
00182 {
00183 #if defined(READ_LOCKED_DATA) || defined(CONFLICT_TRACKING)
00184         int i;
00185         int first = (extend ? data->w_set.size : 0);
00186 #endif /* defined(READ_LOCKED_DATA) || defined(CONFLICT_TRACKING) */
00187 
00188         if (extend) {
00189                 /* Extend write set */
00190                 data->w_set.size *= 2;
00191                 PRINT_DEBUG("==> reallocate write set (%p[%lu-%lu],%d)\n", tx, 
00192                             (unsigned long)data->start, (unsigned long)data->end, data->w_set.size);
00193                 if ((data->w_set.entries = 
00194                      (w_entry_t *)realloc(data->w_set.entries, 
00195                                           data->w_set.size * sizeof(w_entry_t))) == NULL) 
00196                 {
00197                         perror("realloc");
00198                         exit(1);
00199                 }
00200         } else {
00201                 /* Allocate write set */
00202 #if ALIGNMENT == 1 /* no alignment requirement */
00203                 if ((data->w_set.entries = 
00204                      (w_entry_t *)malloc(data->w_set.size * sizeof(w_entry_t))) == NULL)
00205                 {
00206                         perror("malloc");
00207                         exit(1);
00208                 }
00209 #else
00210                 if (posix_memalign((void **)&data->w_set.entries, 
00211                                    ALIGNMENT, 
00212                                    data->w_set.size * sizeof(w_entry_t)) != 0) 
00213                 {
00214                         fprintf(stderr, "Error: cannot allocate aligned memory\n");
00215                         exit(1);
00216                 }
00217 #endif
00218         }
00219 
00220 #if defined(READ_LOCKED_DATA) || defined(CONFLICT_TRACKING)
00221         /* Initialize fields */
00222         for (i = first; i < data->w_set.size; i++) {
00223                 data->w_set.entries[i].tx = tx;
00224         }       
00225 #endif /* defined(READ_LOCKED_DATA) || defined(CONFLICT_TRACKING) */
00226 }
00227 
00228 #endif

Generated on Sat Apr 23 11:43:36 2011 for Mnemosyne by  doxygen 1.4.7