xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

busfault.c (4120B)


      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 }