Skip to content
This repository has been archived by the owner on Jan 20, 2022. It is now read-only.

[LibOS] Make POSIX locks interruptible #2522

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 17 additions & 2 deletions LibOS/shim/include/shim_fs_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ int init_fs_lock(void);
* - The main process has to be able to look up the same file, so locking will not work for files in
* local-process-only filesystems (tmpfs).
* - There is no deadlock detection (EDEADLK).
* - The lock requests cannot be interrupted (EINTR).
* - The locks work only on files that have a dentry (no pipes, sockets etc.)
*/

Expand Down Expand Up @@ -111,7 +110,23 @@ int posix_lock_clear_pid(IDTYPE pid);
* to add a lock (-EAGAIN, -ENOMEM etc.) will be sent in the response instead.
*/
int posix_lock_set_from_ipc(const char* path, struct posix_lock* pl, bool wait, IDTYPE vmid,
unsigned long seq);
uint64_t seq);

/*!
* \brief Cancel a lock request (IPC handler)
*
* \param path absolute path for a file
* \param vmid target process for IPC response
* \param seq sequence number for IPC response
*
* Cancels the request previously added by `posix_lock_set_from_ipc`: if the request with given
* `vmid` and `seq` parameters is still unresolved, it is removed and a response with -EINTR is
* sent. If the request has been resolved in the meantime, nothing happens.
*
* This function should be called if the wait for IPC response has been interrupted. It ensures that
* a response will be sent immediately.
*/
int posix_lock_cancel_from_ipc(const char* path, IDTYPE vmid, uint64_t seq);

/*!
* \brief Check for conflicting locks on a file (IPC handler)
Expand Down
38 changes: 34 additions & 4 deletions LibOS/shim/include/shim_ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum {
IPC_MSG_SYNC_CONFIRM_DOWNGRADE,
IPC_MSG_SYNC_CONFIRM_CLOSE,
IPC_MSG_POSIX_LOCK_SET,
IPC_MSG_POSIX_LOCK_CANCEL,
IPC_MSG_POSIX_LOCK_GET,
IPC_MSG_POSIX_LOCK_CLEAR_PID,
IPC_MSG_CODE_BOUND,
Expand Down Expand Up @@ -117,6 +118,28 @@ int ipc_send_message(IDTYPE dest, struct shim_ipc_msg* msg);
* discarded, but still awaited for.
*/
int ipc_send_msg_and_get_response(IDTYPE dest, struct shim_ipc_msg* msg, void** resp);
/*!
* \brief Send an IPC message and wait for a response (cancel on interrupt)
*
* \param dest vmid of the destination process
* \param msg message to send
* \param on_cancel callback to invoke when the wait is interrupted
* \param arg argument for the callback
* \param[out] resp upon successful return contains a pointer to the response
*
* A version of `ipc_send_msg_and_get_response` that allows canceling a request after the wait is
* interrupted. Intended for implementation of interruptible function calls.
*
* Behaves as `ipc_send_msg_and_get_response`, but after the wait for response is interrupted,
* invokes `on_cancel(dest, arg)`. If it succeeds, the wait is resumed. The callback is invoked only
* once: if the wait is interrupted again afterwards, the function keeps waiting.
*
* The \p on_cancel callback should return 0 on success, or a negative error code on failure. If
* the callback fails, the function does not resume the wait, but returns the error immediately.
*/
int ipc_send_msg_and_get_response_with_cancel(IDTYPE dest, struct shim_ipc_msg* msg,
int (*on_cancel)(IDTYPE, void*), void* arg,
void** resp);
/*!
* \brief Broadcast an IPC message
*
Expand Down Expand Up @@ -258,6 +281,7 @@ int ipc_sync_confirm_close_callback(IDTYPE src, void* data, unsigned long seq);

/*
* POSIX_LOCK_SET: `struct shim_ipc_posix_lock` -> `int`
* POSIX_LOCK_CANCEL: `shim_ipc_posix_lock_cancel` (no response)
* POSIX_LOCK_GET: `struct shim_ipc_posix_lock` -> `struct shim_ipc_posix_lock_resp`
* POSIX_LOCK_CLEAR_PID: `IDTYPE` -> `int`
*/
Expand All @@ -273,6 +297,11 @@ struct shim_ipc_posix_lock {
char path[]; /* null-terminated */
};

struct shim_ipc_posix_lock_cancel {
uint64_t cancel_seq;
char path[]; /* null-terminated */
};

struct shim_ipc_posix_lock_resp {
int result;

Expand All @@ -286,11 +315,12 @@ struct shim_ipc_posix_lock_resp {
struct posix_lock;

int ipc_posix_lock_set(const char* path, struct posix_lock* pl, bool wait);
int ipc_posix_lock_set_send_response(IDTYPE vmid, unsigned long seq, int result);
int ipc_posix_lock_set_send_response(IDTYPE vmid, uint64_t seq, int result);
int ipc_posix_lock_get(const char* path, struct posix_lock* pl, struct posix_lock* out_pl);
int ipc_posix_lock_clear_pid(IDTYPE pid);
int ipc_posix_lock_set_callback(IDTYPE src, void* data, unsigned long seq);
int ipc_posix_lock_get_callback(IDTYPE src, void* data, unsigned long seq);
int ipc_posix_lock_clear_pid_callback(IDTYPE src, void* data, unsigned long seq);
int ipc_posix_lock_set_callback(IDTYPE src, void* data, uint64_t seq);
int ipc_posix_lock_cancel_callback(IDTYPE src, void* data, uint64_t seq);
int ipc_posix_lock_get_callback(IDTYPE src, void* data, uint64_t seq);
int ipc_posix_lock_clear_pid_callback(IDTYPE src, void* data, uint64_t seq);

#endif /* SHIM_IPC_H_ */