(nit) It's more beneficial to check `*object_shm` instead of `lock->id` for previous acquisition, and require the caller to initilaize `object_shm` to NULL instead:
```suggestion:-0+0 if (*object_shm) ```
...and change the assert above to `assert( !*object_shm || lock->id );`.
This has several advantages:
1. Easier typing. `{0}` is hard to type: <kbd>Shift/AltGr</kbd>-<kbd>{</kbd>, <kbd>0</kbd>, <kbd>Shift/AltGr</kbd>-<kbd>}</kbd>. In comparison, `NULL` is <kbd>Shift</kbd>-<kbd>N</kbd><kbd>U</kbd><kbd>L</kbd><kbd>L</kbd>. 2. No constraint on lock's representation. We currently require `(struct object_lock){0}` to be an invalid lock state. Using `object_shm` removes this restriction and allows us to change its fields freely. 3. Minimized heap corruption. Forgetting to zero-initialize `object` causes outright crash or infinite retry in the usual case. In comparison, forgetting to zero-initialize `lock` (`lock->session` in particular) leads to invalid pointer free() which is sometimes hard to debug.