Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2017 - Cambridge Greys Ltd
0004  * Copyright (C) 2011 - 2014 Cisco Systems Inc
0005  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
0006  */
0007 
0008 #include <stdlib.h>
0009 #include <errno.h>
0010 #include <sys/epoll.h>
0011 #include <signal.h>
0012 #include <string.h>
0013 #include <irq_user.h>
0014 #include <os.h>
0015 #include <um_malloc.h>
0016 
0017 /* Epoll support */
0018 
0019 static int epollfd = -1;
0020 
0021 #define MAX_EPOLL_EVENTS 64
0022 
0023 static struct epoll_event epoll_events[MAX_EPOLL_EVENTS];
0024 
0025 /* Helper to return an Epoll data pointer from an epoll event structure.
0026  * We need to keep this one on the userspace side to keep includes separate
0027  */
0028 
0029 void *os_epoll_get_data_pointer(int index)
0030 {
0031     return epoll_events[index].data.ptr;
0032 }
0033 
0034 /* Helper to compare events versus the events in the epoll structure.
0035  * Same as above - needs to be on the userspace side
0036  */
0037 
0038 
0039 int os_epoll_triggered(int index, int events)
0040 {
0041     return epoll_events[index].events & events;
0042 }
0043 /* Helper to set the event mask.
0044  * The event mask is opaque to the kernel side, because it does not have
0045  * access to the right includes/defines for EPOLL constants.
0046  */
0047 
0048 int os_event_mask(enum um_irq_type irq_type)
0049 {
0050     if (irq_type == IRQ_READ)
0051         return EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
0052     if (irq_type == IRQ_WRITE)
0053         return EPOLLOUT;
0054     return 0;
0055 }
0056 
0057 /*
0058  * Initial Epoll Setup
0059  */
0060 int os_setup_epoll(void)
0061 {
0062     epollfd = epoll_create(MAX_EPOLL_EVENTS);
0063     return epollfd;
0064 }
0065 
0066 /*
0067  * Helper to run the actual epoll_wait
0068  */
0069 int os_waiting_for_events_epoll(void)
0070 {
0071     int n, err;
0072 
0073     n = epoll_wait(epollfd,
0074         (struct epoll_event *) &epoll_events, MAX_EPOLL_EVENTS, 0);
0075     if (n < 0) {
0076         err = -errno;
0077         if (errno != EINTR)
0078             printk(
0079                 UM_KERN_ERR "os_waiting_for_events:"
0080                 " epoll returned %d, error = %s\n", n,
0081                 strerror(errno)
0082             );
0083         return err;
0084     }
0085     return n;
0086 }
0087 
0088 
0089 /*
0090  * Helper to add a fd to epoll
0091  */
0092 int os_add_epoll_fd(int events, int fd, void *data)
0093 {
0094     struct epoll_event event;
0095     int result;
0096 
0097     event.data.ptr = data;
0098     event.events = events | EPOLLET;
0099     result = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
0100     if ((result) && (errno == EEXIST))
0101         result = os_mod_epoll_fd(events, fd, data);
0102     if (result)
0103         printk("epollctl add err fd %d, %s\n", fd, strerror(errno));
0104     return result;
0105 }
0106 
0107 /*
0108  * Helper to mod the fd event mask and/or data backreference
0109  */
0110 int os_mod_epoll_fd(int events, int fd, void *data)
0111 {
0112     struct epoll_event event;
0113     int result;
0114 
0115     event.data.ptr = data;
0116     event.events = events;
0117     result = epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);
0118     if (result)
0119         printk(UM_KERN_ERR
0120             "epollctl mod err fd %d, %s\n", fd, strerror(errno));
0121     return result;
0122 }
0123 
0124 /*
0125  * Helper to delete the epoll fd
0126  */
0127 int os_del_epoll_fd(int fd)
0128 {
0129     struct epoll_event event;
0130     int result;
0131     /* This is quiet as we use this as IO ON/OFF - so it is often
0132      * invoked on a non-existent fd
0133      */
0134     result = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &event);
0135     return result;
0136 }
0137 
0138 void os_set_ioignore(void)
0139 {
0140     signal(SIGIO, SIG_IGN);
0141 }
0142 
0143 void os_close_epoll_fd(void)
0144 {
0145     /* Needed so we do not leak an fd when rebooting */
0146     os_close_file(epollfd);
0147 }