#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 = 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; } // initialize the array active static void activeinit(void) { active = kmalloc(12 * sizeof(car *)); if (!(active)) { panic("Failed to create an array"); } for (int i = 0; i < 12; ++i) { *(active + i) = NULL; } } // push a car to the active array static void push(car * newcar) { //kprintf("first third: %d", *(dirs + newcar->origin)); //kprintf("second third: %p", *(compass + newcar->origin)); //kprintf("third third: %d", *(*(compass + newcar->origin) + newcar->dest)); // dirs + origin is our offset for where to start in the array // compass + origin is the array we use to determine what to add to the first number // newcar->dest gives the direction, which we use to find the offset indicating it's additive value int total = *(dirs + newcar->origin) + *(*(compass + newcar->origin) + newcar->dest); //kprintf("halfway through push\n"); // with our offset, set the pointer here to newcar *(active + total) = newcar; } // called when a car clears the intersection static void clearint(car * done) { // dirs + origin is our offset for where to start in the array // compass + origin is the array we use to determine what to add to the first number // newcar->dest gives the direction, which we use to find the offset indicating it's additive value // set the array of active cars to null at this value //kprintf("first third: %d", *(dirs + done->origin)); //kprintf("second third: %p", *(compass + done->origin)); //kprintf("third third: %d", *(*(compass + done->origin) + done->dest)); int total = *(dirs + done->origin) + *(*(compass + done->origin) + done->dest); *(active + total) = 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); } // delete active array, offset calculation arrays static void cleanup() { kfree(active); } // 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"); } // initilaize array of active cars activeinit(); //kprintf("finished init steps\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); cleanup(); 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: //kprintf("starting the for loop for entering\n"); for (int i = 0; i < 12; ++i) { car * temp = *(active + i); if (temp) { //kprintf("temp at %d was not null\n", i); 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"); } //kprintf("put something to sleep\n"); 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 { //kprintf("skipped %d because it was null\n", i); continue; } } //kprintf("made it out of the for loop\n"); push(new); //kprintf("added a car to the int\n"); 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)); //kprintf("released a car from the int\n"); lock_release(globlock); }