#include #include #include #include #include /* * This simple default synchronization mechanism allows only vehicle at a time * into the intersection. The intersectionSem is used as a a lock. * We use a semaphore rather than a lock so that this code will work even * before locks are implemented. */ /* * Replace this default synchronization mechanism with your own (better) mechanism * needed for your solution. Your mechanism may use any of the available synchronzation * primitives, e.g., semaphores, locks, condition variables. You are also free to * declare other global variables if your solution requires them. */ /* * replace this with declarations of any synchronization and other variables you need here */ static struct semaphore * intersectionSem; static struct lock * globlock; static struct semaphore * nsem; static struct semaphore * esem; static struct semaphore * ssem; static struct semaphore * ssem; // This section contains global vars and useful functions to work with them. As well as the structs used for them typedef struct car { Direction origin; Direction dest; bool old; car * next; } car; typedef struct list { car * front; car * back; } list; list * queue = NULL; list * active = NULL; // car initializer/allocator car * newcar(Direction origin, Direction dest) { car * temp = kmalloc(sizeof(car)); if(!(temp)) { kprintf("Failed to create a car."); panic(); } temp->origin = origin; temp->dest = dest; temp->old = 0; temp->next = NULL; } // list initializer/allocator list * newlist() { list * temp = kmalloc(sizeof(list)); if(!(temp)) { kprintf("Could not allocate list."); panic(); } temp->front = NULL; temp->back = NULL; } // puts a car into the queue, at the front if old is true, the back otherwise void enqueue(car * newcar) { if (!(queue->back)) { queue->front = newcar; queue->back = newcar; } if (newcar->old) // if the car is "old", let it go first. be nice to your elders { car * temp = queue->front; queue->front = newcar; newcar->next = temp; return; } queue->back->next = newcar; queue->back = newcar; } // push a car to the end of the active list void push(car * newcar) { if (!(active->front)) { active->front = newcar; active->back = newcar; } active->back->next = newcar; active->back = newcar; } // remove an element from the front of the queue car * pop() { if (!(queue->front)) { return NULL; } if (queue->front == queue->back) { queue->back == NULL; } car * temp = queue->front; queue->front = queue->front->next; return temp; } // called when a car clears the intersection void clearint(car * done) { car * temp = active->front(); car * temp2 = NULL; while(temp != done) { temp = active->next; temp2 = temp; } // first element of the list is being removed if (!(temp2)) { active->front = active->front->next; goto SKIP1; } temp2->next = temp->next; SKIP1: kfree(temp); } // cleans up a list void dellist(list * dead) { car * temp = dead->front; while (temp) { car * temp2 = temp->next; kfree(temp); temp = temp2; } kree(dead); } // returns true if a car is turning right bool rightturn(car * car) { int temp = car->origin - car->dest; return (temp == 1 || temp == -3) } /* * The simulation driver will call this function once before starting * the simulation * * You can use it to initialize synchronization and other variables. * */ void intersection_sync_init(void) { /* replace this default implementation with your own implementation */ intersectionSem = sem_create("intersectionSem",1); if (intersectionSem == NULL) { panic("could not create intersection semaphore"); } return; nsem = sem_create("nsem",1); if (intersectionSem == NULL) { panic("could not create intersection semaphore"); } return; intersectionSem = sem_create("intersectionSem",1); if (intersectionSem == NULL) { panic("could not create intersection semaphore"); } return; intersectionSem = sem_create("intersectionSem",1); if (intersectionSem == NULL) { panic("could not create intersection semaphore"); } return; intersectionSem = sem_create("intersectionSem",1); if (intersectionSem == NULL) { panic("could not create intersection semaphore"); } return; } /* * The simulation driver will call this function once after * the simulation has finished * * You can use it to clean up any synchronization and other variables. * */ void intersection_sync_cleanup() { KASSERT(intersectionSem); KASSERT(queue); KASSERT(active); sem_destroy(intersectionSem); dellist(queue); dellist(active); } /* * The simulation driver will call this function each time a vehicle * tries to enter the intersection, before it enters. * This function should cause the calling simulation thread * to block until it is OK for the vehicle to enter the intersection. * * parameters: * * origin: the Direction from which the vehicle is arriving * * destination: the Direction in which the vehicle is trying to go * * return value: none */ void intersection_before_entry(Direction origin, Direction destination) { /* replace this default implementation with your own implementation */ (void)origin; /* avoid compiler complaint about unused parameter */ (void)destination; /* avoid compiler complaint about unused parameter */ KASSERT(intersectionSem); P(intersectionSem); // starting my own shit car * new = newcar(origin, destination); // Nothing in intersection, so proceed if (!(active->front)) { push(new); return; } // things are in the intersection if (active->front) { car * temp = active->front; while (temp) { if (temp->origin == new->origin || (temp->origin == new->dest && temp->dest == new->origin) || (temp->dest != new->dest && (rightturn(new) || rightturn(temp)))) { temp = temp->next; continue; } else { enqueue(new); new->old = 1; // make new "old", since now it has already waited once // SLEEP AND SET TO WAKE ONCE temp is out of the intersection! } } push(new); } } /* * The simulation driver will call this function each time a vehicle * leaves the intersection. * * parameters: * * origin: the Direction from which the vehicle arrived * * destination: the Direction in which the vehicle is going * * return value: none */ void intersection_after_exit(Direction origin, Direction destination) { /* replace this default implementation with your own implementation */ (void)origin; /* avoid compiler complaint about unused parameter */ (void)destination; /* avoid compiler complaint about unused parameter */ KASSERT(intersectionSem); V(intersectionSem); // My shit car * temp = active->first; while (temp) { if (temp->origin == origin && temp->dest == destination) { clearing(temp); break; } else { temp = temp->next; } } }