#include "../h/asl.h"
static semd_t* semdFree_h; // free
semd_t* semd_h; // active
static semd_t semdTable[MAXPROC + 2];
/*
* Function: insertBlocked
* --------------------
* Insert the PCB pointed to by p at the tail of the process queue
* associated with the semaphore whose physical address is semAdd
* and set the semaphore address of p to semdAdd.
*
* semAdd: pointer to semaphore value
* p: pointer to PCB
*
* returns: returns 1 if semaphore is not in ASL and semdFree is empty
* returns 0 otherwise
*/
int insertBlocked(int *semAdd, pcb_t *p)
{
int found = 0;
semd_t* current = semd_h;
while(current->s_semAdd <= semAdd){
if(current->s_semAdd == semAdd){
found = 1;
break;
}
current = current->s_next;
}
if (found) {
// Semaphore found in ASL
insertProcQ(&(current->s_procQ), p);
} else {
// Semaphore not found in ASL
if(semdFree_h == NULL){
return 1;
}
// Get new semaphore from head of free list
semd_t* semNew = semdFree_h;
semdFree_h = semdFree_h->s_next;
// Place new semaphore in ASL
semd_t* current = semd_h;
while(current->s_next->s_semAdd <= semAdd) {
current = current->s_next;
}
semNew->s_next = current->s_next;
current->s_next = semNew;
semNew->s_semAdd = semAdd;
semNew->s_procQ = mkEmptyProcQ();
insertProcQ(&(semNew->s_procQ), p);
}
p->p_semAdd = semAdd;
return 0;
}
/*
* Function: removeBlocked
* --------------------
* Removes the first PCB from the process queue of the semaphore.
*
* semAdd: pointer to semaphore value
*
* returns: returns pointer to PCB removed if semaphore found
* returns NULL otherwise
*/
pcb_t* removeBlocked(int *semAdd)
{
int found = 0;
semd_t* prev = NULL;
semd_t* current = semd_h;
while(current->s_semAdd <= semAdd){
if(current->s_semAdd == semAdd){
found = 1;
break;
}
prev = current;
current = current->s_next;
}
if(!found){
// Semaphore is not found in ASL
return NULL;
}
// Remove the first PCB from process queue
pcb_t* removed = removeProcQ(&(current->s_procQ));
if(emptyProcQ(current->s_procQ)){
// Process queue is empty, remove the semaphore from ASL
if (prev != NULL) {
prev->s_next = current->s_next;
} else {
return removed;
}
// Return the semaphore to the free list
current->s_next = semdFree_h;
semdFree_h = current;
}
return removed;
}
/*
* Function: outBlocked
* --------------------
* Remove the PCB pointed to by p from the process queue associate with
* p's semaphore (p -> p_semAdd) on the ASL.
*
* p: pointer to PCB
*
* returns: returns pointer to PCB removed if semaphore found and p
* if found in the process queue
* returns NULL otherwise
*/
pcb_t* outBlocked(pcb_t *p)
{
int found = 0;
semd_t* prev = NULL;
semd_t* current = semd_h;
while(current->s_semAdd <= p->p_semAdd){
if(current->s_semAdd == p->p_semAdd){
found = 1;
break;
}
prev = current;
current = current->s_next;
}
if(!found){
// Semaphore not found in ASl
return NULL;
}
pcb_t* result = outProcQ(&(current->s_procQ), p);
if(result == NULL){
return result;
}
p->p_semAdd = NULL;
if(emptyProcQ(current->s_procQ)){
// Process queue is empty, remove the semaphore from ASL
if (prev != NULL) {
prev->s_next = current->s_next;
} else {
return result;
}
// Return the semaphore to the free list
current->s_next = semdFree_h;
semdFree_h = current;
}
return result;
}
/*
* Function: headBlocked
* --------------------
* Return (without removal) a pointer to the PCB that is at the head
* head of the process queue associated with the semaphore semAdd.
*
* p: pointer to PCB
*
* returns: returns pointer to PCB at the head of the process queue if
* semAdd found and the queue is non-empty
* returns NULL otherwise
*/
pcb_t* headBlocked(int *semAdd)
{
int found = 0;
semd_t* current = semd_h;
while(current->s_semAdd <= semAdd){
if(current->s_semAdd == semAdd){
found = 1;
break;
}
current = current->s_next;
}
if(!found){
// Semaphore not found in ASL
return NULL;
}
if(current->s_procQ == NULL){
// Semaphore has empty process queue
return NULL;
}
return current->s_procQ->p_next;
}
/*
* Function: initASL
* --------------------
* Initialize the semdFree list to contain all the elements of
* the array.
*
*/
void initASL()
{
// Free list
semdFree_h = &semdTable[1];
for(int i = 1; i< MAXPROC; i++){
semdTable[i].s_next = &semdTable[i+1];
}
semdTable[MAXPROC].s_next = NULL;
// Active list
semd_h = &semdTable[0];
// head
semd_h->s_procQ = NULL;
semd_h->s_semAdd = (int*) 0x00000000;
// tail
semd_h->s_next = &semdTable[MAXPROC+1];
semd_h->s_next->s_procQ = NULL;
semd_h->s_next->s_semAdd = (int*) 0xFFFFFFFF;
semd_h->s_next->s_next = NULL;
}