Annotation of qemu/compatfd.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com