2 * Copyright © 2013 Keith Packard
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.
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
23 #include <dix-config.h>
26 #include <X11/Xdefs.h>
28 #include "os/busfault.h"
39 struct xorg_list list
;
46 busfault_notify_ptr notify
;
50 static Bool busfaulted
;
51 static struct xorg_list busfaults
;
54 busfault_register_mmap(void *addr
, size_t size
, busfault_notify_ptr notify
, void *context
)
56 struct busfault
*busfault
;
58 busfault
= calloc(1, sizeof (struct busfault
));
62 busfault
->addr
= addr
;
63 busfault
->size
= size
;
64 busfault
->notify
= notify
;
65 busfault
->context
= context
;
66 busfault
->valid
= TRUE
;
68 xorg_list_add(&busfault
->list
, &busfaults
);
73 busfault_unregister(struct busfault
*busfault
)
75 xorg_list_del(&busfault
->list
);
82 struct busfault
*busfault
, *tmp
;
89 xorg_list_for_each_entry_safe(busfault
, tmp
, &busfaults
, list
) {
91 (*busfault
->notify
)(busfault
->context
);
95 static void (*previous_busfault_sigaction
)(int sig
, siginfo_t
*info
, void *param
);
98 busfault_sigaction(int sig
, siginfo_t
*info
, void *param
)
100 void *fault
= info
->si_addr
;
101 struct busfault
*iter
, *busfault
= NULL
;
104 /* Locate the faulting address in our list of shared segments
106 xorg_list_for_each_entry(iter
, &busfaults
, list
) {
107 if ((char *) iter
->addr
<= (char *) fault
&& (char *) fault
< (char *) iter
->addr
+ iter
->size
) {
115 if (!busfault
->valid
)
118 busfault
->valid
= FALSE
;
121 /* The client truncated the file; unmap the shared file, map
122 * /dev/zero over that area and keep going
125 new_addr
= mmap(busfault
->addr
, busfault
->size
, PROT_READ
|PROT_WRITE
,
126 MAP_ANON
|MAP_PRIVATE
|MAP_FIXED
, -1, 0);
128 if (new_addr
== MAP_FAILED
)
133 if (previous_busfault_sigaction
)
134 (*previous_busfault_sigaction
)(sig
, info
, param
);
136 FatalError("bus error\n");
142 struct sigaction act
, old_act
;
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)
149 previous_busfault_sigaction
= old_act
.sa_sigaction
;
150 xorg_list_init(&busfaults
);