////////////////////////////////////////////////////////////
//
//     	Implementation of classes
//	AProcessAttributes, AScheduleRules
//
//      Copyright 2001 
//
////////////////////////////////////////////////////////////

#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "ASchedule.h"
#include "AProcess.h"


	// AProcessAttributes
	

int AProcessAttributes::set(pid_t process_id)
{
	id=process_id;
	policy=0;
	priority=0;
	child_policy=0;
	child_priority=0;
	AScheduleAttributes att(id);
	if(att.status) return 1;
	att.get_priority(priority);
	policy=sched_getscheduler(id);
	child_policy=policy;
	child_priority=priority;
	return 0;
}
	
		
int AProcessAttributes::set_child(int new_policy,int new_priority) 
{ 

	if( status ) return 1;

	sched_param z;
	AScheduleAttributes att(id);
	
	att.set_priority(new_priority);
	
	att.get(z);
	
	child_policy=new_policy;
	child_priority=new_priority;
		
	return sched_setscheduler(id,new_policy,&z); 
}


int AProcessAttributes::set_child_priority(int new_priority)
{

	if( status ) return 1;
	
	sched_param z;
	AScheduleAttributes att(id);
	
	att.set_priority(new_priority);
	
	att.get(z);
	
	child_priority=new_priority;
	
	return sched_setparam(id,&z);
}


	// AScheduleRules

AScheduleRules::AScheduleRules():status(0),policy(0)
{
	policy=sched_getscheduler(0);
}
	
int AScheduleRules::set_policy(int z)
{
	// to do check value !
	policy=z;
	return 0;
}
         
int AScheduleRules::priority_range(int& min_value, int& max_value, int& direction)
{ 
	if(status) return 1;
	
	int g=0;

	
	g=sched_get_priority_min(policy);
	
	if(g<0) return 1;
	
	min_value=g;
	
	g=sched_get_priority_max(policy);
	
	if(g<0) return 2;
	
	max_value=g;
	
	direction=1;
	
	switch(policy)
	{
	//case SCHED_HPUX:
	//case SCHED_TIMESHARE:
	case SCHED_OTHER:
	case SCHED_RTPRIO: direction=-1; break;
	}
				
	return 0;
}


int AScheduleRules::priority_above(int& new_priority, int base_priority) 
{ 
	if(status) return 1;
	
	int g=0, min_value=0, max_value=0, direction=0;
	
	g=priority_range( min_value,  max_value,  direction);
	
	if(g) return 1;
	
	if(base_priority < min_value || base_priority > max_value) return 2;
	
	new_priority=base_priority;
	
	if(direction > 0 && base_priority+1 <= max_value)
		++new_priority;
	else if(direction < 0 && base_priority-1 >= min_value)
		--new_priority;

	return 0;
}


int AScheduleRules::priority_below(int& new_priority, int base_priority)
{ 
	if(status) return 1;
	
	int g=0, min_value=0, max_value=0, direction=0;
	
	g=priority_range( min_value,  max_value,  direction);
	
	if(g) return 1;
	
	if(base_priority < min_value || base_priority > max_value) return 2;
	
	new_priority=base_priority;
	
	if(direction < 0 && base_priority+1 <= max_value)
		++new_priority;
	else if(direction > 0 && base_priority-1 >= min_value)
		--new_priority;
		
	return 0;
}


	// functions

int AMainThreadPriority(int& priority)
{ 	

	// alternative - rtprio (2)

	AScheduleAttributes att;
	
	att.get_priority(priority);
      	
	return 0;
}

int clone_process(bool& original, AProcessAttributes& attributes)
{
	pid_t id=fork();
	
	if(errno) return 1;
	 
	 attributes.set(id);
	 
	 if(0==id) original=false;
	 else original=true;
	
	return 0;
}