* Renamed memmgr.c|h to memory_manager.c|h.
* The functions now check the acquire_sem() result. * mem_freetag() will return an status code now, too. * Moved the mem_block and mem_info definitions into the source file; no reason to have them public. * You can now give the memory manager a name which it will use for its heap area and lock. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17221 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2002, Thomas Kurschel
|
|
||||||
|
|
||||||
|
|
||||||
Part of Radeon kernel driver
|
|
||||||
|
|
||||||
Memory manager used for graphics mem
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _MEMMGR_H
|
|
||||||
#define _MEMMGR_H
|
|
||||||
|
|
||||||
#include <OS.h>
|
|
||||||
|
|
||||||
|
|
||||||
// allocated memory block
|
|
||||||
typedef struct mem_block {
|
|
||||||
struct mem_block *prev, *next;
|
|
||||||
uint32 base;
|
|
||||||
uint32 size;
|
|
||||||
void *tag;
|
|
||||||
bool alloced;
|
|
||||||
} mem_block;
|
|
||||||
|
|
||||||
|
|
||||||
// memory heap
|
|
||||||
typedef struct mem_info {
|
|
||||||
mem_block *first;
|
|
||||||
area_id heap_area;
|
|
||||||
uint32 block_size;
|
|
||||||
sem_id lock;
|
|
||||||
mem_block *heap;
|
|
||||||
mem_block *unused;
|
|
||||||
uint32 heap_entries;
|
|
||||||
} mem_info;
|
|
||||||
|
|
||||||
|
|
||||||
mem_info *mem_init( uint32 start, uint32 len, uint32 block_size, uint32 heap_entries );
|
|
||||||
void mem_destroy( mem_info *mem );
|
|
||||||
status_t mem_alloc( mem_info *mem, uint32 size, void *tag, uint32 *block, uint32 *offset );
|
|
||||||
status_t mem_free( mem_info *mem, uint32 block_id, void *tag );
|
|
||||||
void mem_freetag( mem_info *mem, void *tag );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku Inc.
|
||||||
|
* Copyright 2002, Thomas Kurschel.
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef _MEMORY_MANAGER_H
|
||||||
|
#define _MEMORY_MANAGER_H
|
||||||
|
|
||||||
|
/** Memory manager used for graphics mem */
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct mem_info mem_info;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mem_info *mem_init(const char *name, uint32 start, uint32 length, uint32 blockSize,
|
||||||
|
uint32 heapEntries);
|
||||||
|
void mem_destroy(mem_info *mem);
|
||||||
|
status_t mem_alloc(mem_info *mem, uint32 size, void *tag, uint32 *blockID, uint32 *offset);
|
||||||
|
status_t mem_free(mem_info *mem, uint32 blockID, void *tag);
|
||||||
|
status_t mem_freetag(mem_info *mem, void *tag);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _MEMORY_MANAGER_H */
|
||||||
@@ -9,5 +9,5 @@ UsePrivateHeaders [ FDirName graphics common ] ;
|
|||||||
StaticLibrary libgraphicscommon.a :
|
StaticLibrary libgraphicscommon.a :
|
||||||
log_coll.c
|
log_coll.c
|
||||||
log_dump.c
|
log_dump.c
|
||||||
memmgr.c
|
memory_manager.c
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,282 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2002, Thomas Kurschel
|
|
||||||
|
|
||||||
|
|
||||||
Part of Radeon kernel driver
|
|
||||||
|
|
||||||
Memory manager used for graphics mem
|
|
||||||
|
|
||||||
|
|
||||||
It has the following features
|
|
||||||
- doesn't access memory to be managed
|
|
||||||
- memory block's owner is identified by tag,
|
|
||||||
tag is verified during free, and all memory
|
|
||||||
belonging to one tag can be freed at once
|
|
||||||
- multi-threading save
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "memmgr.h"
|
|
||||||
#include <malloc.h>
|
|
||||||
#include "KernelExport.h"
|
|
||||||
|
|
||||||
#define debug_level_flow 4
|
|
||||||
#define debug_level_info 4
|
|
||||||
#define debug_level_error 4
|
|
||||||
|
|
||||||
#define DEBUG_MSG_PREFIX "Graphics Driver - "
|
|
||||||
#include "debug_ext.h"
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#ifndef _KERNEL_MODE
|
|
||||||
void _kdprintf_(const char *format, ...);
|
|
||||||
//bool set_dprintf_enabled(bool); /* returns old enable flag */
|
|
||||||
|
|
||||||
#define dprintf _kdprintf_
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// init manager
|
|
||||||
// start - start of address space
|
|
||||||
// len - len of address space
|
|
||||||
// block_size - granularity
|
|
||||||
// heap_entries - maximum number of blocks
|
|
||||||
mem_info *mem_init( uint32 start, uint32 len, uint32 block_size, uint32 heap_entries )
|
|
||||||
{
|
|
||||||
mem_block *first;
|
|
||||||
mem_info *mem;
|
|
||||||
uint i;
|
|
||||||
uint32 size;
|
|
||||||
|
|
||||||
SHOW_FLOW( 2, "start=%lx, len=%lx, block_size=%lx, heap_entries=%ld",
|
|
||||||
start, len, block_size, heap_entries );
|
|
||||||
|
|
||||||
mem = malloc( sizeof( *mem ));
|
|
||||||
if( mem == NULL )
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
mem->block_size = block_size;
|
|
||||||
mem->heap_entries = heap_entries;
|
|
||||||
mem->lock = create_sem( 1, "mem_lock" );
|
|
||||||
|
|
||||||
if( mem->lock < 0 )
|
|
||||||
goto err2;
|
|
||||||
|
|
||||||
// align size to B_PAGE_SIZE
|
|
||||||
size = heap_entries * sizeof(mem_block);
|
|
||||||
if ((size / B_PAGE_SIZE) * B_PAGE_SIZE != size)
|
|
||||||
size = ((size / B_PAGE_SIZE) + 1) * B_PAGE_SIZE;
|
|
||||||
|
|
||||||
mem->heap_area = create_area("memmgr_heap_area", (void **)&mem->heap,
|
|
||||||
B_ANY_ADDRESS, size, B_FULL_LOCK,
|
|
||||||
B_READ_AREA | B_WRITE_AREA);
|
|
||||||
|
|
||||||
if (mem->heap_area < 0 || mem->heap == NULL)
|
|
||||||
goto err3;
|
|
||||||
|
|
||||||
for( i = 1; i < heap_entries; ++i )
|
|
||||||
mem->heap[i-1].next = &mem->heap[i];
|
|
||||||
|
|
||||||
mem->heap[heap_entries - 1].next = NULL;
|
|
||||||
mem->unused = &mem->heap[1];
|
|
||||||
|
|
||||||
first = &mem->heap[0];
|
|
||||||
mem->first = first;
|
|
||||||
|
|
||||||
first->base = start;
|
|
||||||
first->size = len;
|
|
||||||
first->prev = first->next = NULL;
|
|
||||||
first->alloced = false;
|
|
||||||
|
|
||||||
return mem;
|
|
||||||
|
|
||||||
err3:
|
|
||||||
delete_sem( mem->lock );
|
|
||||||
err2:
|
|
||||||
free( mem );
|
|
||||||
err:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// destroy heap
|
|
||||||
void mem_destroy( mem_info *mem )
|
|
||||||
{
|
|
||||||
SHOW_FLOW0( 2, "" );
|
|
||||||
|
|
||||||
delete_area(mem->heap_area);
|
|
||||||
delete_sem(mem->lock);
|
|
||||||
free(mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// allocate memory block
|
|
||||||
// in:
|
|
||||||
// mem - heap handle
|
|
||||||
// size - size in bytes
|
|
||||||
// tag - owner tag
|
|
||||||
// out:
|
|
||||||
// block_id - block id
|
|
||||||
// offset - start address of block
|
|
||||||
status_t mem_alloc( mem_info *mem, uint32 size, void *tag, uint32 *block_id, uint32 *offset )
|
|
||||||
{
|
|
||||||
mem_block *cur, *new_entry;
|
|
||||||
|
|
||||||
SHOW_FLOW( 2, "size=%ld, tag=%p", size, tag );
|
|
||||||
|
|
||||||
acquire_sem( mem->lock );
|
|
||||||
|
|
||||||
// we assume block_size is power of two
|
|
||||||
size = (size + mem->block_size - 1) & ~(mem->block_size - 1);
|
|
||||||
|
|
||||||
// simple first fit
|
|
||||||
for( cur = mem->first; cur; cur = cur->next ) {
|
|
||||||
if( !cur->alloced && cur->size >= size )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( cur == NULL ) {
|
|
||||||
SHOW_FLOW0( 2, "out of memory" );
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( size != cur->size ) {
|
|
||||||
new_entry = mem->unused;
|
|
||||||
|
|
||||||
if( new_entry == NULL ) {
|
|
||||||
SHOW_FLOW0( 2, "out of blocks" );
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
mem->unused = new_entry->next;
|
|
||||||
|
|
||||||
new_entry->next = cur->next;
|
|
||||||
new_entry->prev = cur;
|
|
||||||
new_entry->alloced = false;
|
|
||||||
new_entry->base = cur->base + size;
|
|
||||||
new_entry->size = cur->size - size;
|
|
||||||
|
|
||||||
if( cur->next )
|
|
||||||
cur->next->prev = new_entry;
|
|
||||||
|
|
||||||
cur->next = new_entry;
|
|
||||||
cur->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur->alloced = true;
|
|
||||||
cur->tag = tag;
|
|
||||||
|
|
||||||
*block_id = cur - mem->heap + 1;
|
|
||||||
*offset = cur->base;
|
|
||||||
|
|
||||||
release_sem( mem->lock );
|
|
||||||
|
|
||||||
SHOW_FLOW( 2, "block_id=%ld, offset=%lx", *block_id, *offset );
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
err:
|
|
||||||
release_sem( mem->lock );
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// merge "block" with successor
|
|
||||||
static void merge( mem_info *mem, mem_block *block )
|
|
||||||
{
|
|
||||||
mem_block *next;
|
|
||||||
|
|
||||||
next = block->next;
|
|
||||||
|
|
||||||
block->size += next->size;
|
|
||||||
|
|
||||||
if( next->next )
|
|
||||||
next->next->prev = block;
|
|
||||||
|
|
||||||
block->next = next->next;
|
|
||||||
|
|
||||||
next->next = mem->unused;
|
|
||||||
mem->unused = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// internal: free memory block including merge
|
|
||||||
static mem_block *freeblock( mem_info *mem, mem_block *block )
|
|
||||||
{
|
|
||||||
mem_block *prev, *next;
|
|
||||||
|
|
||||||
block->alloced = false;
|
|
||||||
|
|
||||||
prev = block->prev;
|
|
||||||
|
|
||||||
if( prev && !prev->alloced ) {
|
|
||||||
block = prev;
|
|
||||||
merge( mem, prev );
|
|
||||||
}
|
|
||||||
|
|
||||||
next = block->next;
|
|
||||||
|
|
||||||
if( next && !next->alloced )
|
|
||||||
merge( mem, block );
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// free memory
|
|
||||||
// mem - heap handle
|
|
||||||
// block_id - block id
|
|
||||||
// tag - owner tag (must match tag passed to mem_alloc)
|
|
||||||
status_t mem_free( mem_info *mem, uint32 block_id, void *tag )
|
|
||||||
{
|
|
||||||
mem_block *block;
|
|
||||||
|
|
||||||
SHOW_FLOW( 2, "block_id=%ld, tag=%p", block_id, tag );
|
|
||||||
|
|
||||||
acquire_sem( mem->lock );
|
|
||||||
|
|
||||||
--block_id;
|
|
||||||
|
|
||||||
if( block_id >= mem->heap_entries ) {
|
|
||||||
SHOW_ERROR0( 2, "invalid id" );
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
block = &mem->heap[block_id];
|
|
||||||
if( !block->alloced || block->tag != tag ) {
|
|
||||||
SHOW_ERROR0( 2, "not owner" );
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeblock( mem, block );
|
|
||||||
|
|
||||||
release_sem( mem->lock );
|
|
||||||
|
|
||||||
SHOW_FLOW0( 2, "success" );
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
err:
|
|
||||||
release_sem( mem->lock );
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// free all memory belonging to owner "tag"
|
|
||||||
void mem_freetag( mem_info *mem, void *tag )
|
|
||||||
{
|
|
||||||
mem_block *cur;
|
|
||||||
|
|
||||||
SHOW_FLOW( 2, "tag=%p", tag );
|
|
||||||
|
|
||||||
acquire_sem( mem->lock );
|
|
||||||
|
|
||||||
for( cur = mem->first; cur; cur = cur->next ) {
|
|
||||||
if( cur->alloced && cur->tag == tag )
|
|
||||||
cur = freeblock( mem, cur );
|
|
||||||
}
|
|
||||||
|
|
||||||
release_sem( mem->lock );
|
|
||||||
|
|
||||||
SHOW_FLOW0( 2, "done" );
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,316 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku Inc.
|
||||||
|
* Copyright 2002, Thomas Kurschel.
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Memory manager used for graphics mem
|
||||||
|
*
|
||||||
|
* It has the following features
|
||||||
|
* - doesn't access memory to be managed
|
||||||
|
* - memory block's owner is identified by tag,
|
||||||
|
* tag is verified during free, and all memory
|
||||||
|
* belonging to one tag can be freed at once
|
||||||
|
* - multi-threading save
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "memory_manager.h"
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_MEMORY_MANAGER
|
||||||
|
#ifdef TRACE_MEMORY_MANAGER
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// allocated memory block
|
||||||
|
typedef struct mem_block {
|
||||||
|
struct mem_block *prev, *next;
|
||||||
|
uint32 base;
|
||||||
|
uint32 size;
|
||||||
|
void *tag;
|
||||||
|
bool allocated;
|
||||||
|
} mem_block;
|
||||||
|
|
||||||
|
// memory heap
|
||||||
|
struct mem_info {
|
||||||
|
mem_block *first;
|
||||||
|
area_id heap_area;
|
||||||
|
uint32 block_size;
|
||||||
|
sem_id lock;
|
||||||
|
mem_block *heap;
|
||||||
|
mem_block *unused;
|
||||||
|
uint32 heap_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** merge "block" with successor */
|
||||||
|
|
||||||
|
static void
|
||||||
|
merge(mem_info *mem, mem_block *block)
|
||||||
|
{
|
||||||
|
mem_block *next = block->next;
|
||||||
|
|
||||||
|
block->size += next->size;
|
||||||
|
|
||||||
|
if (next->next)
|
||||||
|
next->next->prev = block;
|
||||||
|
|
||||||
|
block->next = next->next;
|
||||||
|
next->next = mem->unused;
|
||||||
|
mem->unused = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** free memory block including merge */
|
||||||
|
|
||||||
|
static mem_block *
|
||||||
|
freeblock(mem_info *mem, mem_block *block)
|
||||||
|
{
|
||||||
|
mem_block *prev, *next;
|
||||||
|
|
||||||
|
block->allocated = false;
|
||||||
|
prev = block->prev;
|
||||||
|
|
||||||
|
if (prev && !prev->allocated) {
|
||||||
|
block = prev;
|
||||||
|
merge(mem, prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
next = block->next;
|
||||||
|
|
||||||
|
if (next && !next->allocated)
|
||||||
|
merge(mem, block);
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
/** Init memory manager.
|
||||||
|
*
|
||||||
|
* \param start start of address space
|
||||||
|
* \param length length of address space
|
||||||
|
* \param blockSize - granularity
|
||||||
|
* \param heapEntries - maximum number of blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
mem_info *
|
||||||
|
mem_init(const char* name, uint32 start, uint32 length,
|
||||||
|
uint32 blockSize, uint32 heapEntries)
|
||||||
|
{
|
||||||
|
mem_block *first;
|
||||||
|
mem_info *mem;
|
||||||
|
uint i;
|
||||||
|
uint32 size;
|
||||||
|
|
||||||
|
TRACE(("mem_init(name=%s, start=%lx, length=%lx, blockSize=%lx, heapEntries=%ld)\n",
|
||||||
|
name, start, length, blockSize, heapEntries));
|
||||||
|
|
||||||
|
mem = malloc(sizeof(*mem));
|
||||||
|
if (mem == NULL)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
|
mem->block_size = blockSize;
|
||||||
|
mem->heap_entries = heapEntries;
|
||||||
|
mem->lock = create_sem(1, name);
|
||||||
|
if (mem->lock < 0)
|
||||||
|
goto err2;
|
||||||
|
|
||||||
|
// align size to B_PAGE_SIZE
|
||||||
|
size = heapEntries * sizeof(mem_block);
|
||||||
|
size = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
|
||||||
|
|
||||||
|
mem->heap_area = create_area(name, (void **)&mem->heap,
|
||||||
|
B_ANY_ADDRESS, size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||||
|
|
||||||
|
if (mem->heap_area < 0 || mem->heap == NULL)
|
||||||
|
goto err3;
|
||||||
|
|
||||||
|
for (i = 1; i < heapEntries; ++i) {
|
||||||
|
mem->heap[i - 1].next = &mem->heap[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
mem->heap[heapEntries - 1].next = NULL;
|
||||||
|
mem->unused = &mem->heap[1];
|
||||||
|
|
||||||
|
first = &mem->heap[0];
|
||||||
|
mem->first = first;
|
||||||
|
|
||||||
|
first->base = start;
|
||||||
|
first->size = length;
|
||||||
|
first->prev = first->next = NULL;
|
||||||
|
first->allocated = false;
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
|
||||||
|
err3:
|
||||||
|
delete_sem(mem->lock);
|
||||||
|
err2:
|
||||||
|
free(mem);
|
||||||
|
err1:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** destroy heap */
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_destroy(mem_info *mem)
|
||||||
|
{
|
||||||
|
TRACE(("mem_destroy(mem %p)\n", mem));
|
||||||
|
|
||||||
|
delete_area(mem->heap_area);
|
||||||
|
delete_sem(mem->lock);
|
||||||
|
free(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Allocate memory block
|
||||||
|
*
|
||||||
|
* \param mem heap handle
|
||||||
|
* \param size size in bytes
|
||||||
|
* \param tag owner tag
|
||||||
|
*
|
||||||
|
* \param blockID - returns block id
|
||||||
|
* \param offset - returns start address of block
|
||||||
|
*/
|
||||||
|
|
||||||
|
status_t
|
||||||
|
mem_alloc(mem_info *mem, uint32 size, void *tag, uint32 *blockID, uint32 *offset)
|
||||||
|
{
|
||||||
|
mem_block *current, *newEntry;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
TRACE(("mem_alloc(mem %p, size=%ld, tag=%p", mem, size, tag));
|
||||||
|
|
||||||
|
status = acquire_sem(mem->lock);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// we assume block_size is power of two
|
||||||
|
size = (size + mem->block_size - 1) & ~(mem->block_size - 1);
|
||||||
|
|
||||||
|
// simple first fit
|
||||||
|
for (current = mem->first; current; current = current->next) {
|
||||||
|
if (!current->allocated && current->size >= size)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == NULL) {
|
||||||
|
TRACE(("mem_alloc: out of memory\n"));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != current->size) {
|
||||||
|
newEntry = mem->unused;
|
||||||
|
|
||||||
|
if (newEntry == NULL) {
|
||||||
|
TRACE(("mem_alloc: out of blocks\n"));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem->unused = newEntry->next;
|
||||||
|
|
||||||
|
newEntry->next = current->next;
|
||||||
|
newEntry->prev = current;
|
||||||
|
newEntry->allocated = false;
|
||||||
|
newEntry->base = current->base + size;
|
||||||
|
newEntry->size = current->size - size;
|
||||||
|
|
||||||
|
if (current->next)
|
||||||
|
current->next->prev = newEntry;
|
||||||
|
|
||||||
|
current->next = newEntry;
|
||||||
|
current->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
current->allocated = true;
|
||||||
|
current->tag = tag;
|
||||||
|
|
||||||
|
*blockID = current - mem->heap + 1;
|
||||||
|
*offset = current->base;
|
||||||
|
|
||||||
|
release_sem(mem->lock);
|
||||||
|
|
||||||
|
TRACE(("mem_alloc(block_id=%ld, offset=%lx)\n", *blockID, *offset));
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
err:
|
||||||
|
release_sem(mem->lock);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Free memory
|
||||||
|
* \param mem heap handle
|
||||||
|
* \param blockID block id
|
||||||
|
* \param tag owner tag (must match tag passed to mem_alloc())
|
||||||
|
*/
|
||||||
|
|
||||||
|
status_t
|
||||||
|
mem_free(mem_info *mem, uint32 blockID, void *tag)
|
||||||
|
{
|
||||||
|
mem_block *block;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
TRACE(("mem_free(mem %p, blockID=%ld, tag=%p)\n", mem, blockID, tag));
|
||||||
|
|
||||||
|
status = acquire_sem(mem->lock);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
--blockID;
|
||||||
|
|
||||||
|
if (blockID >= mem->heap_entries) {
|
||||||
|
TRACE(("mem_free: invalid ID %lu\n", blockID));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = &mem->heap[blockID];
|
||||||
|
if (!block->allocated || block->tag != tag) {
|
||||||
|
TRACE(("mem_free: not owner\n"));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeblock(mem, block);
|
||||||
|
|
||||||
|
release_sem(mem->lock);
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
err:
|
||||||
|
release_sem(mem->lock);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Free all memory belonging to owner "tag" */
|
||||||
|
|
||||||
|
status_t
|
||||||
|
mem_freetag(mem_info *mem, void *tag)
|
||||||
|
{
|
||||||
|
mem_block *current;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
TRACE(("mem_freetag(mem %p, tag=%p)\n", mem, tag));
|
||||||
|
|
||||||
|
status = acquire_sem(mem->lock);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
for (current = mem->first; current; current = current->next) {
|
||||||
|
if (current->allocated && current->tag == tag)
|
||||||
|
current = freeblock(mem, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
release_sem(mem->lock);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2002, Thomas Kurschel
|
* Copyright (c) 2002, Thomas Kurschel
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
Part of Radeon kernel driver
|
/** Graphics card detection */
|
||||||
|
|
||||||
Graphics card detection
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "radeon_driver.h"
|
#include "radeon_driver.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
// this table is gathered from different sources
|
// this table is gathered from different sources
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2002-2004, Thomas Kurschel
|
* Copyright (c) 2002-2004, Thomas Kurschel
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
Part of Radeon kernel driver
|
|
||||||
|
|
||||||
Init and clean-up of devices
|
Init and clean-up of devices
|
||||||
|
|
||||||
TBD: support for multiple virtual card per device is
|
TODO: support for multiple virtual card per device is
|
||||||
not implemented yet - there is only one per device;
|
not implemented yet - there is only one per device;
|
||||||
apart from additional device names, we need proper
|
apart from additional device names, we need proper
|
||||||
management of graphics mem to not interfere.
|
management of graphics mem to not interfere.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dac_regs.h"
|
||||||
#include "radeon_driver.h"
|
#include "radeon_driver.h"
|
||||||
|
#include "mmio.h"
|
||||||
|
|
||||||
#include <PCI.h>
|
#include <PCI.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "dac_regs.h"
|
#include <string.h>
|
||||||
#include "mmio.h"
|
|
||||||
|
|
||||||
// helper macros for easier PCI access
|
// helper macros for easier PCI access
|
||||||
#define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
|
#define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
|
||||||
@@ -309,17 +311,17 @@ status_t Radeon_FirstOpen( device_info *di )
|
|||||||
// resolution of 2D register is 1K, resolution of CRTC etc. is higher,
|
// resolution of 2D register is 1K, resolution of CRTC etc. is higher,
|
||||||
// so 1K is the minimum block size;
|
// so 1K is the minimum block size;
|
||||||
// (CP cannot use local mem)
|
// (CP cannot use local mem)
|
||||||
di->memmgr[mt_local] = mem_init( 0, di->local_mem_size, 1024,
|
di->memmgr[mt_local] = mem_init("radeon local memory", 0, di->local_mem_size, 1024,
|
||||||
di->local_mem_size / 1024 );
|
di->local_mem_size / 1024);
|
||||||
if( di->memmgr[mt_local] == NULL ) {
|
if (di->memmgr[mt_local] == NULL) {
|
||||||
result = B_NO_MEMORY;
|
result = B_NO_MEMORY;
|
||||||
goto err3;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CP requires 4K alignment, which is the most restrictive I found
|
// CP requires 4K alignment, which is the most restrictive I found
|
||||||
di->memmgr[mt_PCI] = mem_init( 0, di->pci_gart.buffer.size, 4096,
|
di->memmgr[mt_PCI] = mem_init("radeon PCI GART memory", 0, di->pci_gart.buffer.size, 4096,
|
||||||
di->pci_gart.buffer.size / 4096 );
|
di->pci_gart.buffer.size / 4096);
|
||||||
if( di->memmgr[mt_PCI] == NULL ) {
|
if (di->memmgr[mt_PCI] == NULL) {
|
||||||
result = B_NO_MEMORY;
|
result = B_NO_MEMORY;
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2002-2004, Thomas Kurschel
|
* Copyright (c) 2002-2004, Thomas Kurschel
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
Part of Radeon kernel driver
|
|
||||||
|
|
||||||
Common header file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _RADEON_DRIVER_H
|
#ifndef _RADEON_DRIVER_H
|
||||||
#define _RADEON_DRIVER_H
|
#define _RADEON_DRIVER_H
|
||||||
|
|
||||||
|
|
||||||
#include "radeon_interface.h"
|
#include "radeon_interface.h"
|
||||||
#include "memmgr.h"
|
#include "memory_manager.h"
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <GraphicsDefs.h>
|
#include <GraphicsDefs.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user