Annotation of qemu/compatfd.c, revision 1.1.1.4

1.1       root        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:  *
1.1.1.4 ! root       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.
1.1       root       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);
1.1.1.2   root       34:     pthread_sigmask(SIG_BLOCK, &all, NULL);
1.1       root       35: 
1.1.1.2   root       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;
1.1       root       49:             size_t offset = 0;
                     50: 
1.1.1.2   root       51:             memset(&buffer, 0, sizeof(buffer));
                     52:             buffer.ssi_signo = sig;
                     53: 
1.1       root       54:             while (offset < sizeof(buffer)) {
                     55:                 ssize_t len;
                     56: 
1.1.1.2   root       57:                 len = write(info->fd, (char *)&buffer + offset,
1.1       root       58:                             sizeof(buffer) - offset);
                     59:                 if (len == -1 && errno == EINTR)
                     60:                     continue;
                     61: 
                     62:                 if (len <= 0) {
1.1.1.2   root       63:                     return NULL;
1.1       root       64:                 }
                     65: 
                     66:                 offset += len;
                     67:             }
                     68:         }
1.1.1.2   root       69:     }
1.1       root       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: }
1.1.1.2   root      120: 
                    121: bool qemu_signalfd_available(void)
                    122: {
                    123: #ifdef CONFIG_SIGNALFD
1.1.1.3   root      124:     sigset_t mask;
                    125:     int fd;
                    126:     bool ok;
                    127:     sigemptyset(&mask);
1.1.1.2   root      128:     errno = 0;
1.1.1.3   root      129:     fd = syscall(SYS_signalfd, -1, &mask, _NSIG / 8);
                    130:     ok = (errno != ENOSYS);
                    131:     if (fd >= 0) {
                    132:         close(fd);
                    133:     }
                    134:     return ok;
1.1.1.2   root      135: #else
                    136:     return false;
                    137: #endif
                    138: }

unix.superglobalmegacorp.com