traffic_synch.c 6.2 KB

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