Advertisement
Guest User

Untitled

a guest
Feb 18th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.35 KB | None | 0 0
  1. Due date:
  2. 2/20/2018 @ 11:59pm for test case
  3. 2/21/2018 @ 11:59pm working code and report
  4.  
  5. Objective:
  6. ~~~~~~~~~~
  7.  
  8. - Learn how to implement (and work with) new control abstractions
  9.  
  10. Description:
  11. ~~~~~~~~~~~~
  12.  
  13. We will implement a form of communicating sequential processes (CSP). We will
  14. not call them processes in order to avoid confusion with Unix processes so
  15. we'll borrow the golang terminology and call them c-routines. Go calls them
  16. go-routines, a clever play on the term coroutines, functions that alternate
  17. their execution as opposed to having a strict caller-callee relationship.
  18.  
  19. The key to figuring out how to make those things work is to think of the
  20. execution stack as a data structure and allow your code to manipulate
  21. stacks, create new ones, insert them in queues, switch between then, etc.
  22.  
  23. Starting a c-routine:
  24. ~~~~~~~~~~~~~~~~~~~~~
  25.  
  26. You start a c-routine using the go() function. For example:
  27.  
  28. void f1(void) {
  29. printf("I'm a c-routine\n");
  30. }
  31.  
  32. int main() {
  33. go(f1);
  34. ...
  35. }
  36.  
  37. After calling go(), we will have 2 concurrent paths through the code, one
  38. that runs the body of the f1 function and another that continues the
  39. execution of main.
  40.  
  41. Calling "go(f1)" creates a new c-routine that runs the body of "f1"
  42.  
  43. Our c-routines will be concurrent but not parallel. This means that they never
  44. run simultaneously (otherwise we'd call them threads). Instead, one of them
  45. will run until it finishes or becomes blocked, giving other c-routines a
  46. chance to run.
  47.  
  48. Terminating a c-routine:
  49. ~~~~~~~~~~~~~~~~~~~~~~~~
  50.  
  51. A c-routines terminates in one of those conditions:
  52.  
  53. (1) its function returns
  54. (2) it tries to send/receive to/from a poisoned channel
  55. (3) a channel on which it is blocked is poisoned
  56.  
  57. Terminating the program:
  58. ~~~~~~~~~~~~~~~~~~~~~~~~
  59.  
  60. Your program terminates if one of 2 things happen:
  61.  
  62. - main returns
  63. - all c-routines terminate or become blocked
  64.  
  65. Channels:
  66. ~~~~~~~~~
  67.  
  68. Channels are communication mechanisms between c-routines. Our channels are
  69. non-buffered and synchronous.
  70.  
  71. Synchronous => a sender/receiver will block until its operation succeeds
  72.  
  73. Non-buffered => the channel doesn't store any values. A sender and receiver
  74. need to be matched before they both proceed
  75.  
  76. What can you do with a channel?
  77.  
  78. Channel* channel(void); // create a new channel
  79. send(Channel* ch, Value v); // send a message on the channel
  80. Value receive(Channel* ch); // receive a message from the channel
  81. void poison(Channel* ch); // put a poison pill in the channel
  82. bool isPoisoned(Channel* ch); // check if the channel is poisoned
  83.  
  84. Associated channels
  85. ~~~~~~~~~~~~~~~~~~
  86.  
  87. Each c-routine comes with an associated channel.
  88.  
  89. The go() function creates a c-routines and returns its associated channel:
  90.  
  91. Channel* go(Func f);
  92.  
  93. A c-routine can discover its channel using the "me()" function:
  94.  
  95. Channel* me(); // returns the channel associated with the
  96. // calling c-routine
  97.  
  98.  
  99. Complete API
  100. ~~~~~~~~~~~~
  101.  
  102. Look in go.h for details
  103.  
  104. typedef void (*Func)(void);
  105.  
  106. typedef union Value {
  107. char asChar;
  108. short asShort;
  109. int asInt;
  110. long asLong;
  111. long long asLongLong;
  112. uint64_t asU64;
  113. uint32_t asU32;
  114. uint16_t asU16;
  115. uint8_t asU8;
  116. int64_t asI64;
  117. int32_t asI32;
  118. int16_t asI16;
  119. int8_t asI8;
  120. Func asFunc;
  121. void* asPointer;
  122. Channel* asChannel;
  123. char* asString;
  124. } Value;
  125.  
  126. extern Channel* go(Func func); // create a c-routine running func
  127. // returns its associated channel
  128.  
  129. extern Channel* me(void); // returns the associated channel
  130. // of the caller
  131.  
  132. extern Channel* channel(void); // create a new channel
  133.  
  134. extern void poison(Channel* ch); // poison a channel
  135.  
  136. extern bool isPoisoned(Channel* ch); // check if a channel is poisoned
  137.  
  138. extern void send(Channel* ch, Value v); // Send the given value on the channel
  139. // blocks until it is matched with
  140. // a receiver
  141.  
  142. extern Value receive(Channel* ch); // Receive the next value in the
  143. // channel. Blocks until it is matched
  144. // with a sender
  145.  
  146. extern void again(void); // restart the current c-routine
  147. // takes it back to its starting
  148. // point
  149.  
  150. How do you start?
  151. ~~~~~~~~~~~~~~~~~
  152.  
  153. Could might look overwhelming but it's easier than you think.
  154.  
  155. - Read the "magic" code in "magic.s" and make sure you understand it. The
  156. best way is to trace through its execution on paper (or a whiteboard)
  157.  
  158. - Look at the Routine struct and think about the other information you'd need
  159. to store in it
  160.  
  161. - Look at the Queue struct and its associated functions (don't you wish we
  162. has methods?). Think about how you'd use that to represent things like
  163. c-routines that are ready to run, those that we waiting to send messages,
  164. those that waiting to receive messages, etc.
  165.  
  166. - Look at the test cases t0.test, t1.test, ..., and try to visualize their
  167. execution
  168.  
  169. What you need to do:
  170. ~~~~~~~~~~~~~~~~~~~~
  171.  
  172. (1) Answer the question in REPORT.txt
  173.  
  174. (2) Add a test case (<csid>.test and <csid>.ok, less then 2000 characters each)
  175.  
  176. - <csid>.test contains a main program written in C
  177. - <csid>.ok contains the expected output
  178.  
  179. Please keep in mind that your test case can't rely in the specific order
  180. of interleaving between c-routines, only on the causal relationships
  181. established by channel communications:
  182.  
  183. - a message can not be received before it is sent
  184.  
  185. The safest thing to do is to limit printing to a single c-routine
  186.  
  187. To compile:
  188. ~~~~~~~~~~~
  189.  
  190. make
  191.  
  192. To run test:
  193. ~~~~~~~~~~~~
  194.  
  195. make clean test
  196.  
  197. To build one test case (e.g. t1)
  198. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  199.  
  200. make t1
  201.  
  202. you can then run it
  203.  
  204. ./t1
  205.  
  206. To see the results of one test (e.g. t1):
  207. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  208.  
  209. make clean t1.result
  210.  
  211. To make the output less noisy:
  212. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  213.  
  214. make -s clean test
  215.  
  216. To debug a test
  217. ~~~~~~~~~~~~~~~
  218.  
  219. make t0
  220. gdb ./t0
  221.  
  222. It is a good idea to replace all -O3 in the Makefile with -O0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement