Revision bcdf9b4d

b/compatfd.c
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
    memcpy(&info->mask, mask, sizeof(*mask));
89
    info->fd = fds[1];
90

  
91
    pthread_attr_init(&attr);
92
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
93

  
94
    pthread_create(&tid, &attr, sigwait_compat, info);
95

  
96
    pthread_attr_destroy(&attr);
97

  
98
    return fds[0];
99
}
100

  
101
int qemu_signalfd(const sigset_t *mask)
102
{
103
#if defined(SYS_signalfd)
104
    int ret;
105

  
106
    ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
107
    if (!(ret == -1 && errno == ENOSYS))
108
	return ret;
109
#endif
110

  
111
    return qemu_signalfd_compat(mask);
112
}
113

  
114
int qemu_eventfd(int *fds)
115
{
116
#if defined(SYS_eventfd)
117
    int ret;
118

  
119
    ret = syscall(SYS_eventfd, 0);
120
    if (ret >= 0) {
121
	fds[0] = fds[1] = ret;
122
	return 0;
123
    } else if (!(ret == -1 && errno == ENOSYS))
124
	return ret;
125
#endif
126

  
127
    return pipe(fds);
128
}
b/compatfd.h
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
#ifndef QEMU_COMPATFD_H
15
#define QEMU_COMPATFD_H
16

  
17
#include <signal.h>
18

  
19
#if defined(__linux__) && !defined(SYS_signalfd)
20
struct signalfd_siginfo {
21
    uint32_t ssi_signo;
22
    uint8_t pad[124];
23
};
24
#else
25
#include <linux/signalfd.h>
26
#endif
27

  
28
int qemu_signalfd(const sigset_t *mask);
29

  
30
int qemu_eventfd(int *fds);
31

  
32
#endif

Also available in: Unified diff