File:  [Qemu by Fabrice Bellard] / qemu / compatfd.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:55:41 2018 UTC (3 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, HEAD
qemu 0.15.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:  */
   13: 
   14: #include "qemu-common.h"
   15: #include "compatfd.h"
   16: 
   17: #include <sys/syscall.h>
   18: #include <pthread.h>
   19: 
   20: struct sigfd_compat_info
   21: {
   22:     sigset_t mask;
   23:     int fd;
   24: };
   25: 
   26: static void *sigwait_compat(void *opaque)
   27: {
   28:     struct sigfd_compat_info *info = opaque;
   29:     sigset_t all;
   30: 
   31:     sigfillset(&all);
   32:     pthread_sigmask(SIG_BLOCK, &all, NULL);
   33: 
   34:     while (1) {
   35:         int sig;
   36:         int err;
   37: 
   38:         err = sigwait(&info->mask, &sig);
   39:         if (err != 0) {
   40:             if (errno == EINTR) {
   41:                 continue;
   42:             } else {
   43:                 return NULL;
   44:             }
   45:         } else {
   46:             struct qemu_signalfd_siginfo buffer;
   47:             size_t offset = 0;
   48: 
   49:             memset(&buffer, 0, sizeof(buffer));
   50:             buffer.ssi_signo = sig;
   51: 
   52:             while (offset < sizeof(buffer)) {
   53:                 ssize_t len;
   54: 
   55:                 len = write(info->fd, (char *)&buffer + offset,
   56:                             sizeof(buffer) - offset);
   57:                 if (len == -1 && errno == EINTR)
   58:                     continue;
   59: 
   60:                 if (len <= 0) {
   61:                     return NULL;
   62:                 }
   63: 
   64:                 offset += len;
   65:             }
   66:         }
   67:     }
   68: }
   69: 
   70: static int qemu_signalfd_compat(const sigset_t *mask)
   71: {
   72:     pthread_attr_t attr;
   73:     pthread_t tid;
   74:     struct sigfd_compat_info *info;
   75:     int fds[2];
   76: 
   77:     info = malloc(sizeof(*info));
   78:     if (info == NULL) {
   79:         errno = ENOMEM;
   80:         return -1;
   81:     }
   82: 
   83:     if (pipe(fds) == -1) {
   84:         free(info);
   85:         return -1;
   86:     }
   87: 
   88:     qemu_set_cloexec(fds[0]);
   89:     qemu_set_cloexec(fds[1]);
   90: 
   91:     memcpy(&info->mask, mask, sizeof(*mask));
   92:     info->fd = fds[1];
   93: 
   94:     pthread_attr_init(&attr);
   95:     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   96: 
   97:     pthread_create(&tid, &attr, sigwait_compat, info);
   98: 
   99:     pthread_attr_destroy(&attr);
  100: 
  101:     return fds[0];
  102: }
  103: 
  104: int qemu_signalfd(const sigset_t *mask)
  105: {
  106: #if defined(CONFIG_SIGNALFD)
  107:     int ret;
  108: 
  109:     ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
  110:     if (ret != -1) {
  111:         qemu_set_cloexec(ret);
  112:         return ret;
  113:     }
  114: #endif
  115: 
  116:     return qemu_signalfd_compat(mask);
  117: }
  118: 
  119: bool qemu_signalfd_available(void)
  120: {
  121: #ifdef CONFIG_SIGNALFD
  122:     errno = 0;
  123:     syscall(SYS_signalfd, -1, NULL, _NSIG / 8);
  124:     return errno != ENOSYS;
  125: #else
  126:     return false;
  127: #endif
  128: }

unix.superglobalmegacorp.com