/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#define DONT_USE_LOCK

#include	<stdlib.h>
#include	"memory_debug.h"
#include	"lock_level.h"

#ifndef DONT_USE_LOCK
#include	"task.h"
#endif

/*
void *
d_alloc(int size,int type)
{
char * ret;
int i;
	ret = malloc(size);
	for ( i = 0; i < size ;i ++ )
		ret[i] = 0x79;
	return (void*)ret;
}
*/

#ifdef MEMORY_DEBUG

#define ALIGN	2

char*  type_msg[MT_MAX];
int memory_type[MT_MAX];
int memory_size[MT_MAX];
int flag;

#ifndef DONT_USE_LOCK
SEM md_lock;
#endif

#ifdef DONT_USE_LOCK
#define LOCK	{}
#define UNLOCK	{}
#define NEW_LOCK {}
#endif

#ifndef DONT_USE_LOCK
#define LOCK	if ( md_lock ) lock_task(md_lock);
#define UNLOCK	if ( md_lock ) unlock_task(md_lock,"unlock");
#define NEW_LOCK	md_lock = new_lock(LL_MD);
#endif

void
init_type_msg()
{
	if ( flag )
		return;
	flag = 1;
	NEW_LOCK;
	type_msg[18] = "gc_stack_routine.c/thread";
	type_msg[19] = "gc_stack_routine.c/stack";
	type_msg[20] = "gc_stack_routine.c/lst in stack";
	type_msg[99] = "euc_workarea";
	type_msg[101] = "l_string.c/ret";
	type_msg[120] = "copy_str.c";
	type_msg[126] = "ll_copy_str.c/ret";
	type_msg[179] = "account.c/ua";
	type_msg[180] = "agent.c/al";
	type_msg[184] = "init.c/S_ACCEPT";
	type_msg[195] = "min_memory.c/module";
	type_msg[196] = "accept_connection.c/key->s";
	type_msg[1000] = "get_url_filepath";
	type_msg[1001] = "get_url_str2";
	type_msg[1002] = "MAP_PATH_INFO";
	type_msg[1003] = "MAP_PATH_TABLE";
	type_msg[1010] = "in the set_buffer";
	type_msg[1030] = "nl_copy_str";
	type_msg[1500] = "RECT_NODE";
	type_msg[1501] = "insert_point";
	type_msg[1502] = "OBJ";
	type_msg[1503] = "draw_string/data";
	type_msg[1504] = "INFO_LIST";
	type_msg[1505] = "SYMBOL_INDICATE";
	type_msg[1506] = "CODE/AVT";
	type_msg[1507] = "RT_OBJ_LIST";
	type_msg[1508] = "PE after";
	type_msg[1509] = "SI ref ll_copy_str 1";
	type_msg[1510] = "SI ref ll_copy_str 2";
	type_msg[1511] = "radar_lump ll_copy_str 1";
	type_msg[1512] = "radar_lump crdpath ll_copy_Str 1";
	type_msg[1513] = "radar_lump crdpath ll_copy_str 2";
	type_msg[1514] = "radar_lump ll_copy_str 2";
}


void * d_alloc(int size,int type)
{
int * ret;
	init_type_msg();
	LOCK;
	ret = malloc(size+sizeof(int)*ALIGN);
	if ( type > MT_MAX )
		type = 0;
	ret[0] = type;
	ret[1] = size;
	memory_type[type] ++;
	memory_size[type] += size;
	UNLOCK;
	return (void*)(ret+ALIGN);
}



void * d_calloc(int size,int el,int no)
{
char * ret;
int i;
	ret = d_alloc(size*el,no);
	if ( ret == 0 )
		return 0;
	for ( i = 0 ; i < size*el ; i ++ )
		ret[i] = 0;
	return ret;
}

