/**********************************************************************
 
	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	<sys/wait.h>
#include	<sys/time.h>
#include	<sys/types.h>
#include	<unistd.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<signal.h>
#include	<errno.h>
#include	"init.h"
#include	"task.h"
#include	"utils.h"

void sigalarm_handler();
void sigpipe_handler();
void sigint_handler();
void siglwp_handler();

extern int task_flags;
int pri_table[PRI_MAX] = {0,10,20,30,40,50};

extern D_SEM task_lock;
int lock_test_tid;

int _sem_getvalue(D_SEM s,int * value);



#ifndef DEADLOCK_CHECK
D_SEM
xx_new_lock(int level,char * file,int line)
{
D_SEM s;
int value;
	s = new_block();
	sem_init(&s->ss,0,1);
	sem_trywait(&s->ss);
	for ( ; sem_post(&s->ss); );
	if ( _sem_getvalue(s,&value) <0  || value >= 2 ) {
		 er_panic("unlock_task");
	}
	return s;
}
#endif
#ifdef DEADLOCK_CHECK

extern D_SEM sem_list;

D_SEM
xx_new_lock(int level)
{
D_SEM s, * sp;
int value;
	s = new_block();
	s->level = level;
	s->tid = 0;
	sem_init(&s->s,0,1);
	sem_trywait(&s->s);
	for ( ; sem_post(&s->s); );
if ( _sem_getvalue(s,&value) <0  || value >= 2 ) {
 er_panic("unlock_task");
}
	for ( sp = &sem_list ; *sp ; sp = &(*sp)->next )
		if ( (*sp)->level > level ) {
			s->next = *sp;
			*sp = s;
			goto ok;
		}
	s->next = 0;
	*sp = s;
ok:
	return s;
}

#endif



#ifndef DEADLOCK_CHECK
void
_lock_task(D_SEM s,char * file,int line)
{
int value;
retry:
	if ( _sem_getvalue(s,&value) < 0 || value > 1 )
		er_panic("lock_task1");
	errno = 0;
	if ( sem_wait(&s->ss) ) {
		if ( errno == EINTR )
			goto retry;
	}
	if ( _sem_getvalue(s,&value) < 0 || value >= 1 ) {
		printf("??????\n");
	  	goto retry;
		er_panic("lock_task");
	}
	s->tid = _get_tid();
	s->lock_file = file;
	s->lock_line = line;
}
#endif

int test;

#ifdef DEADLOCK_CHECK
void
_lock_task(D_SEM s,char * file,int line)
{
D_SEM sp;
int tid;
int value;
extern D_SEM block_lock;


	if ( s == block_lock )
		goto retry;
	tid = _get_tid();
	for ( sp = sem_list ; sp ; sp = sp->next ){
		if ( s == sp ) {
			if ( sp->tid == tid ) {
				fprintf(stderr,"************* DOUBLELOCK\n");
				er_panic("lock_task");
			}
			break;
		}
		if ( sp->tid != tid )
			continue;
		fprintf(stderr,"************* DEADLOCK %i - %i\n",
			sp->level,s->level);
		er_panic("lock_task");
	}
retry:
	if ( _sem_getvalue(s,&value) < 0 || value > 1 )
		er_panic("lock_task2");
	errno = 0;
	if ( sem_wait(&s->s) ) {
		if ( errno == EINTR )
			goto retry;
	}
	if ( _sem_getvalue(s,&value) < 0 || value >= 1 ) {
		printf("??????\n");
		goto retry;
		er_panic("lock_task");
	}
	s->tid = tid;
	s->lock_file = fine;
	s->lock_line = line;
}
#endif

#ifndef DEADLOCK_CHECK
void
_unlock_task(D_SEM s,char *str,char * file,int line)
{
int value;
	s->tid = invalid_htid(); 
	s->unlock_file = file;
	s->unlock_line = line;
	for ( ; sem_post(&s->ss) ; );
if ( _sem_getvalue(s,&value) < 0 || value >= 2 ) {
fprintf(stderr,"*********** ???? %s %i - %s %i ************\n",str,_get_tid().tid,file,line);
 er_panic("unlock_task");
}
}
#endif

#ifdef DEADLOCK_CHECK
void
_unlock_task(D_SEM s,char * str,char * file,int line)
{
int value;
	s->tid = 0;
	s->unlock_file = file;
	s->unlock_line = line;
if ( _sem_getvalue(s,&value) < 0 || value  != 0 )
printf("##########################3 %s\n",str);
retry:
	for ( ; sem_post(&s->s); );
if ( _sem_getvalue(s,&value) <0  || value >= 2 ) {
fprintf(stderr,"*********** ???? %s %i ************\n",str,_get_tid());
 er_panic("unlock_task");
}
}
#endif

#ifndef DEADLOCK_CHECK
void xx_close_lock(D_SEM s)
{
	sem_destroy(&s->ss);
	free_block(s);
}

int
_sem_getvalue(D_SEM s,int * value)
{
	return sem_getvalue(&s->ss,value);
}



#endif

#ifdef DEADLOCK_CHECK
void xx_close_lock(D_SEM s)
{
D_SEM * sp;
	for ( sp = &sem_list ; *sp ; sp = &(*sp)->next )
		if ( *sp == s ) {
			*sp = s->next;
			break;
		}
	sem_destroy(&s->s);
	free_block(s);
}

int
_sem_getvalue(D_SEM s,int * value)
{
	return sem_getvalue(&s->s,value);
}



#endif
