traffic_synch.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include <types.h>
  2. #include <lib.h>
  3. #include <synchprobs.h>
  4. #include <synch.h>
  5. #include <opt-A1.h>
  6. /*
  7. * This simple default synchronization mechanism allows only vehicle at a time
  8. * into the intersection. The intersectionSem is used as a a lock.
  9. * We use a semaphore rather than a lock so that this code will work even
  10. * before locks are implemented.
  11. */
  12. /*
  13. * Replace this default synchronization mechanism with your own (better) mechanism
  14. * needed for your solution. Your mechanism may use any of the available synchronzation
  15. * primitives, e.g., semaphores, locks, condition variables. You are also free to
  16. * declare other global variables if your solution requires them.
  17. */
  18. /*
  19. * replace this with declarations of any synchronization and other variables you need here
  20. */
  21. static struct lock * globlock;
  22. typedef struct cv cv;
  23. // This section contains global vars and useful functions to work with them. As well as the structs used for them
  24. typedef struct car
  25. {
  26. Direction origin;
  27. Direction dest;
  28. bool old;
  29. car * next;
  30. cv * cv;
  31. } car;
  32. typedef struct list
  33. {
  34. car * front;
  35. car * back;
  36. } list;
  37. list * queue = NULL;
  38. list * active = NULL;
  39. // car initializer/allocator
  40. car * newcar(Direction origin, Direction dest)
  41. {
  42. car * temp = kmalloc(sizeof(car));
  43. if(!(temp))
  44. {
  45. panic("Failed to create a car.");
  46. }
  47. temp->origin = origin;
  48. temp->dest = dest;
  49. temp->old = 0;
  50. temp->next = NULL;
  51. temp->cv = NULL;
  52. return temp;
  53. }
  54. // list initializer/allocator
  55. list * newlist()
  56. {
  57. list * temp = kmalloc(sizeof(list));
  58. if(!(temp))
  59. {
  60. panic("Could not allocate list.");
  61. }
  62. temp->front = NULL;
  63. temp->back = NULL;
  64. return temp;
  65. }
  66. // puts a car into the queue, at the front if old is true, the back otherwise
  67. void enqueue(car * newcar)
  68. {
  69. if (!(queue->back))
  70. {
  71. queue->front = newcar;
  72. queue->back = newcar;
  73. }
  74. if (newcar->old) // if the car is "old", let it go first. be nice to your elders
  75. {
  76. car * temp = queue->front;
  77. queue->front = newcar;
  78. newcar->next = temp;
  79. return;
  80. }
  81. queue->back->next = newcar;
  82. queue->back = newcar;
  83. }
  84. // push a car to the end of the active list
  85. void push(car * newcar)
  86. {
  87. if (!(active->front))
  88. {
  89. active->front = newcar;
  90. active->back = newcar;
  91. }
  92. active->back->next = newcar;
  93. active->back = newcar;
  94. }
  95. // remove an element from the front of the queue
  96. struct car * pop()
  97. {
  98. if (!(queue->front))
  99. {
  100. return NULL;
  101. }
  102. if (queue->front == queue->back)
  103. {
  104. queue->back == NULL;
  105. }
  106. car * temp = queue->front;
  107. queue->front = queue->front->next;
  108. return temp;
  109. }
  110. // called when a car clears the intersection
  111. void clearint(car * done)
  112. {
  113. car * temp = active->front;
  114. car * temp2 = NULL;
  115. while(temp != done)
  116. {
  117. temp2 = temp;
  118. temp = temp>next;
  119. }
  120. // first element of the list is being removed
  121. if (!(temp2))
  122. {
  123. active->front = active->front->next;
  124. goto SKIP1;
  125. }
  126. temp2->next = temp->next;
  127. SKIP1:
  128. if (temp->cv) // if this car was blocking something
  129. {
  130. cv_broadcast(temp->cv, globlock); // wake all/inform them you're all good
  131. kfree(temp->cv);
  132. }
  133. kfree(temp);
  134. }
  135. // cleans up a list
  136. void dellist(list * dead)
  137. {
  138. car * temp = dead->front;
  139. while (temp)
  140. {
  141. car * temp2 = temp->next;
  142. kfree(temp->cv);
  143. kfree(temp);
  144. temp = temp2;
  145. }
  146. kfree(dead);
  147. }
  148. // returns true if a car is turning right
  149. bool rightturn(car * car)
  150. {
  151. int temp = car->origin - car->dest;
  152. return (temp == 1 || temp == -3);
  153. }
  154. /*
  155. * The simulation driver will call this function once before starting
  156. * the simulation
  157. *
  158. * You can use it to initialize synchronization and other variables.
  159. *
  160. */
  161. void intersection_sync_init()
  162. {
  163. globlock = lock_create("lightlock");
  164. if (!(globlock))
  165. {
  166. panic("Failed to create lock!");
  167. }
  168. queue = newlist();
  169. active = newlist();
  170. }
  171. /*
  172. * The simulation driver will call this function once after
  173. * the simulation has finished
  174. *
  175. * You can use it to clean up any synchronization and other variables.
  176. *
  177. */
  178. void intersection_sync_cleanup()
  179. {
  180. KASSERT(queue);
  181. KASSERT(active);
  182. dellist(queue);
  183. dellist(active);
  184. lock_destroy(globlock);
  185. }
  186. /*
  187. * The simulation driver will call this function each time a vehicle
  188. * tries to enter the intersection, before it enters.
  189. * This function should cause the calling simulation thread
  190. * to block until it is OK for the vehicle to enter the intersection.
  191. *
  192. * parameters:
  193. * * origin: the Direction from which the vehicle is arriving
  194. * * destination: the Direction in which the vehicle is trying to go
  195. *
  196. * return value: none
  197. */
  198. void intersection_before_entry(Direction origin, Direction destination)
  199. {
  200. lock_acquire(globlock);
  201. car * new = newcar(origin, destination);
  202. RESTART:
  203. // Nothing in intersection, so proceed
  204. if (!(active->front))
  205. {
  206. push(new);
  207. lock_release(globlock);
  208. return;
  209. }
  210. else // things are in the intersection
  211. {
  212. car * temp = active->front;
  213. while (temp)
  214. {
  215. if (temp->origin == new->origin || (temp->origin == new->dest && temp->dest == new->origin) || (temp->dest != new->dest && (rightturn(new) || rightturn(temp))))
  216. {
  217. temp = temp->next;
  218. continue;
  219. }
  220. else
  221. {
  222. enqueue(new);
  223. new->old = 1; // make new "old", since now it has already waited once
  224. lock_release(globlock);
  225. // create cv for temp if it doesn't have one yet
  226. if(!(temp->cv))
  227. {
  228. temp->cv = cv_create("carcv");
  229. }
  230. cv_wait(temp->cv, globlock); // sleep and reacquire lock once woken
  231. goto RESTART; // now we have to make sure there's nothing else screwing us over
  232. }
  233. }
  234. push(new);
  235. lock_release(globlock);
  236. }
  237. }
  238. /*
  239. * The simulation driver will call this function each time a vehicle
  240. * leaves the intersection.
  241. *
  242. * parameters:
  243. * * origin: the Direction from which the vehicle arrived
  244. * * destination: the Direction in which the vehicle is going
  245. *
  246. * return value: none
  247. */
  248. void intersection_after_exit(Direction origin, Direction destination)
  249. {
  250. car * temp = active->front;
  251. while (temp)
  252. {
  253. if (temp->origin == origin && temp->dest == destination)
  254. {
  255. clearint(temp);
  256. break;
  257. }
  258. else
  259. {
  260. temp = temp->next;
  261. }
  262. }
  263. }