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. kprintf("Failed to create a car.");
  46. panic();
  47. }
  48. temp->origin = origin;
  49. temp->dest = dest;
  50. temp->old = 0;
  51. temp->next = NULL;
  52. temp->cv = NULL;
  53. }
  54. // list initializer/allocator
  55. list * newlist()
  56. {
  57. list * temp = kmalloc(sizeof(list));
  58. if(!(temp))
  59. {
  60. kprintf("Could not allocate list.");
  61. panic();
  62. }
  63. temp->front = NULL;
  64. temp->back = NULL;
  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. 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. temp = active->next;
  118. temp2 = temp;
  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
  162. intersection_sync_init()
  163. {
  164. globlock = lock_create("lightlock");
  165. if (!(globlock))
  166. {
  167. kprintf("Failed to create lock!");
  168. panic();
  169. }
  170. queue = newlist();
  171. active = newlist();
  172. }
  173. /*
  174. * The simulation driver will call this function once after
  175. * the simulation has finished
  176. *
  177. * You can use it to clean up any synchronization and other variables.
  178. *
  179. */
  180. void intersection_sync_cleanup()
  181. {
  182. KASSERT(queue);
  183. KASSERT(active);
  184. dellist(queue);
  185. dellist(active);
  186. lock_destroy(globlock);
  187. }
  188. /*
  189. * The simulation driver will call this function each time a vehicle
  190. * tries to enter the intersection, before it enters.
  191. * This function should cause the calling simulation thread
  192. * to block until it is OK for the vehicle to enter the intersection.
  193. *
  194. * parameters:
  195. * * origin: the Direction from which the vehicle is arriving
  196. * * destination: the Direction in which the vehicle is trying to go
  197. *
  198. * return value: none
  199. */
  200. void intersection_before_entry(Direction origin, Direction destination)
  201. {
  202. lock_acquire(globlock);
  203. car * new = newcar(origin, destination);
  204. RESTART:
  205. // Nothing in intersection, so proceed
  206. if (!(active->front))
  207. {
  208. push(new);
  209. lock_release(globlock);
  210. return;
  211. }
  212. else // things are in the intersection
  213. {
  214. car * temp = active->front;
  215. while (temp)
  216. {
  217. if (temp->origin == new->origin || (temp->origin == new->dest && temp->dest == new->origin) || (temp->dest != new->dest && (rightturn(new) || rightturn(temp))))
  218. {
  219. temp = temp->next;
  220. continue;
  221. }
  222. else
  223. {
  224. enqueue(new);
  225. new->old = 1; // make new "old", since now it has already waited once
  226. lock_release(globlock);
  227. // create cv for temp if it doesn't have one yet
  228. if(!(temp->cv))
  229. {
  230. temp->cv = cv_create("carcv");
  231. }
  232. cv_wait(temp->cv, globlock); // sleep and reacquire lock once woken
  233. goto RESTART; // now we have to make sure there's nothing else screwing us over
  234. }
  235. }
  236. push(new);
  237. lock_release(globlock);
  238. }
  239. }
  240. /*
  241. * The simulation driver will call this function each time a vehicle
  242. * leaves the intersection.
  243. *
  244. * parameters:
  245. * * origin: the Direction from which the vehicle arrived
  246. * * destination: the Direction in which the vehicle is going
  247. *
  248. * return value: none
  249. */
  250. void intersection_after_exit(Direction origin, Direction destination)
  251. {
  252. car * temp = active->first;
  253. while (temp)
  254. {
  255. if (temp->origin == origin && temp->dest == destination)
  256. {
  257. clearint(temp);
  258. break;
  259. }
  260. else
  261. {
  262. temp = temp->next;
  263. }
  264. }
  265. }