Ejemplo n.º 1
0
int _createBlock(const size_t blockSize) {
	TRACE_FLOW("(%lu)", blockSize);
	if (_hasAvailableBlock(blockSize)) {
		return 0;
	}
	if (blockSize > READ_FROM_HEAP(lookupTableOffset, Address)) {
		assert(0);
	}
	// all right, block of this size does not exist - we need to
	// split a bigger block
	int parentOkay = _createBlock(blockSize + 1);
	if (parentOkay != 0) {
		return parentOkay;
	}
	
	// =========
	// we can now safely assume that there is a block of
	// blockSize+1 size that we can split
	// get the first from the list
	Address parentBlockAddress = GET_FIRST_BLOCK_ADDRESS(blockSize + 1);
	// remove it from the list
	_removeBlockFromList(parentBlockAddress, blockSize + 1);
	// and split it
	// as we know that there is no other block available, we can write
	// it's address to look-up table
	WRITE_FIRST_BLOCK_ADDRESS(blockSize, parentBlockAddress);
	// let's find the center of the block (there we split)
	Address blockHalfAddress = parentBlockAddress + UNIT * ((Address)1 << (blockSize-1));
	Address leftBlockAddress = parentBlockAddress;
	Address rightBlockAddress = blockHalfAddress;
	TRACE_DUMP("left block starts at %lu, right at %lu (parent starts at %lu)", 
		leftBlockAddress, rightBlockAddress, parentBlockAddress);
	// set addresses and size on the left half...
	WRITE_ON_HEAP(leftBlockAddress, Address, blockSize);
	MARK_BLOCK_FREE(leftBlockAddress);
	SET_ADDRESS_OF_PREVIOUS_SIBLING(leftBlockAddress, 0);
	SET_ADDRESS_OF_FOLLOWING_SIBLING(leftBlockAddress, rightBlockAddress);
	// ... as well as on the right one
	WRITE_ON_HEAP(rightBlockAddress, Address, blockSize);
	MARK_BLOCK_FREE(rightBlockAddress);
	SET_ADDRESS_OF_PREVIOUS_SIBLING(rightBlockAddress, leftBlockAddress);
	SET_ADDRESS_OF_FOLLOWING_SIBLING(rightBlockAddress, 0);
	buddyDump();
	// and that's it!
	return 0;
}
Ejemplo n.º 2
0
Address _allocateBlock(const size_t blockSize) {
	TRACE_FLOW("(%lu)", blockSize);
	int createOkay = _createBlock(blockSize);
	if (createOkay != 0) {
		return 0;
	}
	// we will get the first one
	Address firstBlockAddress = GET_FIRST_BLOCK_ADDRESS(blockSize);
	Address nextBlockAddress = GET_ADDRESS_OF_FOLLOWING_SIBLING(firstBlockAddress);
	// remove it from the list
	_removeBlockFromList(firstBlockAddress, blockSize);
	// set new first block
	WRITE_FIRST_BLOCK_ADDRESS(nextBlockAddress, blockSize);
	// mark it as used
	MARK_BLOCK_USED(firstBlockAddress);
	// and return it
	return firstBlockAddress;
}
Ejemplo n.º 3
0
/**
 * @brief Daemon thread routine
 * @details This function is passed as start_routine to daemon thread,
 *          it waits for new requests to come, and when _pendingCV is fired:
 *          	- daemon takes the request from _pending queue and hashes its data
 *          	- when hashing finished, it adds the block to chain
 *
 * @param chain_ptr pointer to chain
 * @return NULL
 */
void* Chain::daemonRoutine(void *pChain)
{
	(void) pChain;
	int blockId;
	_daemonWorkFlag = true;

	while (s_initiated)
	{
		// Lock _pendingBlocks
		LOCK(_pendingMutex)

		// No requests to process
		if (_pending.empty())
		{
			if (_isClosing)
			{
				UNLOCK(_pendingMutex)
				_daemonWorkFlag = false;
				return NULL;
			}
			// Wait for "hey! someone pending" signal
			if (pthread_cond_wait(&_pendingCV, &_pendingMutex))
			{
				exit(FAIL);
			}
		}

		if (_isClosing)
		{
			UNLOCK(_pendingMutex)
			_daemonWorkFlag = false;
			return NULL;
		}

		if (_pending.size())
		{
			// Get new request
			Request *newReq = _pending.front();
			_pending.pop_front();
			// Release the queue
			UNLOCK(_pendingMutex)

			// Hash and attach
			blockId = _createBlock(newReq);

			// Delete processed request
			delete newReq;

			// Update status
			LOCK(_statusMutex)
			_status[blockId] = ATTACHED;
			UNLOCK(_statusMutex)

			// Send signal to anyone waiting for attaching
			if (pthread_cond_signal(&_attachedCV))
			{
				exit(FAIL);
			}
		}
		else // No requests to process
		{