usermode/library/mtm/src/local.c

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 
00033 #include <mtm_i.h>
00034 
00035 #define LOCAL_LOG_SIZE (256*1024)
00036 
00037 struct mtm_local_undo_entry_s {
00038   void   *addr;
00039   size_t len;
00040   char   *saved;
00041 };
00042 
00043 /*
00044  * Layout of the local undo log
00045  *
00046  *
00047  *  +------------+
00048  *  |            | <--+  <--   local_undo->buf
00049  *  |            |    |
00050  *  |            |    |
00051  *  |            |    |
00052  *  |            |    |
00053  *  +------------+    |   _
00054  *  |   addr     |    |    |  
00055  *  |   len      |    |     >  mtm_local_undo_entry_t
00056  *  |   saved    | ---+   _|
00057  *  +------------+        
00058  *  |            | <--+
00059  *  |            |    |
00060  *  |            |    |
00061  *  +------------+    |
00062  *  |   addr     |    |  <--   local_undo->last_entry
00063  *  |   len      |    |
00064  *  |   saved    | ---+
00065  *  +------------+
00066  *
00067  *
00068  * Rollback proceeds backwards first starting at local_undo->last_entry then 
00069  * finding the previous mtm_local_undo_entry_t by doing arithmetic on saved 
00070  * and len.
00071  */
00072 
00073 static void
00074 local_allocate (mtm_tx_t *tx, int extend)
00075 {
00076         mtm_local_undo_t *local_undo = &tx->local_undo;
00077 
00078         if (extend) {
00079                 /* Extend read set */
00080                 local_undo->size *= 2;
00081                 PRINT_DEBUG2("==> reallocate read set (%p[%lu-%lu],%d)\n", tx, 
00082                              (unsigned long)data->start, 
00083                              (unsigned long)data->end, 
00084                              data->r_set.size);
00085                 if ((local_undo->buf = 
00086                      (char *)realloc((void*) local_undo->buf, 
00087                                      local_undo->size)) == NULL) 
00088                 {
00089                         perror("realloc");
00090                         exit(1);
00091                 }
00092         } else {
00093                 if ((local_undo->buf = 
00094                      (char *)malloc(local_undo->size)) == NULL) 
00095                 {
00096                         perror("malloc");
00097                         exit(1);
00098                 }
00099         }
00100 }
00101 
00102 
00103 void
00104 mtm_local_init(mtm_tx_t *tx)
00105 {
00106         mtm_local_undo_t *local_undo = &tx->local_undo;
00107 
00108         local_undo->size = LOCAL_LOG_SIZE;
00109         local_undo->last_entry = NULL;
00110         local_undo->n = 0;
00111         local_allocate(tx, 0);
00112 }
00113 
00114 
00115 void
00116 mtm_local_commit (mtm_tx_t *tx)
00117 {
00118         mtm_local_undo_t *local_undo = &tx->local_undo;
00119 
00120         local_undo->last_entry = NULL;
00121         local_undo->n = 0;
00122 }
00123 
00124 
00125 void
00126 mtm_local_rollback (mtm_tx_t *tx)
00127 {
00128         mtm_local_undo_t       *local_undo = &tx->local_undo;
00129         mtm_local_undo_entry_t *local_undo_entry;
00130         char                   *buf;
00131         uintptr_t              entryp;
00132         void                   *addr;
00133     uintptr_t              *sp = (uintptr_t *) tx->jb.sp;
00134     uintptr_t              *current_sp = get_stack_pointer();
00135  
00136         local_undo_entry = local_undo->last_entry;
00137         while(local_undo_entry) {
00138                 /* 
00139                  * Make sure I don't corrupt the stack I am operating on. 
00140                  * See Wang et al [CGO'07] for more information. 
00141                  */
00142                 addr = local_undo_entry->addr;
00143                 if (sp+1 < (uintptr_t*) addr || ((uintptr_t*) addr) <= current_sp) {
00144                         memcpy (addr, local_undo_entry->saved, local_undo_entry->len);
00145                 }
00146                 /* Get next local_undo_entry */
00147                 entryp = (uintptr_t) local_undo_entry - local_undo_entry->len - sizeof(mtm_local_undo_entry_t);
00148                 if (entryp > (uintptr_t) local_undo->buf) {
00149                         local_undo_entry = (mtm_local_undo_entry_t *) entryp;
00150                 } else {
00151                         local_undo_entry = NULL;
00152                 }
00153         }
00154 }
00155 
00156 
00157 static
00158 void _ITM_CALL_CONVENTION
00159 log_arbitrarily (mtm_tx_t *tx, const volatile void *ptr, size_t len)
00160 {
00161         mtm_local_undo_t       *local_undo = &tx->local_undo;
00162         mtm_local_undo_entry_t *local_undo_entry;
00163         char                   *buf;
00164 
00165         if ((local_undo->n + len + sizeof(mtm_local_undo_entry_t)) > local_undo->size) {
00166                 local_allocate(tx, 1);  
00167         }
00168         
00169         buf = &local_undo->buf[local_undo->n];
00170         local_undo_entry = (mtm_local_undo_entry_t *) &local_undo->buf[local_undo->n + len];
00171         local_undo->n += (len + sizeof(mtm_local_undo_entry_t));
00172         local_undo_entry->addr = (void*) ptr;
00173         local_undo_entry->len = len;
00174         local_undo_entry->saved = buf;
00175 
00176         memcpy (local_undo_entry->saved, (const void*) ptr, len);
00177 
00178         local_undo->last_entry = local_undo_entry;
00179 }
00180 
00181 
00182 # define DEFINE_LOG_BARRIER(name, type, encoding)                                \
00183 void _ITM_CALL_CONVENTION mtm_##name##L##encoding (mtm_tx_t *tx, const type *ptr)\
00184 { log_arbitrarily (TXARGS ptr, sizeof (type)); }
00185 
00186 
00187 FOR_ALL_TYPES(DEFINE_LOG_BARRIER, local_)
00188 
00189 void _ITM_CALL_CONVENTION 
00190 mtm_local_LB (mtm_tx_t *tx, const void *ptr, size_t len)
00191 { 
00192         log_arbitrarily (TXARGS ptr, len); 
00193 }

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