//Based on the original file written by Prof. Hakner
//just added a few lines
#include <stdio.h>
#include <signal.h>
#include "sched.h"

#define DELAY_FACTOR 29
sched_waitq_t wq1,wq2;

init_fn()
{
 int x;
 int y;
	sched_waitq_init(&wq1);
	sched_waitq_init(&wq2);
	fprintf(stderr,"Hooray made it to init_fn, stkaddr %x\n",&x);
	for(y=1;y<1<<DELAY_FACTOR;y++)
		;
	switch (sched_fork())
	{
	 case -1:
		fprintf(stderr,"fork failed\n");
		return -1;
	 case 0:
		fprintf(stderr,"<<in child addr %x>>\n",&x);
		child_fn1();
		fprintf(stderr,"!!BUG!! at %s:%d\n",__FILE__,__LINE__);
		return 0;
	 default:
		fprintf(stderr,"<<in parent addr %x>>\n",&x);
		parent_fn();
		break;
	}
	exit(0);
}

child_fn1()
{
int pid;
 int y;
	fprintf(stderr,"Start pass1, child_fn1 &y=%x\n",&y);
	for(y=1;y<1<<DELAY_FACTOR;y++)
		;
	fprintf(stderr,"Done pass 1,child_fn1 y=%d\n",y);
	sched_sleep(&wq1);
	fprintf(stderr,"Resuming child_fn1\n");
	for(y=1;y<1<<DELAY_FACTOR;y++)
		;
	fprintf(stderr,"Done pass 2,child_fn1 y=%d\n",y);
	fprintf(stderr,"child with pid %d is forking...\n",sched_getpid());
	switch(sched_fork()) {
		 case -1:fprintf(stderr,"Fork failed\n");
			return;
		 case 0:
			fprintf(stderr,"In the child of the child with pid %d and ppid %d\n",sched_getpid(),sched_getppid());
			for(y=1;y<1<<DELAY_FACTOR;y++)
				;
			fprintf(stderr,"Pid %d is exiting with %d\n",sched_getpid(),22);
			sched_exit(99);
		 default: break;
	}
	fprintf(stderr,"Pid %d is exiting with %d\n",sched_getpid(),22);
	sched_exit(22);
}

parent_fn()
{
 int y,p;
	fprintf(stderr,"Wow, made it to parent, stkaddr=%x\n",&y);
	switch(sched_fork())
	{
	 case -1:fprintf(stderr,"Fork failed\n");
		return;
	 case 0:
		child_fn2();
		fprintf(stderr,"Pid %d is exiting with %d\n",sched_getpid(),11);
		sched_exit(11);
		fprintf(stderr,"!!BUG!! at %s:%d\n",__FILE__,__LINE__);
		return;
	 default:
		while ((p=sched_wait(&y))>0)
			fprintf(stderr,"Child pid %d return code %d\n",p,y);
		return;
	}
}

child_fn2()
{
 int y;
	sched_nice(4);
	fprintf(stderr,"Start pass1, child_fn2 &y=%x\n",&y);
	for(y=0;y<1<<DELAY_FACTOR;y++)
		;
	fprintf(stderr,"Done pass 1,child_fn2 y=%d\n",y);
	sched_sleep(&wq2);
	fprintf(stderr,"Resuming child_fn2\n");
	for(y=0;y<1<<DELAY_FACTOR;y++)
		;
	fprintf(stderr,"Done pass 2,child_fn2 y=%d\n",y);
	
}

wakeup_handler(int sig)
{
	signal(sig,wakeup_handler);
	if (sig==SIGUSR1)
		sched_wakeup(&wq1);
	else
		sched_wakeup(&wq2);
}

abrt_handler(int sig)
{
	signal(sig,abrt_handler);
	sched_ps();
}

main()
{
	fprintf(stderr,"Starting\n");
	signal(SIGUSR1,wakeup_handler);
	signal(SIGUSR2,wakeup_handler);
	signal(SIGABRT,abrt_handler);
	sched_init(init_fn);
	fprintf(stderr,"Whoops\n");
}

