/**********************************************************************
 
	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.

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


#include	<stdio.h>
#include	"task.h"

#define GC_TICK_INTERVAL	10
#define GC_THRESHOLD_UP		1000000
#define GC_THRESHOLD_DOWN	 500000
extern int malloc_count;
int free_count;

int gc_tick_interval;

void
gc_tick()
{
int ret;
int res;
unsigned int st_time,interval;

	res = s_check_resource();

	st_time = get_xltime();

	gc_lock();

	lock_mem();
/*
printf("GC START\n");
*/
	gc();
	sp_gc();
	free_count = ret = _mem_gc();
	after_gc();

	unlock_mem();

	gc_unlock();
/*
printf("END %i %i\n",ret,malloc_count);
*/
	interval = get_xltime() - st_time;

	if ( free_count > GC_THRESHOLD_UP || res < 0 ) {
		gc_tick_interval = gc_tick_interval/2;
		if ( gc_tick_interval < 1)
			gc_tick_interval = 1;
		if ( gc_tick_interval < 5*interval )
			gc_tick_interval = 5*interval;
		change_tick(gc_tick_interval);
	}
	else if ( free_count < GC_THRESHOLD_DOWN ) {
		gc_tick_interval ++;
		if ( gc_tick_interval > GC_TICK_INTERVAL )
			gc_tick_interval = GC_TICK_INTERVAL;
		if ( gc_tick_interval < 5*interval )
			gc_tick_interval = 5*interval;
		change_tick(gc_tick_interval);
	}
	else if ( gc_tick_interval < 5*interval ) {
		gc_tick_interval = 5*interval;
		change_tick(gc_tick_interval);
	}
}

void
gc_tick_notin_tick()
{
int ret;
int res;
unsigned int st_time,interval;

	res = s_check_resource();

	st_time = get_xltime();

	gc_lock();

	lock_mem();
/*
printf("GC START\n");
*/
	gc();
	sp_gc();
	free_count = ret = _mem_gc();
	after_gc();

	unlock_mem();

	gc_unlock();
/*
printf("END %i %i\n",ret,malloc_count);
*/
	interval = get_xltime() - st_time;

	if ( free_count > GC_THRESHOLD_UP || res < 0 ) {
		gc_tick_interval = gc_tick_interval/2;
		if ( gc_tick_interval < 1)
			gc_tick_interval = 1;
		if ( gc_tick_interval < 5*interval )
			gc_tick_interval = 5*interval;
	}
	else if ( free_count < GC_THRESHOLD_DOWN ) {
		gc_tick_interval ++;
		if ( gc_tick_interval > GC_TICK_INTERVAL )
			gc_tick_interval = GC_TICK_INTERVAL;
		if ( gc_tick_interval < 5*interval )
			gc_tick_interval = 5*interval;
	}
	else if ( gc_tick_interval < 5*interval ) {
		gc_tick_interval = 5*interval;
	}
}

void
gc_enable()
{

	gc_lock();

	lock_mem();
mem_test("GC_START");
/*
printf("GC START\n");
*/
	gc();
	sp_gc();
	_mem_gc();
	after_gc();
/*
printf("END %i %i\n",ret,malloc_count);
*/
mem_test("GC_END");
	unlock_mem();

	gc_unlock();
}

void
init_gc_task()
{
	gc_tick_interval = GC_TICK_INTERVAL;
	new_tick(gc_tick,GC_TICK_INTERVAL);
}
