Blame src/blitter/ntapi_blt_block.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
dd89bb
/*  Copyright (C) 2013,2014,2015  Z. Gilboa             */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <ntapi/nt_status.h>
dd89bb
#include <ntapi/nt_blitter.h>
dd89bb
#include <ntapi/nt_sync.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
#include <ntapi/nt_atomic.h>
dd89bb
#include "ntapi_blitter.h"
dd89bb
#include "ntapi_impl.h"
dd89bb
dd89bb
static int32_t __fastcall __blt_bitbite(
dd89bb
	__in	nt_blitter *	blitter,
dd89bb
	__in	unsigned int	bit,
dd89bb
	__in	size_t		byte)
dd89bb
{
dd89bb
	uint32_t	locktry;
dd89bb
	uintptr_t	test;
dd89bb
	uintptr_t	cmp;
dd89bb
	uintptr_t	xchg;
dd89bb
	uintptr_t	mask;
dd89bb
dd89bb
	mask    = ((uintptr_t)1 << bit);
dd89bb
	locktry = blitter->params.lock_tries;
dd89bb
dd89bb
	for (; locktry; locktry--) {
dd89bb
		cmp  = blitter->bitmap[byte] | mask;
dd89bb
		xchg = cmp ^ mask;
dd89bb
dd89bb
		test  = at_locked_cas(
dd89bb
			(intptr_t *)&blitter->bitmap[byte],
dd89bb
			cmp,xchg);
dd89bb
dd89bb
		if (test == cmp) {
dd89bb
			at_locked_dec(&blitter->info.blocks_avail);
dd89bb
			at_locked_inc(&blitter->info.blocks_used);
dd89bb
			return NT_STATUS_SUCCESS;
dd89bb
dd89bb
		} else if (test ^ mask)
dd89bb
			return NT_STATUS_TRANSACTIONAL_CONFLICT;
dd89bb
	}
dd89bb
dd89bb
	if (!locktry) {
dd89bb
		blitter->info.busy = 1;
dd89bb
		blitter->info.lock_tries = blitter->params.lock_tries;
dd89bb
		return NT_STATUS_DEVICE_BUSY;
dd89bb
	}
dd89bb
dd89bb
	return NT_STATUS_MORE_PROCESSING_REQUIRED;
dd89bb
}
dd89bb
dd89bb
static int32_t __fastcall __blt_acquire(
dd89bb
	__in	nt_blitter *	blitter,
dd89bb
	__out	intptr_t *	blkid)
