Introduce finer-grained monitor-style locking for IO.

OpenFile now aggregates a ReentrantReadWriteLock. We are not using
it reentrantly because we need to be able to release the lock deep
in the call stack around blocking operations. There may be a
better pattern for this.

All uses of OpenFile#lock must check the return value to see if
the lock was locked, and only unlock it in (in a finally, of
course) if that was the case.