usermode/library/mcore/src/log/phlog_tornbit.c

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 
00041 /* System header files */
00042 #include <stdio.h>
00043 #include <stdint.h>
00044 #include <stdlib.h>
00045 /* Mnemosyne common header files */
00046 #include <result.h>
00047 #include "phlog_tornbit.h"
00048 #include "hal/pcm_i.h"
00049 #include <smmintrin.h>
00050 
00051 
00052 uint64_t load_nt_word(void *addr)
00053 {
00054         union {
00055                 __m128i x;
00056                 char b[16];
00057         } u;
00058 
00059         uintptr_t aladdr;
00060         uintptr_t offset;
00061 
00062         aladdr = ((uintptr_t) addr) & ~0xF;
00063         offset = ((uintptr_t) addr) & 0xF;
00064 
00065         u.x = _mm_stream_load_si128((__m128i *) aladdr);
00066 
00067         return *((uint64_t *) &u.b[offset]);
00068 }       
00069 
00070 
00071 
00076 m_result_t
00077 m_phlog_tornbit_check_consistency(m_phlog_tornbit_nvmd_t *nvmd, 
00078                                   pcm_word_t *nvphlog,
00079                                   uint64_t *stable_tail)
00080 {
00081         uint64_t          head_index;
00082         uint64_t          i;
00083         uint64_t          tornbit;
00084         uint64_t          valid_tornbit;
00085         int               flip_tornbit = 0;
00086 
00087         valid_tornbit = LF_TORNBIT & nvmd->flags;
00088         i = head_index = nvmd->flags & LF_HEAD_MASK;
00089         while(1) {
00090                 tornbit = (TORN_MASK & nvphlog[i]);
00091                 if (tornbit != valid_tornbit) {
00092                         *stable_tail = i;
00093                         break;
00094                 }
00095                 i = (i + 1) & (PHYSICAL_LOG_NUM_ENTRIES - 1);
00096                 if (i==0) {
00097                         flip_tornbit = 1;
00098                         valid_tornbit = TORN_MASK & ~valid_tornbit;
00099                 }
00100                 if (i==head_index) {
00101                         break;
00102                 }
00103         }
00104 
00105         return M_R_SUCCESS;
00106 }
00107 
00108 
00109 static
00110 m_result_t
00111 tornbit_format_nvlog (pcm_storeset_t *set,
00112                       uint32_t head_index, 
00113                       uint64_t tornbit, 
00114                       m_phlog_tornbit_nvmd_t *nvmd, 
00115                       pcm_word_t *nvphlog)
00116 {
00117         int i;
00118 
00119         PCM_NT_STORE(set, (volatile pcm_word_t *) &nvmd->flags, head_index | tornbit);
00120         for (i=0; i<PHYSICAL_LOG_NUM_ENTRIES; i++) {
00121                 if (i<head_index) {
00122                         if ((nvphlog[i] & TORN_MASK) != tornbit) {
00123                                 PCM_NT_STORE(set, (volatile pcm_word_t *) &nvphlog[i], tornbit);
00124                         }       
00125                 } else {
00126                         if ((nvphlog[i] & TORN_MASK) == tornbit) {
00127                                 PCM_NT_STORE(set, (volatile pcm_word_t *) &nvphlog[i], ~tornbit & TORN_MASK);
00128                         }       
00129                 }
00130         }
00131         PCM_NT_FLUSH(set);
00132         
00133         return M_R_SUCCESS;
00134 }
00135 
00136 
00140 m_result_t
00141 m_phlog_tornbit_format (pcm_storeset_t *set, 
00142                         m_phlog_tornbit_nvmd_t *nvmd, 
00143                         pcm_word_t *nvphlog, 
00144                         int type)
00145 {
00146         m_result_t             rv = M_R_FAILURE;
00147         
00148         if ((nvmd->generic_flags & LF_TYPE_MASK) == type) {
00149                 /* 
00150                  * TODO: Optimization: check consistency and perform a quick format 
00151                  * instead.
00152                  */
00153                 rv = tornbit_format_nvlog (set, 0, TORNBIT_ONE, nvmd, nvphlog);
00154                 if (rv != M_R_SUCCESS) {
00155                         goto out;
00156                 }
00157         } else {
00158                 rv = tornbit_format_nvlog (set, 0, TORNBIT_ONE, nvmd, nvphlog);
00159                 if (rv != M_R_SUCCESS) {
00160                         goto out;
00161                 }
00162         }
00163         rv = M_R_SUCCESS;
00164 out:
00165         return rv;
00166 }
00167 
00168 
00172 m_result_t
00173 m_phlog_tornbit_alloc (m_phlog_tornbit_t **phlog_tornbitp)
00174 {
00175         m_phlog_tornbit_t      *phlog_tornbit;
00176 
00177         if (posix_memalign((void **) &phlog_tornbit, sizeof(uint64_t),sizeof(m_phlog_tornbit_t)) != 0) 
00178         {
00179                 return M_R_FAILURE;
00180         }
00181         *phlog_tornbitp = phlog_tornbit;
00182 
00183         return M_R_SUCCESS;
00184 }
00185 
00186 
00191 m_result_t
00192 m_phlog_tornbit_init (m_phlog_tornbit_t *phlog, 
00193                       m_phlog_tornbit_nvmd_t *nvmd,
00194                       pcm_word_t *nvphlog)                                        
00195 {
00196         pcm_word_t             tornbit;
00197 
00198         phlog->nvmd = nvmd;
00199         phlog->nvphlog = nvphlog;
00200         tornbit = LF_TORNBIT & phlog->nvmd->flags;
00201         phlog->tornbit = tornbit;
00202         phlog->buffer_count = 0;
00203         phlog->write_remainder = 0x0;
00204         phlog->write_remainder_nbits = 0;
00205         phlog->read_remainder = 0x0;
00206         phlog->read_remainder_nbits = 0;
00207         phlog->head = phlog->tail = phlog->stable_tail = phlog->read_index = phlog->nvmd->flags & LF_HEAD_MASK;
00208 
00209         /* initialize statistics */
00210         phlog->stat_wait_for_trunc = 0;
00211         phlog->stat_wait_time_for_trunc = 0;
00212         return M_R_SUCCESS;
00213 }
00214 
00215 
00219 m_result_t
00220 m_phlog_tornbit_truncate_async(pcm_storeset_t *set, m_phlog_tornbit_t *phlog) 
00221 {
00222         pcm_word_t        tornbit;
00223 
00224         tornbit = LF_TORNBIT & phlog->nvmd->flags;
00225         /*
00226          * If head is larger than the current read_index point, then the assignment
00227          * of read_index to the head will cause head to wrap around, thus the 
00228          * torn bit stored in the non-volatile metadata is flipped.
00229          */
00230         if (phlog->head > phlog->read_index) {
00231                 tornbit = ~tornbit & TORN_MASK;
00232         }
00233 
00234         phlog->head = phlog->read_index;
00235 
00236         //FIXME: do we need a flush? PCM_NT_FLUSH(set);
00237         PCM_NT_STORE(set, (volatile pcm_word_t *) &phlog->nvmd->flags, (pcm_word_t) (phlog->head | tornbit));
00238         PCM_NT_FLUSH(set);
00239         
00240         return M_R_SUCCESS;
00241 }
00242 
00243 
00244 void m_phlog_print_buffer(m_phlog_tornbit_t *log)
00245 {
00246         int i;
00247         for (i=0; i<log->buffer_count; i++) {
00248                 printf("buffer[%d] = %lX (", i, log->buffer[i]);
00249                 print_binary64(log->buffer[i]);
00250                 printf(")\n");
00251         }
00252 }

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