Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/um/os-Linux/irq.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2017 - Cambridge Greys Ltd
4
* Copyright (C) 2011 - 2014 Cisco Systems Inc
5
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
6
*/
7
8
#include <stdlib.h>
9
#include <errno.h>
10
#include <sys/epoll.h>
11
#include <signal.h>
12
#include <string.h>
13
#include <irq_user.h>
14
#include <os.h>
15
#include <um_malloc.h>
16
17
/* Epoll support */
18
19
static int epollfd = -1;
20
21
#define MAX_EPOLL_EVENTS 64
22
23
static struct epoll_event epoll_events[MAX_EPOLL_EVENTS];
24
25
/* Helper to return an Epoll data pointer from an epoll event structure.
26
* We need to keep this one on the userspace side to keep includes separate
27
*/
28
29
void *os_epoll_get_data_pointer(int index)
30
{
31
return epoll_events[index].data.ptr;
32
}
33
34
/* Helper to compare events versus the events in the epoll structure.
35
* Same as above - needs to be on the userspace side
36
*/
37
38
39
int os_epoll_triggered(int index, int events)
40
{
41
return epoll_events[index].events & events;
42
}
43
/* Helper to set the event mask.
44
* The event mask is opaque to the kernel side, because it does not have
45
* access to the right includes/defines for EPOLL constants.
46
*/
47
48
int os_event_mask(enum um_irq_type irq_type)
49
{
50
if (irq_type == IRQ_READ)
51
return EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
52
if (irq_type == IRQ_WRITE)
53
return EPOLLOUT;
54
return 0;
55
}
56
57
/*
58
* Initial Epoll Setup
59
*/
60
int os_setup_epoll(void)
61
{
62
epollfd = epoll_create(MAX_EPOLL_EVENTS);
63
return epollfd;
64
}
65
66
/*
67
* Helper to run the actual epoll_wait
68
*/
69
int os_waiting_for_events_epoll(void)
70
{
71
int n, err;
72
73
n = epoll_wait(epollfd,
74
(struct epoll_event *) &epoll_events, MAX_EPOLL_EVENTS, 0);
75
if (n < 0) {
76
err = -errno;
77
if (errno != EINTR)
78
printk(
79
UM_KERN_ERR "os_waiting_for_events:"
80
" epoll returned %d, error = %s\n", n,
81
strerror(errno)
82
);
83
return err;
84
}
85
return n;
86
}
87
88
89
/*
90
* Helper to add a fd to epoll
91
*/
92
int os_add_epoll_fd(int events, int fd, void *data)
93
{
94
struct epoll_event event;
95
int result;
96
97
event.data.ptr = data;
98
event.events = events | EPOLLET;
99
result = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
100
if ((result) && (errno == EEXIST))
101
result = os_mod_epoll_fd(events, fd, data);
102
if (result)
103
printk("epollctl add err fd %d, %s\n", fd, strerror(errno));
104
return result;
105
}
106
107
/*
108
* Helper to mod the fd event mask and/or data backreference
109
*/
110
int os_mod_epoll_fd(int events, int fd, void *data)
111
{
112
struct epoll_event event;
113
int result;
114
115
event.data.ptr = data;
116
event.events = events;
117
result = epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);
118
if (result)
119
printk(UM_KERN_ERR
120
"epollctl mod err fd %d, %s\n", fd, strerror(errno));
121
return result;
122
}
123
124
/*
125
* Helper to delete the epoll fd
126
*/
127
int os_del_epoll_fd(int fd)
128
{
129
struct epoll_event event;
130
/* This is quiet as we use this as IO ON/OFF - so it is often
131
* invoked on a non-existent fd
132
*/
133
return epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &event);
134
}
135
136
void os_set_ioignore(void)
137
{
138
signal(SIGIO, SIG_IGN);
139
}
140
141
void os_close_epoll_fd(void)
142
{
143
/* Needed so we do not leak an fd when rebooting */
144
os_close_file(epollfd);
145
}
146
147