Annotation of qemu/compatfd.c, revision 1.1.1.2

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
        !           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