/**
 * If the buddy block is on the free list then coalesce and insert into the next
 * list until we reach an allocated or split buddy block, or the max list size.
 */
static inline uint32_t __gnix_buddy_coalesce(gnix_buddy_alloc_handle_t *alloc_handle
					 , void **ptr, uint32_t block_size)
{
	void *buddy;

	for (buddy = __gnix_buddy_address(*ptr, block_size, alloc_handle->base);
	     block_size < alloc_handle->max &&
		     !_gnix_test_bit(&alloc_handle->bitmap,
				     __gnix_buddy_bitmap_index(buddy,
							       block_size,
							       alloc_handle->base,
							       alloc_handle->len,
							       MIN_BLOCK_SIZE));
	     buddy = __gnix_buddy_address(*ptr, block_size, alloc_handle->base)) {

		dlist_remove(buddy);

		/* Ensure ptr is the beginning of the new block */
		if (*ptr > buddy)
			*ptr = buddy;

		block_size *= 2;

		_gnix_clear_bit(&alloc_handle->bitmap,
				__gnix_buddy_bitmap_index(*ptr, block_size,
							  alloc_handle->base,
							  alloc_handle->len,
							  MIN_BLOCK_SIZE));
	}
	return block_size;
}
Exemple #2
0
static struct gnix_vc *__gnix_nic_next_pending_rx_vc(struct gnix_nic *nic)
{
	struct gnix_vc *vc = NULL;

	fastlock_acquire(&nic->rx_vc_lock);
	vc = dlist_first_entry(&nic->rx_vcs, struct gnix_vc, rx_list);
	if (vc)
		dlist_remove_init(&vc->rx_list);
	fastlock_release(&nic->rx_vc_lock);

	if (vc) {
		GNIX_INFO(FI_LOG_EP_CTRL, "Dequeued RX VC (%p)\n", vc);
		_gnix_clear_bit(&vc->flags, GNIX_VC_FLAG_RX_SCHEDULED);
	}

	return vc;
}
int _gnix_buddy_free(gnix_buddy_alloc_handle_t *alloc_handle, void *ptr,
		     uint32_t len)
{
	uint32_t block_size;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if (unlikely(!alloc_handle || !len || len > alloc_handle->max ||
		     ptr >= (void *) ((uint8_t *) alloc_handle->base +
				      alloc_handle->len) ||
		     ptr < alloc_handle->base)) {

		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Invalid parameter to _gnix_buddy_free.\n");
		return -FI_EINVAL;
	}

	block_size = BLOCK_SIZE(len, MIN_BLOCK_SIZE);

	_gnix_clear_bit(&alloc_handle->bitmap,
			__gnix_buddy_bitmap_index(ptr, block_size,
						  alloc_handle->base,
						  alloc_handle->len,
						  MIN_BLOCK_SIZE));

	fastlock_acquire(&alloc_handle->lock);

	block_size = __gnix_buddy_coalesce(alloc_handle, &ptr, block_size);

	dlist_insert_tail(ptr, alloc_handle->lists +
			  LIST_INDEX(block_size, MIN_BLOCK_SIZE));

	fastlock_release(&alloc_handle->lock);

	return FI_SUCCESS;
}