void * d_re_alloc(void * ptr,int size)
{
int * ret;
int type,old_size;
	LOCK;
	if ( ptr == 0 ) {
		UNLOCK;
		return d_alloc(size,0); 
	}
	ret = (int*)ptr;
	ret = ret - ALIGN;
	type = ret[0];
	old_size = ret[1];
	ret = realloc(ret,size+sizeof(int)*ALIGN);
	ret[0] = type;
	ret[1] = size;
	memory_size[type] = memory_size[type] - old_size + size;
	UNLOCK;
	return (void*)(ret+ALIGN);
}

void d_f_ree(void * ptr)
{
int * ret;
int size;
int i;
char * p;
	LOCK;
	ret = ptr;
	ret = ret - ALIGN;

	size = ret[1];
	memory_type[ret[0]] --;
	memory_size[ret[0]] -= size;
	for ( p = ptr, i = size ; i > 0 ; i -- )
		*p++ = 0x37;
	free(ret);
	UNLOCK;
}

void
change_memtype(void * ptr,int type)
{
int * ret;
int old_type;
int size;
	LOCK;
	ret = ptr;
	ret = ret - ALIGN;
	old_type = ret[0];
	size = ret[1];
	ret[0] = type;
	memory_type[old_type] --;
	memory_size[old_type] -= size;
	memory_type[type] ++;
	memory_size[type] += size;
	UNLOCK;
}


void
indicate_md()
{
int i;
int fg;
	printf("----\n");
	fg = 0;
	for ( i = 0 ; i < MT_MAX ; i ++ ) {
		if ( memory_type[i] == 0 )
			continue;
		if ( type_msg[i] )
			printf("(%s - %i) ",type_msg[i],memory_type[i]);
		else	printf("(%i - %i) ",i,memory_type[i]);
		fg = 1;
	}
	if ( fg )
		printf("\n");
}



void
indicate_md_by_large()
{
int i;
int fg;
int max;
int cur_max;
	printf("----\n");
	fg = 0;
	max = 0x7fffffff;
	for ( ; max ; ) {
		cur_max = 0;
		for ( i = 0 ; i < MT_MAX ; i ++ ) {
			if ( memory_type[i] == 0 )
				continue;
			if ( memory_type[i] >= max ) 
				continue;
			if ( cur_max < memory_type[i] )
				cur_max = memory_type[i];
		}
		for ( i = 0 ; i < MT_MAX ; i ++ ) {
			if ( memory_type[i] == 0 )
				continue;
			if ( memory_type[i] != cur_max )
				continue;
			if ( type_msg[i] )
				printf("(%s - %i) ",
					type_msg[i],memory_type[i]);
			else	printf("(%i - %i) ",i,memory_type[i]);
			fg = 1;
		}
		max = cur_max;
	}
	if ( fg )
		printf("\n");
}


void
indicate_md_in_buf(char ** ptr,int * cnt,int * size)
{
int i;
int fg;
	fg = 0;
	for ( i = 0 ; i < MT_MAX ; i ++ ) {
		if ( memory_type[i] == 0 ) {
			ptr[i] = 0;
			cnt[i] = 0;
			size[i] = 0;
			continue;
		}
		if ( type_msg[i] ) {
			ptr[i] = d_alloc(100,12);
			sprintf(ptr[i],"%s",
				type_msg[i],memory_type[i]);
			cnt[i] = memory_type[i];
			size[i] = memory_size[i];
		}
		else {
			ptr[i] = d_alloc(30,13);
			sprintf(ptr[i],"%i",i,memory_type[i]);
			cnt[i] = memory_type[i];
			size[i] = memory_size[i];
		}
		fg = 1;
		
	}
}


#endif


#ifndef MEMORY_DEBUG

void
indicate_md_in_buf(char ** ptr,int * cnt,int * size)
{
int i;
int fg;
	fg = 0;
	for ( i = 0 ; i < MT_MAX ; i ++ ) {
		ptr[i] = 0;
		cnt[i] = 0;
		size[i] = 0;
	}
}

#endif


void
free_indicate_md_buf(char ** ptr)
{
int i;
	for ( i = 0 ; i < MT_MAX ; i ++ ) {
		if ( ptr[i] == 0 )
			continue;
		d_f_ree(ptr[i]);
		ptr[i] = 0;
	}
}


