Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2020
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.43 KB | None | 0 0
  1. /*
  2.  * stoplight.c
  3.  *
  4.  * You can use any synchronization primitives available to solve
  5.  * the stoplight problem in this file.
  6.  
  7.  - Could have 2 keys: North_South Light, West_East Light
  8.  - 3 condition variables: left, right, straight
  9.  
  10.  */
  11.  
  12.  
  13. /*
  14.  *
  15.  * Includes
  16.  *
  17.  */
  18.  
  19. #include <types.h>
  20. #include <lib.h>
  21. #include <test.h>
  22. #include <thread.h>
  23. #include <synch.h>
  24. #include <queue.h>
  25. #include <curthread.h>
  26.  
  27.  
  28. /*
  29.  * Number of cars created.
  30.  */
  31.  
  32. #define NCARS 20
  33.  
  34. // struct lock *intersection[4];
  35. // struct cv *right_of_way[4];
  36.  
  37. struct queue *north_south_light;
  38. struct queue *west_east_light;
  39.  
  40. struct lock *light;
  41. struct cv *not_approaching;
  42.  
  43. // struct lock *NW;
  44. // struct lock *NE;
  45. // struct lock *SW;
  46. // struct lock *SE;
  47.  
  48. int north_south; //(1 means NS, 0 means WE)
  49.  
  50. // int straight; //bools
  51. // int left;
  52. // int right;
  53. // int driver_dir; // 0 = N, 1 = E, 2 = S, 3 = W;
  54.  
  55. // 0 = NW, 1 = NE, 2 = SW, 3 = SE
  56.  
  57.  
  58. /*
  59.  *
  60.  * Function Definitions
  61.  *
  62.  */
  63.  
  64. static const char *directions[] = { "N", "E", "S", "W" };
  65.  
  66. static const char *msgs[] = {
  67.         "approaching:",
  68.         "region1:    ",
  69.         "region2:    ",
  70.         "region3:    ",
  71.         "leaving:    "
  72. };
  73.  
  74. /* use these constants for the first parameter of message */
  75. enum { APPROACHING, REGION1, REGION2, REGION3, LEAVING };
  76.  
  77. static void
  78. message(int msg_nr, int carnumber, int cardirection, int destdirection)
  79. {
  80.         kprintf("%s car = %2d, direction = %s, destination = %s\n",
  81.                 msgs[msg_nr], carnumber,
  82.                 directions[cardirection], directions[destdirection]);
  83. }
  84.  
  85. /////////////////////////////////////////////////////////////////////////////////
  86. // Stop Light Queues
  87.  
  88. void
  89. up_for_grabs(){
  90.         north_south = random() % 1;
  91. }
  92.  
  93. int
  94. get_destination(int turn, int cardirection){
  95.         if (turn == 0)
  96.                 return ((cardirection + 2) % 4);
  97.         else if (turn == 1)
  98.                 return ((cardirection + 1) % 4);
  99.         else if (turn == 2)
  100.                 return ((cardirection + 3) % 4);
  101.         else return 0;
  102. }
  103.  
  104. int
  105. *getPath(const char *path_way, unsigned long cardirection){
  106.        
  107.         if (path_way == "straight"){
  108.                 static int path[2];
  109.  
  110.                 switch(cardirection) {
  111.                         case 0:
  112.                                 path[0] = 0;
  113.                                 path[1] = 2;
  114.                                 break;
  115.                         case 1:
  116.                                 path[0] = 1;
  117.                                 path[1] = 0;
  118.                                 break;
  119.                         case 2:
  120.                                 path[0] = 3;
  121.                                 path[1] = 1;
  122.                                 break;
  123.                         case 3:
  124.                                 path[0] = 2;
  125.                                 path[1] = 3;
  126.                                 break;
  127.  
  128.                 }
  129.                 return path;
  130.         }
  131.  
  132.         else if (path_way == "right"){
  133.                 static int path[1];
  134.                 switch(cardirection) {
  135.                         case 0:
  136.                                 path[0] = 0;
  137.                                 break;
  138.                         case 1:
  139.                                 path[0] = 1;
  140.                                 break;
  141.                         case 2:
  142.                                 path[0] = 3;
  143.                                 break;
  144.                         case 3:
  145.                                 path[0] = 2;
  146.                                 break;
  147.  
  148.                 }
  149.                 return path;
  150.         }
  151.         else {
  152.                 static int path[3];
  153.  
  154.                 switch(cardirection) {
  155.                         case 0:
  156.                                 path[0] = 0;
  157.                                 path[1] = 2;
  158.                                 path[2] = 3;
  159.                                 break;
  160.                         case 1:
  161.                                 path[0] = 1;
  162.                                 path[1] = 0;
  163.                                 path[2] = 2;
  164.                                 break;
  165.                         case 2:
  166.                                 path[0] = 3;
  167.                                 path[1] = 1;
  168.                                 path[2] = 0;
  169.                                 break;
  170.                         case 3:
  171.                                 path[0] = 2;
  172.                                 path[1] = 3;
  173.                                 path[2] = 1;
  174.                                 break;
  175.  
  176.                 }
  177.                 return path;
  178.         }
  179.         return NULL;
  180. }
  181.  
  182. // static void
  183. // checkLocksIntersections(struct lock *lock1, struct lock *lock2, struct lock *lock3, int numOfRegionsPassed, int carnumber, int cardirection, int destdirection){
  184.        
  185. //         if (lock1 != NULL) lock_acquire(lock1);
  186. //         if (lock2 != NULL) lock_acquire(lock2);
  187. //         if (lock3 != NULL) lock_acquire(lock3);
  188. //         printRealMessage(numOfRegionsPassed, carnumber, cardirection, destdirection);
  189. //         if (lock3 != NULL) lock_release(lock3);
  190. //         if (lock2 != NULL) lock_release(lock2);
  191. //         if (lock1 != NULL) lock_release(lock1);
  192. // }
  193.  
  194. // void
  195. // right(int cardirection){
  196. //         // north goes west (NW)
  197. //         if (cardirection == 0){
  198. //                 lock_acquire()
  199. //         }
  200. //         // east goes north (NE)
  201. //         // south goes east (SE)
  202. //         // west goes south (SW)
  203. // }
  204.  
  205. // void
  206. // acquire_path(int *path, int size, int carnumber, int cardirection, int turn){
  207.  
  208. //         int i;
  209. //         int destination;
  210. //         destination = get_destination(turn, cardirection);
  211. //         for (i = 0; i < size; i++){
  212. //                 // if (lock_do_i_hold(intersection[*(path + i)])) {
  213. //                 //         cv_wait(right_of_way[*(path + i)], intersection[*(path + i)]);
  214. //                 // }
  215. //                 lock_acquire(intersection[*(path + i)]);
  216. //                 message(i+1, carnumber, cardirection, destination);
  217. //         }
  218.  
  219. // }
  220.  
  221. // void
  222. // release_path(int *path, int size, /*int carnumber,*/ int cardirection, int turn){
  223.  
  224. //         int i;
  225. //         int index;
  226. //         int destination;
  227. //         destination = get_destination(turn, cardirection);
  228. //         for (i = 0; i < size; i++){
  229. //                 index = size - i;
  230. //                 // message(LEAVING, carnumber, cardirection, destination);
  231. //                 lock_release(intersection[*(path + index)]);
  232. //                 // cv_signal(right_of_way[*(path + i)], intersection[*(path + i)]);
  233. //         }
  234. //
  235. // }
  236.  
  237.  
  238. // void path (int cardirection, int destdirection, int turn) {
  239.        
  240. // }
  241.  
  242. /*
  243.  * gostraight()
  244.  *
  245.  * Arguments:
  246.  *      unsigned long cardirection: the direction from which the car
  247.  *              approaches the intersection.
  248.  *      unsigned long carnumber: the car id number for printing purposes.
  249.  *
  250.  * Returns:
  251.  *      nothing.
  252.  *
  253.  * Notes:
  254.  *      This function should implement passing straight through the
  255.  *      intersection from any direction.
  256.  *      Write and comment this function.
  257.  */
  258.  
  259. static
  260. void
  261. gostraight(unsigned long cardirection,
  262.            unsigned long carnumber)
  263. {
  264.         /*
  265.          * Avoid unused variable warnings.
  266.          */
  267.  
  268.         // based on car direction, which locks should I try and acquire
  269.         // 0 = north, 1 = east, 2 = south, 3 = west
  270.  
  271.         // int *path;
  272.         // path = getPath("straight", cardirection);
  273.         // acquire_path(path, 2, carnumber, cardirection, 0);
  274.         // release_path(path, 2, /*carnumber,*/ cardirection, 0);
  275.        
  276.         int destination = get_destination(0, cardirection);
  277.  
  278.         message(REGION1, carnumber, cardirection, destination);
  279.         message(REGION2, carnumber, cardirection, destination);
  280.         message(LEAVING, carnumber, cardirection, destination);
  281.  
  282.         // up_for_grabs();
  283.         lock_release(light);
  284.  
  285.  
  286.  
  287.  
  288.         // needs to acquire 2 locks
  289.         // if you can't
  290.  
  291.  
  292.         // lock_release(intersection);
  293.  
  294.         (void) cardirection;
  295.         (void) carnumber;
  296. }
  297.  
  298.  
  299. /*
  300.  * turnleft()
  301.  *
  302.  * Arguments:
  303.  *      unsigned long cardirection: the direction from which the car
  304.  *              approaches the intersection.
  305.  *      unsigned long carnumber: the car id number for printing purposes.
  306.  *
  307.  * Returns:
  308.  *      nothing.
  309.  *
  310.  * Notes:
  311.  *      This function should implement making a left turn through the
  312.  *      intersection from any direction.
  313.  *      Write and comment this function.
  314.  */
  315.  
  316. static
  317. void
  318. turnleft(unsigned long cardirection,
  319.          unsigned long carnumber)
  320. {
  321.         /*
  322.          * Avoid unused variable warnings.
  323.          */
  324.  
  325.         // lock_release(intersection);
  326.  
  327.         /*
  328.          * While I either don't have lock1 , lock2 , or lock3
  329.          * Lock do I hold returns false here
  330.          * cv_wait on the locks that I do have
  331.         */
  332.  
  333.         /*
  334.          * Acquire locks 1 and 2
  335.          * if you can acquire 1 but not 2, let 1 go and try again
  336.          * if you can acquire both, try and aquire 3
  337.          * if you can't acquire 3, let 1 and 2 go and try again
  338.          * if you acquire 3, let go of lock 1
  339.          */
  340.  
  341.          /*
  342.           * Avoid unused variable warnings.
  343.           *
  344.           */
  345.  
  346.         // int *path;
  347.         // path = getPath("left", cardirection);
  348.         // acquire_path(path, 3, carnumber, cardirection, 1);
  349.         // release_path(path, 3, /*carnumber,*/ cardirection, 1);
  350.  
  351.         int destination = get_destination(1, cardirection);
  352.  
  353.         message(REGION1, carnumber, cardirection, destination);
  354.         message(REGION2, carnumber, cardirection, destination);
  355.         message(REGION3, carnumber, cardirection, destination);
  356.         message(LEAVING, carnumber, cardirection, destination);
  357.  
  358.         // up_for_grabs();
  359.         lock_release(light);
  360.  
  361.         (void) cardirection;
  362.         (void) carnumber;
  363. }
  364.  
  365.  
  366. /*
  367.  * turnright()
  368.  *
  369.  * Arguments:
  370.  *      unsigned long cardirection: the direction from which the car
  371.  *              approaches the intersection.
  372.  *      unsigned long carnumber: the car id number for printing purposes.
  373.  *
  374.  * Returns:
  375.  *      nothing.
  376.  *
  377.  * Notes:
  378.  *      This function should implement making a right turn through the
  379.  *      intersection from any direction.
  380.  *      Write and comment this function.
  381.  */
  382.  
  383. static
  384. void
  385. turnright(unsigned long cardirection,
  386.           unsigned long carnumber)
  387. {
  388.         /*
  389.          * Avoid unused variable warnings.
  390.          */
  391.  
  392.         // lock_release(intersection);
  393.  
  394.         // int *path;
  395.         // path = getPath("right", cardirection);
  396.         // acquire_path(path, 1, carnumber, cardirection, 2);
  397.         // release_path(path, 1, /*carnumber,*/ cardirection, 2);
  398.  
  399.         int destination = get_destination(2, cardirection);
  400.  
  401.         // if you have the green on a right, you can go immediately
  402.  
  403.         message(REGION1, carnumber, cardirection, destination);
  404.         message(LEAVING, carnumber, cardirection, destination);
  405.  
  406.         // up_for_grabs();
  407.         lock_release(light);
  408.  
  409.         (void) cardirection;
  410.         (void) carnumber;
  411. }
  412.  
  413.  
  414. /*
  415.  * approachintersection()
  416.  *
  417.  * Arguments:
  418.  *      void * unusedpointer: currently unused.
  419.  *      unsigned long carnumber: holds car id number.
  420.  *
  421.  * Returns:
  422.  *      nothing.
  423.  *
  424.  * Notes:
  425.  *      Change this function as necessary to implement your solution. These
  426.  *      threads are created by createcars().  Each one must choose a direction
  427.  *      randomly, approach the intersection, choose a turn randomly, and then
  428.  *      complete that turn.  The code to choose a direction randomly is
  429.  *      provided, the rest is left to you to implement.  Making a turn
  430.  *      or going straight should be done by calling one of the functions
  431.  *      above.
  432.  */
  433.  
  434. static
  435. void
  436. approachintersection(void * unusedpointer,
  437.                      unsigned long carnumber)
  438. {
  439.         /*
  440.          * if direction is north or south, acquire the intersection
  441.          */
  442.  
  443.         int cardirection;
  444.         int turn;
  445.         int destination;
  446.  
  447.         int num_threads = thread_count();
  448.         if (num_threads == 1) up_for_grabs();
  449.  
  450.         /*
  451.          * Avoid unused variable and function warnings.
  452.          */
  453.  
  454.         (void) unusedpointer;
  455.         (void) carnumber;
  456.         (void) gostraight;
  457.         (void) turnleft;
  458.         (void) turnright;
  459.  
  460.         /*
  461.          * cardirection is set randomly.
  462.          * { "N", "E", "S", "W" }
  463.          */
  464.  
  465.         cardirection = random() % 4;
  466.         turn = random() % 3;
  467.         destination = get_destination(turn, cardirection);
  468.  
  469.         // north south
  470.         if (cardirection == 0 || cardirection == 2) {
  471.                 while (!north_south) thread_yield();
  472.                 // q_addtail(north_south_light, curthread); // adding the current thread to q
  473.                 lock_acquire(light);
  474.                 // which_dir = "NS";
  475.  
  476.                 // assert (!q_empty(north_south_light));
  477.                 // void *next_car = q_remhead(west_east_light);
  478.                 // if (next_car != curthread) cv_wait(not_approaching, light);
  479.         }
  480.         else {
  481.                 // q_addtail(west_east_light, curthread);
  482.                 while (north_south) thread_yield();
  483.                 lock_acquire(light);
  484.  
  485.                 // on the condition that the current thread is not next in line, cv_wait
  486.                 // if you were able to acquire the lock but don't need the lock
  487.                 // assert (!q_empty(west_east_light));
  488.                 // void *next_car = q_remhead(west_east_light);
  489.                 // if (next_car != curthread) cv_wait(not_approaching, light);
  490.  
  491.                 // which_dir = "WE";
  492.         }
  493.  
  494.         message(APPROACHING, carnumber, cardirection, destination);
  495.  
  496.         if (turn == 0)
  497.                 gostraight(cardirection, carnumber);
  498.         else if (turn == 1)
  499.                 turnleft(cardirection, carnumber);
  500.         else if (turn == 2)
  501.                 turnright(cardirection, carnumber);
  502.  
  503.         if (north_south) north_south = 0;
  504.         else north_south = 1;
  505. }
  506.  
  507.  
  508. /*
  509.  * createcars()
  510.  *
  511.  * Arguments:
  512.  *      int nargs: unused.
  513.  *      char ** args: unused.
  514.  *
  515.  * Returns:
  516.  *      0 on success.
  517.  *
  518.  * Notes:
  519.  *      Driver code to start up the approachintersection() threads.  You are
  520.  *      free to modiy this code as necessary for your solution.
  521.  */
  522.  
  523. void
  524. creating(){
  525.  
  526.         north_south_light = q_create(NCARS);
  527.         west_east_light = q_create(NCARS);
  528.  
  529.         light = lock_create("light");
  530.         not_approaching = cv_create("not_approaching");
  531.  
  532.         // intersection[0] = lock_create("NW");
  533.         // intersection[1] = lock_create("NE");
  534.         // intersection[2] = lock_create("SW");
  535.         // intersection[3] = lock_create("SE");
  536.  
  537.         // right_of_way[0] = cv_create("NW");
  538.         // right_of_way[1] = cv_create("NE");
  539.         // right_of_way[2] = cv_create("SW");
  540.         // right_of_way[3] = cv_create("SE");
  541. }
  542.  
  543. void
  544. destroying(){
  545.  
  546.         q_destroy(north_south_light);
  547.         q_destroy(west_east_light);
  548.  
  549.         lock_destroy(light);
  550.         cv_destroy(not_approaching);
  551.  
  552.         // lock_destroy(intersection[0]);
  553.         // lock_destroy(intersection[1]);
  554.         // lock_destroy(intersection[2]);
  555.         // lock_destroy(intersection[3]);
  556.  
  557.         // cv_destroy(right_of_way[0]);
  558.         // cv_destroy(right_of_way[1]);
  559.         // cv_destroy(right_of_way[2]);
  560.         // cv_destroy(right_of_way[3]);  
  561. }
  562.  
  563. int
  564. createcars(int nargs,
  565.            char ** args)
  566. {
  567.         int index, error;
  568.  
  569.         creating();
  570.    
  571.         /*
  572.          * Start NCARS approachintersection() threads.
  573.          */
  574.  
  575.         for (index = 0; index < NCARS; index++) {
  576.                 error = thread_fork("approachintersection thread",
  577.                                     NULL, index, approachintersection, NULL);
  578.  
  579.                 /*
  580.                 * panic() on error.
  581.                 */
  582.  
  583.                 if (error) {        
  584.                         panic("approachintersection: thread_fork failed: %s\n",
  585.                               strerror(error));
  586.                 }
  587.         }
  588.        
  589.         /*
  590.          * wait until all other threads finish
  591.          */
  592.  
  593.         while (thread_count() > 1)
  594.                 thread_yield();
  595.  
  596.  
  597.     (void)message;
  598.         (void)nargs;
  599.         (void)args;
  600.         kprintf("stoplight test done\n");
  601.  
  602.         destroying();
  603.  
  604.         return 0;
  605. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement