The OpenGL specification, usually, defines the behavior of commands such that they will execute in the order given, and that every subsequent command must behave as if all prior commands have completed and their contents are visible. However, it is important to keep in mind that this is how OpenGL is specified, not how it is implemented.
OpenGL implementations attempt to do as much work asynchronously as possible. When a rendering function returns, odds are good that the actual rendering operation has not even started yet, let alone has finished. However, as long as you don't query any state that would be changed by that rendering command (such as the content of the destination images), you would not be able to tell the difference.
The key phrase to remember from the above definition is "as if". The implementation must make rendering look synchronous, while being as asynchronous as possible. So for best performance, you must avoid querying state that has been affected by rendering commands. You must also avoid changing the contents of objects that will be used by rendering commands that have been sent but may not yet have executed.