diff --git a/.ci/lib/stage-test-direct.jenkinsfile b/.ci/lib/stage-test-direct.jenkinsfile index 57694f3cd3..21fbe745ec 100644 --- a/.ci/lib/stage-test-direct.jenkinsfile +++ b/.ci/lib/stage-test-direct.jenkinsfile @@ -83,6 +83,7 @@ stage('test-direct') { LOOP=1 CONCURRENCY_LIST="1 32" ../common_tools/benchmark-http.sh 127.0.0.1:8002 ''' } + /* timeout(time: 20, unit: 'MINUTES') { sh ''' cd Examples/apache @@ -94,6 +95,7 @@ stage('test-direct') { LOOP=1 CONCURRENCY_LIST="1 32" ../common_tools/benchmark-http.sh https://127.0.0.1:8443 ''' } + */ timeout(time: 5, unit: 'MINUTES') { sh ''' cd Examples/blender diff --git a/.ci/lib/stage-test-sgx.jenkinsfile b/.ci/lib/stage-test-sgx.jenkinsfile index 46084641ef..81d63f4fa7 100644 --- a/.ci/lib/stage-test-sgx.jenkinsfile +++ b/.ci/lib/stage-test-sgx.jenkinsfile @@ -74,6 +74,7 @@ stage('test-sgx') { LOOP=1 CONCURRENCY_LIST="1 32" ../common_tools/benchmark-http.sh 127.0.0.1:8002 ''' } + /* timeout(time: 25, unit: 'MINUTES') { sh ''' cd Examples/apache @@ -85,6 +86,7 @@ stage('test-sgx') { LOOP=1 CONCURRENCY_LIST="1 32" ../common_tools/benchmark-http.sh https://127.0.0.1:8443 ''' } + */ timeout(time: 5, unit: 'MINUTES') { sh ''' cd Examples/blender diff --git a/LibOS/shim/include/shim_handle.h b/LibOS/shim/include/shim_handle.h index 45cec8b244..2a4b059ec9 100644 --- a/LibOS/shim/include/shim_handle.h +++ b/LibOS/shim/include/shim_handle.h @@ -22,7 +22,6 @@ #include "list.h" #include "pal.h" #include "shim_defs.h" -#include "shim_sysv.h" #include "shim_types.h" /* Handle types. Many of these are used by a single filesystem. */ @@ -40,8 +39,6 @@ enum shim_handle_type { TYPE_SOCK, /* sockets, used by `socket` filesystem */ /* Special handles: */ - TYPE_SEM, /* System V semaphores, see `shim_semget.c` */ - TYPE_MSG, /* System V messages, see `shim_msgget.c` */ TYPE_EPOLL, /* epoll handles, see `shim_epoll.c` */ TYPE_EVENTFD, /* eventfd handles, used by `eventfd` filesystem */ }; @@ -203,52 +200,6 @@ struct shim_dir_handle { size_t pos; }; -struct msg_type; -struct msg_item; -struct msg_client; - -#define MAX_SYSV_CLIENTS 32 - -DEFINE_LIST(shim_msg_handle); -struct shim_msg_handle { - unsigned long msqkey; /* msg queue key from user */ - IDTYPE msqid; /* msg queue identifier */ - bool owned; /* owned by current process */ - int perm; /* access permissions */ - bool deleted; /* marking the queue deleted */ - int nmsgs; /* number of msgs */ - int currentsize; /* current size in bytes */ - struct msg_qobj* queue; - int queuesize; - int queueused; - struct msg_qobj* freed; - PAL_HANDLE event; /* event for waiting */ - int ntypes; - int maxtypes; - struct msg_type* types; - LIST_TYPE(shim_msg_handle) key_hlist; - LIST_TYPE(shim_msg_handle) qid_hlist; -}; - -struct sem_objs; - -DEFINE_LIST(shim_sem_handle); -struct shim_sem_handle { - unsigned long semkey; - IDTYPE semid; - bool owned; - int perm; - bool deleted; - PAL_HANDLE event; - int nsems; - struct sem_obj* sems; - int nreqs; - LISTP_TYPE(sem_ops) migrated; - LIST_TYPE(shim_sem_handle) list; - LIST_TYPE(shim_sem_handle) key_hlist; - LIST_TYPE(shim_sem_handle) sid_hlist; -}; - struct shim_str_data { REFTYPE ref_count; char* str; @@ -332,8 +283,6 @@ struct shim_handle { struct shim_pipe_handle pipe; /* TYPE_PIPE */ struct shim_sock_handle sock; /* TYPE_SOCK */ - struct shim_sem_handle sem; /* TYPE_SEM */ - struct shim_msg_handle msg; /* TYPE_MSG */ struct shim_epoll_handle epoll; /* TYPE_EPOLL */ /* (no data) */ /* TYPE_EVENTFD */ } info; diff --git a/LibOS/shim/include/shim_ipc.h b/LibOS/shim/include/shim_ipc.h index 71269a10e2..a14291ab41 100644 --- a/LibOS/shim/include/shim_ipc.h +++ b/LibOS/shim/include/shim_ipc.h @@ -12,7 +12,6 @@ #include "shim_defs.h" #include "shim_handle.h" #include "shim_internal.h" -#include "shim_sysv.h" #include "shim_thread.h" #include "shim_types.h" @@ -21,8 +20,6 @@ #define RANGE_SIZE 32 -#define IPC_SEM_NOTIMEOUT ((unsigned long)-1) - enum { IPC_MSG_RESP = 0, IPC_MSG_CONNBACK, /*!< Request for establishing a connection to the sender. */ @@ -39,14 +36,6 @@ enum { IPC_MSG_PID_RETSTATUS, IPC_MSG_PID_GETMETA, IPC_MSG_PID_RETMETA, - IPC_MSG_SYSV_FINDKEY, - IPC_MSG_SYSV_TELLKEY, - IPC_MSG_SYSV_DELRES, - IPC_MSG_SYSV_MSGSND, - IPC_MSG_SYSV_MSGRCV, - IPC_MSG_SYSV_SEMOP, - IPC_MSG_SYSV_SEMCTL, - IPC_MSG_SYSV_SEMRET, IPC_MSG_CODE_BOUND, }; @@ -54,8 +43,6 @@ enum kill_type { KILL_THREAD, KILL_PROCESS, KILL_PGROUP, KILL_ALL }; enum pid_meta_code { PID_META_CRED, PID_META_EXEC, PID_META_CWD, PID_META_ROOT }; -enum sysv_type { SYSV_NONE, SYSV_MSGQ, SYSV_SEM, SYSV_SHM }; - struct shim_ipc_ids { IDTYPE parent_vmid; IDTYPE leader_vmid; @@ -67,7 +54,6 @@ extern struct shim_ipc_ids g_process_ipc_ids; int init_ipc(void); int init_ns_ranges(void); int init_ns_pid(void); -int init_ns_sysv(void); /*! * \brief Initialize the IPC worker thread @@ -116,8 +102,6 @@ struct shim_ipc_msg { /* * XXX: Currently required by: * - `msg_add_range` in `LibOS/shim/src/ipc/shim_ipc_ranges.c`, - * - `msgsnd_callback` in `LibOS/shim/src/ipc/shim_ipc_sysv.c`, - * - `semret_callback` in `LibOS/shim/src/ipc/shim_ipc_sysv.c`. */ static_assert(offsetof(struct shim_ipc_msg, data) % 8 == 0, "Currently proper alignment is required"); @@ -334,95 +318,4 @@ int ipc_pid_retmeta_send(IDTYPE dest, IDTYPE pid, enum pid_meta_code code, const int datasize, unsigned long seq); int ipc_pid_retmeta_callback(IDTYPE src, void* data, unsigned long seq); -/* sysv namespace */ -struct sysv_key { - unsigned long key; - enum sysv_type type; -}; - -int sysv_add_key(struct sysv_key* key, IDTYPE id); -int sysv_get_key(struct sysv_key* key, bool delete); - -/* SYSV_FINDKEY */ -struct shim_ipc_sysv_findkey { - struct sysv_key key; -} __attribute__((packed)); - -int ipc_sysv_findkey_send(struct sysv_key* key); -int ipc_sysv_findkey_callback(IDTYPE src, void* data, unsigned long seq); - -/* SYSV_TELLKEY */ -struct shim_ipc_sysv_tellkey { - struct sysv_key key; - IDTYPE id; -} __attribute__((packed)); - -int ipc_sysv_tellkey_send(IDTYPE dest, struct sysv_key* key, IDTYPE id, unsigned long seq); -int ipc_sysv_tellkey_callback(IDTYPE src, void* data, unsigned long seq); - -/* SYSV_DELRES */ -struct shim_ipc_sysv_delres { - IDTYPE resid; - enum sysv_type type; -} __attribute__((packed)); - -int ipc_sysv_delres_send(IDTYPE dest, IDTYPE resid, enum sysv_type type); -int ipc_sysv_delres_callback(IDTYPE src, void* data, unsigned long seq); - -/* SYSV_MSGSND */ -struct shim_ipc_sysv_msgsnd { - IDTYPE msgid; - long msgtype; - size_t size; - char msg[]; -} __attribute__((packed)); - -int ipc_sysv_msgsnd_send(IDTYPE dest, IDTYPE msgid, long msgtype, const void* buf, size_t size, - unsigned long seq); -int ipc_sysv_msgsnd_callback(IDTYPE src, void* data, unsigned long seq); - -/* SYSV_MSGRCV */ -struct shim_ipc_sysv_msgrcv { - IDTYPE msgid; - long msgtype; - size_t size; - int flags; -} __attribute__((packed)); - -int ipc_sysv_msgrcv_send(IDTYPE msgid, long msgtype, int flags, void* buf, size_t size); -int ipc_sysv_msgrcv_callback(IDTYPE src, void* data, unsigned long seq); - -/* SYSV_SEMOP */ -struct shim_ipc_sysv_semop { - IDTYPE semid; - unsigned long timeout; - int nsops; - struct sembuf sops[]; -}; - -int ipc_sysv_semop_send(IDTYPE semid, struct sembuf* sops, int nsops, unsigned long timeout, - unsigned long* seq); -int ipc_sysv_semop_callback(IDTYPE src, void* data, unsigned long seq); - -/* SYSV_SEMCTL */ -struct shim_ipc_sysv_semctl { - IDTYPE semid; - int semnum; - int cmd; - size_t valsize; - unsigned char vals[]; -} __attribute__((packed)); - -int ipc_sysv_semctl_send(IDTYPE semid, int semnum, int cmd, void* vals, size_t valsize); -int ipc_sysv_semctl_callback(IDTYPE src, void* data, unsigned long seq); - -/* SYSV_SEMRET */ -struct shim_ipc_sysv_semret { - size_t valsize; - unsigned char vals[]; -} __attribute__((packed)); - -int ipc_sysv_semret_send(IDTYPE dest, void* vals, size_t valsize, unsigned long seq); -int ipc_sysv_semret_callback(IDTYPE src, void* data, unsigned long seq); - #endif /* SHIM_IPC_H_ */ diff --git a/LibOS/shim/include/shim_sysv.h b/LibOS/shim/include/shim_sysv.h deleted file mode 100644 index 1c03adeb4d..0000000000 --- a/LibOS/shim/include/shim_sysv.h +++ /dev/null @@ -1,130 +0,0 @@ -/* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* Copyright (C) 2014 Stony Brook University */ - -/* - * This file includes functions and types for implementing System V IPC functionality. - */ - -#ifndef __SHIM_SYSV_H__ -#define __SHIM_SYSV_H__ - -#include "list.h" -#include "shim_handle.h" -#include "shim_types.h" - -#define SYSV_TYPE_STR(type) \ - ((type) == SYSV_MSGQ ? "MSGQ" \ - : ((type) == SYSV_SEM ? "SEM" : ((type) == SYSV_SHM ? "SHM" : ""))) - -struct sysv_client { - IDTYPE vmid; - unsigned seq; -}; - -struct shim_handle; - -#define MSG_NOERROR 010000 - -struct __kernel_msgbuf { - long mtype; /* type of message */ - char mtext[]; /* message text */ -}; - -#define MSG_QOBJ_SIZE 64 - -struct msg_qobj { - void* next; - char data[MSG_QOBJ_SIZE - sizeof(void*)]; -} __attribute__((packed)); - -struct msg_item { - void* next; - size_t size; - char data[]; -} __attribute__((packed)); - -#define MSG_ITEM_DATA_SIZE(size) \ - ((size) < MSG_QOBJ_SIZE - sizeof(struct msg_item) ? (size) \ - : MSG_QOBJ_SIZE - sizeof(struct msg_item)) - -struct msg_ext_item { - void* next; - char data[]; -} __attribute__((packed)); - -#define MSG_EXT_ITEM_DATA_SIZE(size) \ - ((size) < MSG_QOBJ_SIZE - sizeof(struct msg_ext_item) \ - ? (size) \ - : MSG_QOBJ_SIZE - sizeof(struct msg_ext_item)) - -struct msg_req { - struct msg_req* next; - size_t size; - int flags; - struct sysv_client dest; -}; - -#define INIT_MSG_TYPE_SIZE 32 - -struct msg_type { - long type; /* type of the messages */ - struct msg_item* msgs; - struct msg_item* msg_tail; - struct msg_req* reqs; - struct msg_req* req_tail; -}; - -#define DEFAULT_MSG_QUEUE_SIZE 2048 - -struct shim_msg_handle; - -int add_msg_handle(unsigned long key, IDTYPE id, bool owned); -int del_msg_handle(struct shim_msg_handle* msgq); - -struct shim_msg_handle* get_msg_handle_by_key(unsigned long key); -struct shim_msg_handle* get_msg_handle_by_id(IDTYPE id); - -void put_msg_handle(struct shim_msg_handle* msgq); - -int add_sysv_msg(struct shim_msg_handle* msgq, long type, size_t size, const void* data, - struct sysv_client* src); -int get_sysv_msg(struct shim_msg_handle* msgq, long type, size_t size, void* data, int flags, - struct sysv_client* src); - -DEFINE_LIST(sem_ops); -struct sem_ops { - LIST_TYPE(sem_ops) progress; - struct sem_stat { - bool completed; - bool failed; - int nops; - int current; - unsigned long timeout; - } stat; - struct sysv_client client; - struct sembuf ops[]; -}; - -DEFINE_LISTP(sem_ops); -struct sem_obj { - unsigned short num; - unsigned short val; - unsigned short zcnt; - unsigned short ncnt; - IDTYPE pid; - PAL_NUM host_sem_id; - PAL_HANDLE host_sem; - LISTP_TYPE(sem_ops) ops; - LISTP_TYPE(sem_ops) next_ops; -}; - -int add_sem_handle(unsigned long key, IDTYPE id, int nsems, bool owned); -struct shim_sem_handle* get_sem_handle_by_key(unsigned long key); -struct shim_sem_handle* get_sem_handle_by_id(IDTYPE semid); -void put_sem_handle(struct shim_sem_handle* sem); -int del_sem_handle(struct shim_sem_handle* sem); - -int submit_sysv_sem(struct shim_sem_handle* sem, struct sembuf* sops, int nsops, - unsigned long timeout, struct sysv_client* client); - -#endif /* __SHIM_SYSV_H__ */ diff --git a/LibOS/shim/include/shim_table.h b/LibOS/shim/include/shim_table.h index cc1f94d8ac..0a0d0551bc 100644 --- a/LibOS/shim/include/shim_table.h +++ b/LibOS/shim/include/shim_table.h @@ -88,13 +88,6 @@ long shim_do_waitid(int which, pid_t id, siginfo_t* infop, int options, struct _ long shim_do_wait4(pid_t pid, int* stat_addr, int options, struct __kernel_rusage* ru); long shim_do_kill(pid_t pid, int sig); long shim_do_uname(struct new_utsname* buf); -long shim_do_semget(key_t key, int nsems, int semflg); -long shim_do_semop(int semid, struct sembuf* sops, unsigned int nsops); -long shim_do_semctl(int semid, int semnum, int cmd, unsigned long arg); -long shim_do_msgget(key_t key, int msgflg); -long shim_do_msgsnd(int msqid, const void* msgp, size_t msgsz, int msgflg); -long shim_do_msgrcv(int msqid, void* msgp, size_t msgsz, long msgtyp, int msgflg); -long shim_do_msgctl(int msqid, int cmd, struct msqid_ds* buf); long shim_do_fcntl(int fd, int cmd, unsigned long arg); long shim_do_fsync(int fd); long shim_do_fdatasync(int fd); @@ -155,8 +148,6 @@ long shim_do_futex(int* uaddr, int op, int val, void* utime, int* uaddr2, int va long shim_do_sched_setaffinity(pid_t pid, unsigned int cpumask_size, unsigned long* user_mask_ptr); long shim_do_sched_getaffinity(pid_t pid, unsigned int cpumask_size, unsigned long* user_mask_ptr); long shim_do_set_tid_address(int* tidptr); -long shim_do_semtimedop(int semid, struct sembuf* sops, unsigned int nsops, - const struct timespec* timeout); long shim_do_epoll_create(int size); long shim_do_getdents64(int fd, struct linux_dirent64* buf, size_t count); long shim_do_epoll_wait(int epfd, struct __kernel_epoll_event* events, int maxevents, diff --git a/LibOS/shim/src/arch/x86_64/shim_table.c b/LibOS/shim/src/arch/x86_64/shim_table.c index fcb8c0685b..cdc38bc6a9 100644 --- a/LibOS/shim/src/arch/x86_64/shim_table.c +++ b/LibOS/shim/src/arch/x86_64/shim_table.c @@ -79,14 +79,14 @@ shim_fp shim_table[LIBOS_SYSCALL_BOUND] = { [__NR_wait4] = (shim_fp)shim_do_wait4, [__NR_kill] = (shim_fp)shim_do_kill, [__NR_uname] = (shim_fp)shim_do_uname, - [__NR_semget] = (shim_fp)shim_do_semget, - [__NR_semop] = (shim_fp)shim_do_semop, - [__NR_semctl] = (shim_fp)shim_do_semctl, + [__NR_semget] = (shim_fp)0, // shim_do_semget, + [__NR_semop] = (shim_fp)0, // shim_do_semop, + [__NR_semctl] = (shim_fp)0, // shim_do_semctl, [__NR_shmdt] = (shim_fp)0, // shim_do_shmdt - [__NR_msgget] = (shim_fp)shim_do_msgget, - [__NR_msgsnd] = (shim_fp)shim_do_msgsnd, - [__NR_msgrcv] = (shim_fp)shim_do_msgrcv, - [__NR_msgctl] = (shim_fp)shim_do_msgctl, + [__NR_msgget] = (shim_fp)0, // shim_do_msgget, + [__NR_msgsnd] = (shim_fp)0, // shim_do_msgsnd, + [__NR_msgrcv] = (shim_fp)0, // shim_do_msgrcv, + [__NR_msgctl] = (shim_fp)0, // shim_do_msgctl, [__NR_fcntl] = (shim_fp)shim_do_fcntl, [__NR_flock] = (shim_fp)0, // shim_do_flock [__NR_fsync] = (shim_fp)shim_do_fsync, @@ -235,7 +235,7 @@ shim_fp shim_table[LIBOS_SYSCALL_BOUND] = { [__NR_getdents64] = (shim_fp)shim_do_getdents64, [__NR_set_tid_address] = (shim_fp)shim_do_set_tid_address, [__NR_restart_syscall] = (shim_fp)0, // shim_do_restart_syscall - [__NR_semtimedop] = (shim_fp)shim_do_semtimedop, + [__NR_semtimedop] = (shim_fp)0, // shim_do_semtimedop, [__NR_fadvise64] = (shim_fp)0, // shim_do_fadvise64 [__NR_timer_create] = (shim_fp)0, // shim_do_timer_create [__NR_timer_settime] = (shim_fp)0, // shim_do_timer_settime diff --git a/LibOS/shim/src/ipc/shim_ipc.c b/LibOS/shim/src/ipc/shim_ipc.c index 9757c01798..ec764a18b7 100644 --- a/LibOS/shim/src/ipc/shim_ipc.c +++ b/LibOS/shim/src/ipc/shim_ipc.c @@ -65,8 +65,6 @@ int init_ipc(void) { int ret = 0; if ((ret = init_ns_ranges()) < 0) return ret; - if ((ret = init_ns_sysv()) < 0) - return ret; return 0; } diff --git a/LibOS/shim/src/ipc/shim_ipc_ranges.c b/LibOS/shim/src/ipc/shim_ipc_ranges.c index 0b5147a501..ef90c46d5c 100644 --- a/LibOS/shim/src/ipc/shim_ipc_ranges.c +++ b/LibOS/shim/src/ipc/shim_ipc_ranges.c @@ -71,19 +71,6 @@ static int nowned = 0; static int noffered = 0; static int nsubed = 0; -#define KEY_HASH_LEN 8 -#define KEY_HASH_NUM (1 << KEY_HASH_LEN) -#define KEY_HASH_MASK (KEY_HASH_NUM - 1) - -DEFINE_LIST(key); -struct key { - struct sysv_key key; - IDTYPE id; - LIST_TYPE(key) hlist; -}; -DEFINE_LISTP(key); -static LISTP_TYPE(key) key_map[KEY_HASH_NUM]; - static int __extend_range_bitmap(IDTYPE expected) { assert(locked(&range_map_lock)); @@ -893,60 +880,3 @@ int get_all_pid_status(struct pid_status** status) { *status = status_buf; return statuses_cnt; } - -int sysv_add_key(struct sysv_key* key, IDTYPE id) { - assert(key); - - LISTP_TYPE(key)* head = &key_map[key->key & KEY_HASH_MASK]; - struct key* k; - int ret = -EEXIST; - - lock(&range_map_lock); - - LISTP_FOR_EACH_ENTRY(k, head, hlist) { - if (k->key.key == key->key && k->key.type == key->type) - goto out; - } - - k = malloc(sizeof(struct key)); - if (!k) { - ret = -ENOMEM; - goto out; - } - - k->key.key = key->key; - k->key.type = key->type; - k->id = id; - INIT_LIST_HEAD(k, hlist); - LISTP_ADD(k, head, hlist); - - log_debug("added key/id pair (%lu, %u) to hash list: %p\n", key->key, id, head); - ret = 0; -out: - unlock(&range_map_lock); - return ret; -} - -int sysv_get_key(struct sysv_key* key, bool delete) { - assert(key); - - LISTP_TYPE(key)* head = &key_map[key->key & KEY_HASH_MASK]; - struct key* k; - int id = -ENOENT; - - lock(&range_map_lock); - - LISTP_FOR_EACH_ENTRY(k, head, hlist) { - if (k->key.key == key->key && k->key.type == key->type) { - id = k->id; - if (delete) { - LISTP_DEL(k, head, hlist); - free(k); - } - break; - } - } - - unlock(&range_map_lock); - return id; -} diff --git a/LibOS/shim/src/ipc/shim_ipc_sysv.c b/LibOS/shim/src/ipc/shim_ipc_sysv.c deleted file mode 100644 index 8f46605c35..0000000000 --- a/LibOS/shim/src/ipc/shim_ipc_sysv.c +++ /dev/null @@ -1,659 +0,0 @@ -/* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* Copyright (C) 2014 Stony Brook University */ - -/* - * This file contains functions and callbacks to handle IPC of SYSV namespace. - */ - -#include - -#include "pal.h" -#include "pal_error.h" -#include "shim_checkpoint.h" -#include "shim_internal.h" -#include "shim_ipc.h" -#include "shim_sysv.h" -#include "shim_thread.h" - -int init_ns_sysv(void) { - return 0; -} - -int ipc_sysv_findkey_send(struct sysv_key* key) { - int ret = 0; - - ret = sysv_get_key(key, false); - if (!ret) - goto out; - - if (!g_process_ipc_ids.leader_vmid) { - ret = -ENOENT; - goto out; - } - - struct shim_ipc_sysv_findkey msgin = { - .key = *key, - }; - - size_t total_msg_size = get_ipc_msg_with_ack_size(sizeof(msgin)); - struct shim_ipc_msg_with_ack* msg = __alloca(total_msg_size); - init_ipc_msg_with_ack(msg, IPC_MSG_SYSV_FINDKEY, total_msg_size); - - memcpy(&msg->msg.data, &msgin, sizeof(msgin)); - - IDTYPE dest = g_process_ipc_ids.leader_vmid; - log_debug("ipc send to %u: IPC_MSG_SYSV_FINDKEY(%lu)\n", dest, key->key); - - ret = send_ipc_message_with_ack(msg, dest, NULL); - - if (!ret) - ret = sysv_get_key(key, false); -out: - return ret; -} - -int ipc_sysv_findkey_callback(IDTYPE src, void* data, unsigned long seq) { - int ret = 0; - struct shim_ipc_sysv_findkey* msgin = data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_FINDKEY(%lu)\n", src, msgin->key.key); - - ret = sysv_get_key(&msgin->key, false); - if (ret < 0) - return ret; - - return ipc_sysv_tellkey_send(src, &msgin->key, ret, seq); -} - -int ipc_sysv_tellkey_send(IDTYPE dest, struct sysv_key* key, IDTYPE id, unsigned long seq) { - bool owned = true; - int ret = 0; - - if (!dest) { - if ((ret = sysv_add_key(key, id)) < 0) - goto out; - - if (!g_process_ipc_ids.leader_vmid) - goto out; - - dest = g_process_ipc_ids.leader_vmid; - - owned = false; - } - - if (owned) { - struct shim_ipc_sysv_tellkey msgin = { - .key = *key, - .id = id, - }; - - size_t total_msg_size = get_ipc_msg_size(sizeof(msgin)); - struct shim_ipc_msg* msg = __alloca(total_msg_size); - init_ipc_msg(msg, IPC_MSG_SYSV_TELLKEY, total_msg_size); - msg->header.seq = seq; - - memcpy(&msg->data, &msgin, sizeof(msgin)); - - log_debug("ipc send to %u: IPC_MSG_SYSV_TELLKEY(%lu, %u)\n", dest, key->key, id); - - ret = send_ipc_message(msg, dest); - goto out; - } - - struct shim_ipc_sysv_tellkey msgin = { - .key = *key, - .id = id, - }; - - size_t total_msg_size = get_ipc_msg_with_ack_size(sizeof(msgin)); - struct shim_ipc_msg_with_ack* msg = __alloca(total_msg_size); - init_ipc_msg_with_ack(msg, IPC_MSG_SYSV_TELLKEY, total_msg_size); - - memcpy(&msg->msg.data, &msgin, sizeof(msgin)); - - log_debug("ipc send to %u: IPC_MSG_SYSV_TELLKEY(%lu, %u)\n", dest, key->key, id); - - ret = send_ipc_message_with_ack(msg, dest, NULL); -out: - return ret; -} - -static void tellkey_callback(struct shim_ipc_msg_with_ack* req_msg, void* args) { - if (!req_msg) { - *(int*)args = RESPONSE_CALLBACK; - return; - } - - assert(req_msg->thread); - thread_wakeup(req_msg->thread); -} - -int ipc_sysv_tellkey_callback(IDTYPE src, void* data, unsigned long seq) { - int ret = 0; - struct shim_ipc_sysv_tellkey* msgin = data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_TELLKEY(%lu, %u)\n", src, msgin->key.key, - msgin->id); - - ret = sysv_add_key(&msgin->key, msgin->id); - - ipc_msg_response_handle(seq, tellkey_callback, &ret); - - return ret; -} - -int ipc_sysv_delres_send(IDTYPE dest, IDTYPE resid, enum sysv_type type) { - int ret = 0; - bool owned = false; - - if (!dest) { - if ((ret = find_owner(resid, &dest)) < 0) - goto out; - - owned = true; - } - - if (!owned) { - struct shim_ipc_sysv_delres msgin = { - .resid = resid, - .type = type, - }; - - size_t total_msg_size = get_ipc_msg_size(sizeof(msgin)); - struct shim_ipc_msg* msg = __alloca(total_msg_size); - init_ipc_msg(msg, IPC_MSG_SYSV_DELRES, total_msg_size); - - memcpy(&msg->data, &msgin, sizeof(msgin)); - - log_debug("ipc send to %u: IPC_MSG_SYSV_DELRES(%u, %s)\n", dest, resid, - SYSV_TYPE_STR(type)); - - ret = send_ipc_message(msg, dest); - goto out; - } - - struct shim_ipc_sysv_delres msgin = { - .resid = resid, - .type = type, - }; - - size_t total_msg_size = get_ipc_msg_with_ack_size(sizeof(msgin)); - struct shim_ipc_msg_with_ack* msg = __alloca(total_msg_size); - init_ipc_msg_with_ack(msg, IPC_MSG_SYSV_DELRES, total_msg_size); - - memcpy(&msg->msg.data, &msgin, sizeof(msgin)); - - log_debug("ipc send to %u: IPC_MSG_SYSV_DELRES(%u, %s)\n", dest, resid, - SYSV_TYPE_STR(type)); - - ret = send_ipc_message_with_ack(msg, dest, NULL); -out: - return ret; -} - -int ipc_sysv_delres_callback(IDTYPE src, void* data, unsigned long seq) { - __UNUSED(seq); - int ret = 0; - struct shim_ipc_sysv_delres* msgin = (struct shim_ipc_sysv_delres*)data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_DELRES(%u, %s)\n", src, msgin->resid, - SYSV_TYPE_STR(msgin->type)); - - bool owned = false; - ret = -ENOENT; - switch (msgin->type) { - case SYSV_MSGQ: { - struct shim_msg_handle* msgq = get_msg_handle_by_id(msgin->resid); - if (!msgq) - goto out; - owned = msgq->owned; - ret = del_msg_handle(msgq); - break; - } - case SYSV_SEM: { - struct shim_sem_handle* sem = get_sem_handle_by_id(msgin->resid); - if (!sem) - goto out; - owned = sem->owned; - ret = del_sem_handle(sem); - break; - } - default: - ret = -ENOSYS; - break; - } - - if (!ret) - ret = owned ? RESPONSE_CALLBACK : 0; -out: - return ret; -} - -int ipc_sysv_msgsnd_send(IDTYPE dest, IDTYPE msgid, long msgtype, const void* buf, size_t size, - unsigned long seq) { - int ret = 0; - - if (!dest) { - if ((ret = find_owner(msgid, &dest)) < 0) - goto out; - } - - struct shim_ipc_sysv_msgsnd msgin = { - .msgid = msgid, - .msgtype = msgtype, - .size = size, - }; - - size_t total_msg_size = get_ipc_msg_size(sizeof(msgin) + size); - struct shim_ipc_msg* msg = __alloca(total_msg_size); - init_ipc_msg(msg, IPC_MSG_SYSV_MSGSND, total_msg_size); - msg->header.seq = seq; - - memcpy(&msg->data, &msgin, sizeof(msgin)); - memcpy(&((struct shim_ipc_sysv_msgsnd*)&msg->data)->msg, buf, size); - - log_debug("ipc send to %u: IPC_MSG_SYSV_MSGSND(%u, %ld)\n", dest, msgid, msgtype); - - ret = send_ipc_message(msg, dest); -out: - return ret; -} - -struct msgsnd_callback_args { - size_t size; - void* msg; - bool handled; -}; - -static void msgsnd_callback(struct shim_ipc_msg_with_ack* req_msg, void* _args) { - if (!req_msg || !req_msg->private) { - return; - } - - struct msgsnd_callback_args* args = _args; - size_t size = args->size; - struct shim_ipc_sysv_msgrcv* rcv = (struct shim_ipc_sysv_msgrcv*)req_msg->msg.data; - - if (size > rcv->size) { - size = rcv->size; - } - - memcpy(req_msg->private, args->msg, size); - req_msg->retval = size; - - assert(req_msg->thread); - thread_wakeup(req_msg->thread); - - args->handled = true; -} - -int ipc_sysv_msgsnd_callback(IDTYPE src, void* data, unsigned long seq) { - int ret = 0; - struct shim_ipc_sysv_msgsnd* msgin = (struct shim_ipc_sysv_msgsnd*)data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_MSGSND(%u, %ld)\n", src, msgin->msgid, - msgin->msgtype); - - size_t size = msgin->size; - - if (seq) { - struct msgsnd_callback_args args = { - .size = size, - .msg = msgin->msg, - .handled = false, - }; - ipc_msg_response_handle(seq, msgsnd_callback, &args); - if (args.handled) { - goto out; - } - } - - struct shim_msg_handle* msgq = get_msg_handle_by_id(msgin->msgid); - if (!msgq) { - ret = -ENOENT; - goto out; - } - - if (seq) { - ret = add_sysv_msg(msgq, msgin->msgtype, size, msgin->msg, NULL); - } else { - struct sysv_client client = { - .vmid = src, - .seq = seq, - }; - ret = add_sysv_msg(msgq, msgin->msgtype, size, msgin->msg, &client); - } - -out: - return ret; -} - -int ipc_sysv_msgrcv_send(IDTYPE msgid, long msgtype, int flags, void* buf, size_t size) { - IDTYPE owner; - int ret = 0; - - if ((ret = find_owner(msgid, &owner)) < 0) - goto out; - - if (owner == g_self_vmid) { - ret = -EAGAIN; - goto out; - } - - struct shim_ipc_sysv_msgrcv msgin = { - .msgid = msgid, - .msgtype = msgtype, - .size = size, - .flags = flags, - }; - - size_t total_msg_size = get_ipc_msg_with_ack_size(sizeof(msgin)); - struct shim_ipc_msg_with_ack* msg = __alloca(total_msg_size); - init_ipc_msg_with_ack(msg, IPC_MSG_SYSV_MSGRCV, total_msg_size); - msg->private = buf; - - memcpy(&msg->msg.data, &msgin, sizeof(msgin)); - - log_debug("ipc send to %u: IPC_MSG_SYSV_MSGRCV(%u, %ld)\n", owner, msgid, msgtype); - - ret = send_ipc_message_with_ack(msg, owner, NULL); -out: - return ret; -} - -int ipc_sysv_msgrcv_callback(IDTYPE src, void* data, unsigned long seq) { - int ret = 0; - struct shim_ipc_sysv_msgrcv* msgin = (struct shim_ipc_sysv_msgrcv*)data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_MSGRCV(%u, %ld)\n", src, msgin->msgid, - msgin->msgtype); - - struct shim_msg_handle* msgq = get_msg_handle_by_id(msgin->msgid); - - if (!msgq) { - ret = -ENOENT; - goto out; - } - - void* buf = __alloca(msgin->size); - struct sysv_client client = { - .vmid = src, - .seq = seq, - }; - - ret = get_sysv_msg(msgq, msgin->msgtype, msgin->size, buf, msgin->flags, &client); - - if (ret > 0) { - size_t size = ret; - ret = ipc_sysv_msgsnd_send(src, msgin->msgid, msgin->msgtype, buf, size, seq); - } - - put_msg_handle(msgq); -out: - return ret; -} - -int ipc_sysv_semop_send(IDTYPE semid, struct sembuf* sops, int nsops, unsigned long timeout, - unsigned long* seq) { - IDTYPE owner; - int ret = 0; - bool waitforreply = false; - - for (int i = 0; i < nsops; i++) - if (sops[i].sem_op <= 0) { - waitforreply = true; - break; - } - - if ((ret = find_owner(semid, &owner)) < 0) - goto out; - - if (owner == g_self_vmid) { - ret = -EAGAIN; - goto out; - } - - if (!waitforreply) { - struct shim_ipc_sysv_semop msgin = { - .semid = semid, - .timeout = timeout, - .nsops = nsops, - }; - - size_t total_msg_size = get_ipc_msg_size(sizeof(msgin) + sizeof(struct sembuf) * nsops); - struct shim_ipc_msg* msg = __alloca(total_msg_size); - init_ipc_msg(msg, IPC_MSG_SYSV_SEMOP, total_msg_size); - msg->header.seq = *seq; - - memcpy(&msg->data, &msgin, sizeof(msgin)); - memcpy(&((struct shim_ipc_sysv_semop*)&msg->data)->sops, sops, - sizeof(struct sembuf) * nsops); - - log_debug("ipc send to %u: IPC_MSG_SYSV_SEMOP(%u, %ld, %u)\n", owner, semid, timeout, - nsops); - - ret = send_ipc_message(msg, owner); - goto out; - } - - struct shim_ipc_sysv_semop msgin = { - .semid = semid, - .timeout = timeout, - .nsops = nsops, - }; - - size_t total_msg_size = get_ipc_msg_with_ack_size(sizeof(msgin) - + sizeof(struct sembuf) * nsops); - struct shim_ipc_msg_with_ack* msg = __alloca(total_msg_size); - init_ipc_msg_with_ack(msg, IPC_MSG_SYSV_SEMOP, total_msg_size); - msg->msg.header.seq = *seq; - - memcpy(&msg->msg.data, &msgin, sizeof(msgin)); - memcpy(&((struct shim_ipc_sysv_semop*)&msg->msg.data)->sops, sops, - sizeof(struct sembuf) * nsops); - - log_debug("ipc send to %u: IPC_MSG_SYSV_SEMOP(%u, %ld, %u)\n", owner, semid, timeout, nsops); - - ret = send_ipc_message_with_ack(msg, owner, seq); -out: - return ret; -} - -int ipc_sysv_semop_callback(IDTYPE src, void* data, unsigned long seq) { - int ret = 0; - struct shim_ipc_sysv_semop* msgin = (struct shim_ipc_sysv_semop*)data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_SEMOP(%u, %ld, %u)\n", src, msgin->semid, - msgin->timeout, msgin->nsops); - - struct shim_sem_handle* sem = get_sem_handle_by_id(msgin->semid); - if (!sem) { - ret = -ENOENT; - goto out; - } - - struct sysv_client client; - client.vmid = src; - client.seq = seq; - ret = submit_sysv_sem(sem, msgin->sops, msgin->nsops, msgin->timeout, &client); - put_sem_handle(sem); -out: - return ret; -} - -int ipc_sysv_semctl_send(IDTYPE semid, int semnum, int cmd, void* vals, size_t valsize) { - IDTYPE owner; - int ret = 0; - - if ((ret = find_owner(semid, &owner)) < 0) - goto out; - - int ctlvalsize = (cmd == SETALL || cmd == SETVAL) ? valsize : 0; - - struct shim_ipc_sysv_semctl msgin = { - .semid = semid, - .semnum = semnum, - .cmd = cmd, - .valsize = ctlvalsize, - }; - - size_t total_msg_size = get_ipc_msg_with_ack_size(sizeof(msgin) + ctlvalsize); - struct shim_ipc_msg_with_ack* msg = __alloca(total_msg_size); - init_ipc_msg_with_ack(msg, IPC_MSG_SYSV_SEMCTL, total_msg_size); - msg->private = vals; - - memcpy(&msg->msg.data, &msgin, sizeof(msgin)); - memcpy(&((struct shim_ipc_sysv_semctl*)&msg->msg.data)->vals, vals, ctlvalsize); - - log_debug("ipc send to %u: IPC_MSG_SYSV_SEMCTL(%u, %d, %d)\n", owner, semid, semnum, cmd); - - ret = send_ipc_message_with_ack(msg, owner, NULL); -out: - return ret; -} - -int ipc_sysv_semctl_callback(IDTYPE src, void* data, unsigned long seq) { - int ret = 0; - struct shim_ipc_sysv_semctl* msgin = (struct shim_ipc_sysv_semctl*)data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_SEMCTL(%u, %d, %d)\n", src, msgin->semid, - msgin->semnum, msgin->cmd); - - struct shim_sem_handle* sem = get_sem_handle_by_id(msgin->semid); - if (!sem) { - ret = -ENOENT; - goto out; - } - - void* vals = NULL; - size_t valsize; - switch (msgin->cmd) { - case GETALL: { - unsigned short* allsems = __alloca(sizeof(unsigned short) * sem->nsems); - for (int i = 0; i < sem->nsems; i++) { - allsems[i] = sem->sems[i].val; - } - - vals = allsems; - valsize = sizeof(unsigned short) * sem->nsems; - goto semret; - } - - case GETNCNT: - vals = &sem->sems[msgin->semnum].ncnt; - valsize = sizeof(unsigned short); - goto semret; - - case GETPID: - vals = &sem->sems[msgin->semnum].pid; - valsize = sizeof(IDTYPE); - goto semret; - - case GETVAL: - vals = &sem->sems[msgin->semnum].val; - valsize = sizeof(unsigned short); - goto semret; - - case GETZCNT: - vals = &sem->sems[msgin->semnum].zcnt; - valsize = sizeof(unsigned short); - break; - - case SETALL: { - if (msgin->valsize != sizeof(unsigned short) * sem->nsems) { - ret = -EINVAL; - break; - } - - unsigned short* vals = (void*)msgin->vals; - - for (int i = 0; i < sem->nsems; i++) { - sem->sems[i].val = vals[i]; - } - - ret = RESPONSE_CALLBACK; - break; - } - - case SETVAL: { - ret = -EINVAL; - if (msgin->valsize != sizeof(sem->sems[msgin->semnum].val)) - break; - if (msgin->semnum >= sem->nsems) - break; - - memcpy(&sem->sems[msgin->semnum].val, msgin->vals, msgin->valsize); - ret = RESPONSE_CALLBACK; - break; - } - - default: - ret = -ENOSYS; - break; - } - - put_sem_handle(sem); - goto out; -semret: - ret = ipc_sysv_semret_send(src, vals, valsize, seq); -out: - return ret; -} - -int ipc_sysv_semret_send(IDTYPE dest, void* vals, size_t valsize, unsigned long seq) { - struct shim_ipc_sysv_semret msgin = { - .valsize = valsize, - }; - - size_t total_msg_size = get_ipc_msg_size(sizeof(msgin) + valsize); - struct shim_ipc_msg* msg = __alloca(total_msg_size); - init_ipc_msg(msg, IPC_MSG_SYSV_SEMRET, total_msg_size); - msg->header.seq = seq; - - memcpy(&msg->data, &msgin, sizeof(msgin)); - memcpy(&((struct shim_ipc_sysv_semret*)&msg->data)->vals, vals, valsize); - - log_debug("ipc send to %u: IPC_MSG_SYSV_SEMRET\n", dest); - - return send_ipc_message(msg, dest); -} - -static void semret_callback(struct shim_ipc_msg_with_ack* req_msg, void* _args) { - if (!req_msg) { - return; - } - - struct shim_ipc_sysv_semret* semret = _args; - struct shim_ipc_sysv_semctl* semctl = (struct shim_ipc_sysv_semctl*)&req_msg->msg.data; - - void* vals = req_msg->private; - - if (vals) { - switch (semctl->cmd) { - case GETALL: - case GETNCNT: - case GETPID: - case GETVAL: - case GETZCNT: { - size_t retvalsize = semret->valsize; - if (retvalsize > semctl->valsize) - retvalsize = semctl->valsize; - memcpy(vals, semret->vals, retvalsize); - break; - } - } - } - - assert(req_msg->thread); - thread_wakeup(req_msg->thread); -} - -int ipc_sysv_semret_callback(IDTYPE src, void* data, unsigned long seq) { - struct shim_ipc_sysv_semret* semret = (struct shim_ipc_sysv_semret*)data; - - log_debug("ipc callback from %u: IPC_MSG_SYSV_SEMRET\n", src); - - ipc_msg_response_handle(seq, semret_callback, semret); - - return 0; -} diff --git a/LibOS/shim/src/ipc/shim_ipc_worker.c b/LibOS/shim/src/ipc/shim_ipc_worker.c index 7a1f3c35ce..61f395822a 100644 --- a/LibOS/shim/src/ipc/shim_ipc_worker.c +++ b/LibOS/shim/src/ipc/shim_ipc_worker.c @@ -62,14 +62,6 @@ static ipc_callback ipc_callbacks[] = { [IPC_MSG_PID_RETSTATUS] = ipc_pid_retstatus_callback, [IPC_MSG_PID_GETMETA] = ipc_pid_getmeta_callback, [IPC_MSG_PID_RETMETA] = ipc_pid_retmeta_callback, - [IPC_MSG_SYSV_FINDKEY] = ipc_sysv_findkey_callback, - [IPC_MSG_SYSV_TELLKEY] = ipc_sysv_tellkey_callback, - [IPC_MSG_SYSV_DELRES] = ipc_sysv_delres_callback, - [IPC_MSG_SYSV_MSGSND] = ipc_sysv_msgsnd_callback, - [IPC_MSG_SYSV_MSGRCV] = ipc_sysv_msgrcv_callback, - [IPC_MSG_SYSV_SEMOP] = ipc_sysv_semop_callback, - [IPC_MSG_SYSV_SEMCTL] = ipc_sysv_semctl_callback, - [IPC_MSG_SYSV_SEMRET] = ipc_sysv_semret_callback, }; static void ipc_leader_died_callback(void) { diff --git a/LibOS/shim/src/meson.build b/LibOS/shim/src/meson.build index aa7c50d59f..c0c649a878 100644 --- a/LibOS/shim/src/meson.build +++ b/LibOS/shim/src/meson.build @@ -47,7 +47,6 @@ libos_sources = files( 'ipc/shim_ipc_child.c', 'ipc/shim_ipc_pid.c', 'ipc/shim_ipc_ranges.c', - 'ipc/shim_ipc_sysv.c', 'ipc/shim_ipc_worker.c', 'shim_async.c', 'shim_checkpoint.c', @@ -79,12 +78,10 @@ libos_sources = files( 'sys/shim_getuid.c', 'sys/shim_ioctl.c', 'sys/shim_mmap.c', - 'sys/shim_msgget.c', 'sys/shim_open.c', 'sys/shim_pipe.c', 'sys/shim_poll.c', 'sys/shim_sched.c', - 'sys/shim_semget.c', 'sys/shim_sigaction.c', 'sys/shim_sleep.c', 'sys/shim_socket.c', diff --git a/LibOS/shim/src/sys/shim_msgget.c b/LibOS/shim/src/sys/shim_msgget.c deleted file mode 100644 index 2774a8e8dd..0000000000 --- a/LibOS/shim/src/sys/shim_msgget.c +++ /dev/null @@ -1,665 +0,0 @@ -/* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* Copyright (C) 2014 Stony Brook University */ - -/* - * Implementation of system calls "msgget", "msgsnd", "msgrcv" and "msgctl". - * - * XXX(borysp): I'm pretty sure there are possible deadlocks in this code. Sometimes it first takes - * `msgq_list_lock` and then `hdl->lock`, sometimes other way round. Someone will have to rewrite - * it someday. - */ - -#include - -#include "list.h" -#include "pal.h" -#include "pal_error.h" -#include "perm.h" -#include "shim_handle.h" -#include "shim_internal.h" -#include "shim_ipc.h" -#include "shim_lock.h" -#include "shim_sysv.h" -#include "shim_table.h" -#include "shim_types.h" -#include "shim_utils.h" -#include "stat.h" - -#define MSGQ_HASH_LEN 8 -#define MSGQ_HASH_NUM (1 << MSGQ_HASH_LEN) -#define MSGQ_HASH_MASK (MSGQ_HASH_NUM - 1) -#define MSGQ_HASH(idx) ((idx) & MSGQ_HASH_MASK) - -/* The msgq_key_hlist links them by key_hlist, and qid_hlist by qid_hlist */ -DEFINE_LISTP(shim_msg_handle); -static LISTP_TYPE(shim_msg_handle) msgq_key_hlist[MSGQ_HASH_NUM]; -static LISTP_TYPE(shim_msg_handle) msgq_qid_hlist[MSGQ_HASH_NUM]; -static struct shim_lock msgq_list_lock; - -#define MSG_TO_HANDLE(msghdl) container_of((msghdl), struct shim_handle, info.msg) - -static int __add_msg_handle(unsigned long key, IDTYPE msqid, bool owned, - struct shim_msg_handle** msghdl) { - assert(locked(&msgq_list_lock)); - - LISTP_TYPE(shim_msg_handle)* key_head = - (key != IPC_PRIVATE) ? &msgq_key_hlist[MSGQ_HASH(key)] : NULL; - LISTP_TYPE(shim_msg_handle)* qid_head = msqid ? &msgq_qid_hlist[MSGQ_HASH(msqid)] : NULL; - - struct shim_msg_handle* tmp; - - if (key_head) - LISTP_FOR_EACH_ENTRY(tmp, key_head, key_hlist) { - if (tmp->msqkey == key) { - if (tmp->msqid == msqid) { - if (msghdl) - *msghdl = tmp; - return 0; - } - return -EEXIST; - } - } - - if (qid_head) - LISTP_FOR_EACH_ENTRY(tmp, qid_head, qid_hlist) { - if (tmp->msqid == msqid) { - if (key) - tmp->msqkey = key; - if (msghdl) - *msghdl = tmp; - return 0; - } - } - - struct shim_handle* hdl = get_new_handle(); - if (!hdl) - return -ENOMEM; - - hdl->type = TYPE_MSG; - - struct shim_msg_handle* msgq = &hdl->info.msg; - - msgq->msqkey = key; - msgq->msqid = msqid; - msgq->owned = owned; - msgq->deleted = false; - msgq->currentsize = 0; - int ret = DkEventCreate(&msgq->event, /*init_signaled=*/false, /*auto_clear=*/true); - if (ret < 0) { - // Needs some cleanup, but this function is broken anyway... - return pal_to_unix_errno(ret); - } - - msgq->queue = malloc(MSG_QOBJ_SIZE * DEFAULT_MSG_QUEUE_SIZE); - msgq->queuesize = DEFAULT_MSG_QUEUE_SIZE; - msgq->queueused = 0; - msgq->freed = NULL; - - msgq->ntypes = 0; - msgq->maxtypes = INIT_MSG_TYPE_SIZE; - msgq->types = malloc(sizeof(struct msg_type) * INIT_MSG_TYPE_SIZE); - - INIT_LIST_HEAD(msgq, key_hlist); - if (key_head) { - get_handle(hdl); - LISTP_ADD(msgq, key_head, key_hlist); - } - INIT_LIST_HEAD(msgq, qid_hlist); - if (qid_head) { - get_handle(hdl); - LISTP_ADD(msgq, qid_head, qid_hlist); - } - - if (!msghdl) { - put_handle(hdl); - return 0; - } - - *msghdl = msgq; - return 0; -} - -int add_msg_handle(unsigned long key, IDTYPE id, bool owned) { - lock(&msgq_list_lock); - int ret = __add_msg_handle(key, id, owned, NULL); - unlock(&msgq_list_lock); - return ret; -} - -struct shim_msg_handle* get_msg_handle_by_key(unsigned long key) { - LISTP_TYPE(shim_msg_handle)* key_head = &msgq_key_hlist[MSGQ_HASH(key)]; - struct shim_msg_handle* tmp; - struct shim_msg_handle* found = NULL; - - lock(&msgq_list_lock); - - LISTP_FOR_EACH_ENTRY(tmp, key_head, key_hlist) { - if (tmp->msqkey == key) { - found = tmp; - break; - } - } - - if (found) - get_handle(MSG_TO_HANDLE(found)); - - unlock(&msgq_list_lock); - return found; -} - -struct shim_msg_handle* get_msg_handle_by_id(IDTYPE msqid) { - LISTP_TYPE(shim_msg_handle)* qid_head = &msgq_qid_hlist[MSGQ_HASH(msqid)]; - struct shim_msg_handle* tmp; - struct shim_msg_handle* found = NULL; - - lock(&msgq_list_lock); - - LISTP_FOR_EACH_ENTRY(tmp, qid_head, qid_hlist) { - if (tmp->msqid == msqid) { - found = tmp; - break; - } - } - - if (found) - get_handle(MSG_TO_HANDLE(found)); - - unlock(&msgq_list_lock); - return found; -} - -void put_msg_handle(struct shim_msg_handle* msgq) { - put_handle(MSG_TO_HANDLE(msgq)); -} - -static void* __get_msg_qobj(struct shim_msg_handle* msgq) { - struct msg_qobj* obj = NULL; - - if (msgq->freed) { - obj = msgq->freed; - msgq->freed = obj->next; - obj->next = NULL; - return obj; - } - - if (msgq->queueused < msgq->queuesize) { - obj = &msgq->queue[msgq->queueused]; - msgq->queueused++; - obj->next = NULL; - return obj; - } - - return NULL; -} - -static void __free_msg_qobj(struct shim_msg_handle* msgq, void* obj) { - ((struct msg_qobj*)obj)->next = msgq->freed; - msgq->freed = obj; -} - -static void __free_msg_linked_qobjs(struct shim_msg_handle* msgq, void* obj) { - struct msg_qobj* qobj = obj; - while (qobj) { - struct msg_qobj* next = qobj->next; - __free_msg_qobj(msgq, qobj); - qobj = next; - } -} - -static int __del_msg_handle(struct shim_msg_handle* msgq) { - struct shim_handle* hdl = MSG_TO_HANDLE(msgq); - assert(locked(&hdl->lock)); - - if (msgq->deleted) - return -EIDRM; - - msgq->deleted = true; - free(msgq->queue); - msgq->queuesize = 0; - msgq->queueused = 0; - free(msgq->types); - msgq->ntypes = 0; - - lock(&msgq_list_lock); - if (!LIST_EMPTY(msgq, key_hlist)) { - // DEP: Yuck, re-find the head; maybe we can do better... - LISTP_TYPE(shim_msg_handle)* key_head = &msgq_key_hlist[MSGQ_HASH(msgq->msqkey)]; - LISTP_DEL_INIT(msgq, key_head, key_hlist); - put_handle(hdl); - } - if (!LIST_EMPTY(msgq, qid_hlist)) { - // DEP: Yuck, re-find the head; maybe we can do better... - LISTP_TYPE(shim_msg_handle)* qid_head = &msgq_qid_hlist[MSGQ_HASH(msgq->msqid)]; - LISTP_DEL_INIT(msgq, qid_head, qid_hlist); - put_handle(hdl); - } - unlock(&msgq_list_lock); - return 0; -} - -int del_msg_handle(struct shim_msg_handle* msgq) { - struct shim_handle* hdl = MSG_TO_HANDLE(msgq); - lock(&hdl->lock); - int ret = __del_msg_handle(msgq); - unlock(&hdl->lock); - return ret; -} - -long shim_do_msgget(key_t key, int msgflg) { - IDTYPE msgid = 0; - int ret; - - if (!create_lock_runtime(&msgq_list_lock)) { - return -ENOMEM; - } - - if (key != IPC_PRIVATE) { - struct shim_msg_handle* msgq = get_msg_handle_by_key(key); - if (msgq) { - msgid = msgq->msqid; - put_msg_handle(msgq); - return (msgflg & IPC_EXCL) ? -EEXIST : (int)msgid; - } - } - - struct sysv_key k; - k.key = key; - k.type = SYSV_MSGQ; - - if (msgflg & IPC_CREAT) { - do { - msgid = allocate_ipc_id(0, 0); - if (!msgid) - ipc_lease_send(); - } while (!msgid); - - if (key != IPC_PRIVATE) { - if ((ret = ipc_sysv_tellkey_send(0, &k, msgid, 0)) < 0) { - release_ipc_id(msgid); - return ret; - } - } - - add_msg_handle(key, msgid, true); - } else { - /* query the manager with the key to find the - corresponding sysvkey */ - if ((ret = ipc_sysv_findkey_send(&k)) < 0) - return ret; - - msgid = ret; - - if ((ret = ipc_query_send(msgid)) < 0) - return ret; - - add_msg_handle(key, msgid, false); - } - - return msgid; -} - -static int connect_msg_handle(int msqid, struct shim_msg_handle** msgqp) { - struct shim_msg_handle* msgq = get_msg_handle_by_id(msqid); - int ret; - - if (!msgq) { - if ((ret = ipc_query_send(msqid)) < 0) - return ret; - - if (!msgq) { - lock(&msgq_list_lock); - ret = __add_msg_handle(IPC_PRIVATE, msqid, false, &msgq); - unlock(&msgq_list_lock); - if (ret < 0) - return ret; - } - } - - if (msgq->deleted) - return -EIDRM; - - *msgqp = msgq; - return 0; -} - -long shim_do_msgsnd(int msqid, const void* msgp, size_t msgsz, int msgflg) { - // Issue #755 - https://github.com/oscarlab/graphene/issues/755 - __UNUSED(msgflg); - - int ret; - - if (msgsz > MSGMAX) - return -EINVAL; - - if (!msgp) - return -EFAULT; - - struct __kernel_msgbuf* msgbuf = (struct __kernel_msgbuf*)msgp; - - if (msgbuf->mtype < 0) - return -EINVAL; - - struct shim_msg_handle* msgq; - - if (!create_lock_runtime(&msgq_list_lock)) { - return -ENOMEM; - } - - if ((ret = connect_msg_handle(msqid, &msgq)) < 0) - return ret; - - // FIXME: This call crashes Graphene, causing NULL dereference in add_sysv_msg. Everything in - // this file seems to be broken, so probably better to just rewrite it? - ret = add_sysv_msg(msgq, msgbuf->mtype, msgsz, msgbuf->mtext, NULL); - put_msg_handle(msgq); - return ret; -} - -long shim_do_msgrcv(int msqid, void* msgp, size_t msgsz, long msgtype, int msgflg) { - // Issue #755 - https://github.com/oscarlab/graphene/issues/755 - __UNUSED(msgflg); - - int ret; - - if (msgsz > MSGMAX) - return -EINVAL; - if (!msgp) - return -EFAULT; - - struct __kernel_msgbuf* msgbuf = (struct __kernel_msgbuf*)msgp; - struct shim_msg_handle* msgq; - - if (!create_lock_runtime(&msgq_list_lock)) { - return -ENOMEM; - } - - if ((ret = connect_msg_handle(msqid, &msgq)) < 0) - return ret; - - ret = get_sysv_msg(msgq, msgtype, msgsz, msgbuf->mtext, msgflg, NULL); - put_msg_handle(msgq); - return ret; -} - -long shim_do_msgctl(int msqid, int cmd, struct msqid_ds* buf) { - // Issue #756 - https://github.com/oscarlab/graphene/issues/756 - __UNUSED(buf); - - struct shim_msg_handle* msgq; - int ret; - - if (!create_lock_runtime(&msgq_list_lock)) { - return -ENOMEM; - } - - if ((ret = connect_msg_handle(msqid, &msgq)) < 0) - return ret; - - switch (cmd) { - case IPC_RMID: - if (!msgq->owned) { - ret = ipc_sysv_delres_send(0, msgq->msqid, SYSV_MSGQ); - if (ret < 0) - break; - } - - del_msg_handle(msgq); - break; - - default: - ret = -ENOSYS; - break; - } - - put_msg_handle(msgq); - return ret; -} - -static struct msg_type* __add_msg_type(int type, struct msg_type** ptypes, int* pntypes, - int* pmaxtypes) { - struct msg_type* types = *ptypes; - int ntypes = *pntypes; - int maxtypes = *pmaxtypes; - - struct msg_type* mtype; - for (mtype = types; mtype < &types[ntypes] && mtype->type <= type; mtype++) - if (mtype->type == type) - return mtype; - - int off = mtype - types; - struct msg_type* new_types = types; - - if (ntypes == maxtypes) - new_types = malloc(sizeof(struct msg_type) * maxtypes * 2); - - if (mtype < &types[ntypes]) - memmove(new_types + off + 1, mtype, sizeof(struct msg_type) * (ntypes - off)); - - if (new_types != types) { - memcpy(new_types, types, sizeof(struct msg_type) * off); - free(types); - mtype = new_types + off; - *ptypes = new_types; - *pmaxtypes = maxtypes * 2; - } - - mtype->type = type; - mtype->msgs = NULL; - mtype->msg_tail = NULL; - mtype->reqs = NULL; - mtype->req_tail = NULL; - - (*pntypes)++; - return mtype; -} - -static int __load_msg_qobjs(struct shim_msg_handle* msgq, struct msg_type* mtype, - struct msg_item* msg, void* data) { - size_t copysize = MSG_ITEM_DATA_SIZE(msg->size); - memcpy(data, msg->data, copysize); - mtype->msgs = msg->next; - __free_msg_qobj(msgq, msg); - - while (copysize < msg->size) { - assert(mtype->msgs); - struct msg_ext_item* ext = (struct msg_ext_item*)mtype->msgs; - size_t sz = MSG_EXT_ITEM_DATA_SIZE(msg->size - copysize); - memcpy(data + copysize, ext->data, sz); - copysize += sz; - mtype->msgs = ext->next; - __free_msg_qobj(msgq, ext); - } - - if (!mtype->msgs) - mtype->msg_tail = NULL; - - msgq->nmsgs--; - msgq->currentsize -= msg->size; - return 0; -} - -static int __store_msg_qobjs(struct shim_msg_handle* msgq, struct msg_type* mtype, size_t size, - const void* data) { - struct msg_item* newmsg = __get_msg_qobj(msgq); - if (!newmsg) - return -EAGAIN; - - struct msg_item* old_tail = mtype->msg_tail; - - newmsg->next = NULL; - newmsg->size = size; - size_t copysize = MSG_ITEM_DATA_SIZE(size); - memcpy(newmsg->data, data, copysize); - - if (mtype->msg_tail) { - mtype->msg_tail->next = newmsg; - mtype->msg_tail = newmsg; - } else { - assert(!mtype->msgs); - mtype->msgs = mtype->msg_tail = newmsg; - } - - while (copysize < size) { - struct msg_ext_item* ext = __get_msg_qobj(msgq); - if (!ext) - goto eagain; - - size_t sz = MSG_EXT_ITEM_DATA_SIZE(size - copysize); - memcpy(ext->data, data + copysize, sz); - ext->next = NULL; - mtype->msg_tail->next = ext; - mtype->msg_tail = (struct msg_item*)ext; - copysize += sz; - } - - msgq->nmsgs++; - msgq->currentsize += size; - return 0; - -eagain: - __free_msg_linked_qobjs(msgq, newmsg); - - if (mtype->msgs == newmsg) - mtype->msgs = NULL; - - mtype->msg_tail = old_tail; - return -EAGAIN; -} - -int add_sysv_msg(struct shim_msg_handle* msgq, long type, size_t size, const void* data, - struct sysv_client* src) { - struct shim_handle* hdl = MSG_TO_HANDLE(msgq); - int ret = 0; - - lock(&hdl->lock); - - if (msgq->deleted) { - ret = -EIDRM; - goto out_locked; - } - - if (!msgq->owned) { - unlock(&hdl->lock); - assert(src); - ret = ipc_sysv_msgsnd_send(src->vmid, msgq->msqid, type, data, size, src->seq); - goto out; - } - - struct msg_type* mtype = __add_msg_type(type, &msgq->types, &msgq->ntypes, &msgq->maxtypes); - - if ((ret = __store_msg_qobjs(msgq, mtype, size, data)) < 0) - goto out_locked; - - DkEventSet(msgq->event); - ret = 0; -out_locked: - unlock(&hdl->lock); -out: - return ret; -} - -static struct msg_type* __find_msg_type(int type, struct msg_type* types, int ntypes) { - for (struct msg_type* mtype = types; mtype < &types[ntypes] && mtype->type <= type; mtype++) - if (mtype->type == type) - return mtype; - return NULL; -} - -static int __add_msg_req(struct shim_msg_handle* msgq, struct msg_type* mtype, int size, int flags, - struct sysv_client* src) { - if (msgq->deleted) - return -EIDRM; - - struct msg_req* req = __get_msg_qobj(msgq); - if (!req) - return -ENOMEM; - - req->next = NULL; - req->size = size; - req->flags = flags; - req->dest = *src; - - if (mtype->req_tail) { - mtype->req_tail->next = req; - mtype->req_tail = req; - } else { - assert(!mtype->reqs); - mtype->reqs = mtype->req_tail = req; - } - - return 0; -} - -int get_sysv_msg(struct shim_msg_handle* msgq, long type, size_t size, void* data, int flags, - struct sysv_client* src) { - int ret = 0; - struct shim_handle* hdl = MSG_TO_HANDLE(msgq); - struct msg_item* msg = NULL; - struct msg_type* alltypes = NULL; - struct msg_type* mtype = NULL; - lock(&hdl->lock); - - if (msgq->deleted) { - ret = -EIDRM; - goto out_locked; - } - - if (!msgq->owned) { - if (src) { - ret = -ECONNREFUSED; - goto out_locked; - } - - unowned: - unlock(&hdl->lock); - ret = ipc_sysv_msgrcv_send(msgq->msqid, type, flags, data, size); - if (ret != -EAGAIN && ret != -ECONNREFUSED) - goto out; - - lock(&hdl->lock); - - if (!msgq->owned) - goto out_locked; - } - - while (1) { - if (alltypes != msgq->types || !mtype || mtype->type != type) { - alltypes = msgq->types; - mtype = __find_msg_type(type, alltypes, msgq->ntypes); - } - - if (mtype && mtype->msgs) { - msg = mtype->msgs; - if (msg->size > size && !(flags & MSG_NOERROR)) { - ret = -E2BIG; - goto out; - } - break; - } - - if (flags & IPC_NOWAIT || src) - break; - - unlock(&hdl->lock); - object_wait_with_retry(msgq->event); - lock(&hdl->lock); - - if (!msgq->owned) - goto unowned; - } - - if (!msg) { - ret = - (!(flags & IPC_NOWAIT) && src) ? __add_msg_req(msgq, mtype, size, flags, src) : -ENOMSG; - goto out_locked; - } - - if ((ret = __load_msg_qobjs(msgq, mtype, msg, data)) < 0) - goto out_locked; - - ret = msg->size; -out_locked: - unlock(&hdl->lock); -out: - return ret; -} diff --git a/LibOS/shim/src/sys/shim_semget.c b/LibOS/shim/src/sys/shim_semget.c deleted file mode 100644 index b3b18bfcda..0000000000 --- a/LibOS/shim/src/sys/shim_semget.c +++ /dev/null @@ -1,735 +0,0 @@ -/* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* Copyright (C) 2014 Stony Brook University */ - -/* - * Implementation of system calls "semget", "semop", "semtimedop" and "semctl". - */ - -#include - -#include "list.h" -#include "pal.h" -#include "pal_error.h" -#include "shim_handle.h" -#include "shim_internal.h" -#include "shim_ipc.h" -#include "shim_lock.h" -#include "shim_sysv.h" -#include "shim_table.h" -#include "shim_utils.h" - -#define SEM_HASH_LEN 8 -#define SEM_HASH_NUM (1 << SEM_HASH_LEN) -#define SEM_HASH_MASK (SEM_HASH_NUM - 1) -#define SEM_HASH(idx) ((idx) & SEM_HASH_MASK) - -/* The sem_list links shim_sem_handle objects by the list field. - * The sem_key_hlist links them by key_hlist, and qid_hlist by qid_hlist */ -DEFINE_LISTP(shim_sem_handle); -static LISTP_TYPE(shim_sem_handle) sem_list; -static LISTP_TYPE(shim_sem_handle) sem_key_hlist[SEM_HASH_NUM]; -static LISTP_TYPE(shim_sem_handle) sem_sid_hlist[SEM_HASH_NUM]; -static struct shim_lock sem_list_lock; - -#define SEM_TO_HANDLE(semhdl) container_of((semhdl), struct shim_handle, info.sem) - -static int __add_sem_handle(unsigned long key, IDTYPE semid, int nsems, bool owned, - struct shim_sem_handle** semhdl) { - assert(locked(&sem_list_lock)); - - LISTP_TYPE(shim_sem_handle)* key_head = - (key != IPC_PRIVATE) ? &sem_key_hlist[SEM_HASH(key)] : NULL; - LISTP_TYPE(shim_sem_handle)* sid_head = semid ? &sem_sid_hlist[SEM_HASH(semid)] : NULL; - - struct shim_sem_handle* tmp; - struct shim_handle* hdl = NULL; - int ret = 0; - - if (key_head) - LISTP_FOR_EACH_ENTRY(tmp, key_head, key_hlist) { - if (tmp->semkey == key) { - if (tmp->semid == semid) - goto out; - return -EEXIST; - } - } - - if (sid_head) - LISTP_FOR_EACH_ENTRY(tmp, sid_head, sid_hlist) { - if (tmp->semid == semid) { - if (key) - tmp->semkey = key; - goto out; - } - } - - hdl = get_new_handle(); - if (!hdl) - return -ENOMEM; - - hdl->type = TYPE_SEM; - tmp = &hdl->info.sem; - - tmp->semkey = key; - tmp->semid = semid; - tmp->owned = owned; - - ret = DkEventCreate(&tmp->event, /*init_signaled=*/false, /*auto_clear=*/false); - if (ret < 0) { - ret = pal_to_unix_errno(ret); - goto failed; - } - - if (owned && nsems) { - tmp->nsems = nsems; - tmp->sems = malloc(sizeof(struct sem_obj) * nsems); - if (!tmp->sems) { - ret = -ENOMEM; - goto failed; - } - - for (int i = 0; i < nsems; i++) { - tmp->sems[i].num = i; - tmp->sems[i].val = 0; - tmp->sems[i].host_sem_id = 0; - tmp->sems[i].host_sem = NULL; - INIT_LISTP(&tmp->sems[i].ops); - INIT_LISTP(&tmp->sems[i].next_ops); - } - } - - INIT_LISTP(&tmp->migrated); - INIT_LIST_HEAD(tmp, list); - get_handle(hdl); - LISTP_ADD_TAIL(tmp, &sem_list, list); - INIT_LIST_HEAD(tmp, key_hlist); - if (key_head) { - get_handle(hdl); - LISTP_ADD(tmp, key_head, key_hlist); - } - if (sid_head) { - get_handle(hdl); - LISTP_ADD(tmp, sid_head, sid_hlist); - } - -out: - if (!semhdl) { - put_handle(hdl); - return 0; - } - - *semhdl = tmp; - return 0; - -failed: - put_handle(hdl); - return ret; -} - -int add_sem_handle(unsigned long key, IDTYPE id, int nsems, bool owned) { - lock(&sem_list_lock); - int ret = __add_sem_handle(key, id, nsems, owned, NULL); - unlock(&sem_list_lock); - return ret; -} - -struct shim_sem_handle* get_sem_handle_by_key(unsigned long key) { - LISTP_TYPE(shim_sem_handle)* key_head = &sem_key_hlist[SEM_HASH(key)]; - struct shim_sem_handle* tmp; - struct shim_sem_handle* found = NULL; - - lock(&sem_list_lock); - - LISTP_FOR_EACH_ENTRY(tmp, key_head, key_hlist) { - if (tmp->semkey == key) { - found = tmp; - break; - } - } - - if (found) - get_handle(SEM_TO_HANDLE(found)); - - unlock(&sem_list_lock); - return found; -} - -struct shim_sem_handle* get_sem_handle_by_id(IDTYPE semid) { - LISTP_TYPE(shim_sem_handle)* sid_head = &sem_sid_hlist[SEM_HASH(semid)]; - struct shim_sem_handle* tmp; - struct shim_sem_handle* found = NULL; - - lock(&sem_list_lock); - - LISTP_FOR_EACH_ENTRY(tmp, sid_head, sid_hlist) { - if (tmp->semid == semid) { - found = tmp; - break; - } - } - - if (found) - get_handle(SEM_TO_HANDLE(found)); - - unlock(&sem_list_lock); - return found; -} - -void put_sem_handle(struct shim_sem_handle* sem) { - put_handle(SEM_TO_HANDLE(sem)); -} - -static int __del_sem_handle(struct shim_sem_handle* sem) { - struct shim_handle* hdl = SEM_TO_HANDLE(sem); - assert(locked(&hdl->lock)); - - if (sem->deleted) - return 0; - - sem->deleted = true; - - lock(&sem_list_lock); - LISTP_DEL_INIT(sem, &sem_list, list); - put_handle(hdl); - if (!LIST_EMPTY(sem, key_hlist)) { - // DEP: Yuck - LISTP_TYPE(shim_sem_handle)* key_head = &sem_key_hlist[SEM_HASH(sem->semkey)]; - LISTP_DEL_INIT(sem, key_head, key_hlist); - put_handle(hdl); - } - if (!LIST_EMPTY(sem, sid_hlist)) { - // DEP: Yuck - LISTP_TYPE(shim_sem_handle)* sid_head = &sem_sid_hlist[SEM_HASH(sem->semid)]; - LISTP_DEL_INIT(sem, sid_head, sid_hlist); - put_handle(hdl); - } - unlock(&sem_list_lock); - return 0; -} - -int del_sem_handle(struct shim_sem_handle* sem) { - struct shim_handle* hdl = SEM_TO_HANDLE(sem); - lock(&hdl->lock); - int ret = __del_sem_handle(sem); - unlock(&hdl->lock); - return ret; -} - -long shim_do_semget(key_t key, int nsems, int semflg) { - IDTYPE semid = 0; - int ret; - - if (!create_lock_runtime(&sem_list_lock)) { - return -ENOMEM; - } - - if (key != IPC_PRIVATE) { - struct shim_sem_handle* sem = get_sem_handle_by_key(key); - if (sem) { - semid = sem->semid; - put_sem_handle(sem); - return (semflg & IPC_EXCL) ? -EEXIST : (int)semid; - } - } - - struct sysv_key k; - k.key = key; - k.type = SYSV_SEM; - - if (semflg & IPC_CREAT) { - do { - semid = allocate_ipc_id(0, 0); - if (!semid) - semid = ipc_lease_send(); - } while (!semid); - - if (key != IPC_PRIVATE) { - if ((ret = ipc_sysv_tellkey_send(0, &k, semid, 0)) < 0) { - release_ipc_id(semid); - return ret; - } - } - - add_sem_handle(key, semid, nsems, true); - } else { - if ((ret = ipc_sysv_findkey_send(&k)) < 0) - return ret; - - semid = ret; - if ((ret = ipc_query_send(semid)) < 0) - return ret; - } - - return semid; -} - -static int connect_sem_handle(int semid, int nsems, struct shim_sem_handle** semp) { - struct shim_sem_handle* sem = get_sem_handle_by_id(semid); - int ret; - - if (!sem) { - if ((ret = ipc_query_send(semid)) < 0) - return ret; - - if (!sem) { - lock(&sem_list_lock); - ret = __add_sem_handle(IPC_PRIVATE, semid, nsems, false, &sem); - unlock(&sem_list_lock); - if (ret < 0) - return ret; - } - } - - *semp = sem; - return 0; -} - -static int __do_semop(int semid, struct sembuf* sops, unsigned int nsops, unsigned long timeout) { - int ret; - struct shim_sem_handle* sem; - size_t nsems = 0; - - for (size_t i = 0; i < nsops; i++) - if (sops[i].sem_num >= nsems) - nsems = sops[i].sem_num + 1; - - if (!create_lock_runtime(&sem_list_lock)) { - return -ENOMEM; - } - - if ((ret = connect_sem_handle(semid, nsems, &sem)) < 0) - return ret; - - ret = submit_sysv_sem(sem, sops, nsops, timeout, NULL); - put_sem_handle(sem); - return ret; -} - -long shim_do_semop(int semid, struct sembuf* sops, unsigned int nsops) { - return __do_semop(semid, sops, nsops, IPC_SEM_NOTIMEOUT); -} - -long shim_do_semtimedop(int semid, struct sembuf* sops, unsigned int nsops, - const struct timespec* timeout) { - unsigned long timeout_ns = IPC_SEM_NOTIMEOUT; - if (timeout) { - timeout_ns = timeout->tv_sec * 1000000000ULL + timeout->tv_nsec; - } - - return __do_semop(semid, sops, nsops, timeout_ns); -} - -long shim_do_semctl(int semid, int semnum, int cmd, unsigned long arg) { - struct shim_sem_handle* sem; - int ret; - - if (!create_lock_runtime(&sem_list_lock)) { - return -ENOMEM; - } - - if ((ret = connect_sem_handle(semid, 0, &sem)) < 0) - return ret; - - struct shim_handle* hdl = SEM_TO_HANDLE(sem); - lock(&hdl->lock); - - switch (cmd) { - case IPC_RMID: { - if (!sem->owned) { - ret = ipc_sysv_delres_send(0, semid, SYSV_SEM); - if (ret < 0) - goto out; - } - - __del_sem_handle(sem); - goto out; - } - } - - if (sem->owned) { - if (sem->deleted) { - ret = -EIDRM; - goto out; - } - - switch (cmd) { - case GETALL: - for (int i = 0; i < sem->nsems; i++) { - unsigned short val = sem->sems[i].val; - ((unsigned short*)arg)[i] = val; - } - break; - - case GETNCNT: - ret = sem->sems[semnum].ncnt; - break; - - case GETPID: - ret = sem->sems[semnum].pid; - break; - - case GETVAL: - ret = sem->sems[semnum].val; - break; - - case GETZCNT: - ret = sem->sems[semnum].zcnt; - break; - - case SETALL: - for (int i = 0; i < sem->nsems; i++) { - unsigned short val = ((unsigned short*)arg)[i]; - sem->sems[i].val = val; - } - break; - - case SETVAL: { - unsigned short val = arg; - sem->sems[semnum].val = val; - break; - } - } - } else { - switch (cmd) { - case GETALL: - case SETALL: { - int valsize = sem->nsems * sizeof(unsigned short); - ret = ipc_sysv_semctl_send(sem->semid, 0, cmd, (unsigned short*)arg, valsize); - break; - } - - case GETVAL: - case GETNCNT: - case GETPID: - case GETZCNT: { - int valsize = sizeof(unsigned short); - unsigned short val; - ret = ipc_sysv_semctl_send(sem->semid, semnum, cmd, &val, valsize); - if (!ret) - ret = val; - break; - } - - case SETVAL: { - unsigned short val = arg; - ret = ipc_sysv_semctl_send(sem->semid, semnum, cmd, &val, sizeof(unsigned short)); - break; - } - } - } - -out: - unlock(&hdl->lock); - put_sem_handle(sem); - return ret; -} - -static bool __handle_sysv_sems(struct shim_sem_handle* sem) { - bool progressed = false; - bool setevent = false; - - struct sem_obj* sobj; - for (sobj = sem->sems; sobj < &sem->sems[sem->nsems]; sobj++) - LISTP_SPLICE_TAIL_INIT(&sobj->next_ops, &sobj->ops, progress, sem_ops); - - for (sobj = sem->sems; sobj < &sem->sems[sem->nsems]; sobj++) { - struct sem_ops* sops; - struct sem_ops* n; - - LISTP_FOR_EACH_ENTRY_SAFE(sops, n, &sobj->ops, progress) { - struct sembuf* op = &sops->ops[sops->stat.current]; - assert(op->sem_num == sobj->num); - // first_iter is a variable defined by LISTP_FOR_EACH_ENTRY_SAFE - // The second part of this assertion is only valid after the first attempt - assert(first_iter || (sops != n)); - if (sops->stat.completed) - goto send_result; - again: - if (op->sem_op > 0) { - sobj->val += op->sem_op; - log_debug("sem %u: add %u => %u\n", sobj->num, op->sem_op, sobj->val); - } else if (op->sem_op < 0) { - if (sobj->val < -op->sem_op) { - if (op->sem_flg & IPC_NOWAIT) { - log_error("sem %u: wait for %u failed\n", sobj->num, -op->sem_op); - goto failed; - } - continue; - } - sobj->val -= -op->sem_op; - log_debug("sem %u: wait for %u => %u\n", sobj->num, -op->sem_op, sobj->val); - } else { - if (sobj->val) { - if (op->sem_flg & IPC_NOWAIT) { - log_error("sem %u: wait for 0 failed\n", sobj->num); - goto failed; - } - continue; - } - log_debug("sem %u: wait for 0\n", sobj->num); - } - - progressed = true; - sops->stat.current++; - if (sops->stat.current == sops->stat.nops) { - sops->stat.completed = true; - goto send_result; - } - - op = &sops->ops[sops->stat.current]; - if (op->sem_num != sobj->num) { - LISTP_MOVE_TAIL(sops, &sem->sems[op->sem_num].next_ops, &sobj->ops, progress); - continue; - } - - goto again; - failed: - progressed = true; - sops->stat.failed = true; - send_result: - /* Chia-Che 10/17/17: If the code reaches this point, sops should - * still be in sobj->ops. */ - LISTP_DEL_INIT(sops, &sobj->ops, progress); - sem->nreqs--; - if (!sops->client.vmid) { - setevent = true; - continue; - } - - struct shim_ipc_resp resp = { - .retval = sops->stat.completed ? 0 : -EAGAIN, - }; - - size_t total_msg_size = get_ipc_msg_size(sizeof(resp)); - struct shim_ipc_msg* resp_msg = __alloca(total_msg_size); - init_ipc_msg(resp_msg, IPC_MSG_RESP, total_msg_size); - resp_msg->header.seq = sops->client.seq; - - memcpy(&resp_msg->data, &resp, sizeof(resp)); - - send_ipc_message(resp_msg, sops->client.vmid); - - sops->client.vmid = 0; - sops->client.seq = 0; - free(sops); - } - } - - if (setevent) - DkEventSet(sem->event); - - return progressed; -} - -static void __handle_one_sysv_sem(struct shim_sem_handle* sem, struct sem_stat* stat, - struct sembuf* sops) { - bool progressed = false; - -again: - while (stat->current < stat->nops) { - struct sem_obj* sobj = &sem->sems[sops[stat->current].sem_num]; - struct sembuf* op = &sops[stat->current]; - - if (op->sem_op > 0) { - progressed = true; - sobj->val += op->sem_op; - log_debug("sem %u: add %u => %u\n", sobj->num, op->sem_op, sobj->val); - } else if (op->sem_op < 0) { - if (sobj->val < -op->sem_op) { - if (op->sem_flg & IPC_NOWAIT) { - stat->failed = true; - log_error("sem %u: wait for %u failed\n", sobj->num, -op->sem_op); - return; - } - goto failed; - } - progressed = true; - sobj->val -= -op->sem_op; - log_debug("sem %u: wait for %u => %u\n", sobj->num, -op->sem_op, sobj->val); - } else { - if (sobj->val) { - if (op->sem_flg & IPC_NOWAIT) { - stat->failed = true; - log_error("sem %u: wait for 0 failed\n", sobj->num); - return; - } - goto failed; - } - progressed = true; - log_debug("sem %u: wait for 0\n", sobj->num); - } - - stat->current++; - } - - stat->completed = true; -failed: - if (progressed) { - while (__handle_sysv_sems(sem)) - ; - progressed = false; - if (!stat->completed) - goto again; - } -} - -int submit_sysv_sem(struct shim_sem_handle* sem, struct sembuf* sops, int nsops, - unsigned long timeout, struct sysv_client* client) { - int ret = 0; - struct shim_handle* hdl = SEM_TO_HANDLE(sem); - struct sem_ops* sem_ops = NULL; - bool malloced = false; - struct sem_stat stat; - stat.nops = nsops; - stat.current = 0; - stat.timeout = timeout; - stat.completed = false; - stat.failed = false; - - lock(&hdl->lock); - - if (sem->deleted) { - ret = -EIDRM; - goto out_locked; - } - - IDTYPE semid = sem->semid; - bool sendreply = false; - unsigned long seq = client ? client->seq : 0; - - for (int i = 0; i < nsops; i++) { - struct sembuf* op = &sops[i]; - - if (op->sem_op > 0) { - /* nothing to do */ - } else { - sendreply = true; - } - } - - if (sem->deleted) { - if (!client || sendreply) { - ret = -EIDRM; - goto out_locked; - } - - ret = ipc_sysv_delres_send(client->vmid, sem->semid, SYSV_SEM); - goto out_locked; - } - - if (!sem->owned) { - if (client) { - ret = -ECONNREFUSED; - goto out_locked; - } - - unowned: - unlock(&hdl->lock); - ret = ipc_sysv_semop_send(semid, sops, nsops, timeout, &seq); - if (ret != -EAGAIN && ret != -ECONNREFUSED) - goto out; - - lock(&hdl->lock); - if (!sem->owned) - goto out_locked; - } - - if (seq) { - struct sem_ops* op; - - LISTP_FOR_EACH_ENTRY(op, &sem->migrated, progress) { - if (op->client.vmid == (client ? client->vmid : g_self_vmid) && - seq == op->client.seq) { - LISTP_DEL_INIT(op, &sem->migrated, progress); - sem_ops = op; - stat = sem_ops->stat; - malloced = true; - break; - } - } - } - - __handle_one_sysv_sem(sem, &stat, sops); - - if (stat.completed || stat.failed) { - ret = stat.completed ? 0 : -EAGAIN; - if (client && sendreply) { - struct shim_ipc_resp resp = { - .retval = ret, - }; - size_t total_msg_size = get_ipc_msg_size(sizeof(resp)); - struct shim_ipc_msg* resp_msg = __alloca(total_msg_size); - init_ipc_msg(resp_msg, IPC_MSG_RESP, total_msg_size); - resp_msg->header.seq = client->seq; - - memcpy(&resp_msg->data, &resp, sizeof(resp)); - - ret = send_ipc_message(resp_msg, client->vmid); - } - goto out_locked; - } - - if (client) { - assert(sendreply); - if (!sem_ops || !malloced) { - sem_ops = malloc(sizeof(struct sem_ops) + sizeof(struct sembuf) * nsops); - if (!sem_ops) { - ret = -ENOMEM; - goto out_locked; - } - - sem_ops->client.vmid = 0; - sem_ops->client.seq = 0; - INIT_LIST_HEAD(sem_ops, progress); - malloced = true; - } - } else { - if (!sem_ops) { - sem_ops = __alloca(sizeof(struct sem_ops) + sizeof(struct sembuf) * nsops); - sem_ops->client.vmid = 0; - sem_ops->client.seq = 0; - INIT_LIST_HEAD(sem_ops, progress); - } - } - - sem_ops->stat = stat; - for (int i = 0; i < nsops; i++) { - sem_ops->ops[i] = sops[i]; - } - - LISTP_TYPE(sem_ops)* next_ops = &sem->sems[sops[stat.current].sem_num].next_ops; - assert(LIST_EMPTY(sem_ops, progress)); - LISTP_ADD_TAIL(sem_ops, next_ops, progress); - // CHECK_LIST_HEAD(next_ops); - sem->nreqs++; - - if (client) { - assert(sendreply); - sem_ops->client = *client; - sem_ops = NULL; - goto out_locked; - } - - while (!sem_ops->stat.completed && !sem_ops->stat.failed) { - if (!sem->owned) { - /* Chia-Che 10/17/17: sem_ops may move from semaphore to semaphore - base on its current state */ - next_ops = &sem->sems[sem_ops->ops[sem_ops->stat.current].sem_num].next_ops; - LISTP_DEL_INIT(sem_ops, next_ops, progress); - goto unowned; - } - - unlock(&hdl->lock); - object_wait_with_retry(sem->event); - lock(&hdl->lock); - } - - ret = sem_ops->stat.completed ? 0 : -EAGAIN; - -out_locked: - unlock(&hdl->lock); -out: - if (sem_ops && malloced) - free(sem_ops); - return ret; -} diff --git a/LibOS/shim/test/ltp/ltp.cfg b/LibOS/shim/test/ltp/ltp.cfg index f3c7ec935b..300655863d 100644 --- a/LibOS/shim/test/ltp/ltp.cfg +++ b/LibOS/shim/test/ltp/ltp.cfg @@ -1245,75 +1245,16 @@ skip = yes [mremap05] skip = yes -[msgctl01] +[msgctl*] skip = yes -[msgctl02] +[msgget*] skip = yes -[msgctl03] +[msgrcv*] skip = yes -[msgctl04] -skip = yes - -# TCONF: test requires struct msqid64_ds to have the time_high fields -[msgctl05] -skip = yes - -[msgctl12] -skip = yes - -[msgget02] -must-pass = - 1 - 2 - 3 - -[msgget03] -skip = yes - -# kernel config -[msgget04] -skip = yes - -# kernel config -[msgget05] -skip = yes - -# no msgctl(IPC_STAT) -[msgrcv01] -skip = yes - -[msgrcv02] -skip = yes - -[msgrcv03] -skip = yes - -[msgrcv05] -skip = yes - -[msgrcv06] -skip = yes - -[msgrcv07] -skip = yes - -[msgrcv08] -skip = yes - -[msgsnd01] -skip = yes - -[msgsnd02] -skip = yes - -# Crashes Graphene due to shim_do_msgsnd calling add_sysv_msg with src=NULL, causing NULL deref. -[msgsnd05] -skip = yes - -[msgsnd06] +[msgsnd*] skip = yes [msgstress01] @@ -1953,47 +1894,13 @@ skip = yes [select04] timeout = 40 -[semctl01] -must-pass = - 2 - 3 - -[semctl02] -skip = yes - -[semctl03] -skip = yes - -[semctl04] -skip = yes - -[semctl05] -skip = yes - -[semctl07] -skip = yes - -# TCONF: test requires struct semid64_ds to have the time_high fields -[semctl08] -skip = yes - -[semget01] -skip = yes - -[semget02] -must-pass = - 2 - -[semget05] +[semctl*] skip = yes -[semget06] +[semget*] skip = yes -[semop02] -skip = yes - -[semop03] +[semop*] skip = yes [send01] @@ -2054,6 +1961,10 @@ skip = yes [sendmsg01] skip = yes +# uses sysv semaphores +[sendmsg02] +skip = yes + # opens /proc/sys/kernel/tainted [sendmsg03] skip = yes