File:  [Qemu by Fabrice Bellard] / qemu / compatfd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:33:23 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

    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:     int err;
   30:     sigset_t all;
   31: 
   32:     sigfillset(&all);
   33:     sigprocmask(SIG_BLOCK, &all, NULL);
   34: 
   35:     do {
   36:         siginfo_t siginfo;
   37: 
   38:         err = sigwaitinfo(&info->mask, &siginfo);
   39:         if (err == -1 && errno == EINTR) {
   40:             err = 0;
   41:             continue;
   42:         }
   43: 
   44:         if (err > 0) {
   45:             char buffer[128];
   46:             size_t offset = 0;
   47: 
   48:             memcpy(buffer, &err, sizeof(err));
   49:             while (offset < sizeof(buffer)) {
   50:                 ssize_t len;
   51: 
   52:                 len = write(info->fd, buffer + offset,
   53:                             sizeof(buffer) - offset);
   54:                 if (len == -1 && errno == EINTR)
   55:                     continue;
   56: 
   57:                 if (len <= 0) {
   58:                     err = -1;
   59:                     break;
   60:                 }
   61: 
   62:                 offset += len;
   63:             }
   64:         }
   65:     } while (err >= 0);
   66: 
   67:     return NULL;
   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: }

unix.superglobalmegacorp.com