static int32_t testPoolNewElement(OMRPortLibrary *portLib, PoolInputData *inputData, J9Pool *currentPool) { void *element = NULL; uint8_t *walkBytes; uint32_t elementsInPuddle = 0; uint32_t expectedNumElems = (inputData->numberElements == 0) ? 1 : inputData->numberElements; uint32_t expectedAlignment = (inputData->elementAlignment == 0) ? MIN_GRANULARITY : inputData->elementAlignment; J9PoolPuddleList* puddleList = J9POOL_PUDDLELIST(currentPool); J9PoolPuddle* initialPuddle = J9POOLPUDDLELIST_NEXTAVAILABLEPUDDLE(puddleList); J9PoolPuddle* currentPuddle = initialPuddle; /* Call pool_newElement until a new puddle is allocated... and then allocate a couple of new elements into the new puddle */ while (initialPuddle == currentPuddle) { uint32_t j = 0; /* Get a single element and check that it's the right size and that each byte can be written to */ element = pool_newElement(currentPool); if (NULL == element) { return -1; } /* Verify element alignment. Aligned elements are expected for use in AVL trees, for example. */ if (((uintptr_t) element % expectedAlignment) != 0) { return -2; } if (inputData->poolFlags & POOL_NO_ZERO) { memset(element, 0, inputData->structSize); /* Expect a crash if the element is too small */ } /* Walk each byte of the returned element */ walkBytes = (uint8_t *)element; for (j = 0; j < inputData->structSize; j++) { if (walkBytes[j] != 0) { return -3; } /* Test that we can write to each byte */ if (j == 0) { walkBytes[j] = FIRST_BYTE_MARKER; } else { walkBytes[j] = BYTE_MARKER; } } if (inputData->structSize > 1) { walkBytes[inputData->structSize - 1] = LAST_BYTE_MARKER; } /* currentPuddle will become NULL when the puddle being used becomes FULL if there has been no deletions */ elementsInPuddle++; currentPuddle = J9POOLPUDDLELIST_NEXTAVAILABLEPUDDLE(puddleList); } if (elementsInPuddle < expectedNumElems) { return -4; } return elementsInPuddle; }
/** * Ensures that the pool is large enough for newCapacity elements. * This has the side effect of setting the POOL_NEVER_FREE_PUDDLES flag. * Without this, the pool could shrink back down to its original size. * Note that this does not take into account the number of elements already * used in the pool. * * @param[in] aPool The pool * @param[in] newCapacity The desired new-size of the pool * * @return 0 on success * @return -1 on failure * */ uintptr_t pool_ensureCapacity(J9Pool *aPool, uintptr_t newCapacity) { uintptr_t numElements; uintptr_t result = 0; Trc_pool_ensureCapacity_Entry(aPool, newCapacity); numElements = pool_capacity(aPool); /* mark each pool as POOL_NEVER_FREE_PUDDLES */ aPool->flags |= POOL_NEVER_FREE_PUDDLES; if (newCapacity > numElements) { J9PoolPuddleList *puddleList; J9PoolPuddle *newPuddle, *lastPuddle; uintptr_t newSize = newCapacity - numElements; puddleList = J9POOL_PUDDLELIST(aPool); lastPuddle = J9POOLPUDDLELIST_NEXTPUDDLE(puddleList); for (;;) { if (lastPuddle->nextPuddle == 0) { break; } lastPuddle = J9POOLPUDDLE_NEXTPUDDLE(lastPuddle); } while (newSize > 0) { J9PoolPuddle *puddle; if (newSize < aPool->elementsPerPuddle) { newSize = aPool->elementsPerPuddle; } newPuddle = poolPuddle_new(aPool); if (newPuddle == 0) { Trc_pool_ensureCapacity_OutOfMemory(newCapacity); result = -1; } /* Stick it at the end of the list. */ NNWSRP_SET(lastPuddle->nextPuddle, newPuddle); NNWSRP_SET(newPuddle->prevPuddle, lastPuddle); /* And also at the top of the available puddle list. */ puddle = WSRP_GET(puddleList->nextAvailablePuddle, J9PoolPuddle *); if (puddle) { NNWSRP_SET(newPuddle->nextAvailablePuddle, puddle); } NNWSRP_SET(puddleList->nextAvailablePuddle, newPuddle); lastPuddle = newPuddle; newSize -= aPool->elementsPerPuddle; } }