dd89bb
{
dd89bb
	unsigned int	bit;
dd89bb
	uintptr_t		i,n;
dd89bb
dd89bb
	if (blitter->info.blocks_avail == 0)
dd89bb
		return NT_STATUS_ALLOCATE_BUCKET;
dd89bb
dd89bb
	for (n=0,bit=0; blitter->info.blocks_avail && (n < blitter->params.round_trips); n++) {
dd89bb
		for (i=*blkid/(8*sizeof(size_t)); (i<blitter->ptrs); i++)
dd89bb
			if (at_bsf(&bit,blitter->bitmap[i]))
dd89bb
				break;
dd89bb
dd89bb
		if (i == blitter->ptrs)
dd89bb
			return NT_STATUS_ALLOCATE_BUCKET;
dd89bb
dd89bb
		switch (__blt_bitbite(blitter,bit,i)) {
dd89bb
			case NT_STATUS_SUCCESS:
dd89bb
				*blkid = bit + (i * 8 * sizeof(size_t));
dd89bb
				return NT_STATUS_SUCCESS;
dd89bb
dd89bb
			case NT_STATUS_DEVICE_BUSY:
dd89bb
				return NT_STATUS_DEVICE_BUSY;
dd89bb
dd89bb
			default:
dd89bb
				break;
dd89bb
		}
dd89bb
	}
dd89bb
dd89bb
	return NT_STATUS_ALLOCATE_BUCKET;
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t __fastcall __ntapi_blt_obtain(
dd89bb
	__in	nt_blitter *	blitter,
dd89bb
	__out	intptr_t *	blkid)
dd89bb
{
dd89bb
	unsigned int	bit;
dd89bb
	uintptr_t	i,n;
dd89bb
	uintptr_t	mask;
dd89bb
dd89bb
	if (blitter->info.blocks_avail == 0)
dd89bb
		return NT_STATUS_ALLOCATE_BUCKET;
dd89bb
	else if ((bit = *blkid % sizeof(size_t)) == 0)
dd89bb
		return __ntapi_blt_acquire(blitter,blkid);
dd89bb
dd89bb
	for (n=0,mask=(uintptr_t)-1; n
dd89bb
		mask ^= ((size_t)1 << n);
dd89bb
dd89bb
	i = *blkid / (8*sizeof(size_t));
dd89bb
dd89bb
	for (n=0; blitter->info.blocks_avail && (n < blitter->params.round_trips); n++) {
dd89bb
		if (!(at_bsf(&bit,(mask & blitter->bitmap[i]))))
dd89bb
			break;
dd89bb
dd89bb
		switch (__blt_bitbite(blitter,bit,i)) {
dd89bb
			case NT_STATUS_SUCCESS:
dd89bb
				*blkid = bit + (i * 8 * sizeof(size_t));
dd89bb
				return NT_STATUS_SUCCESS;
dd89bb
dd89bb
			case NT_STATUS_DEVICE_BUSY:
dd89bb
				return NT_STATUS_DEVICE_BUSY;
dd89bb
dd89bb
			default:
dd89bb
				break;
dd89bb
		}
dd89bb
	}
dd89bb
dd89bb
	*blkid = ++i * 8 * sizeof(size_t);
dd89bb
	return __blt_acquire(blitter,blkid);
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t __fastcall __ntapi_blt_possess(
dd89bb
	__in	nt_blitter *	blitter,
dd89bb
	__out	intptr_t *	blkid)
dd89bb
{
dd89bb
	int		bit;
dd89bb
	size_t		byte;
dd89bb
	uintptr_t 	test;
dd89bb
	uintptr_t	mask;
dd89bb
dd89bb
	bit  = *blkid % (8*sizeof(size_t));
dd89bb
	byte = *blkid / (8*sizeof(size_t));
dd89bb
dd89bb
	mask = ((uintptr_t)1 << bit);
dd89bb
	test  = at_locked_and(
dd89bb
		(intptr_t *)&blitter->bitmap[byte],
dd89bb
		~mask);
dd89bb
dd89bb
	if (test & mask) {
dd89bb
		at_locked_dec(&blitter->info.blocks_avail);
dd89bb
		at_locked_inc(&blitter->info.blocks_used);
dd89bb
	}
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t __fastcall __ntapi_blt_acquire(
dd89bb
	__in	nt_blitter *	blitter,
dd89bb
	__out	intptr_t *	blkid)
dd89bb
{
dd89bb
	*blkid = 0;
dd89bb
	return __blt_acquire(blitter,blkid);
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t __fastcall	__ntapi_blt_release(
dd89bb
	__in	nt_blitter *	blitter,
dd89bb
	__out	intptr_t	blkid)
dd89bb
{
dd89bb
	size_t		i;
dd89bb
	unsigned int	idx;
dd89bb
	uintptr_t	bit;
dd89bb
dd89bb
	i   = blkid / (8 * sizeof(uintptr_t));
dd89bb
	idx = blkid % (8 * sizeof(uintptr_t));
dd89bb
	bit = ((uintptr_t)1 << idx);
dd89bb
dd89bb
	at_locked_or((intptr_t *)&blitter->bitmap[i],bit);
dd89bb
	at_locked_dec(&blitter->info.blocks_used);
dd89bb
	at_locked_inc(&blitter->info.blocks_avail);
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
dd89bb
dd89bb
void * __fastcall __ntapi_blt_get(
dd89bb
	__in	const nt_blitter *	blitter,
dd89bb
	__in	intptr_t		block_id)
dd89bb
{
dd89bb
	size_t * addr = (size_t *)blitter->info.region_addr;
dd89bb
	addr += block_id;
dd89bb
	return addr;
dd89bb
}
dd89bb
dd89bb
dd89bb
void __fastcall __ntapi_blt_set(
dd89bb
	__in	const nt_blitter *	blitter,
dd89bb
	__in	intptr_t		block_id,
dd89bb
	__in	void *			val)
dd89bb
{
dd89bb
	size_t * addr = (size_t *)blitter->info.region_addr;
dd89bb
	addr += block_id;
dd89bb
	*addr = (size_t)val;
dd89bb
	return;
dd89bb
}