/* -*-C-*- */

/*  kcond.c  */

/*
 * Author: Nikita Danilov <NikitaDanilov@yahoo.COM>
 * Keywords: kernel condition variables
 *
 * Copyright (C) 2000 Namesys (Hans Reiser)
 *
 * This file is part of kcond.
 *
 * Kcond is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This software 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.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 */

/* $Id$ */
static char cvsid[] = "@(#)$Id$";
static char debugFileId[] = __FILE__;

#include "kcond.h"

#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>

#define KCOND_TEST
#if defined( KCOND_TEST )
static int kcond_test_thread_waiter( void *data );

kcond_t cvar = KCOND_INIT;
DECLARE_MUTEX( lock );
int datum = 1;

int kcond_test()
{
  int i;

  TRACE;
  for( i = 0 ; i < 10 ; ++i )
	{
	  TRACE;
	  kernel_thread( kcond_test_thread_waiter, NULL, 0 );
	  TRACE;
	}
  DEBUG( "Threads created" );
  for( i = 0 ; i < 100 ; ++i )
	{
	  ++datum;
	  PRINT( "signaling: %li", ( long ) current -> pid );
	  kcond_signal( &cvar );
	  PRINT( "signaled: %li", ( long ) current -> pid );
	  udelay( 100 );
	}
  datum = -1;
  PRINT( "broadcasting: %li", ( long ) current -> pid );
  kcond_broadcast( &cvar );
  PRINT( "broadcasted: %li", ( long ) current -> pid );
  return 1;
}

static int kcond_test_thread_waiter( void *data )
{
  TRACE;

  lock_kernel();

  exit_files( current );
  exit_mm( current );

  current->session = 1;
  current->pgrp = 1;
	
  exit_fs( current );
  current -> fs = init_task.fs;
  atomic_inc( &init_task.fs -> count );

  strcpy( current -> comm, "kcond-test" );

  unlock_kernel();

  TRACE;
  down_interruptible( &lock );
  TRACE;
  if( signal_pending( current ) )
	{
	  PRINT( "interrupted: %li", ( long ) current -> pid );
	  break;
	}
  do
	{
	  kcond_wait( &cvar, &lock );
	}
  while( datum > 0 );
  PRINT( "wake up: %li datum: %i", ( long ) current -> pid, datum );
  up( &lock );
  return 1;
}

/* KCOND_TEST */
#else

int kcond_test()
{
  return 1;
}

/* KCOND_TEST */
#endif

/*
 * $Log$
 */
