LCOV - code coverage report
Current view: top level - arch/um/os-Linux - irq.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 20 41 48.8 %
Date: 2023-08-24 13:40:31 Functions: 6 10 60.0 %

          Line data    Source code
       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           0 : void *os_epoll_get_data_pointer(int index)
      30             : {
      31           0 :         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           0 : int os_epoll_triggered(int index, int events)
      40             : {
      41           0 :         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           1 : int os_event_mask(enum um_irq_type irq_type)
      49             : {
      50           1 :         if (irq_type == IRQ_READ)
      51             :                 return EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
      52           0 :         if (irq_type == IRQ_WRITE)
      53             :                 return EPOLLOUT;
      54           0 :         return 0;
      55             : }
      56             : 
      57             : /*
      58             :  * Initial Epoll Setup
      59             :  */
      60           1 : int os_setup_epoll(void)
      61             : {
      62           1 :         epollfd = epoll_create(MAX_EPOLL_EVENTS);
      63           1 :         return epollfd;
      64             : }
      65             : 
      66             : /*
      67             :  * Helper to run the actual epoll_wait
      68             :  */
      69           0 : int os_waiting_for_events_epoll(void)
      70             : {
      71             :         int n, err;
      72             : 
      73           0 :         n = epoll_wait(epollfd,
      74             :                 (struct epoll_event *) &epoll_events, MAX_EPOLL_EVENTS, 0);
      75           0 :         if (n < 0) {
      76           0 :                 err = -errno;
      77           0 :                 if (errno != EINTR)
      78           0 :                         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           1 : int os_add_epoll_fd(int events, int fd, void *data)
      93             : {
      94             :         struct epoll_event event;
      95             :         int result;
      96             : 
      97           1 :         event.data.ptr = data;
      98           1 :         event.events = events | EPOLLET;
      99           1 :         result = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
     100           1 :         if ((result) && (errno == EEXIST))
     101           0 :                 result = os_mod_epoll_fd(events, fd, data);
     102           1 :         if (result)
     103           0 :                 printk("epollctl add err fd %d, %s\n", fd, strerror(errno));
     104           1 :         return result;
     105             : }
     106             : 
     107             : /*
     108             :  * Helper to mod the fd event mask and/or data backreference
     109             :  */
     110           0 : int os_mod_epoll_fd(int events, int fd, void *data)
     111             : {
     112             :         struct epoll_event event;
     113             :         int result;
     114             : 
     115           0 :         event.data.ptr = data;
     116           0 :         event.events = events;
     117           0 :         result = epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);
     118           0 :         if (result)
     119           0 :                 printk(UM_KERN_ERR
     120             :                         "epollctl mod err fd %d, %s\n", fd, strerror(errno));
     121           0 :         return result;
     122             : }
     123             : 
     124             : /*
     125             :  * Helper to delete the epoll fd
     126             :  */
     127           1 : 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           1 :         return epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &event);
     134             : }
     135             : 
     136           1 : void os_set_ioignore(void)
     137             : {
     138           1 :         signal(SIGIO, SIG_IGN);
     139           1 : }
     140             : 
     141           1 : void os_close_epoll_fd(void)
     142             : {
     143             :         /* Needed so we do not leak an fd when rebooting */
     144           1 :         os_close_file(epollfd);
     145           1 : }

Generated by: LCOV version 1.14