|
@@ -2,45 +2,30 @@
|
|
|
#include <lib.h>
|
|
|
#include <synchprobs.h>
|
|
|
#include <synch.h>
|
|
|
-//#include <wchan.h>
|
|
|
#include <opt-A1.h>
|
|
|
|
|
|
-/*
|
|
|
- * 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 lock * globlock;
|
|
|
typedef struct cv cv;
|
|
|
+typedef struct array arr;
|
|
|
|
|
|
// 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 car * next;
|
|
|
struct cv * cv;
|
|
|
} car;
|
|
|
|
|
|
-typedef struct list
|
|
|
-{
|
|
|
- car * front;
|
|
|
- car * back;
|
|
|
-} list;
|
|
|
+// array of all 12 possible cars in the intersection
|
|
|
+car * active = NULL;
|
|
|
|
|
|
-list * active = NULL;
|
|
|
+// all of our offset arrays
|
|
|
+int * dirs;
|
|
|
+int ** compass;
|
|
|
+int * north;
|
|
|
+int * east;
|
|
|
+int * south;
|
|
|
+int * west;
|
|
|
|
|
|
// car initializer/allocator
|
|
|
static car * newcar(Direction origin, Direction dest)
|
|
@@ -54,103 +39,68 @@ static car * newcar(Direction origin, Direction dest)
|
|
|
|
|
|
temp->origin = origin;
|
|
|
temp->dest = dest;
|
|
|
- temp->next = NULL;
|
|
|
temp->cv = NULL;
|
|
|
|
|
|
return temp;
|
|
|
}
|
|
|
|
|
|
-// list initializer/allocator
|
|
|
-static list * newlist()
|
|
|
+// initialize the array active
|
|
|
+void activeinit()
|
|
|
{
|
|
|
- list * temp = kmalloc(sizeof(list));
|
|
|
+ active = kmalloc(12 * sizeof(car *));
|
|
|
|
|
|
- if(!(temp))
|
|
|
+ if (!(active))
|
|
|
{
|
|
|
- panic("Could not allocate list.\n");
|
|
|
+ panic("Failed to create an array");
|
|
|
}
|
|
|
|
|
|
- temp->front = NULL;
|
|
|
- temp->back = NULL;
|
|
|
-
|
|
|
- return temp;
|
|
|
+ for (int i = 0; i < 12; ++i)
|
|
|
+ {
|
|
|
+ active + i = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-// push a car to the end of the active list
|
|
|
+// push a car to the active array
|
|
|
static void push(car * newcar)
|
|
|
{
|
|
|
- // empty list
|
|
|
- if (!(active->front))
|
|
|
- {
|
|
|
- active->front = newcar;
|
|
|
- active->back = newcar;
|
|
|
- return;
|
|
|
- }
|
|
|
+ // 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);
|
|
|
|
|
|
- active->back->next = newcar;
|
|
|
- active->back = newcar;
|
|
|
+ // with our offset, set the pointer here to newcar
|
|
|
+ active + total = newcar;
|
|
|
}
|
|
|
|
|
|
// called when a car clears the intersection
|
|
|
static void clearint(car * done)
|
|
|
{
|
|
|
- car * temp = active->front;
|
|
|
- car * temp2 = NULL;
|
|
|
-
|
|
|
- // loop through until we match, storing the parent element
|
|
|
- while(temp != done)
|
|
|
- {
|
|
|
- temp2 = temp;
|
|
|
- temp = temp->next;
|
|
|
- }
|
|
|
+ // 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
|
|
|
+ int total = *(dirs + newcar->origin) + *(*(compass + newcar->origin) + newcar->dest);
|
|
|
+ active + total = NULL;
|
|
|
|
|
|
- // first element of the list is being removed
|
|
|
- if (!(temp2))
|
|
|
+ if (done->cv) // if this car was blocking something
|
|
|
{
|
|
|
- // if this is the only element
|
|
|
- if (temp == active->back)
|
|
|
- {
|
|
|
- active->back = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- active->front = active->front->next;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // we are removing the middle or end, so we can set the previous to point to the element after the removed
|
|
|
- temp2->next = temp->next;
|
|
|
+ cv_broadcast(done->cv, globlock); // wake all/inform them you're all good
|
|
|
+ cv_destroy(done->cv);
|
|
|
}
|
|
|
|
|
|
- if (temp->cv) // if this car was blocking something
|
|
|
- {
|
|
|
- cv_broadcast(temp->cv, globlock); // wake all/inform them you're all good
|
|
|
- cv_destroy(temp->cv);
|
|
|
-
|
|
|
- /*while (!(wchan_isempty(temp->cv->wc)))
|
|
|
- {
|
|
|
- cv_signal(temp->cv, globlock);
|
|
|
- }
|
|
|
-
|
|
|
- cv_destroy(temp->cv);*/
|
|
|
- }
|
|
|
-
|
|
|
- kfree(temp);
|
|
|
+ kfree(done);
|
|
|
}
|
|
|
|
|
|
-// cleans up a list
|
|
|
-static void dellist(list * dead)
|
|
|
+// delete active array, offset calculation arrays
|
|
|
+static void cleanup()
|
|
|
{
|
|
|
- car * temp = dead->front;
|
|
|
-
|
|
|
- while (temp)
|
|
|
- {
|
|
|
- car * temp2 = temp->next;
|
|
|
- if (temp->cv) cv_destroy(temp->cv);
|
|
|
- kfree(temp);
|
|
|
- temp = temp2;
|
|
|
- }
|
|
|
-
|
|
|
- kfree(dead);
|
|
|
+ kfree(active);
|
|
|
+ kfree(north);
|
|
|
+ kfree(east);
|
|
|
+ kfree(south);
|
|
|
+ kfree(west);
|
|
|
+ kfree(compass);
|
|
|
+ kfree(dirs);
|
|
|
}
|
|
|
|
|
|
// returns true if a car is turning right
|
|
@@ -160,13 +110,7 @@ static bool rightturn(car * car)
|
|
|
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.
|
|
|
- *
|
|
|
- */
|
|
|
+// inits all arrays we need, lock.
|
|
|
void intersection_sync_init()
|
|
|
{
|
|
|
globlock = lock_create("lightlock");
|
|
@@ -176,7 +120,57 @@ void intersection_sync_init()
|
|
|
panic("Failed to create lock!\n");
|
|
|
}
|
|
|
|
|
|
- active = newlist();
|
|
|
+ // 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 = north;
|
|
|
+ *(compass + 1) = east;
|
|
|
+ *(compass + 2) = south;
|
|
|
+ *(compass + 3) = west;
|
|
|
+
|
|
|
+
|
|
|
+ // represents offests for the dest coordinate in our array
|
|
|
+ north = kmalloc(4 * sizeof(int));
|
|
|
+ *north = 0;
|
|
|
+ *(north + 1) = 0;
|
|
|
+ *(north + 2) = 1;
|
|
|
+ *(north + 3) = 2;
|
|
|
+
|
|
|
+ // represents offests for the dest coordinate in our array
|
|
|
+ east = kmalloc(4 * sizeof(int));
|
|
|
+ *east = 2;
|
|
|
+ *(east + 1) = 0;
|
|
|
+ *(east + 2) = 0;
|
|
|
+ *(east + 3) = 1;
|
|
|
+
|
|
|
+ // represents offests for the dest coordinate in our array
|
|
|
+ south = kmalloc(4 * sizeof(int));
|
|
|
+ *south = 1;
|
|
|
+ *(south + 1) = 2;
|
|
|
+ *(south + 2) = 0;
|
|
|
+ *(south + 3) = 0;
|
|
|
+
|
|
|
+ // represents offests for the dest coordinate in our array
|
|
|
+ west = kmalloc(4 * sizeof(int));
|
|
|
+ *west = 0;
|
|
|
+ *(west + 1) = 1;
|
|
|
+ *(west + 2) = 2;
|
|
|
+ *(west + 3) = 0;
|
|
|
+
|
|
|
+ if ((!compass) || !(dirs) || !(north) || !(east) || !(south) || !(west))
|
|
|
+ {
|
|
|
+ panic("Could not allocate offset arrays.\n");
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -190,7 +184,7 @@ void intersection_sync_cleanup()
|
|
|
{
|
|
|
KASSERT(active);
|
|
|
|
|
|
- dellist(active);
|
|
|
+ cleanup();
|
|
|
lock_destroy(globlock);
|
|
|
}
|
|
|
|
|
@@ -215,24 +209,14 @@ void intersection_before_entry(Direction origin, Direction destination)
|
|
|
|
|
|
RESTART:
|
|
|
|
|
|
- // Nothing in intersection, so proceed
|
|
|
- if (!(active->front))
|
|
|
+ for (int i = 0; i < 12; ++i)
|
|
|
{
|
|
|
- push(new);
|
|
|
- lock_release(globlock);
|
|
|
- return;
|
|
|
- }
|
|
|
- else // things are in the intersection
|
|
|
- {
|
|
|
- car * temp = active->front;
|
|
|
+ car * temp = *(active + i);
|
|
|
|
|
|
- while (temp)
|
|
|
+ if (temp)
|
|
|
{
|
|
|
- //kprintf("New o: %d, Comp o: %d, New d: %d, Comp d: %d\n", new->origin, temp->origin, new->dest, temp->dest);
|
|
|
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))))
|
|
|
{
|
|
|
- //kprintf("Everything is fine, continue\n");
|
|
|
- temp = temp->next;
|
|
|
continue;
|
|
|
}
|
|
|
else
|
|
@@ -248,10 +232,14 @@ void intersection_before_entry(Direction origin, Direction destination)
|
|
|
goto RESTART; // now we have to make sure there's nothing else screwing us over
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- push(new);
|
|
|
- lock_release(globlock);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ push(new);
|
|
|
+ lock_release(globlock);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -269,21 +257,7 @@ void intersection_before_entry(Direction origin, Direction destination)
|
|
|
void intersection_after_exit(Direction origin, Direction destination)
|
|
|
{
|
|
|
lock_acquire(globlock);
|
|
|
- car * temp = active->front;
|
|
|
-
|
|
|
- // since this is a list we append to, loop through and stop on first match
|
|
|
- while (temp)
|
|
|
- {
|
|
|
- if (temp->origin == origin && temp->dest == destination)
|
|
|
- {
|
|
|
- clearint(temp);
|
|
|
- break;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- temp = temp->next;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ int position = *(dirs + origin) + *(*(compass + origin) + dest);
|
|
|
+ clearint(active + position);
|
|
|
lock_release(globlock);
|
|
|
}
|