#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; int ** compass; int * northa; int * easta; int * southa; int * 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); kfree(northa); kfree(easta); kfree(southa); kfree(westa); kfree(compass); kfree(dirs); } // 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(); // represents offests for the origin coordinate in our array dirs = kmalloc(4 * sizeof(int)); *dirs = 0; *(dirs + 1) = 3; *(dirs + 2) = 6; *(dirs + 3) = 9; // holds the 4 offests for the dest coordinate in our array compass = kmalloc(4 * sizeof(int *)); *compass = northa; *(compass + 1) = easta; *(compass + 2) = southa; *(compass + 3) = westa; // represents offests for the dest coordinate in our array northa = kmalloc(4 * sizeof(int)); *northa = 0; *(northa + 1) = 0; *(northa + 2) = 1; *(northa + 3) = 2; // represents offests for the dest coordinate in our array easta = kmalloc(4 * sizeof(int)); *easta = 2; *(easta + 1) = 0; *(easta + 2) = 0; *(easta + 3) = 1; // represents offests for the dest coordinate in our array southa = kmalloc(4 * sizeof(int)); *southa = 1; *(southa + 1) = 2; *(southa + 2) = 0; *(southa + 3) = 0; // represents offests for the dest coordinate in our array westa = kmalloc(4 * sizeof(int)); *westa = 0; *(westa + 1) = 1; *(westa + 2) = 2; *(westa + 3) = 0; if ((!compass) || !(dirs) || !(northa) || !(easta) || !(southa) || !(westa)) { panic("Could not allocate offset arrays.\n"); } 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); }