[266ccb]: src / runtime / sunos-os.c Maximize Restore History

Download this file

sunos-os.c    304 lines (254 with data), 7.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/file.h>
#include <unistd.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/utsname.h>
#include "sbcl.h"
#include "os.h"
#include "arch.h"
#include "interr.h"
#include "interrupt.h"
#include "globals.h"
#include "validate.h"
#include "target-arch-os.h"
#ifdef LISP_FEATURE_X86
#include "genesis/static-symbols.h"
#include "genesis/fdefn.h"
#endif
#ifdef LISP_FEATURE_GENCGC
#include "gencgc-internal.h"
#endif
#ifdef LISP_FEATURE_SB_WTIMER
# include <port.h>
# include <time.h>
# include <errno.h>
#endif
os_vm_size_t os_vm_page_size=0;
void
os_init(char *argv[], char *envp[])
{
/*
* historically, this used sysconf to select the runtime page size
* per recent changes on other arches and discussion on sbcl-devel,
* however, this is not necessary -- the VM page size need not match
* the OS page size (and the default backend page size has been
* ramped up accordingly for efficiency reasons).
*/
os_vm_page_size = BACKEND_PAGE_BYTES;
}
os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
{
int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANON;
if (addr)
flags |= MAP_FIXED;
addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
if (addr == MAP_FAILED) {
perror("mmap");
/* While it is generally hard to recover from out-of-memory
* situations, we require callers to decide on the right course
* of action here. Consider thread creation: Failure to mmap
* here is common if users have started too many threads, and
* often we can recover from that and treat it as an ordinary
* error. */
return 0;
}
return addr;
}
void os_invalidate(os_vm_address_t addr, os_vm_size_t len)
{
if(munmap((void*) addr, len) == -1)
perror("munmap");
}
os_vm_address_t
os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
{
addr = mmap(addr, len,
OS_VM_PROT_ALL,
MAP_PRIVATE | MAP_FIXED,
fd, (off_t) offset);
if (addr == MAP_FAILED) {
perror("mmap");
lose("Unexpedted mmap(..) failure\n");
}
return addr;
}
void
os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
{
if(mprotect((void*)address, length, prot) == -1) {
perror("mprotect");
}
}
static boolean in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
{
char* beg = (char*) sbeg;
char* end = (char*) sbeg + slen;
char* adr = (char*) a;
return (adr >= beg && adr < end);
}
boolean is_valid_lisp_addr(os_vm_address_t addr)
{
/* Old CMUCL comment:
Just assume address is valid if it lies within one of the known
spaces. (Unlike sunos-os which keeps track of every valid page.) */
/* FIXME: this looks like a valid definition for all targets with
cheney-gc; it may not be impressively smart (witness the
comment above) but maybe associating these functions with the
GC rather than the OS would be a maintainability win. -- CSR,
2003-04-04 */
struct thread *th;
if(in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE) ||
in_range_p(addr, STATIC_SPACE_START , STATIC_SPACE_SIZE) ||
#ifdef LISP_FEATURE_GENCGC
in_range_p(addr, DYNAMIC_SPACE_START , dynamic_space_size)
#else
in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size) ||
in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
#endif
)
return 1;
for_each_thread(th) {
if((th->control_stack_start <= addr) && (addr < th->control_stack_end))
return 1;
if(in_range_p(addr, th->binding_stack_start, BINDING_STACK_SIZE))
return 1;
}
return 0;
}
#if defined LISP_FEATURE_GENCGC
void
sigsegv_handler(int signal, siginfo_t *info, os_context_t *context)
{
void* fault_addr = (void*)info->si_addr;
#ifdef LISP_FEATURE_SB_SAFEPOINT
if (handle_safepoint_violation(context, fault_addr))
return;
#endif
if (!gencgc_handle_wp_violation(fault_addr))
if(!handle_guard_page_triggered(context, fault_addr))
lisp_memory_fault_error(context, fault_addr);
}
#else
static void
sigsegv_handler(int signal, siginfo_t *info, os_context_t *context)
{
os_vm_address_t addr = arch_get_bad_addr(signal, info, context);
if (!cheneygc_handle_wp_violation(context, addr)) {
if (!handle_guard_page_triggered(context,addr))
lisp_memory_fault_error(context, addr);
}
}
#endif
void
os_install_interrupt_handlers()
{
undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT,
sigsegv_handler);
/* OAOOM c.f. linux-os.c.
* Should we have a reusable function gc_install_interrupt_handlers? */
#ifdef LISP_FEATURE_SB_THREAD
# ifdef LISP_FEATURE_SB_SAFEPOINT
# ifdef LISP_FEATURE_SB_THRUPTION
undoably_install_low_level_interrupt_handler(SIGPIPE, thruption_handler);
# endif
# else
undoably_install_low_level_interrupt_handler(SIG_STOP_FOR_GC,
sig_stop_for_gc_handler);
# endif
#endif
}
char *
os_get_runtime_executable_path(int external)
{
char path[] = "/proc/self/object/a.out";
if (external || access(path, R_OK) == -1)
return NULL;
return copied_string(path);
}
#ifdef LISP_FEATURE_SB_WTIMER
/*
* Waitable timer implementation for the safepoint-based (SIGALRM-free)
* timer facility using SunOS completion ports.
*/
struct os_wtimer {
int port;
int timer;
};
struct os_wtimer *
os_create_wtimer()
{
int port = port_create();
if (port == -1) {
perror("port_create");
lose("os_create_wtimer");
}
port_notify_t pn;
pn.portnfy_port = port;
pn.portnfy_user = 0;
struct sigevent ev;
memset(&ev, 0, sizeof(ev));
ev.sigev_notify = SIGEV_PORT;
ev.sigev_value.sival_ptr = &pn;
timer_t timer;
if (timer_create(CLOCK_HIGHRES, &ev, &timer) == -1
&& (errno != EPERM || timer_create(CLOCK_REALTIME, &ev, &timer) == -1))
{
perror("timer_create");
lose("os_create_wtimer");
}
struct os_wtimer *wt = malloc(sizeof(struct os_wtimer));
if (!wt)
lose("os_create_wtimer: malloc");
wt->port = port;
wt->timer = timer;
return wt;
}
int
os_wait_for_wtimer(struct os_wtimer *wt)
{
port_event_t pe;
if (port_get(wt->port, &pe, 0) == -1) {
if (errno == EINTR)
return 1;
perror("port_get");
lose("os_wtimer_listen failed");
}
return 0;
}
void
os_close_wtimer(struct os_wtimer *wt)
{
if (close(wt->port) == -1) {
perror("close");
lose("os_close_wtimer");
}
if (timer_delete(wt->timer) == -1) {
perror("timer_delete");
lose("os_close_wtimer");
}
free(wt);
}
void
os_set_wtimer(struct os_wtimer *wt, int sec, int nsec)
{
struct itimerspec spec;
spec.it_value.tv_sec = sec;
spec.it_value.tv_nsec = nsec;
spec.it_interval.tv_sec = 0;
spec.it_interval.tv_nsec = 0;
if (timer_settime(wt->timer, 0, &spec, 0) == -1) {
int x = errno;
perror("timer_settime");
if (x != EINVAL)
lose("os_set_wtimer");
}
}
void
os_cancel_wtimer(struct os_wtimer *wt)
{
os_set_wtimer(wt, 0, 0);
}
#endif