traffic_synch.c 6.0 KB

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