/* Function used to create a new graph page for adjecent lists */ Gdb_ret_t createGraphPage(Graph_t *graph){ // this will double memory usage while it does the copying!!! pthread_mutex_lock(&graph_mutex); pthread_mutex_lock(&node_mutex); List_p new_block = (List_p)resizeMemory(graph->arr_list, (graph->num_vertices + MAX_PAGE_SIZE)*sizeof(List_t)); if(!new_block){ pthread_mutex_unlock(&graph_mutex); pthread_mutex_unlock(&node_mutex); return MEM_FULL; } graph->arr_list = new_block; graph->num_vertices += MAX_PAGE_SIZE; // inclrease vertex count without needing to count - keep it O(1) pthread_mutex_unlock(&graph_mutex); pthread_mutex_unlock(&node_mutex); return OK; }
/* heap_clear(): Set the heap state to inactive, and free the block lists. This is called when the game starts or restarts. */ void heap_clear() { while (heap_head) { heapblock_t *blo = heap_head; heap_head = blo->next; blo->next = NULL; blo->prev = NULL; glulx_free(blo); } heap_tail = NULL; if (heap_start) { glui32 res = resizeMemory(heap_start, 1); if (res) fatalError("Unable to revert memory size when deactivating heap."); } heap_start = 0; alloc_count = 0; /* heap_sanity_check(); */ }
git_sint32 restoreFromFile (git_sint32 * base, git_sint32 id, git_uint32 protectPos, git_uint32 protectSize) { git_uint32 protectEnd = protectPos + protectSize; git_uint32 i; strid_t file; glui32 fileSize, fileStart; int gotIdent = 0; int gotMemory = 0; int gotStack = 0; int gotHeap = 0; // Find out what stream they want to use, and make sure it's valid. file = git_find_stream_by_id (id); if (file == 0) return 1; // Read IFF header. if (readWord (file) != read32("FORM")) return 1; // Not an IFF file. fileSize = readWord (file); fileStart = glk_stream_get_position (file); if (readWord (file) != read32("IFZS")) return 1; // Not a Quetzal file. // Discard the current heap. heap_clear(); // Read all the chunks. while (glk_stream_get_position(file) < fileStart + fileSize) { git_uint32 chunkType, chunkSize, chunkStart; chunkType = readWord (file); chunkSize = readWord (file); chunkStart = glk_stream_get_position (file); if (chunkType == read32("IFhd")) { if (gotIdent) return 1; gotIdent = 1; if (chunkSize != 128) return 1; for (i = 0 ; i < 128 ; ++i) { glui32 c = glk_get_char_stream (file); if (gRom [i] != c) return 1; } } else if (chunkType == read32("Stks")) { if (gotStack) return 1; gotStack = 1; if (chunkSize & 3) return 1; gStackPointer = base; for ( ; chunkSize > 0 ; chunkSize -= 4) *gStackPointer++ = readWord(file); } else if (chunkType == read32("CMem")) { git_uint32 bytesRead = 0; if (gotMemory) return 1; gotMemory = 1; if (resizeMemory (readWord(file), 1)) fatalError ("Can't resize memory map"); bytesRead = 4; i = gRamStart; while (i < gExtStart && bytesRead < chunkSize) { int mult = 0; char c = (char) glk_get_char_stream(file); ++bytesRead; if (c == 0) { mult = (unsigned char) glk_get_char_stream(file); ++bytesRead; } for (++mult ; mult > 0 ; --mult, ++i) if (i >= protectEnd || i < protectPos) gRam [i] = gRom [i] ^ c; } while (i < gEndMem && bytesRead < chunkSize) { int mult = 0; char c = (char) glk_get_char_stream(file); ++bytesRead; if (c == 0) { mult = (unsigned char) glk_get_char_stream(file); ++bytesRead; } for (++mult ; mult > 0 ; --mult, ++i) if (i >= protectEnd || i < protectPos) gRam [i] = c; } while (i < gExtStart) if (i >= protectEnd || i < protectPos) gRam [i] = gRom [i], ++i; while (i < gEndMem) if (i >= protectEnd || i < protectPos) gRam [i] = 0, ++i; if (bytesRead != chunkSize) return 1; // Too much data! if (chunkSize & 1) glk_get_char_stream (file); } else if (chunkType == read32("MAll")) { glui32 heapSize = 0; glui32 * heap = 0; if (gotHeap) return 1; gotHeap = 1; if (chunkSize & 3) return 1; if (chunkSize > 0) { heap = malloc (chunkSize); heapSize = chunkSize / 4; for (i = 0 ; i < heapSize ; ++i) heap[i] = readWord(file); /* The summary might have come from any interpreter, so it could be out of order. We'll sort it. */ qsort(heap+2, (heapSize-2)/2, 8, &sort_heap_summary); if (heap_apply_summary (heapSize, heap)) fatalError ("Couldn't apply heap summary"); free (heap); } } else { // Unknown chunk type -- just skip it. glk_stream_set_position (file, (chunkSize + 1) & ~1, seekmode_Current); } } // Make sure we have all the chunks we need. if (!gotIdent) fatalError ("No ident chunk in save file"); if (!gotStack) fatalError ("No stack chunk in save file"); if (!gotMemory) fatalError ("No memory chunk in save file"); // If we reach this point, we restored successfully. return 0; }
SquareMatrix::SquareMatrix(const int size) : matrix_(NULL), size_(size) { resizeMemory(size_); }
SquareMatrix::SquareMatrix(const SquareMatrix & rhs) : matrix_(NULL), size_(0) { resizeMemory(rhs.size_); std::copy(rhs.matrix_, rhs.matrix_ + (rhs.size_ * rhs.size_), matrix_); }
/* heap_alloc(): Allocate a block. If necessary, activate the heap and/or extend memory. Returns the memory address of the block, or 0 if the operation failed. */ glui32 heap_alloc(glui32 len) { heapblock_t *blo, *newblo; if (len <= 0) fatalError("Heap allocation length must be positive."); blo = heap_head; while (blo) { if (blo->isfree && blo->len >= len) break; if (!blo->isfree) { blo = blo->next; continue; } if (!blo->next || !blo->next->isfree) { blo = blo->next; continue; } /* This is a free block, but the next block in the list is also free, so we "advance" by merging rather than by going to blo->next. */ newblo = blo->next; blo->len += newblo->len; if (newblo->next) { blo->next = newblo->next; newblo->next->prev = blo; } else { blo->next = NULL; heap_tail = blo; } newblo->next = NULL; newblo->prev = NULL; glulx_free(newblo); newblo = NULL; continue; } if (!blo) { /* No free area is visible on the list. Try extending memory. How much? Double the heap size, or by 256 bytes, or by the memory length requested -- whichever is greatest. */ glui32 res; glui32 extension; glui32 oldendmem = gEndMem; extension = 0; if (heap_start) extension = gEndMem - heap_start; if (extension < len) extension = len; if (extension < 256) extension = 256; /* And it must be rounded up to a multiple of 256. */ extension = (extension + 0xFF) & (~(glui32)0xFF); res = resizeMemory(gEndMem+extension, 1); if (res) return 0; /* If we just started the heap, note that. */ if (heap_start == 0) heap_start = oldendmem; if (heap_tail && heap_tail->isfree) { /* Append the new space to the last block. */ blo = heap_tail; blo->len += extension; } else { /* Append the new space to the block list, as a new block. */ newblo = glulx_malloc(sizeof(heapblock_t)); if (!newblo) fatalError("Unable to allocate record for heap block."); newblo->addr = oldendmem; newblo->len = extension; newblo->isfree = TRUE; newblo->next = NULL; newblo->prev = NULL; if (!heap_tail) { heap_head = newblo; heap_tail = newblo; } else { blo = heap_tail; heap_tail = newblo; blo->next = newblo; newblo->prev = blo; } blo = newblo; newblo = NULL; } /* and continue forwards, using this new block (blo). */ } /* Something strange happened. */ if (!blo || !blo->isfree || blo->len < len) return 0; /* We now have a free block of size len or longer. */ if (blo->len == len) { blo->isfree = FALSE; } else { newblo = glulx_malloc(sizeof(heapblock_t)); if (!newblo) fatalError("Unable to allocate record for heap block."); newblo->isfree = TRUE; newblo->addr = blo->addr + len; newblo->len = blo->len - len; blo->len = len; blo->isfree = FALSE; newblo->next = blo->next; if (newblo->next) newblo->next->prev = newblo; newblo->prev = blo; blo->next = newblo; if (heap_tail == blo) heap_tail = newblo; } alloc_count++; /* heap_sanity_check(); */ return blo->addr; }
int restoreUndo (git_sint32* base, git_uint32 protectPos, git_uint32 protectSize) { if (gUndo == NULL) { // Nothing to undo! return 1; } else { UndoRecord * undo = gUndo; git_uint32 addr = gRamStart; // Address in glulx memory. MemoryMap map = undo->memoryMap; // Glulx memory map. // Restore the size of the memory map heap_clear (); resizeMemory (undo->endMem, 1); // Restore the stack. memcpy (base, undo->stack, undo->stackSize); gStackPointer = base + (undo->stackSize / sizeof(git_sint32)); // Restore the contents of RAM. if (protectSize > 0 && protectPos < gEndMem) { for ( ; addr < (protectPos & ~0xff) ; addr += 256, ++map) memcpy (gMem + addr, *map, 256); memcpy (gMem + addr, *map, protectPos & 0xff); protectSize += protectPos & 0xff; while (protectSize > 256) addr += 256, ++map, protectSize -= 256; if (addr < gEndMem) { memcpy (gMem + addr + protectSize, *map + protectSize, 256 - protectSize); } addr += 256, ++map; } for ( ; addr < gEndMem ; addr += 256, ++map) memcpy (gMem + addr, *map, 256); // Restore the heap. if (heap_apply_summary (undo->heapSize, undo->heap)) fatalError ("Couldn't apply heap summary"); // Delete the undo record. gUndo = undo->prev; deleteRecord (undo); if (gUndo) gUndo->next = NULL; else assert (gUndoSize == 0); // And we're done. return 0; } }