// semlib.c

#include <912d60.h>
#include "kernel.h"
#include "semlib.h"




// GLOBAL VARIABLES
extern unsigned int current;		   	 	// current task id number

// task control block
extern struct task_block {
	 	void (*address)();			   		// Address of the task
	 	unsigned char id; 			  		// ID of task
		char name[9];	  					// Name
		enum task_state state;				// State
		unsigned char priority;				// Priority
		unsigned long int period_tick;			// for determining if deadline is up
		unsigned int interrupt_msg_box;		// flags for pending interrupts
		enum message_box message;			// misc flags
		unsigned char message_data[2];		// data for misc_msg_box flags
	 	unsigned char *heap_ptr;			// heap addr while not current task
		unsigned int heap_size;				// heap size
		unsigned char *frame_ptr;			// CCR pointer
		};


// resource control block
extern struct resource_block {
		unsigned char id;	   				// ID of resource
		char name[5];	  					// Name of resource
		enum resource_state state;			// State (busy, free...)
		unsigned char owner;				// Current resource owner
		signed char queue[3];				// Tasks waiting on resource
		unsigned char queue_ptr;			// Next free spot in queue
		};
		

extern struct task_block *task[MAXTASKS];
extern struct resource_block resource[NUMRESOURCES];

extern char error_msg[9][25];
extern char error_src[5][18];







int sem_get(char rid) {

	 /* Gives a resource to a requesting task.
	 	returns the resource id number (0,1,2,...) if free.
	 	otherwise returns -1.
		
		At this point, semaphores are a procedural control
		that the tasks have to follow to avoid resource contention.
		There is no kernel control over resources yet.  */
	 
	 
	 // critical section
	 INTR_OFF();
	 
	 
	 
	 // GET SEMAPHORE
	 // give semaphore to task
	 if (resource[rid].state == NOTBUSY) {
	 	resource[rid].state = BUSY;
		resource[rid].owner = current;
		
		INTR_ON();
		return rid;
	 	}
	 
	 // resource is taken/busy so make task wait
	 else {
		  task[current]->message |= STATE_FLAG;
		  task[current]->message_data[STATE_BOX] = WAITING;
		
		  // put waiting task into the resources queue if there's space
		  if (resource[rid].queue_ptr < 3) {
		   	 resource[rid].queue[resource[rid].queue_ptr] = current;
		   	 resource[rid].queue_ptr++;
		   	 }
		
		  INTR_ON();
		  return -1;
	 	  } 	 
		
}




int sem_give(char rid) {

	/* Takes a resource back from a task.
	   will (eventually) pass a message to a waiting task.  
	   
	   	At this point, semaphores are a procedural control
		that the tasks have to follow to avoid resource contention.
		There is no kernel control over resources yet.  */
	
	
	// critical section
	INTR_OFF();
	
	
	// return the resource
	resource[rid].state = NOTBUSY;
	//resource[rid].owner = NULL;
	
	INTR_ON();
	
	return 0;
	  
}



