

#include	"task.h"

#define WAIT_SUPER_MAX		2
#define SUPER_WAITING_TIME_MAX 	3600
/*
#define SUPER_LOG
*/

typedef struct super_t {
	struct super_t *	next;
	int			_tid;
	int			_do_tid;
	void 			(*func)(void *);
	void *			arg;
} SUPER_T;

void super_task();
extern SEM task_lock;
int wait_super;
SUPER_T * sq_head, * sq_tail;
SUPER_T * sq_deal;
int stick_flag;

void
super_tick_func()
{
#ifdef SUPER_LOG
printf("SUPER %i %i TICK %i\n",getpid(),_get_tid(),wait_super);
#endif
	wakeup_task((int)&sq_head);
}

SUPER_T * 
_get_super()
{
SUPER_T * ret;
int t,waiting_time;
	waiting_time = 0;
	t = get_xltime();
	for ( ; sq_head == 0 ; ) {
		waiting_time = get_xltime() - t;
		if ( wait_super > WAIT_SUPER_MAX &&
			waiting_time > SUPER_WAITING_TIME_MAX )
			return 0;
		wait_super ++;
		sleep_task((int)&sq_head,task_lock);
		lock_task(task_lock);
		wait_super --;
	}
	ret = sq_head;
	sq_head = ret->next;
	if ( sq_head == 0 )
		sq_tail = 0;
	return ret;
}

SUPER_T *
get_super()
{
SUPER_T * ret;
	lock_task(task_lock);
	ret = _get_super();
	unlock_task(task_lock,"get_super");
	return ret;
}

void
_set_super(SUPER_T * s)
{
	if ( stick_flag == 0 ) {
		new_tick(super_tick_func,SUPER_WAITING_TIME_MAX/2,0);
		stick_flag = 1;
	}
	s->next = 0;
	if ( sq_head ) {
		sq_tail->next = s;
		sq_tail = s;
	}
	else	sq_tail = sq_head = s;
	if ( wait_super <= 0 )
		_create_task(super_task,0,-1);
	wakeup_task((int)&sq_head);
	sleep_task((int)s,task_lock);
	lock_task(task_lock);
}

void
set_super(SUPER_T * s)
{
	lock_task(task_lock);
	_set_super(s);
	unlock_task(task_lock,"set_super");
}


void
ins_deal(SUPER_T * s)
{
	lock_task(task_lock);
	s->next = sq_deal;
	sq_deal = s;
	unlock_task(task_lock,"set_deal");
}

void
del_deal(SUPER_T * s)
{
SUPER_T ** sp;
	lock_task(task_lock);
	for ( sp = &sq_deal ; *sp ; sp = &(*sp)->next )
		if ( *sp == s ) {
			*sp = s->next;
			break;
		}
	unlock_task(task_lock,"set_deal");
}

void
super_task()
{
SUPER_T * w;


#ifdef SUPER_LOG
printf("SUPER %i %i\n",getpid(),_get_tid());
#endif
	for ( ; ; ) {
		w = get_super();
		if ( w == 0 )
			break;
		w->_do_tid = _get_tid();
		ins_deal(w);
		(*w->func)(w->arg);
		del_deal(w);
		lock_task(task_lock);
		wakeup_task((int)w);
		unlock_task(task_lock,"super_task");
	}
#ifdef SUPER_LOG
printf("SUPER %i %i END\n",getpid(),_get_tid());
#endif
}

void
ss_do(void (*func)(void*),void * arg)
{
SUPER_T w;
	w.func = func;
	w.arg = arg;
	w._tid = _get_tid();
	w._do_tid = 0;
	set_super(&w);
	return;
}

typedef struct throw_signal_t {
	int		_tid;
	int		sig;
} THROW_SIGNAL_T;

void
do_throw_signal(THROW_SIGNAL_T * arg)
{
	pthread_kill(arg->_tid,arg->sig);
}

void
throw_signal(int tid,int sig)
{
THROW_SIGNAL_T s;
SUPER_T * st;

	s._tid = get_hard_tid(tid);
	s.sig = sig;
	lock_task(task_lock);
	for ( st = sq_deal ; st ; st = st->next )
		if ( st->_tid == s._tid ) {
			s._tid = st->_do_tid;
			break;
		}
	unlock_task(task_lock,"throw_signal");
	ss_do((void (*)(void*))do_throw_signal,&s);
}


