#include #include #include #include #include static struct lock * globlock; typedef struct cv cv; // 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; struct cv * cv; } car; // array of all 12 possible cars in the intersection car * active[12] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; // all of our offset arrays int dirs[4] = {0, 3, 6, 9}; int northa[4] = {0, 0, 1, 2}; int easta[4] = {2, 0, 0, 1}; int southa[4] = {1, 2, 0, 0}; int westa[4] = {0, 1, 2, 0}; int * compass[4] = {northa, easta, southa, westa}; // car initializer/allocator static car * newcar(Direction origin, Direction dest) { car * temp = kmalloc(sizeof(car)); if(!(temp)) { panic("Failed to create a car.\n"); } temp->origin = origin; temp->dest = dest; temp->cv = NULL; return temp; } // called when a car clears the intersection static void clearint(car * done, int pos) { active[pos] = NULL; if (done->cv) // if this car was blocking something { cv_broadcast(done->cv, globlock); // wake all/inform them you're all good cv_destroy(done->cv); } kfree(done); } // returns true if a car is turning right static bool rightturn(car * car) { int temp = car->origin - car->dest; return (temp == 1 || temp == -3); } // inits all arrays we need, lock. void intersection_sync_init() { globlock = lock_create("lightlock"); if (!(globlock)) { panic("Failed to create lock!\n"); } } /* * 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(active); lock_destroy(globlock); } /* * 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) { lock_acquire(globlock); car * new = newcar(origin, destination); RESTART: for (int i = 0; i < 12; ++i) { car * temp = active[i]; if (temp) { if ((temp->origin == new->origin && temp->dest != new->dest) || (temp->origin == new->dest && temp->dest == new->origin) || (temp->dest != new->dest && (rightturn(new) || rightturn(temp)))) { continue; } else { // create cv for temp if it doesn't have one yet if(!(temp->cv)) { temp->cv = cv_create("carcv"); } cv_wait(temp->cv, globlock); // sleep and reacquire lock once woken goto RESTART; // now we have to make sure there's nothing else screwing us over } } else { continue; } } active[(dirs[new->origin] + *(compass[new->origin] + new->dest))] = new; lock_release(globlock); } /* * 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) { lock_acquire(globlock); int position = dirs[origin] + *(compass[origin] + destination); clearint(active[position], position); lock_release(globlock); }