|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
64e606 |
/* Copyright (C) 2013--2021 SysDeer Technologies, LLC */
|
|
|
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;
|
|
|
58b5e3 |
else if ((bit = *blkid % (8*sizeof(size_t))) == 0)
|
|
|
7740ea |
return __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;
|
|
|
dc7e61 |
uintptr_t cmp;
|
|
|
dc7e61 |
uintptr_t xchg;
|
|
|
dd89bb |
|
|
|
dd89bb |
bit = *blkid % (8*sizeof(size_t));
|
|
|
dd89bb |
byte = *blkid / (8*sizeof(size_t));
|
|
|
dc7e61 |
mask = (uintptr_t)1 << bit;
|
|
|
dc7e61 |
|
|
|
dc7e61 |
do {
|
|
|
dc7e61 |
cmp = blitter->bitmap[byte];
|
|
|
dc7e61 |
xchg = cmp & ~mask;
|
|
|
dd89bb |
|
|
|
dc7e61 |
test = at_locked_cas(
|
|
|
dc7e61 |
(intptr_t *)&blitter->bitmap[byte],
|
|
|
dc7e61 |
cmp,xchg);
|
|
|
dc7e61 |
} while (test != cmp);
|
|
|
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 |
}
|