src/hbcore/core/hbmultisegmentallocator_p.cpp
changeset 28 b7da29130b0e
parent 21 4633027730f5
equal deleted inserted replaced
23:e6ad4ef83b23 28:b7da29130b0e
    29 #include <QDebug>
    29 #include <QDebug>
    30 #include <QSharedMemory>
    30 #include <QSharedMemory>
    31 
    31 
    32 // this identifier is used to check, if the multisegment allocator is already
    32 // this identifier is used to check, if the multisegment allocator is already
    33 // initialized in given shared chunk
    33 // initialized in given shared chunk
    34 static const unsigned int INITIALIZED_MULTISEGMENTALLOCATOR_IDENTIFIER = 0x4D554C54; //'MULT'
    34 static const quint32 INITIALIZED_MULTISEGMENTALLOCATOR_IDENTIFIER = 0x4D554C54; //'MULT'
    35 
    35 
    36 // chunk sizes
    36 // chunk sizes
    37 // every size is aligned to 8
    37 // every size is aligned to 8
    38 static const int ChunkSizes[AMOUNT_OF_DIFFERENT_CHUNK_SIZES] = {8, 16, 24, 32, 48, 64, 120, 224};
    38 static const int ChunkSizes[AMOUNT_OF_DIFFERENT_CHUNK_SIZES] = {8, 16, 24, 32, 48, 64, 120, 224};
    39 
    39 
    92 
    92 
    93     // every chunk list have space for 512 chunks
    93     // every chunk list have space for 512 chunks
    94     ChunkListHeader *listHeader;
    94     ChunkListHeader *listHeader;
    95     for (int i = 0; i < AMOUNT_OF_DIFFERENT_CHUNK_SIZES; i++) {
    95     for (int i = 0; i < AMOUNT_OF_DIFFERENT_CHUNK_SIZES; i++) {
    96         header->offsetsToChunkLists[i] = mainAllocator->alloc(sizeof(ChunkListHeader)
    96         header->offsetsToChunkLists[i] = mainAllocator->alloc(sizeof(ChunkListHeader)
    97                                                               + (sizeof(int) + ChunkSizes[i])
    97                                                               + (sizeof(qptrdiff) + ChunkSizes[i])
    98                                                               * CHUNKS_IN_ONE_LIST);
    98                                                               * CHUNKS_IN_ONE_LIST);
    99         header->offsetsToFreeChunkLists[i] = header->offsetsToChunkLists[i];
    99         header->offsetsToFreeChunkLists[i] = header->offsetsToChunkLists[i];
   100         listHeader = address<ChunkListHeader>(header->offsetsToChunkLists[i]);
   100         listHeader = address<ChunkListHeader>(header->offsetsToChunkLists[i]);
   101         listHeader->chunkListIndex = i;
   101         listHeader->chunkListIndex = i;
   102         listHeader->freedChunkCursor = -1;
   102         listHeader->freedChunkCursor = -1;
   136     // size should already be between 1...max. chunk size - no need to check
   136     // size should already be between 1...max. chunk size - no need to check
   137 
   137 
   138     // first find out correct list of chunks
   138     // first find out correct list of chunks
   139     int i = indexTable[size];
   139     int i = indexTable[size];
   140     qptrdiff dataOffset = -1;
   140     qptrdiff dataOffset = -1;
   141     int *metaData = 0;
   141     qptrdiff *metaData = 0;
   142     // this should always point to list with free chunks
   142     // this should always point to list with free chunks
   143     ChunkListHeader *listHeader = address<ChunkListHeader>(header->offsetsToFreeChunkLists[i]);
   143     ChunkListHeader *listHeader = address<ChunkListHeader>(header->offsetsToFreeChunkLists[i]);
   144 
   144 
   145     if (listHeader->freedChunkCursor >= 0) { // freedChunkCursor points to freed chunk
   145     if (listHeader->freedChunkCursor >= 0) { // freedChunkCursor points to freed chunk
   146         dataOffset = listHeader->freedChunkCursor + sizeof(int);
   146         dataOffset = listHeader->freedChunkCursor + sizeof(qptrdiff);
   147         metaData = address<int>(listHeader->freedChunkCursor);
   147         metaData = address<qptrdiff>(listHeader->freedChunkCursor);
   148         listHeader->freedChunkCursor = *metaData; // point to next freed chunk
   148         listHeader->freedChunkCursor = *metaData; // points to next freed chunk
   149     } else { // no chunks freed -> allocate in order
   149     } else { // no chunks freed -> allocate in order
   150         dataOffset = listHeader->allocCursor + sizeof(int);
   150         dataOffset = listHeader->allocCursor + sizeof(qptrdiff);
   151         metaData = address<int>(listHeader->allocCursor);
   151         metaData = address<qptrdiff>(listHeader->allocCursor);
   152         // we will never allocate from full list, so allocCursor is always valid
   152         // we will never allocate from full list, so allocCursor is always valid
   153         listHeader->allocCursor += ChunkSizes[listHeader->chunkListIndex] + sizeof(int);
   153         listHeader->allocCursor += ChunkSizes[listHeader->chunkListIndex] + sizeof(qptrdiff);
   154     }
   154     }
   155 
   155 
   156     // for allocated chunks metadata is:
   156     // for allocated chunks metadata is the offset to this list's header
   157     // 00xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx,
   157     // for freed chunks, metadata points to next free chunk (or -1 if no more freed chunks)
   158     // where xx... = offset to this list's header (max. 1 GB)
   158     *metaData = header->offsetsToFreeChunkLists[i];
   159     *metaData = header->offsetsToFreeChunkLists[i] /* & 0x3FFFFFFF */;
       
   160     listHeader->allocatedChunks++;
   159     listHeader->allocatedChunks++;
   161     if (listHeader->allocatedChunks == CHUNKS_IN_ONE_LIST) { // list full
   160     if (listHeader->allocatedChunks == CHUNKS_IN_ONE_LIST) { // list full
   162         if (!setFreeList(listHeader->chunkListIndex)) {
   161         if (!setFreeList(listHeader->chunkListIndex)) {
   163             // there is no list(s) with free chunks, so add new list
   162             // there is no list(s) with free chunks, so add new list
   164             addList(listHeader->chunkListIndex,
   163             addList(listHeader->chunkListIndex,
   165                 mainAllocator->alloc((sizeof(ChunkListHeader) + sizeof(int)
   164                 mainAllocator->alloc(sizeof(ChunkListHeader) + (sizeof(qptrdiff)
   166                                       + ChunkSizes[listHeader->chunkListIndex])
   165                                       + ChunkSizes[listHeader->chunkListIndex])
   167                                         * CHUNKS_IN_ONE_LIST));
   166                                         * CHUNKS_IN_ONE_LIST));
   168         }
   167         }
   169     }
   168     }
   170 
   169 
   175 * free the offset
   174 * free the offset
   176 */
   175 */
   177 void HbMultiSegmentAllocator::free(qptrdiff offset)
   176 void HbMultiSegmentAllocator::free(qptrdiff offset)
   178 {
   177 {
   179     // metadata has offset to list's header
   178     // metadata has offset to list's header
   180     int *metaData = address<int>(offset - sizeof(int));
   179     qptrdiff *metaData = address<qptrdiff>(offset - sizeof(qptrdiff));
   181     int listHeaderOffset = *metaData;
   180     qptrdiff listHeaderOffset = *metaData;
   182     ChunkListHeader *listHeader = address<ChunkListHeader>(listHeaderOffset);
   181     ChunkListHeader *listHeader = address<ChunkListHeader>(listHeaderOffset);
   183     listHeader->allocatedChunks--;
   182     listHeader->allocatedChunks--;
   184     if (listHeader->allocatedChunks == 0) {
   183     if (listHeader->allocatedChunks == 0) {
   185         // if there are multiple lists, this list could be released
   184         // if there are multiple lists, this list could be released
   186         ChunkListHeader *previous = 0;
   185         ChunkListHeader *previous = 0;
   211                 addList(listHeader->chunkListIndex, listHeaderOffset);
   210                 addList(listHeader->chunkListIndex, listHeaderOffset);
   212             }
   211             }
   213         } else {
   212         } else {
   214             // only list can't be freed
   213             // only list can't be freed
   215             *metaData = listHeader->freedChunkCursor;
   214             *metaData = listHeader->freedChunkCursor;
   216             listHeader->freedChunkCursor = offset - sizeof(int);
   215             listHeader->freedChunkCursor = offset - sizeof(qptrdiff);
   217         }
   216         }
   218     } else {
   217     } else {
   219         // this list is not yet empty
   218         // this list is not yet empty
   220         *metaData = listHeader->freedChunkCursor;
   219         *metaData = listHeader->freedChunkCursor;
   221         listHeader->freedChunkCursor = offset - sizeof(int);
   220         listHeader->freedChunkCursor = offset - sizeof(qptrdiff);
   222     }
   221     }
   223 }
   222 }
   224 
   223 
   225 /**
   224 /**
   226  * HbMultiSegmentAllocator::allocatedSize
   225  * HbMultiSegmentAllocator::allocatedSize
   228  * Used for reallocation.
   227  * Used for reallocation.
   229  * Returns actual allocated size for given offset.
   228  * Returns actual allocated size for given offset.
   230  */
   229  */
   231 int HbMultiSegmentAllocator::allocatedSize(qptrdiff offset)
   230 int HbMultiSegmentAllocator::allocatedSize(qptrdiff offset)
   232 {
   231 {
   233     int *metaData = address<int>(offset - sizeof(int));
   232     qptrdiff *metaData = address<qptrdiff>(offset - sizeof(qptrdiff));
   234     ChunkListHeader *listHeader = address<ChunkListHeader>(*metaData);
   233     ChunkListHeader *listHeader = address<ChunkListHeader>(*metaData);
   235     // not actual size in alloc(), but the size of chunk, where this data is stored
   234     // not actual size in alloc(), but the size of chunk, where this data is stored
   236     return ChunkSizes[listHeader->chunkListIndex];
   235     return ChunkSizes[listHeader->chunkListIndex];
   237 }
   236 }
   238 
   237 
   262 * return false. Otherwise sets free list and returns true.
   261 * return false. Otherwise sets free list and returns true.
   263 */
   262 */
   264 bool HbMultiSegmentAllocator::setFreeList(int index)
   263 bool HbMultiSegmentAllocator::setFreeList(int index)
   265 {
   264 {
   266     ChunkListHeader *listHeader;
   265     ChunkListHeader *listHeader;
   267     listHeader = address<ChunkListHeader>(header->offsetsToChunkLists[index]);
   266     qptrdiff offset = header->offsetsToChunkLists[index];
       
   267     listHeader = address<ChunkListHeader>(offset);
   268     bool retVal = false;
   268     bool retVal = false;
   269     for (;;) {
   269     for (;;) {
   270         if (listHeader->allocatedChunks < CHUNKS_IN_ONE_LIST) {
   270         if (listHeader->allocatedChunks < CHUNKS_IN_ONE_LIST) {
   271             qptrdiff offset = static_cast<int>(reinterpret_cast<char*>(listHeader)
       
   272                                           - reinterpret_cast<char*>(chunk->data()));
       
   273             header->offsetsToFreeChunkLists[index] = offset;
   271             header->offsetsToFreeChunkLists[index] = offset;
   274             retVal = true;
   272             retVal = true;
   275             break;
   273             break;
   276         }
   274         }
   277         if (listHeader->nextListOffset == -1) {
   275         if (listHeader->nextListOffset == -1) {
   278             break;
   276             break;
   279         }
   277         }
   280         listHeader = address<ChunkListHeader>(listHeader->nextListOffset);
   278         offset = listHeader->nextListOffset;
       
   279         listHeader = address<ChunkListHeader>(offset);
   281     }
   280     }
   282     return retVal;
   281     return retVal;
   283 }
   282 }
   284 
   283 
   285 #ifdef HB_THEME_SERVER_MEMORY_REPORT
   284 #ifdef HB_THEME_SERVER_MEMORY_REPORT