00001 // Copyright (C) 2001, Compaq Computer Corporation 00002 // 00003 // This file is part of Vesta. 00004 // 00005 // Vesta is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public 00007 // License as published by the Free Software Foundation; either 00008 // version 2.1 of the License, or (at your option) any later version. 00009 // 00010 // Vesta is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public 00016 // License along with Vesta; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 // 00020 // VMemPool.H 00021 // Last modified on Thu Jul 29 10:06:54 EDT 2004 by ken@xorian.net 00022 // modified on Fri May 26 14:22:38 PDT 2000 by mann 00023 // 00024 // Memory pool for Vesta repository directory structure. Confined to 00025 // a range of addresses that can be represented in 32 bits. 00026 // 00027 00028 #ifndef _VMEMPOOL 00029 #define _VMEMPOOL 1 00030 00031 #include "Basics.H" 00032 #include "SourceOrDerived.H" 00033 #include <assert.h> 00034 #include <fstream> 00035 00036 // All memory allocated by VMemPool has the following format. 00037 // See VDirChangeable.H for an explanation of the notation. 00038 // 00039 // packed struct VMemPoolBlock { 00040 // Bit8 clientBits: 4; // Available to client. 00041 // Bit8 typeCode: 4; // Contains the typeCode for this 00042 // // block, as supplied by the 00043 // // client at allocation time. 00044 // Bit8 clientData[]; // Arbitrary data; client must be 00045 // // able to determine the block's 00046 // // length by parsing the data. 00047 // }; 00048 00049 extern "C" void VMemPool_init(); 00050 00051 class VMemPool { 00052 public: 00053 enum typeCode { freeByte = 0, freeBlock, vDirChangeable, vForward, 00054 vDirEvaluator, vDirImmutable, vAttrib, vDirAppendable, 00055 maxTypeCodes = 0x10, unspecified }; 00056 00057 // The blocks returned are always aligned to the following 00058 // multiple (must be at least 8 for the Alpha) so that it is safe 00059 // to protect different blocks with different locks. This will 00060 // cause some space wastage if you allocate objects whose size is 00061 // not a multiple of the alignment. 00062 static int alignmentMask; 00063 00064 // Allocate a block of memory with typeCode "type". The first 00065 // byte of the allocated memory contains typeCode. The caller 00066 // must remember the size of the block, or be able to determine it 00067 // by scanning the block's contents. 00068 // 00069 // Warning: the caller must be holding a lock that prevents 00070 // weeding and checkpointing, such as StableLock, 00071 // VolatileRootLock, or a lock on a volatile subtree. Otherwise 00072 // the memory might be freed by the garbage collector or moved by 00073 // the checkpointer before the caller gets a chance to put a 00074 // pointer somewhere they will find it! 00075 // 00076 static void* allocate(typeCode type, Bit32 size) throw(); 00077 00078 // Explicitly free a block of memory, not waiting for the next 00079 // garbage collection. If type is specified, assert that the 00080 // type code is as given; crash if it is not. 00081 static void free(void* addr, Bit32 size, 00082 typeCode type =unspecified) throw(); 00083 00084 // Retrieve the type of a block. 00085 static typeCode type(void* addr) throw(); 00086 00087 // Because all memory allocated by VMemPool is within a range of 00088 // 2^32 addresses, pointers returned by allocate can be shortened 00089 // to 32 bits and lengthened again without loss of information. 00090 static inline Bit32 shortenPointer(const void* pointer) throw() { 00091 if (pointer == 0) 00092 return 0; 00093 else 00094 return (Bit32) (((Bit8*) pointer) - base + 1); 00095 } 00096 static inline void* lengthenPointer(Bit32 spointer) throw() { 00097 if (spointer == 0) 00098 return (void*) 0; 00099 else 00100 return base + spointer - 1; 00101 } 00102 00103 // Perform a garbage collection, consisting of one mark phase and 00104 // one sweep phase. In the mark phase, each registered 00105 // markCallback is invoked once. A markCallback may be NULL if 00106 // none is needed. In the sweep phase, the registered 00107 // sweepCallback is invoked once for each allocated block. The 00108 // sweepCallback sets "size" to the block's size, and returns true 00109 // if the block is still in use. A sweepCallback must be 00110 // registered for every typeCode that is used in an allocate call. 00111 // Do not register callbacks for freeByte or freeBlock. The 00112 // rebuildCallback is used in an additional sweep pass that 00113 // rebuilds the DirShortId table. 00114 // 00115 static void gc(ShortIdsFile keepDerivedSid) throw(); 00116 typedef void (*markCallback)(void* closure, typeCode type) /*throw ()*/; 00117 typedef bool (*sweepCallback)(void* closure, typeCode type, void* addr, 00118 Bit32& size) /*throw ()*/; 00119 typedef void (*rebuildCallback)(void* closure, typeCode type, void* addr, 00120 Bit32& size) /*throw ()*/; 00121 static void registerCallbacks(typeCode type, 00122 markCallback markcb, void* markcl, 00123 sweepCallback sweepcb, void* sweepcl, 00124 rebuildCallback rebuildcb, void* rebuildcl) 00125 throw(); 00126 00127 // Write and read checkpoints. Writing a checkpoint destroys the 00128 // memory pool contents, so the checkpoint must be immediately 00129 // read back or the server must exit. Volatile directories are 00130 // included in the checkpoint to support immediate rereading. 00131 // When reading a checkpoint, the volatile portion is ignored if 00132 // readVolatile is false. These routines do not use callbacks as 00133 // with mark and sweep above; instead, they have built-in 00134 // knowledge of the roots (RepositoryRoot, MutableRoot, and 00135 // VolatileRoot). Reading a checkpoint also rebuilds the 00136 // DirShortId table. 00137 // 00138 // The checkpoint methods that are called by these routines must 00139 // pad each object written to a multiple of 8 bytes, filling at 00140 // the end with freeByte objects (bytes with value 0) if needed. 00141 // 00142 static void writeCheckpoint(std::fstream& ckpt) throw(); 00143 static void readCheckpoint(std::fstream& ckpt, bool readVolatile) throw(); 00144 00145 protected: 00146 static Bit8* base; 00147 static void init(); 00148 00149 private: 00150 static Bit32 totalSize, minGrowBy; 00151 static void rebuildDirShortIdTable() throw (); 00152 static void grow(Bit32 growBy) throw(); 00153 00154 friend void VMemPool_init(); 00155 }; 00156 00157 #endif //_VMEMPOOL