18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * signalfd/eventfd compatibility 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright IBM, Corp. 2008 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Authors: 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Anthony Liguori <aliguori@us.ibm.com> 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This work is licensed under the terms of the GNU GPL, version 2. See 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the COPYING file in the top-level directory. 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h" 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "compatfd.h" 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/syscall.h> 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <pthread.h> 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct sigfd_compat_info 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sigset_t mask; 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int fd; 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void *sigwait_compat(void *opaque) 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct sigfd_compat_info *info = opaque; 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sigset_t all; 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sigfillset(&all); 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sigprocmask(SIG_BLOCK, &all, NULL); 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner while (1) { 35e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner int sig; 36e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner int err; 37e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner 38e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner err = sigwait(&info->mask, &sig); 39e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner if (err != 0) { 40e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner if (errno == EINTR) { 41e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner continue; 42e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner } else { 43e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner return NULL; 44e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner } 45e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner } else { 46e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner struct qemu_signalfd_siginfo buffer; 47e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner size_t offset = 0; 48e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner 49e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner memset(&buffer, 0, sizeof(buffer)); 50e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner buffer.ssi_signo = sig; 51e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner 52e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner while (offset < sizeof(buffer)) { 53e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner ssize_t len; 54e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner 55e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner len = write(info->fd, (char *)&buffer + offset, 56e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner sizeof(buffer) - offset); 57e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner if (len == -1 && errno == EINTR) 58e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner continue; 59e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner 60e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner if (len <= 0) { 61e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner return NULL; 62e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner } 63e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner 64e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner offset += len; 65e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner } 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner } 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int qemu_signalfd_compat(const sigset_t *mask) 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pthread_attr_t attr; 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pthread_t tid; 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct sigfd_compat_info *info; 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int fds[2]; 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project info = malloc(sizeof(*info)); 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (info == NULL) { 79e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner errno = ENOMEM; 80e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner return -1; 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pipe(fds) == -1) { 84e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner free(info); 85e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner return -1; 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 88e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner qemu_set_cloexec(fds[0]); 89e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner qemu_set_cloexec(fds[1]); 90e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(&info->mask, mask, sizeof(*mask)); 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project info->fd = fds[1]; 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pthread_attr_init(&attr); 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pthread_create(&tid, &attr, sigwait_compat, info); 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pthread_attr_destroy(&attr); 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return fds[0]; 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint qemu_signalfd(const sigset_t *mask) 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 106e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner#if defined(CONFIG_SIGNALFD) 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8); 110e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner if (ret != -1) { 111e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner qemu_set_cloexec(ret); 112e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner return ret; 113e49c3f3e66b4337859af7c1be013b076eb4de136David 'Digit' Turner } 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return qemu_signalfd_compat(mask); 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 118