// 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 {
	 	unsigned char id; 			  		// ID of task
		enum task_state state;				// State
		unsigned char priority;				// Priority
	 	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
		enum resource_state state;			// State (busy, free...)
		unsigned char user;					// Current resource user/owner
		signed char queue[4];				// Tasks waiting on resource
		unsigned char queue_pos;			// Next free spot in queue
		};
		

extern struct task_block task[numtasks];
extern struct resource_block resource[numresources];







signed char sem_get(char resource_id) {

	 /* 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[resource_id].state == notbusy) {
	 	resource[resource_id].state = busy;
		resource[resource_id].user = current;
		if (task[current].state == waiting)
		   task[current].state = running;
		INTR_ON();
		return resource_id;
	 }
	 // busy
	else {
		task[current].state = waiting;
		INTR_ON();
		return -1;
	} 	 
}




void sem_give(char resource_id) {

	/* 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[resource_id].state = notbusy;
	
	INTR_ON();
	  
}



