/** * Update method used by free * This needs to handle the special case when both children are completely free * in which case parent be directly allocated on request of size = child-size * 2 * * @param id id */ private void updateParentsFree(int id) { int logChild = depth(id) + 1; while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); logChild -= 1; // in first iteration equals log, subsequently reduce 1 from logChild as we traverse up if (val1 == logChild && val2 == logChild) { setValue(parentId, (byte) (logChild - 1)); } else { byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); } id = parentId; } }
/** * Update method used by allocate * This is triggered only when a successor is allocated and all its predecessors * need to update their state * The minimal depth at which subtree rooted at id has some free space * * @param id id */ private void updateParentsAlloc(int id) { while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); id = parentId; } }
/** * Update method used by free * This needs to handle the special case when both children are completely free * in which case parent be directly allocated on request of size = child-size * 2 * * @param id id */ private void updateParentsFree(int id) { int logChild = depth(id) + 1; while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); logChild -= 1; // in first iteration equals log, subsequently reduce 1 from logChild as we traverse up if (val1 == logChild && val2 == logChild) { setValue(parentId, (byte) (logChild - 1)); } else { byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); } id = parentId; } }
/** * Update method used by allocate * This is triggered only when a successor is allocated and all its predecessors * need to update their state * The minimal depth at which subtree rooted at id has some free space * * @param id id */ private void updateParentsAlloc(int id) { while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); id = parentId; } }
/** * Update method used by free * This needs to handle the special case when both children are completely free * in which case parent be directly allocated on request of size = child-size * 2 * * @param id id */ private void updateParentsFree(int id) { int logChild = depth(id) + 1; while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); logChild -= 1; // in first iteration equals log, subsequently reduce 1 from logChild as we traverse up if (val1 == logChild && val2 == logChild) { setValue(parentId, (byte) (logChild - 1)); } else { byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); } id = parentId; } }
/** * Update method used by allocate * This is triggered only when a successor is allocated and all its predecessors * need to update their state * The minimal depth at which subtree rooted at id has some free space * * @param id id */ private void updateParentsAlloc(int id) { while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); id = parentId; } }
/** * Algorithm to allocate an index in memoryMap when we query for a free node * at depth d * * @param d depth * @return index in memoryMap */ private int allocateNode(int d) { int id = 1; int initial = - (1 << d); // has last d bits = 0 and rest all = 1 byte val = value(id); if (val > d) { // unusable return -1; } while (val < d || (id & initial) == 0) { // id & initial == 1 << d for all ids at depth d, for < d it is 0 id <<= 1; val = value(id); if (val > d) { id ^= 1; val = value(id); } } byte value = value(id); assert value == d && (id & initial) == 1 << d : String.format("val = %d, id & initial = %d, d = %d", value, id & initial, d); setValue(id, unusable); // mark as unusable updateParentsAlloc(id); return id; }
/** * Algorithm to allocate an index in memoryMap when we query for a free node * at depth d * * @param d depth * @return index in memoryMap */ private int allocateNode(int d) { int id = 1; int initial = - (1 << d); // has last d bits = 0 and rest all = 1 byte val = value(id); if (val > d) { // unusable return -1; } while (val < d || (id & initial) == 0) { // id & initial == 1 << d for all ids at depth d, for < d it is 0 id <<= 1; val = value(id); if (val > d) { id ^= 1; val = value(id); } } byte value = value(id); assert value == d && (id & initial) == 1 << d : String.format("val = %d, id & initial = %d, d = %d", value, id & initial, d); setValue(id, unusable); // mark as unusable updateParentsAlloc(id); return id; }
/** * Algorithm to allocate an index in memoryMap when we query for a free node * at depth d * * @param d depth * @return index in memoryMap */ private int allocateNode(int d) { int id = 1; int initial = - (1 << d); // has last d bits = 0 and rest all = 1 byte val = value(id); if (val > d) { // unusable return -1; } while (val < d || (id & initial) == 0) { // id & initial == 1 << d for all ids at depth d, for < d it is 0 id <<= 1; val = value(id); if (val > d) { id ^= 1; val = value(id); } } byte value = value(id); assert value == d && (id & initial) == 1 << d : String.format("val = %d, id & initial = %d, d = %d", value, id & initial, d); setValue(id, unusable); // mark as unusable updateParentsAlloc(id); return id; }
setValue(memoryMapIdx, depth(memoryMapIdx)); updateParentsFree(memoryMapIdx);
setValue(memoryMapIdx, depth(memoryMapIdx)); updateParentsFree(memoryMapIdx);
/** * Free a subpage or a run of pages * When a subpage is freed from PoolSubpage, it might be added back to subpage pool of the owning PoolArena * If the subpage pool in PoolArena has at least one other PoolSubpage of given elemSize, we can * completely free the owning Page so it is available for subsequent allocations * * @param handle handle to free */ void free(long handle) { int memoryMapIdx = memoryMapIdx(handle); int bitmapIdx = bitmapIdx(handle); if (bitmapIdx != 0) { // free a subpage PoolSubpage<T> subpage = subpages[subpageIdx(memoryMapIdx)]; assert subpage != null && subpage.doNotDestroy; // Obtain the head of the PoolSubPage pool that is owned by the PoolArena and synchronize on it. // This is need as we may add it back and so alter the linked-list structure. PoolSubpage<T> head = arena.findSubpagePoolHead(subpage.elemSize); synchronized (head) { if (subpage.free(head, bitmapIdx & 0x3FFFFFFF)) { return; } } } freeBytes += runLength(memoryMapIdx); setValue(memoryMapIdx, depth(memoryMapIdx)); updateParentsFree(memoryMapIdx); }
/** * Update method used by free * This needs to handle the special case when both children are completely free * in which case parent be directly allocated on request of size = child-size * 2 * * @param id id */ private void updateParentsFree(int id) { int logChild = depth(id) + 1; while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); logChild -= 1; // in first iteration equals log, subsequently reduce 1 from logChild as we traverse up if (val1 == logChild && val2 == logChild) { setValue(parentId, (byte) (logChild - 1)); } else { byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); } id = parentId; } }
/** * Update method used by allocate * This is triggered only when a successor is allocated and all its predecessors * need to update their state * The minimal depth at which subtree rooted at id has some free space * * @param id id */ private void updateParentsAlloc(int id) { while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); id = parentId; } }
/** * Algorithm to allocate an index in memoryMap when we query for a free node * at depth d * * @param d depth * @return index in memoryMap */ private int allocateNode(int d) { int id = 1; int initial = - (1 << d); // has last d bits = 0 and rest all = 1 byte val = value(id); if (val > d) { // unusable return -1; } while (val < d || (id & initial) == 0) { // id & initial == 1 << d for all ids at depth d, for < d it is 0 id <<= 1; val = value(id); if (val > d) { id ^= 1; val = value(id); } } byte value = value(id); assert value == d && (id & initial) == 1 << d : String.format("val = %d, id & initial = %d, d = %d", value, id & initial, d); setValue(id, unusable); // mark as unusable updateParentsAlloc(id); return id; }
setValue(memoryMapIdx, depth(memoryMapIdx)); updateParentsFree(memoryMapIdx);
/** * Update method used by free * This needs to handle the special case when both children are completely free * in which case parent be directly allocated on request of size = child-size * 2 * * @param id id */ private void updateParentsFree(int id) { int logChild = depth(id) + 1; while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); logChild -= 1; // in first iteration equals log, subsequently reduce 1 from logChild as we traverse up if (val1 == logChild && val2 == logChild) { setValue(parentId, (byte) (logChild - 1)); } else { byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); } id = parentId; } }
/** * Update method used by allocate * This is triggered only when a successor is allocated and all its predecessors * need to update their state * The minimal depth at which subtree rooted at id has some free space * * @param id id */ private void updateParentsAlloc(int id) { while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); id = parentId; } }
/** * Update method used by allocate * This is triggered only when a successor is allocated and all its predecessors * need to update their state * The minimal depth at which subtree rooted at id has some free space * * @param id id */ private void updateParentsAlloc(int id) { while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); id = parentId; } }
/** * Update method used by allocate * This is triggered only when a successor is allocated and all its predecessors * need to update their state * The minimal depth at which subtree rooted at id has some free space * * @param id id */ private void updateParentsAlloc(int id) { while (id > 1) { int parentId = id >>> 1; byte val1 = value(id); byte val2 = value(id ^ 1); byte val = val1 < val2 ? val1 : val2; setValue(parentId, val); id = parentId; } }