File:  [Qemu by Fabrice Bellard] / qemu / compatfd.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:33:43 2018 UTC (3 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

    1: /*
    2:  * signalfd/eventfd compatibility
    3:  *
    4:  * Copyright IBM, Corp. 2008
    5:  *
    6:  * Authors:
    7:  *  Anthony Liguori   <aliguori@us.ibm.com>
    8:  *
    9:  * This work is licensed under the terms of the GNU GPL, version 2.  See
   10:  * the COPYING file in the top-level directory.
   11:  *
   12:  * Contributions after 2012-01-13 are licensed under the terms of the
   13:  * GNU GPL, version 2 or (at your option) any later version.
   14:  */
   15: 
   16: #include "qemu-common.h"
   17: #include "compatfd.h"
   18: 
   19: #include <sys/syscall.h>
   20: #include <pthread.h>
   21: 
   22: struct sigfd_compat_info
   23: {
   24:     sigset_t mask;
   25:     int fd;
   26: };
   27: 
   28: static void *sigwait_compat(void *opaque)
   29: {
   30:     struct sigfd_compat_info *info = opaque;
   31:     sigset_t all;
   32: 
   33:     sigfillset(&all);
   34:     pthread_sigmask(SIG_BLOCK, &all, NULL);
   35: 
   36:     while (1) {
   37:         int sig;
   38:         int err;
   39: 
   40:         err = sigwait(&info->mask, &sig);
   41:         if (err != 0) {
   42:             if (errno == EINTR) {
   43:                 continue;
   44:             } else {
   45:                 return NULL;
   46:             }
   47:         } else {
   48:             struct qemu_signalfd_siginfo buffer;
   49:             size_t offset = 0;
   50: 
   51:             memset(&buffer, 0, sizeof(buffer));
   52:             buffer.ssi_signo = sig;
   53: 
   54:             while (offset < sizeof(buffer)) {
   55:                 ssize_t len;
   56: 
   57:                 len = write(info->fd, (char *)&buffer + offset,
   58:                             sizeof(buffer) - offset);
   59:                 if (len == -1 && errno == EINTR)
   60:                     continue;
   61: 
   62:                 if (len <= 0) {
   63:                     return NULL;
   64:                 }
   65: 
   66:                 offset += len;
   67:             }
   68:         }
   69:     }
   70: }
   71: 
   72: static int qemu_signalfd_compat(const sigset_t *mask)
   73: {
   74:     pthread_attr_t attr;
   75:     pthread_t tid;
   76:     struct sigfd_compat_info *info;
   77:     int fds[2];
   78: 
   79:     info = malloc(sizeof(*info));
   80:     if (info == NULL) {
   81:         errno = ENOMEM;
   82:         return -1;
   83:     }
   84: 
   85:     if (pipe(fds) == -1) {
   86:         free(info);
   87:         return -1;
   88:     }
   89: 
   90:     qemu_set_cloexec(fds[0]);
   91:     qemu_set_cloexec(fds[1]);
   92: 
   93:     memcpy(&info->mask, mask, sizeof(*mask));
   94:     info->fd = fds[1];
   95: 
   96:     pthread_attr_init(&attr);
   97:     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   98: 
   99:     pthread_create(&tid, &attr, sigwait_compat, info);
  100: 
  101:     pthread_attr_destroy(&attr);
  102: 
  103:     return fds[0];
  104: }
  105: 
  106: int qemu_signalfd(const sigset_t *mask)
  107: {
  108: #if defined(CONFIG_SIGNALFD)
  109:     int ret;
  110: 
  111:     ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
  112:     if (ret != -1) {
  113:         qemu_set_cloexec(ret);
  114:         return ret;
  115:     }
  116: #endif
  117: 
  118:     return qemu_signalfd_compat(mask);
  119: }
  120: 
  121: bool qemu_signalfd_available(void)
  122: {
  123: #ifdef CONFIG_SIGNALFD
  124:     sigset_t mask;
  125:     int fd;
  126:     bool ok;
  127:     sigemptyset(&mask);
  128:     errno = 0;
  129:     fd = syscall(SYS_signalfd, -1, &mask, _NSIG / 8);
  130:     ok = (errno != ENOSYS);
  131:     if (fd >= 0) {
  132:         close(fd);
  133:     }
  134:     return ok;
  135: #else
  136:     return false;
  137: #endif
  138: }

unix.superglobalmegacorp.com