"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.5/os/busfault.c" (30 May 2019, 4120 Bytes) of package /linux/misc/xorg-server-1.20.5.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "busfault.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright © 2013 Keith Packard
    3  *
    4  * Permission to use, copy, modify, distribute, and sell this software and its
    5  * documentation for any purpose is hereby granted without fee, provided that
    6  * the above copyright notice appear in all copies and that both that copyright
    7  * notice and this permission notice appear in supporting documentation, and
    8  * that the name of the copyright holders not be used in advertising or
    9  * publicity pertaining to distribution of the software without specific,
   10  * written prior permission.  The copyright holders make no representations
   11  * about the suitability of this software for any purpose.  It is provided "as
   12  * is" without express or implied warranty.
   13  *
   14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
   15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
   16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
   17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
   18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
   19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
   20  * OF THIS SOFTWARE.
   21  */
   22 
   23 #ifdef HAVE_DIX_CONFIG_H
   24 #include <dix-config.h>
   25 #endif
   26 
   27 #include <X11/Xos.h>
   28 #include <X11/Xdefs.h>
   29 #include "misc.h"
   30 #include <busfault.h>
   31 #include <list.h>
   32 #include <stddef.h>
   33 #include <stdlib.h>
   34 #include <stdint.h>
   35 #include <sys/mman.h>
   36 #include <signal.h>
   37 
   38 struct busfault {
   39     struct xorg_list    list;
   40 
   41     void                *addr;
   42     size_t              size;
   43 
   44     Bool                valid;
   45 
   46     busfault_notify_ptr notify;
   47     void                *context;
   48 };
   49 
   50 static Bool             busfaulted;
   51 static struct xorg_list busfaults;
   52 
   53 struct busfault *
   54 busfault_register_mmap(void *addr, size_t size, busfault_notify_ptr notify, void *context)
   55 {
   56     struct busfault     *busfault;
   57 
   58     busfault = calloc(1, sizeof (struct busfault));
   59     if (!busfault)
   60         return NULL;
   61 
   62     busfault->addr = addr;
   63     busfault->size = size;
   64     busfault->notify = notify;
   65     busfault->context = context;
   66     busfault->valid = TRUE;
   67 
   68     xorg_list_add(&busfault->list, &busfaults);
   69     return busfault;
   70 }
   71 
   72 void
   73 busfault_unregister(struct busfault *busfault)
   74 {
   75     xorg_list_del(&busfault->list);
   76     free(busfault);
   77 }
   78 
   79 void
   80 busfault_check(void)
   81 {
   82     struct busfault     *busfault, *tmp;
   83 
   84     if (!busfaulted)
   85         return;
   86 
   87     busfaulted = FALSE;
   88 
   89     xorg_list_for_each_entry_safe(busfault, tmp, &busfaults, list) {
   90         if (!busfault->valid)
   91             (*busfault->notify)(busfault->context);
   92     }
   93 }
   94 
   95 static void (*previous_busfault_sigaction)(int sig, siginfo_t *info, void *param);
   96 
   97 static void
   98 busfault_sigaction(int sig, siginfo_t *info, void *param)
   99 {
  100     void                *fault = info->si_addr;
  101     struct busfault     *iter, *busfault = NULL;
  102     void                *new_addr;
  103 
  104     /* Locate the faulting address in our list of shared segments
  105      */
  106     xorg_list_for_each_entry(iter, &busfaults, list) {
  107     if ((char *) iter->addr <= (char *) fault && (char *) fault < (char *) iter->addr + iter->size) {
  108         busfault = iter;
  109         break;
  110     }
  111     }
  112     if (!busfault)
  113         goto panic;
  114 
  115     if (!busfault->valid)
  116         goto panic;
  117 
  118     busfault->valid = FALSE;
  119     busfaulted = TRUE;
  120 
  121     /* The client truncated the file; unmap the shared file, map
  122      * /dev/zero over that area and keep going
  123      */
  124 
  125     new_addr = mmap(busfault->addr, busfault->size, PROT_READ|PROT_WRITE,
  126                     MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
  127 
  128     if (new_addr == MAP_FAILED)
  129         goto panic;
  130 
  131     return;
  132 panic:
  133     if (previous_busfault_sigaction)
  134         (*previous_busfault_sigaction)(sig, info, param);
  135     else
  136         FatalError("bus error\n");
  137 }
  138 
  139 Bool
  140 busfault_init(void)
  141 {
  142     struct sigaction    act, old_act;
  143 
  144     act.sa_sigaction = busfault_sigaction;
  145     act.sa_flags = SA_SIGINFO;
  146     sigemptyset(&act.sa_mask);
  147     if (sigaction(SIGBUS, &act, &old_act) < 0)
  148         return FALSE;
  149     previous_busfault_sigaction = old_act.sa_sigaction;
  150     xorg_list_init(&busfaults);
  151     return TRUE;
  152 }