📄 rvmem.c
字号:
#if (0)
************************************************************************
Filename:
Description:
************************************************************************
Copyright (c) 1999 RADVision Inc.
************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever
without written prior approval by RADVision LTD..
RADVision LTD. reserves the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
************************************************************************
************************************************************************
$Revision:$
$Date:$
$Author: S. Cipolli$
************************************************************************
#endif
#include "rvplatform.h"
#include "rvtypes.h"
#include "rvmem.h"
#if defined(RV_MEM_ANSI)
#include <stdlib.h>
# if defined(RV_MEMTRACE_ON)
#include <stdio.h>
#include "rvmutex.h"
static int rvMemTraceCnt = 0;
static int rvMemTraceMax = 0;
static RvMutex rvMemTraceMutex;
static FILE * rvMemTraceLog = NULL;
static char rvMemTraceChkpName[50];
static int rvMemTraceChkpStart;
typedef struct RvMemTraceRecord_ {
int size;
struct RvMemTraceRecord_ * last;
struct RvMemTraceRecord_ * next;
} RvMemTraceRecord;
static RvMemTraceRecord rvMemTraceFirst = {0,NULL,NULL};
static RvMemTraceRecord * rvMemTraceHead = &rvMemTraceFirst;
static RvMemTraceRecord * rvMemTraceTail = &rvMemTraceFirst;
void rvMemTraceConstruct(void) {
rvMutexConstruct(&rvMemTraceMutex);
rvMemTraceLog = fopen("rvmem.log","w+");
}
void rvMemTraceCheckpoint(const char * chkpname) {
if(rvMemTraceLog!=NULL)
fprintf(rvMemTraceLog,"%-26s %-10u\n",chkpname,rvMemTraceCnt);
}
void rvMemTraceStart(const char * chkpname) {
rvMutexLock(&rvMemTraceMutex);
strcpy(rvMemTraceChkpName,chkpname);
rvMemTraceChkpStart = rvMemTraceCnt;
if(rvMemTraceLog!=NULL)
fprintf(rvMemTraceLog,"Start %-20s %-10u\n",chkpname,rvMemTraceCnt);
rvMutexUnlock(&rvMemTraceMutex);
}
void rvMemTraceStop(const char * chkpname) {
rvMutexLock(&rvMemTraceMutex);
if(rvMemTraceLog!=NULL) {
if(!strcmp(chkpname,rvMemTraceChkpName) )
fprintf(rvMemTraceLog,"Stop %-20s %-10u diff: %-10d max:%-10u\n",rvMemTraceChkpName,
rvMemTraceCnt,rvMemTraceCnt-rvMemTraceChkpStart,rvMemTraceMax);
else
fprintf(rvMemTraceLog,"Stop %-20s %-10u max:%-10u\n",chkpname,rvMemTraceCnt,rvMemTraceMax);
}
rvMutexUnlock(&rvMemTraceMutex);
}
void rvMemTraceDestruct(void) {
FILE * fp;
RvMemTraceRecord * cur = rvMemTraceHead->next;
rvMutexDestruct(&rvMemTraceMutex);
fprintf(rvMemTraceLog,"\nUnreleased memory: %u, Maximal memory used: %u\n",rvMemTraceCnt,rvMemTraceMax);
fclose(rvMemTraceLog);
/* Dump unreleased blocks */
if(rvMemTraceCnt) {
fp = fopen("rvmem_alloc.log","w+");
if(fp) {
fprintf(fp,"Unreleased blocks\n");
while(cur!=NULL) {
fprintf(fp,"Unreleased: address=%p, size=%u\n",
(char *)cur+sizeof(RvMemTraceRecord),cur->size);
cur=cur->next;
}
}
fclose(fp);
}
}
void rvMemTraceSetRecord(size_t n,void * p) {
RvMemTraceRecord * record = (RvMemTraceRecord*)p;
record->size = n;
record->next = NULL;
record->last = rvMemTraceTail;
rvMemTraceTail->next = record;
rvMemTraceTail = record;
}
void* rvMemAlloc_(size_t n) {
size_t n_ = n+sizeof(RvMemTraceRecord);
char * p = malloc(n_);
char * buf;
rvMutexLock(&rvMemTraceMutex);
rvMemTraceCnt+=n;
if(rvMemTraceCnt>rvMemTraceMax)
rvMemTraceMax=rvMemTraceCnt;
rvMemTraceSetRecord(n,p);
rvMutexUnlock(&rvMemTraceMutex);
buf = (char*)p+sizeof(RvMemTraceRecord);
return buf;
}
void rvMemFree_(void* p) {
char * p_ = (char*)p-sizeof(RvMemTraceRecord);
RvMemTraceRecord * record = (RvMemTraceRecord *)p_;
rvMutexLock(&rvMemTraceMutex);
rvMemTraceCnt-=record->size;
/* Free record from linked list */
record->last->next = record->next;
if(record->next!=NULL)
record->next->last = record->last;
else
rvMemTraceTail = record->last;
free(p_);
rvMutexUnlock(&rvMemTraceMutex);
}
RvBool rvMemInit_(void)
{
return rvTrue;
}
void rvMemEnd_(void)
{
}
int rvMemTraceGetMemOut()
{
return rvMemTraceCnt;
}
int rvMemTraceGetPeakMemUsage()
{
return rvMemTraceMax;
}
# else
# define rvMemAlloc_(n) (malloc(n))
# define rvMemFree_(p) (free(p))
RvBool rvMemInit_(void)
{
return rvTrue;
}
void rvMemEnd_(void)
{
}
# endif
#elif defined(RV_MEM_OSE)
#include "ose.h"
#include "heapapi.h"
#define rvMemAlloc_(n) (heap_alloc_shared((n), (__FILE__), (__LINE__)))
#define rvMemFree_(p) (heap_free_shared(p))
RvBool rvMemInit_(void)
{
return rvTrue;
}
void rvMemEnd_(void)
{
}
#elif defined(RV_MEM_NUCLEUS)
#include "nucleus.h"
extern NU_MEMORY_POOL System_Memory;
void *rvMemAlloc_(size_t n)
{
int status;
void *ptr;
status = NU_Allocate_Memory(&System_Memory, &ptr, n, NU_NO_SUSPEND);
if(status != NU_SUCCESS) return NULL;
return ptr;
}
#define rvMemFree_(p) (NU_Deallocate_Memory(p))
RvBool rvMemInit_(void)
{
return rvTrue;
}
void rvMemEnd_(void)
{
}
#elif defined(RV_MEM_PSOS)
#include <psos.h>
#include "rvpool.h"
#include "rvalloc.h"
/* Which psos memory region to use */
#define PSOS_MEM_REGION 0
/* Smallest sub-allocation buffer pool to create. Must be a power */
/* of 2 >= 4 as per pSOS */
#define RVMEM_MINBUFSIZE 32
static RvPool *mempools;
static int numpools;
static unsigned long region_unit_size; /* pSOS forces size to power of 2 >= 16 */
static RvAlloc pSOSalloc;
static void *rvMempSOSrnAlloc(void *rnid, size_t size) {
void *result;
if(rn_getseg((unsigned long)rnid, size, RN_NOWAIT, 0, &result) != 0)
return NULL;
return result;
}
static void rvMempSOSrnFree(void *rnid, size_t size, void *ptr){
rn_retseg((unsigned long)rnid, ptr);
}
void *rvMemAlloc_(size_t request_size)
{
int pool;
int *poolptr;
unsigned long bufsize;
size_t required_size;
char *result;
required_size = request_size + sizeof(pool);
bufsize = RVMEM_MINBUFSIZE;
for(pool = 0; pool < numpools; pool++) {
if(required_size <= bufsize) {
result = (char *)rvPoolAllocate(&mempools[pool]);
if(result == NULL)
return NULL;
poolptr = (int *)result;
*poolptr = pool; /* save pool number for memfree */
result = result + sizeof(*poolptr);
return (void *)result;
}
bufsize = bufsize * 2;
}
/* Go directly to pSOS memory manager */
if(rn_getseg(PSOS_MEM_REGION, required_size, RN_NOWAIT, 0, &result) != 0)
return NULL;
poolptr = (int *)result;
*poolptr = -1; /* store -1 as pool number to indicate direct allocation */
result = result + sizeof(*poolptr);
return (void *)result;
}
void *rvMemFree_(void *p)
{
int *poolptr;
char *result;
if(p == NULL)
return;
result = (char *)p - sizeof(*poolptr);
poolptr = (int *)result;
if(*poolptr == -1) {
/* memory allocated directly from pSOS */
rn_retseg(PSOS_MEM_REGION, result);
return;
}
rvPoolDeallocate(&mempools[*poolptr], result);
}
RvBool rvMemInit_(void)
{
struct rninfo rbuf;
unsigned long bufsize;
int pool;
mempools = NULL;
numpools = 0;
region_unit_size = 0;
rvAllocConstruct(&pSOSalloc, PSOS_MEM_REGION, ~0U, rvMempSOSrnAlloc, rvMempSOSrnFree);
if(rn_info(PSOS_MEM_REGION, &rbuf) != 0)
return rvFalse;
region_unit_size = rbuf.unit_size;
/* figure out number of buffer pools to use */
bufsize = region_unit_size;
for(numpools = 0; bufsize > RVMEM_MINBUFSIZE; numpools++) {
bufsize = bufsize / 2;
}
/* special case, we'll just send calls directly to pSOS */
if(numpools == 0)
return rvTrue;
/* Initialize memory pools */
if(rn_getseg(PSOS_MEM_REGION, numpools * sizeof(RvPool), RN_NOWAIT, 0, (void **)&mempools) != 0) {
return rvFalse;
}
bufsize = RVMEM_MINBUFSIZE;
for(pool = 0; pool < numpools; pool++) {
rvPoolConstructEx1(&mempools[pool], bufsize, region_unit_size * 2, NULL, NULL, NULL, &pSOSalloc);
bufsize = bufsize * 2;
}
return rvTrue;
}
void rvMemEnd_(void)
{
int pool;
if(numpools == 0)
return;
for(pool = 0; pool < numpools; pool++)
rvPoolDestruct(&mempools[pool]);
numpools = 0;
rn_retseg(PSOS_MEM_REGION, mempools);
mempools = NULL;
}
#endif
static RvMemHandler rvMemHandler = NULL;
/*$
{function:
{name: rvMemAlloc}
{superpackage: Util}
{include: rvmem.h}
{description:
{p:
Allocate memory from the "default" dynamic heap. The "default"
dynamic heap is the standard C library functions malloc/free
on most OS's.
}
}
{proto: void* rvMemAlloc(size_t n);}
{params:
{param: {n: n} {d: The number of bytes to allocate.}}
}
{returns:
A pointer to a suitably sized and aligned block of memory or
NULL if memory exhaustion occurs.
}
}
$*/
void* rvMemAlloc(size_t n) {
void* p;
do {
p = rvMemAlloc_(n);
} while ((p == NULL) && (rvMemHandler) && (rvMemHandler(n)));
return p;
}
void* rvMemCalloc(size_t num, size_t size) {
void* p;
size_t total;
total = num * size;
p = rvMemAlloc(total);
if(p != NULL)
memset(p, 0, total);
return p;
}
/*$
{function:
{name: rvMemFree}
{superpackage: Util}
{include: rvmem.h}
{description:
{p:
Deallocate a block of memory pointed to by p. The memory
must have been previously allocated with rvMemAlloc.
}
}
{proto: void rvMemFree(void* p);}
{params:
{param: {n: p} {d: A pointer to the memory block to deallocate.}}
}
}
$*/
void rvMemFree(void* p) {
rvMemFree_(p);
}
/*$
{function scope="protected":
{name: rvMemInit}
{superpackage: Util}
{include: rvmem.h}
{description:
{p:
Initializes memory allocation routines. Must be called
before any allocations.
}
}
{proto: RvBool rvMemInit(void);}
{returns:
rvTrue if successfull, rvFalse if initialization failed.
}
}
$*/
RvBool rvMemInit(void)
{
return rvMemInit_();
}
/*$
{function scope="protected":
{name: rvMemEnd}
{superpackage: Util}
{include: rvmem.h}
{description:
{p:
Cleans up memory allocation routines. Must be called
before system exits.
}
}
{proto: void rvMemEnd(void);}
}
$*/
void rvMemEnd(void)
{
rvMemEnd_();
}
/*$
{function:
{name: rvMemGetHandler}
{superpackage: Util}
{include: rvmem.h}
{description:
{p:
Get the "handler" for the dynamic heap. The handler is a function
pointer, that is called when the heap is exhausted. The handler
can log the event, initiate a safe-shutdown, or take action to
collect enough memory to satisfy the rvMemAlloc that caused the
heap exhaustion.
}
}
{proto: RvMemHandler rvMemGetHandler(void);}
{returns:
A pointer to the "handler" function or NULL if not set.
}
{see_also:
{n: RvMemHandler}
}
}
$*/
RvMemHandler rvMemGetHandler(void) {
return rvMemHandler;
}
/*$
{function:
{name: rvMemSetHandler}
{superpackage: Util}
{include: rvmem.h}
{description:
{p:
Set the "handler" for the dynamic heap. The handler is a function
pointer, that is called when the heap is exhausted. The handler
can log the event, initiate a safe-shutdown, or take action to
collect enough memory to satisfy the rvMemAlloc that caused the
heap exhaustion.
}
}
{proto: RvMemHandler rvMemSetHandler(RvMemHandler h);}
{params:
{param: {n: h} {d: A pointer to the new "handler" function.}}
}
{returns:
A pointer to the previous "handler" function or NULL if not set.
}
{see_also:
{n: RvBool RvMemHandler(size_t n);}
}
}
$*/
RvMemHandler rvMemSetHandler(RvMemHandler h) {
RvMemHandler old = rvMemHandler;
rvMemHandler = h;
return old;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -