io.txt 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. run vec and blocked vec
  2. both trimmed to sum-of-both-sizes
  3. proc is in one or the other
  4. maybe circular doubly-linked lists rather than vecs? possible. more convenient for many things. but
  5. a distraction for now.
  6. Initially we had a non-buffered channel scheme. This was appealing (writer writes directly into slot
  7. address provided from reader) but subtly wrong:
  8. - reader and writer become *too temporally coupled* in this model.
  9. - in particular, assume (as is likely normal) that both reader and writer wish to do some i/o
  10. but do *not* wish to block for "the other guy". IOW they always want to be able to check if
  11. communication has become possible and if not, *do useful work* rather than block. if the
  12. channel is unbuffered, they're sunk: one of them has to block. Either reader commits to
  13. reading and then blocks until a writer shows up, or vice-versa. If neither commits to a
  14. blocking i/o operation, the "ready to communicate" bit of information is never passed, and
  15. they will never decide to communicate. neither can signal their intent-to-communicate passively.
  16. - one can think of a channel has *really* being bidirectional: one direction sends 1-bit signals
  17. of communication-readyness and the other direction sends data. the problem with an unbuffered
  18. channel is that the sender/receiver roles are *not defined* for the comm-ready signal. it's not
  19. clear from looking at an idle channel whether it's waiting for a reader or a writer (as it can
  20. be waiting for *both*).
  21. - if we insist that a channel always have a buffer of at least 1 entry, we avoid this:
  22. - if the buffer 'has room', it's waiting for a writer.
  23. - if the buffer 'has data', it's waiting for a reader.
  24. - if the buffer 'has both', it's waiting for both.
  25. - 'having room' is a soft condition, as we permit writers to *always* attempt insertion
  26. by expanding their send buffer. possibly crashing OOM, but still.
  27. - key point: it always has either room or data (or both). there is no state of having
  28. neither room nor data. so both sides can always determine what the appropriate next
  29. action for them is. if a writer polls and sees room, it can go do work and be sure that
  30. it has somewhere to put it with zero delay. if a reader polls and sees data, it can
  31. read it and do work with zero delay.
  32. - as a sort of mental-model and implementation-simplicity issue, this is also important in that
  33. buffering (of not-entirely-clear size) is the correct assumption for nearly every physical
  34. communication system. synchronicity is always an illusion engineered at some cost on top of
  35. buffered / asynchronous communication. arguably the real physical world of physics consists of
  36. the same assumption: sender of a bit is temporally (and spatially) decoupled from receiver of a
  37. bit. so it is better to provide an honest primitive and let people build higher level systems
  38. when and if they want them.
  39. --- NOTE: BUSTED NON-BUFFERED PROTOCOL FOLLOWS ---
  40. writing into a chan:
  41. - note that the chan *belongs to* the proc; it represents "everything this proc has buffered to send to a port"
  42. - check port to see if blocked-reading-on is set:
  43. - if so, perform rendezvous
  44. - else
  45. - set blocked-writing-on bit on chan, add the chan to the port's queued-writer set if not already so
  46. - set proc state to blocked-writing (if blocking-write), remove from runnable queue
  47. reading from a *single* port:
  48. - if port writer set is nonempty:
  49. - randomly select writer from writers
  50. - perform rendezvous
  51. - else
  52. - set blocked-reading-on bit on port
  53. - set proc state to blocked-reading, remove from runnable queue
  54. rendezvous(reader, writer):
  55. - switch writer to runnable, remove writer from writer-set
  56. - return 'go' to writer; writer now has addr of dst in reader. reader still suspended.
  57. - writer checks return code, conditionally branches do either do nothing or copy-to-reader and continue
  58. - writer upcalls "write complete". important? maybe. depends if copy is an involved thing that might reschedule. for now yes.
  59. - on write complete, reader unblocked.