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

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


extern int task_flags;
/*
int pri_table[PRI_MAX] = {1,20,39,58,77,96};
*/
int pri_table[PRI_MAX] = {0,0,0,0,0,0};

void
ignore_chld(int sig)
{
	while (1)  {
		if ( waitpid(-1,NULL,WNOHANG) <= 0 )
			break;
	}
	signal(SIGCHLD,ignore_chld);
}

void
set_ignore_chld()
{
	signal(SIGCHLD,ignore_chld);
}

void
set_alarm_mask(int flags)
{
	all_signal_mask(1,45);
	signal(SIGALRM,sigalarm_handler);
	signal(SIGPIPE,sigpipe_handler);
	signal(SIGINT,sigint_handler);
	task_flags = flags;
	if ( (flags&INI_THREAD) == INI_DONTWAITCHI )
		set_ignore_chld();
}


#ifndef DEADLOCK_CHECK
SEM
new_lock(int level)
{
SEM s;
	s = new_block();
	sem_init(s,0,1);
	sem_trywait(s);
	sem_post(s);
	return s;
}
#endif
#ifdef DEADLOCK_CHECK


SEM
new_lock(int level)
{
SEM s, * sp;
	s = new_block();
	s->level = level;
	s->tid = 0;
	sem_init(&s->s,0,1);
	sem_trywait(&s->s);
	sem_post(&s->s);
	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(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) ) {
		if ( errno == EINTR )
			goto retry;
	}
	if ( _sem_getvalue(s,&value) < 0 || value >= 1 ) {
		printf("??????\n");
	  	goto retry;
		er_panic("lock_task");
	}
}
#endif

int test;

#ifdef DEADLOCK_CHECK
void
_lock_task(SEM s,char * file,int line)
{
SEM sp;
int tid;
int value;
extern 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_task1");
	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;
}
#endif

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

#ifdef DEADLOCK_CHECK
void
_unlock_task(SEM s,char * str,char * file,int line)
{
int value;
	s->tid = 0;
if ( _sem_getvalue(s,&value) < 0 || value  != 0 )
printf("##########################3 %s\n",str);
	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 close_lock(SEM s)
{
	sem_destroy(s);
	free_block(s);
}
#endif

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

int
_sem_getvalue(SEM s,int * value)
{
	return sem_getvalue(s,value);
}


