usermode/library/pmalloc/src/persistentsuperblock.h

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 #ifndef _PERSISTENTSUPERBLOCK_H
00034 #define _PERSISTENTSUPERBLOCK_H
00035 
00036 #include "config.h"
00037 
00038 #include <iostream>
00039 #include <stdint.h>
00040 #include <assert.h>
00041 #include <pcm.h>
00042 #include "hoardheap.h"
00043 
00044 class superblock; // forward declaration
00045 
00046 #if 0
00047 # define __BITMAP_ZERO(bitsetp) \
00048   do {                                                                        \
00049     unsigned int __i;                                                         \
00050     bitmap_t *__arr = (bitsetp);                                              \
00051     for (__i = 0; __i < sizeof (bitmap_t) / sizeof (__bitmap_mask); ++__i)      \
00052       __arr->__bits[__i] = 0;                                                 \
00053   } while (0)
00054 #endif
00055 
00056 
00057 /* Basic access macros for bitmaps.  */
00058 # define __BITMAPELT(bit)       ((bit) / BITMAP_ARRAY_ENTRY_SIZE_BITS)
00059 # define __BITMAPMASK(bit)      ((uint64_t) 1 << ((bit) % BITMAP_ARRAY_ENTRY_SIZE_BITS))
00060 # define __BITMAP_SET(set, bit, bitmap)                               \
00061   PCM_NT_STORE(set, &bitmap[__BITMAPELT (bit)],                       \
00062                bitmap[__BITMAPELT (bit)] | __BITMAPMASK (bit));
00063 # define __BITMAP_CLR(set, bit, bitmap)                               \
00064   PCM_NT_STORE(set, &bitmap[__BITMAPELT (bit)],                       \
00065                bitmap[__BITMAPELT (bit)] & ~__BITMAPMASK (bit));
00066 # define __BITMAP_ISSET(bit, bitmap) \
00067   ((bitmap[__BITMAPELT (bit)] & __BITMAPMASK (bit)) != 0)
00068 
00069 
00070 
00071 # define __BITMAP_CLR2(bit, bitmap)                                              \
00072   bitmap[__BITMAPELT (bit)] = bitmap[__BITMAPELT (bit)] & ~__BITMAPMASK (bit);
00073 # define __BITMAP_SET2(bit, bitmap)                                              \
00074   bitmap[__BITMAPELT (bit)] = bitmap[__BITMAPELT (bit)] | __BITMAPMASK (bit);
00075 
00076 class persistentSuperblock {
00077 
00078 public:
00079         enum { PERSISTENTSUPERBLOCK_SIZE = SUPERBLOCK_SIZE  };
00080         enum { PERSISTENTBLOCK_MIN_SIZE = 8  };
00081         enum { PERSISTENTBLOCK_MAX_SIZE = 8192  };
00082         enum { BITMAP_SIZE = PERSISTENTSUPERBLOCK_SIZE / PERSISTENTBLOCK_MIN_SIZE  };
00083         enum { BITMAP_ARRAY_ENTRY_SIZE_BITS = 8 * sizeof(uint64_t)  };
00084         enum { BITMAP_ARRAY_ENTRY_MASK = -1  };
00085         enum { BITMAP_ARRAY_SIZE = BITMAP_SIZE / BITMAP_ARRAY_ENTRY_SIZE_BITS  };
00086 
00087         persistentSuperblock(char *pregion) {
00088                 int            i;
00089                 pcm_storeset_t *set = pcm_storeset_get();
00090 
00091                 for (i=0; i<BITMAP_ARRAY_SIZE; i++) {
00092                         PCM_NT_STORE(set, &_bitmap[i], 0);
00093                 }
00094                 PCM_NT_STORE(set, (volatile pcm_word_t *) &_pregion, (pcm_word_t) pregion); /* _pregion is a pointer, so it has a size of 64-bit on 64-bit systems */
00095                 //PCM_NT_STORE(set, (volatile pcm_word_t *) &_blksize, (pcm_word_t) PERSISTENTBLOCK_MIN_SIZE);
00096 
00097                 /* FIXME: We currently have an ugly hack:
00098                  * When creating the persistentSuperblocks, we don't want to create them using the smallest
00099                  * possible block size because this would allocate lots of memory to support the free lists
00100                  * in the superblocks. Instead we assume the largest possible block size and when we reformat
00101                  * the superblock we allocate the right amount of memory
00102                  */
00103                 PCM_NT_STORE(set, (volatile pcm_word_t *) &_blksize, (pcm_word_t) PERSISTENTBLOCK_MAX_SIZE);
00104                 PCM_NT_FLUSH(set);
00105         }
00106 
00107         void volatileInit() {
00108                 _cached = false;
00109                 _acquired = false;
00110         }
00111 
00112         bool isAcquired() {
00113                 return _acquired;
00114         }
00115 
00116         void acquire() {
00117                 _acquired = true;
00118         }
00119 
00120         int getFullness() {
00121                 int i;
00122                 int setBits = 0;
00123 
00124                 for (i=0; i<BITMAP_SIZE; i++) {
00125                         if (__BITMAP_ISSET(i, _bitmap)) {
00126                                 setBits++;
00127                         }
00128                 }
00129 
00130                 return (SUPERBLOCK_FULLNESS_GROUP-1) * setBits / BITMAP_SIZE;
00131         }
00132 
00133         void allocBlock(int index) {
00134                 int            bitsPerBlock = _blksize / PERSISTENTBLOCK_MIN_SIZE;
00135                 int            firstBit = index * bitsPerBlock;
00136                 int            i;
00137                 //pcm_storeset_t *set = pcm_storeset_get();
00138 
00139                 for (i=firstBit; i<firstBit+bitsPerBlock; i++) {
00140                         //__BITMAP_SET(set, i, _bitmap);
00141                         __BITMAP_SET2(i, _bitmap);
00142                 }
00143         }
00144 
00145         void freeBlock(int index) {
00146                 int            bitsPerBlock = _blksize / PERSISTENTBLOCK_MIN_SIZE;
00147                 int            firstBit = index * bitsPerBlock;
00148                 int            i;
00149                 //pcm_storeset_t *set = pcm_storeset_get();
00150 
00151                 for (i=firstBit; i<firstBit+bitsPerBlock; i++) {
00152                         //__BITMAP_CLR(set, i, _bitmap);
00153                         __BITMAP_CLR2(i, _bitmap);
00154                 }
00155         }
00156 
00157         bool isBlockFree(int index) {
00158                 int bitsPerBlock = _blksize / PERSISTENTBLOCK_MIN_SIZE;
00159                 int firstBit = index * bitsPerBlock;
00160 
00161                 if (__BITMAP_ISSET(firstBit, _bitmap)) {
00162                         return false;
00163                 }
00164                 return true;
00165         }
00166 
00167 
00168         void * getBlockRegion(int index) {
00169                 return (void *) (_pregion + index * _blksize);
00170         }
00171         
00172         int getNumBlocks (void)
00173         {
00174                 return PERSISTENTSUPERBLOCK_SIZE/_blksize;
00175         }
00176 
00177         int getNumAvailable (void)
00178         {
00179                 int bitsPerBlock = _blksize / PERSISTENTBLOCK_MIN_SIZE;
00180                 int i;
00181                 int numAvailable = 0;
00182 
00183                 for (i=0; i<BITMAP_SIZE; i+=bitsPerBlock) {
00184                         if (__BITMAP_ISSET(i, _bitmap)) {
00185                                 numAvailable++;
00186                         }
00187                 }
00188 
00189                 return PERSISTENTSUPERBLOCK_SIZE/_blksize;
00190         }
00191 
00192         bool isFree() {
00193                 int i;
00194 
00195                 for (i=0; i<BITMAP_ARRAY_SIZE; i++) {
00196                         if (_bitmap[i] != 0) {
00197                                 return false;
00198                         }
00199                 }
00200         
00201                 return true;
00202         }
00203 
00204         void setBlockSize(int blksize) {
00205                 assert(isFree() == true); // block must be free to change its size class 
00206                 _blksize = blksize;
00207         }
00208 
00209         int getBlockSize() {
00210                 return _blksize;
00211         }
00212 
00213         void makePersistentSuperblock(int blksize);
00214 
00215         superblock *getSuperblock() {
00216                 return _superblock;
00217         }
00218 
00219         void setSuperblock(superblock *sb) {
00220                 _superblock = sb;
00221         }
00222 
00223 private:
00224         uint64_t _blksize;
00225         uint64_t _bitmap[BITMAP_ARRAY_SIZE];
00226         char     *_pregion;
00227 
00228         // volatile members
00229         bool       _cached;
00230         bool       _acquired;
00231         superblock *_superblock; // points to the volatile superblock caching this persistent superblock
00232 };
00233 
00234 #endif

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