Add moar documentation.

(Mostly about handles, some about synchronous use of message pipes.)

R=vardhan@google.com

Review URL: https://codereview.chromium.org/1756603003 .
diff --git a/docs/intro/handles.md b/docs/intro/handles.md
index c59105c..b0b9459 100644
--- a/docs/intro/handles.md
+++ b/docs/intro/handles.md
@@ -1,3 +1,29 @@
 # Mojo handles (objects)
 
-**TODO(vtl)**
+Mojo handles are analogous to Unix file descriptors or Windows `HANDLE`s. That
+is, they are basically-opaque integers that a program can use to refer to system
+resources. Like their Unix and Windows equivalents, a Mojo handle value only has
+meaning within a given process.
+
+That said, there are some differences:
+* There is a single value, 0, that is guaranteed to never be a valid Mojo
+  handle. This is unlike Unix, where all negative file descriptors are usually
+  taken to be invalid, even if -1 is often taken to be the "canonical" invalid
+  file descriptor value.
+* The allocation of Mojo handle values is not specified. This is unlike Unix,
+  where file descriptors are allocated sequentially, with the lowest (positive)
+  unused value allocated.
+* Unlike Windows, there are no "pseudohandles". That is, there is no Mojo handle
+  value whose meaning is context dependent (within the same process).
+* In general, Mojo handles need not be duplicatable, whereas their Unix and
+  Windows equivalents can universally be duplicated.
+* Mojo handles can be sent across [message pipes](message_pipes.md). Unlike
+  sending file descriptors over Unix domain sockets (using `SCM_RIGHTS`), this
+  is done with transfer semantics: after a message with attached Mojo handles is
+  sent, the Mojo handle values become invalid in the sending process. (Even if
+  the receiving process is the same as the sending process, the received Mojo
+  handle values will probably be different from the values that were sent.)
+* Mojo handles have a well-defined life-cycle, and are only invalidated by
+  either transfer across a message pipe (as above) or by closing them. Unlike
+  Unix's overloaded `close()` (which may fail due to data loss, i.e., inability
+  to flush), closing a (valid) Mojo handle never fails.
diff --git a/docs/intro/message_pipes.md b/docs/intro/message_pipes.md
index cf9959e..abe3013 100644
--- a/docs/intro/message_pipes.md
+++ b/docs/intro/message_pipes.md
@@ -11,13 +11,13 @@
 properties).
 
 That said, Mojo provides a *standard* way of communicating over message pipes,
-namely via a standardized protocol together with [Mojom IDL](mojom.md) files.
+namely via a standardized protocol together with [Mojom](mojom.md) IDL files.
 
 ## Messages
 
 A *message* consists of two things:
 * a finite sequence of bytes, and
-* a finite sequence of Mojo handles.
+* a finite sequence of [Mojo handles](handles.md).
 
 Both of these are determined when the message is sent (or *written*). Messages
 are *framed* in the sense that they are "atomic" units: they are sent and
@@ -75,4 +75,44 @@
 
 ## "Synchronous" operation
 
-**TODO(vtl)**
+Though message pipes are asynchronous as discussed above, they may be used in a
+synchronous fashion: immediately after sending a *request* message, one can then
+just block and wait for the *response* message (and then read it and process
+it). Of course, this requires that the protocol support this:
+* Message pipes must be used in a "directional" way: there must be fixed request
+  and response directions or, equivalently, one endpoint belongs to the *client*
+  and the other to the *server* (or *impl*). (Historical note: This is the case
+  for the current Mojom protocol, but not in previous versions.) The issue here
+  is that without this, the sender of the request messages may have to process
+  incoming request messages from its peer.
+* Request messages must have unique response messages. (In the Mojom protocol,
+  request messages have optional unique responses. For messages without
+  responses, one can just proceed immediately without waiting. However, without
+  response messages there may be flow control issues; again, see above.) The
+  important point is that for each request message, there is a well-defined
+  number of response messages for each request and not arbitrary "callback"
+  messages.
+* The sending of a response message must not depend on a future action of the
+  client. (This is a higher-level semantic that is not enforced by the Mojom
+  protocol. E.g., one may define a Mojom interface in which the response to a
+  message *Foo* isn't sent until the client sends a request *Bar*.)
+
+That said, whether one wants to, or even can, use this synchronous mode of
+operation may depend on a number of things:
+* For message-loop-centric programming languages, this mode is at best
+  undesirable (and possibly infeasible, depending on what facilities are exposed
+  to user code). (E.g., this is the case for JavaScript and Dart.)
+* Similarly, on a message-loop programming model (in which threads -- if there
+  are more than one -- are mostly coordinated by "message passing"), it is
+  typically undesirable to block any thread (with a message loop). Indeed, if
+  other message pipes are serviced by a message loop, blocking the thread may
+  result in deadlock. (E.g., this is the usual programming model for the
+  standard Mojom C++ bindings.)
+* Even when blocking is permissible, it may not be desirable to do so:
+  advancement of the program then relies on trusting the server to be
+  responsive and send responses in a timely fashion.
+* Mixing asynchronous and synchronous operation is problematic: one cannot send
+  a request and synchronously wait for a response while responses to other
+  messages are still pending. (Theoretically, one could buffer such other
+  responses until the response to particular request is received, and process
+  those other responses later, but this would be dubious at best.)