Annotation of qemu/compatfd.c, revision 1.1.1.1

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