/**********************************************************************
 
	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	"memory_debug.h"
#include	"task.h"
#include	"utils.h"
#include	"lock_level.h"


extern SEM utils_lock;


NESTED_LOCK *
new_nlock()
{
NESTED_LOCK * ret;
	ret = d_alloc(sizeof(*ret));
	ret->tid = 0;
	ret->cnt = 0;
	return ret;
}

void
nlock_task(NESTED_LOCK * n)
{
int tid;
	tid = get_tid();
retry:
	lock_task(utils_lock);
	if ( n->tid == 0 ) {
		n->cnt = 1;
		n->tid = tid;
	}
	else if ( n->tid == tid ) {
		n->cnt ++;
	}
	else {
		sleep_task((int)n,utils_lock);
		goto retry;
	}
	unlock_task(utils_lock,"nlock_task");
}

void
unnlock_task(NESTED_LOCK * n)
{
int tid;
	tid = get_tid();
	lock_task(utils_lock);
	if ( n->tid != tid )
		er_panic("unnlock_task(1)");
	n->cnt --;
	if ( n->cnt < 0 )
		er_panic("unnlock_task(2)");
	if ( n->cnt == 0 ) {
		n->tid = 0;
		wakeup_task((int)n);
	}
	unlock_task(utils_lock,"unnlock_task");
}

void
destroy_nlock(NESTED_LOCK * n)
{
	d_f_ree(n);
}
