More stuff that I thought I already checked in (did cvs burp ?)

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8436 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
shadow303 2004-07-20 02:19:46 +00:00
parent 5f6e3f515c
commit ed03de4ccf
4 changed files with 488 additions and 0 deletions

View File

@ -0,0 +1,13 @@
SubDir OBOS_TOP src add-ons kernel drivers graphics common ;
SubDirCcFlags -DENABLE_LOGGING -DLOG_INCLUDE_STARTUP ;
UsePrivateHeaders graphics ;
UsePrivateHeaders [ FDirName graphics radeon ] ;
UsePrivateHeaders [ FDirName graphics common ] ;
StaticLibrary graphicscommon :
log_coll.c
log_dump.c
memmgr.c
;

View File

@ -0,0 +1,129 @@
/*
Copyright (c) 2002, Thomas Kurschel
Part of Radeon driver
Both kernel and user space part.
(init and clean-up must be done in
kernel space).
*/
#include <KernelExport.h>
#include <stdlib.h>
#include <stdarg.h>
#include <perfmon_kernel.h>
#include "log_coll.h"
#include <OS.h>
#include <string.h>
typedef struct log_info_t {
char *log_buffer;
uint32 log_buffer_len;
uint32 log_buffer_pos;
area_id area;
} log_info;
#ifdef ENABLE_LOGGING
// write one log entry
void log( log_info *li, uint16 what, const uint8 num_args, ... )
{
uint32 pos;
va_list vl;
log_entry *entry;
uint32 i;
uint32 entry_size;
entry_size = sizeof( log_entry ) + (num_args - 1) * sizeof( uint32 );
pos = atomic_add( &li->log_buffer_pos, entry_size );
if( li->log_buffer_pos > li->log_buffer_len ) {
atomic_add( &li->log_buffer_pos, -entry_size );
return;
}
entry = (log_entry *)&li->log_buffer[pos];
entry->tsc = read_tsc();
entry->what = what;
entry->num_args = num_args;
va_start( vl, num_args );
for( i = 0; i < num_args; ++i ) {
entry->args[i] = va_arg( vl, uint32 );
}
va_end( vl );
}
#ifdef LOG_INCLUDE_STARTUP
// create log buffer
log_info *log_init( uint32 size )
{
log_info *li;
area_id area;
// buffer must be accessible from user mem
// to allow logging from there as well;
// you cannot clone this area as there are
// pointers which would break (it wouldn't be
// hard to get rid of them, but I don't care
// and keep it as simple as possible)
area = create_area( "fast_logger",
(void **)&li, B_ANY_KERNEL_ADDRESS,
(sizeof( log_info ) + size + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1),
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA );
if( area < 0 )
panic( "Radeon Fast logger: cannot allocate %ld byte for logging data\n", size );
li->area = area;
li->log_buffer = (char *)li + sizeof( log_info );
li->log_buffer_len = size;
li->log_buffer_pos = 0;
return li;
}
// clean-up logging
void log_exit( log_info *li )
{
li->log_buffer_pos = 0;
//free( li->log_buffer );
delete_area( li->area );
}
#endif
#endif
#ifdef LOG_INCLUDE_STARTUP
// get *current* size of logging data
uint32 log_getsize( log_info *li )
{
if( li == NULL )
return 0;
dprintf( "RADEON -- log_getsize: log_pos %ld\n", li->log_buffer_pos );
return li->log_buffer_pos;
}
// get up to max_size bytes of logging data
void log_getcopy( log_info *li, void *dest, uint32 max_size )
{
if( li == NULL )
return;
dprintf( "RADEON -- log_getcopy: max_size %ld, log_pos %ld\n",
max_size, li->log_buffer_pos );
memcpy( dest, li->log_buffer, min( li->log_buffer_pos, max_size ));
li->log_buffer_pos = 0;
}
#endif

View File

@ -0,0 +1,73 @@
/*
Copyright (c) 2002, Thomas Kurschel
Part of Radeon driver
Fast logger - functions to create dump
*/
#include <stdio.h>
#include <OS.h>
#include "log_coll.h"
#include "log_dump.h"
#include "log_enum.h"
#include "log_names.h"
system_info sysinfo;
// dump one entry
void log_printentry( FILE *logfile, log_entry *entry )
{
uint64 time;
uint32 min, sec, mill, mic;
time = entry->tsc / (sysinfo.cpu_clock_speed / 1000000);
mic = time % 1000;
time /= 1000;
mill = time % 1000;
time /= 1000;
sec = time % 60;
time /= 60;
min = time;
fprintf( logfile, "%03ld:%02ld:%03ld.%03ld ", min, sec, mill, mic );
if( entry->what < sizeof( log_names ) / sizeof( log_names[0] ) )
fprintf( logfile, log_names[entry->what] );
else
fprintf( logfile, "unknown %ld", (uint32)entry->what );
if( entry->num_args > 0 ) {
uint32 i;
fprintf( logfile, " (" );
for( i = 0; i < entry->num_args; ++i ) {
if( i > 0 )
fprintf( logfile, ", " );
fprintf( logfile, "0x%08lx", entry->args[i] );
}
fprintf( logfile, ")" );
}
fprintf( logfile, "\n" );
}
// dump entire log
void log_printall( FILE *logfile, char *buffer, uint32 buffer_len )
{
uint32 pos;
get_system_info( &sysinfo );
for( pos = 0; pos < buffer_len; ) {
log_entry *entry;
entry = (log_entry *)(buffer + pos);
log_printentry( logfile, entry/*, &tsc*/ );
pos += sizeof( log_entry ) + (entry->num_args - 1) * sizeof( uint32 );
}
}

View File

@ -0,0 +1,273 @@
/*
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;
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;
mem->heap = malloc( heap_entries * sizeof( mem_block ));
if( mem->heap == NULL )
goto err3;
for( i = 1; i < heap_entries; ++i )
mem->heap[i].next = &mem->heap[i+1];
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, "" );
free( mem->heap );
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" );
}