/[cmucl]/src/lisp/sunos-os.c
ViewVC logotype

Contents of /src/lisp/sunos-os.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6.12.1 - (show annotations)
Wed Sep 3 11:32:05 2003 UTC (10 years, 7 months ago) by gerd
Branch: lisp-executable
Changes since 1.6: +1 -2 lines
File MIME type: text/plain
Fred Gilham's Lisp executable support for CMUCL.
1 /*
2 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/sunos-os.c,v 1.6.12.1 2003/09/03 11:32:05 gerd Exp $
3 *
4 * OS-dependent routines. This file (along with os.h) exports an
5 * OS-independent interface to the operating system VM facilities.
6 * Suprisingly, this interface looks a lot like the Mach interface
7 * (but simpler in some places). For some operating systems, a subset
8 * of these functions will have to be emulated.
9 *
10 * This is the SunOS version.
11 * March 1991, Miles Bader <miles@cogsci.ed.ack.uk> & ted <ted@edu.NMSU>
12 *
13 */
14
15 /* #define DEBUG */
16
17 #include <stdio.h>
18
19 #include <signal.h>
20 #include <sys/file.h>
21
22 #ifdef SOLARIS
23 #include <errno.h>
24 #include <sys/param.h>
25 #define OS_PROTERR SEGV_ACCERR
26 #define OS_MAPERR SEGV_MAPERR
27 #define OS_HASERRNO(code) ((code)->si_errno != 0)
28 #define OS_ERRNO(code) ((code)->si_errno)
29 #else
30 #define OS_PROTERR SEGV_PROT
31 #define OS_MAPERR SEGV_NOMAP
32 #define OS_HASERRNO(code) (SEGV_CODE(code)==SEGV_OBJERR)
33 #define OS_ERRNO(code) SEGV_ERRNO(code)
34 extern int errno;
35 #endif /* SOLARIS */
36
37 #include "os.h"
38 /* To get dynamic_0_space and friends */
39 #include "globals.h"
40 /* To get memory map */
41 #include "sparc-validate.h"
42
43 /* block size must be larger than the system page size */
44 #define SPARSE_BLOCK_SIZE (1<<15)
45 #define SPARSE_SIZE_MASK (SPARSE_BLOCK_SIZE-1)
46
47 #define PROT_DEFAULT OS_VM_PROT_ALL
48
49 #define OFFSET_NONE ((os_vm_offset_t)(~0))
50
51 #define EMPTYFILE "/tmp/empty"
52 #define ZEROFILE "/dev/zero"
53
54 #define INITIAL_MAX_SEGS 32
55 #define GROW_MAX_SEGS 16
56
57 extern char *getenv();
58
59 /* ---------------------------------------------------------------- */
60
61 #define ADJ_OFFSET(off,adj) (((off)==OFFSET_NONE) ? OFFSET_NONE : ((off)+(adj)))
62
63 long os_vm_page_size=(-1);
64 static long os_real_page_size=(-1);
65
66 static struct segment {
67 os_vm_address_t start; /* note: start & length are expected to be on page */
68 os_vm_size_t length; /* boundaries */
69 long file_offset;
70 short mapped_fd;
71 short protection;
72 } *segments;
73
74 static int n_segments=0, max_segments=0;
75
76 static int zero_fd=(-1), empty_fd=(-1);
77
78 static os_vm_address_t last_fault=0;
79 static os_vm_size_t real_page_size_difference=0;
80
81 static void os_init_bailout(arg)
82 char *arg;
83 {
84 char buf[500];
85 sprintf(buf,"os_init: %s",arg);
86 perror(buf);
87 exit(1);
88 }
89
90 void os_init()
91 {
92 char *empty_file=getenv("CMUCL_EMPTYFILE");
93
94 if(empty_file==NULL)
95 empty_file=EMPTYFILE;
96
97 empty_fd=open(empty_file,O_RDONLY|O_CREAT);
98 if(empty_fd<0)
99 os_init_bailout(empty_file);
100 unlink(empty_file);
101
102 zero_fd=open(ZEROFILE,O_RDONLY);
103 if(zero_fd<0)
104 os_init_bailout(ZEROFILE);
105
106
107 #ifdef SOLARIS
108 os_vm_page_size = os_real_page_size = sysconf(_SC_PAGESIZE);
109 #else
110 os_vm_page_size = os_real_page_size = getpagesize();
111 #endif
112
113 max_segments=INITIAL_MAX_SEGS;
114 segments=(struct segment *)malloc(sizeof(struct segment)*max_segments);
115 if(segments==NULL){
116 fprintf(stderr,"os_init: Couldn't allocate %d segment descriptors\n",
117 max_segments);
118 exit(1);
119 }
120
121 if(os_vm_page_size>OS_VM_DEFAULT_PAGESIZE){
122 fprintf(stderr,"os_init: Pagesize too large (%d > %d)\n",
123 os_vm_page_size,OS_VM_DEFAULT_PAGESIZE);
124 exit(1);
125 }else{
126 /*
127 * we do this because there are apparently dependencies on
128 * the pagesize being OS_VM_DEFAULT_PAGESIZE somewhere...
129 * but since the OS doesn't know we're using this restriction,
130 * we have to grovel around a bit to enforce it, thus anything
131 * that uses real_page_size_difference.
132 */
133 real_page_size_difference=OS_VM_DEFAULT_PAGESIZE-os_vm_page_size;
134 os_vm_page_size=OS_VM_DEFAULT_PAGESIZE;
135 }
136 }
137
138 /* ---------------------------------------------------------------- */
139
140 void seg_force_resident(struct segment *seg,
141 os_vm_address_t addr,
142 os_vm_size_t len)
143 {
144 int prot=seg->protection;
145
146 if(prot!=0){
147 os_vm_address_t end=addr+len, touch=addr;
148
149 while(touch<end){
150 int contents=(*(char *)touch);
151 if(prot&OS_VM_PROT_WRITE)
152 (*(char *)touch)=contents;
153 touch=(os_vm_address_t)(((long)touch+SPARSE_BLOCK_SIZE)&~SPARSE_SIZE_MASK);
154 }
155 }
156 }
157
158 static struct segment *seg_create_nomerge(addr,len,protection,mapped_fd,file_offset)
159 os_vm_address_t addr;
160 os_vm_size_t len;
161 int protection;
162 int mapped_fd;
163 {
164 int n;
165 struct segment *seg;
166
167 if(len==0)
168 return NULL;
169
170 if(n_segments==max_segments){
171 struct segment *new_segs;
172
173 max_segments+=GROW_MAX_SEGS;
174
175 new_segs=(struct segment *)
176 realloc(segments,max_segments*sizeof(struct segment));
177
178 if(new_segs==NULL){
179 fprintf(stderr,
180 "seg_create_nomerge: Couldn't grow segment descriptor table to %s segments\n",
181 max_segments);
182 max_segments-=GROW_MAX_SEGS;
183 return NULL;
184 }
185
186 segments=new_segs;
187 }
188
189 for(n=n_segments, seg=segments; n>0; n--, seg++)
190 if(addr<seg->start){
191 seg=(&segments[n_segments]);
192 while(n-->0){
193 seg[0]=seg[-1];
194 seg--;
195 }
196 break;
197 }
198
199 n_segments++;
200
201 seg->start=addr;
202 seg->length=len;
203 seg->protection=protection;
204 seg->mapped_fd=mapped_fd;
205 seg->file_offset=file_offset;
206
207 return seg;
208 }
209
210 #if 1
211 /* returns the first segment containing addr */
212 static struct segment *seg_find(addr)
213 os_vm_address_t addr;
214 {
215 int n;
216 struct segment *seg;
217
218 for(n=n_segments, seg=segments; n>0; n--, seg++)
219 if(seg->start<=addr && seg->start+seg->length>addr)
220 return seg;
221
222 return NULL;
223 }
224 #else
225 /* returns the first segment containing addr */
226 static struct segment *seg_find(addr)
227 os_vm_address_t addr;
228 {
229 /* does a binary search */
230 struct segment *lo=segments, *hi=segments+n_segments;
231
232 while(hi>lo){
233 struct segment *mid=lo+((hi-lo)>>1);
234 os_vm_address_t start=mid->start;
235
236 if(addr>=start && addr<start+mid->length)
237 return mid;
238 else if(addr<start)
239 hi=mid;
240 else
241 lo=mid+1;
242 }
243
244 return NULL;
245 }
246 #endif
247
248 /* returns TRUE if the range from addr to addr+len intersects with any segment */
249 static boolean collides_with_seg_p(addr,len)
250 os_vm_address_t addr;
251 os_vm_size_t len;
252 {
253 int n;
254 struct segment *seg;
255 os_vm_address_t end=addr+len;
256
257 for(n=n_segments, seg=segments; n>0; n--, seg++)
258 if(seg->start>=end)
259 return FALSE;
260 else if(seg->start+seg->length>addr)
261 return TRUE;
262
263 return FALSE;
264 }
265
266 #if 0 /* WAY to SLOW */
267 /* returns TRUE if the range from addr to addr+len is a valid mapping
268 * (that we don't know about) */
269 static boolean mem_in_use(addr,len)
270 os_vm_address_t addr;
271 os_vm_size_t len;
272 {
273 os_vm_address_t p;
274
275 for (p = addr; addr < addr + len; p += os_real_page_size) {
276 char c;
277
278 if (mincore((caddr_t)p, os_real_page_size, &c) == 0 || errno != ENOMEM)
279 return TRUE;
280 }
281 return FALSE;
282 }
283 #endif
284
285 #define seg_last_p(seg) (((seg)-segments)>=n_segments-1)
286
287 static void seg_destroy(seg)
288 struct segment *seg;
289 {
290 if(seg!=NULL){
291 int n;
292
293 for(n=seg-segments+1; n<n_segments; n++){
294 seg[0]=seg[1];
295 seg++;
296 }
297
298 n_segments--;
299 }
300 }
301
302 static void seg_try_merge_next(seg)
303 struct segment *seg;
304 {
305 struct segment *nseg=seg+1;
306
307 if(!seg_last_p(seg)
308 && seg->start+seg->length==nseg->start
309 && seg->protection==nseg->protection
310 && seg->mapped_fd==nseg->mapped_fd
311 && ADJ_OFFSET(seg->file_offset,seg->length)==nseg->file_offset)
312 {
313 /* can merge with the next segment */
314 #ifdef DEBUG
315 fprintf(stderr,
316 ";;; seg_try_merge: Merged 0x%08x[0x%08x] with 0x%08x[0x%08x]\n",
317 seg->start,seg->length,nseg->start,nseg->length);
318 #endif
319
320 if(((long)nseg->start&SPARSE_SIZE_MASK)!=0){
321 /*
322 * if not on a block boundary, we have to ensure both parts
323 * of a common block are in a known state
324 */
325 seg_force_resident(seg,nseg->start-1,1);
326 seg_force_resident(nseg,nseg->start,1);
327 }
328
329 seg->length+=nseg->length;
330 seg_destroy(nseg);
331 }
332 }
333
334
335 /*
336 * Try to merge seg with adjacent segments.
337 */
338 static void seg_try_merge_adjacent(seg)
339 struct segment *seg;
340 {
341 if(!seg_last_p(seg))
342 seg_try_merge_next(seg);
343 if(seg>segments)
344 seg_try_merge_next(seg-1);
345 }
346
347 static struct segment *seg_create(addr,len,protection,mapped_fd,file_offset)
348 os_vm_address_t addr;
349 os_vm_size_t len;
350 int protection;
351 int mapped_fd;
352 {
353 struct segment *seg=seg_create_nomerge(addr,len,protection,mapped_fd,file_offset);
354 if(seg!=NULL)
355 seg_try_merge_adjacent(seg);
356 return seg;
357 }
358
359 /*
360 * Change the attributes of the given range of an existing segment, and return
361 * a segment corresponding to the new bit.
362 */
363 static struct segment *seg_change_range(seg,addr,len,protection,mapped_fd,file_offset)
364 struct segment *seg;
365 os_vm_address_t addr;
366 os_vm_size_t len;
367 int protection;
368 int mapped_fd;
369 {
370 os_vm_address_t end=addr+len;
371
372 if(len==0)
373 return NULL;
374
375 if(protection!=seg->protection
376 || mapped_fd!=seg->mapped_fd
377 || file_offset!=ADJ_OFFSET(seg->file_offset,addr-seg->start))
378 {
379 os_vm_size_t old_len=seg->length, seg_offset=(addr-seg->start);
380
381 if(old_len<len+seg_offset){
382 struct segment *next=seg+1;
383
384 #ifdef DEBUG
385 fprintf(stderr,
386 ";;; seg_change_range: region 0x%08x[0x%08x] overflows 0x%08x[0x%08x]\n",
387 addr,len,
388 seg->start,old_len);
389 #endif
390
391 while(!seg_last_p(seg) && next->start+next->length<=end){
392 #ifdef DEBUG
393 fprintf(stderr,
394 ";;; seg_change_range: merging extra segment 0x%08x[0x%08x]\n",
395 next->start,
396 next->length);
397 #endif
398 seg_destroy(next);
399 }
400
401 if(!seg_last_p(seg) && next->start<end){
402 next->length-=end-next->start;
403 next->start=end;
404 old_len=next->start-seg->start;
405 }else
406 old_len=len+seg_offset;
407
408 #ifdef DEBUG
409 fprintf(stderr,
410 ";;; seg_change_range: extended first seg to 0x%08x[0x%08x]\n",
411 seg->start,
412 old_len);
413 #endif
414 }
415
416 if(seg_offset+len<old_len){
417 /* add second part of old segment */
418 seg_create_nomerge(end,
419 old_len-(seg_offset+len),
420 seg->protection,
421 seg->mapped_fd,
422 ADJ_OFFSET(seg->file_offset,seg_offset+len));
423
424 #ifdef DEBUG
425 fprintf(stderr,
426 ";;; seg_change_range: Split off end of 0x%08x[0x%08x]: 0x%08x[0x%08x]\n",
427 seg->start,old_len,
428 end,old_len-(seg_offset+len));
429 #endif
430 }
431
432 if(seg_offset==0){
433 seg->length=len;
434 seg->protection=protection;
435 seg->mapped_fd=mapped_fd;
436 seg->file_offset=file_offset;
437 }else{
438 /* adjust first part of remaining old segment */
439 seg->length=seg_offset;
440
441 #ifdef DEBUG
442 fprintf(stderr,
443 ";;; seg_change_range: Split off beginning of 0x%08x[0x%08x]: 0x%08x[0x%08x]\n",
444 seg->start,old_len,
445 seg->start,seg_offset);
446 #endif
447
448 /* add new middle segment for new protected region */
449 seg=seg_create_nomerge(addr,len,protection,mapped_fd,file_offset);
450 }
451
452 seg_try_merge_adjacent(seg);
453
454 last_fault=0;
455 }
456
457 return seg;
458 }
459
460 /* ---------------------------------------------------------------- */
461
462 static os_vm_address_t mapin(addr,len,protection,map_fd,offset,is_readable)
463 os_vm_address_t addr;
464 os_vm_size_t len;
465 int protection;
466 int map_fd;
467 long offset;
468 int is_readable;
469 {
470 os_vm_address_t real;
471 boolean sparse=(len>=SPARSE_BLOCK_SIZE);
472
473 if(offset!=OFFSET_NONE
474 && (offset<os_vm_page_size || (offset&(os_vm_page_size-1))!=0))
475 {
476 fprintf(stderr,
477 "mapin: file offset (%d) not multiple of pagesize (%d)\n",
478 offset,
479 os_vm_page_size);
480 }
481
482 if(addr==NULL)
483 len+=real_page_size_difference; /* futz around to get an aligned region */
484
485 last_fault=0;
486 real=(os_vm_address_t)
487 mmap((caddr_t)addr,
488 (long)len,
489 sparse ? (is_readable ? PROT_READ|PROT_EXEC : 0) : protection,
490 (addr==NULL? 0 : MAP_FIXED)|MAP_PRIVATE,
491 (is_readable || !sparse) ? map_fd : empty_fd,
492 (off_t)(offset==OFFSET_NONE ? 0 : offset));
493
494 if((long)real==-1){
495 perror("mapin: mmap");
496 return NULL;
497 }
498
499 if(addr==NULL){
500 /*
501 * now play around with what the os gave us to make it align by
502 * our standards (which is why we overallocated)
503 */
504 os_vm_size_t overflow;
505
506 addr=os_round_up_to_page(real);
507 if(addr!=real)
508 munmap((caddr_t)real,addr-real);
509
510 overflow=real_page_size_difference-(addr-real);
511 if(overflow!=0)
512 munmap((caddr_t)(addr+len-real_page_size_difference),overflow);
513
514 real=addr;
515 }
516
517
518 return real;
519 }
520
521 static os_vm_address_t map_and_remember(addr,len,protection,map_fd,offset,is_readable)
522 os_vm_address_t addr;
523 os_vm_size_t len;
524 int protection;
525 int map_fd;
526 long offset;
527 int is_readable;
528 {
529 os_vm_address_t real=mapin(addr,len,protection,map_fd,offset,is_readable);
530
531 if(real!=NULL){
532 struct segment *seg=seg_find(real);
533
534 if(seg!=NULL)
535 seg=seg_change_range(seg,real,len,protection,map_fd,offset);
536 else
537 seg=seg_create(real,len,protection,map_fd,offset);
538
539 if(seg==NULL){
540 munmap((caddr_t)real,len);
541 return NULL;
542 }
543 }
544
545 #ifdef DEBUG
546 fprintf(stderr,";;; map_and_remember: 0x%08x[0x%08x] offset: %d, mapped to: %d\n",
547 real,len,offset,map_fd);
548 #endif
549
550 return real;
551 }
552
553 /* ---------------------------------------------------------------- */
554
555 os_vm_address_t os_validate(addr, len)
556 os_vm_address_t addr;
557 os_vm_size_t len;
558 {
559 addr=os_trunc_to_page(addr);
560 len=os_round_up_size_to_page(len);
561
562 #ifdef DEBUG
563 fprintf(stderr, ";;; os_validate: 0x%08x[0x%08x]\n",addr,len);
564 #endif
565
566 if(addr!=NULL && collides_with_seg_p(addr,len))
567 return NULL;
568
569 return map_and_remember(addr,len,PROT_DEFAULT,zero_fd,OFFSET_NONE,FALSE);
570 }
571
572 void os_invalidate(addr, len)
573 os_vm_address_t addr;
574 os_vm_size_t len;
575 {
576 struct segment *seg=seg_find(addr);
577
578 addr=os_trunc_to_page(addr);
579 len=os_round_up_size_to_page(len);
580
581 #ifdef DEBUG
582 fprintf(stderr, ";;; os_invalidate: 0x%08x[0x%08x]\n",addr,len);
583 #endif
584
585 if(seg==NULL)
586 fprintf(stderr, "os_invalidate: Unknown segment: 0x%08x[0x%08x]\n",addr,len);
587 else{
588 seg=seg_change_range(seg,addr,len,0,0,OFFSET_NONE);
589 if(seg!=NULL)
590 seg_destroy(seg);
591
592 last_fault=0;
593 if(munmap((caddr_t)addr,len)!=0)
594 perror("os_invalidate: munmap");
595 }
596 }
597
598 os_vm_address_t os_map(fd, offset, addr, len)
599 int fd;
600 int offset;
601 os_vm_address_t addr;
602 long len;
603 {
604 addr=os_trunc_to_page(addr);
605 len=os_round_up_size_to_page(len);
606
607 #ifdef DEBUG
608 fprintf(stderr, ";;; os_map: 0x%08x[0x%08x]\n",addr,len);
609 #endif
610
611 return map_and_remember(addr,len,PROT_DEFAULT,fd,offset,TRUE);
612 }
613
614 void os_flush_icache(address, length)
615 os_vm_address_t address;
616 os_vm_size_t length;
617 {
618 #if defined(MACH) && defined(mips)
619 vm_machine_attribute_val_t flush;
620 kern_return_t kr;
621
622 flush = MATTR_VAL_ICACHE_FLUSH;
623
624 kr = vm_machine_attribute(task_self(), address, length,
625 MATTR_CACHE, &flush);
626 if (kr != KERN_SUCCESS)
627 mach_error("Could not flush the instruction cache", kr);
628 #endif
629 #ifdef SOLARIS /* also SunOS ?? */
630 static int flushit = -1;
631 /*
632 * On some systems, iflush needs to be emulated in the kernel
633 * On those systems, it isn't necessary
634 * Call getenv() only once.
635 */
636 if (flushit == -1)
637 flushit = getenv("CMUCL_NO_SPARC_IFLUSH") == 0;
638
639 if (flushit) {
640 static int traceit = -1;
641 if (traceit == -1)
642 traceit = getenv("CMUCL_TRACE_SPARC_IFLUSH") != 0;
643
644 if (traceit)
645 fprintf(stderr,";;;iflush %p - %x\n", address,length);
646 flush_icache(address,length);
647 }
648 #endif
649 }
650
651 void os_protect(addr, len, prot)
652 os_vm_address_t addr;
653 os_vm_size_t len;
654 int prot;
655 {
656 struct segment *seg=seg_find(addr);
657
658 addr=os_trunc_to_page(addr);
659 len=os_round_up_size_to_page(len);
660
661 #ifdef DEBUG
662 fprintf(stderr,";;; os_protect: 0x%08x[0x%08x]\n",addr,len);
663 #endif
664
665 if(seg!=NULL){
666 int old_prot=seg->protection;
667
668 if(prot!=old_prot){
669 /*
670 * oooooh, sick: we have to make sure all the pages being protected have
671 * faulted in, so they're in a known state...
672 */
673 seg_force_resident(seg,addr,len);
674
675 seg_change_range(seg,addr,len,prot,seg->mapped_fd,seg->file_offset);
676
677 if(mprotect((caddr_t)addr,(long)len,prot)!=0)
678 perror("os_unprotect: mprotect");
679 }
680 }else
681 fprintf(stderr,"os_protect: Unknown segment: 0x%08x[0x%08x]\n",addr,len);
682 }
683
684 boolean valid_addr(test)
685 os_vm_address_t test;
686 {
687 return seg_find(test)!=NULL;
688 }
689
690 /* ---------------------------------------------------------------- */
691
692 static boolean maybe_gc(HANDLER_ARGS)
693 {
694 /*
695 * It's necessary to enable recursive SEGVs, since the handle is
696 * used for multiple things (e.g., both gc-trigger & faulting in pages).
697 * We check against recursive gc's though...
698 */
699
700 boolean did_gc;
701 static already_trying=0;
702
703 if(already_trying)
704 return FALSE;
705
706 SAVE_CONTEXT();
707
708 #ifdef POSIX_SIGS
709 sigprocmask(SIG_SETMASK, &context->uc_sigmask,0);
710 #else
711 sigsetmask(context->sc_mask);
712 #endif
713
714 already_trying=TRUE;
715 did_gc=interrupt_maybe_gc(signal, code, context);
716 already_trying=FALSE;
717
718 return did_gc;
719 }
720
721 /*
722 * The primary point of catching segmentation violations is to allow
723 * read only memory to be re-mapped with more permissions when a write
724 * is attempted. this greatly decreases the residency of the program
725 * in swap space since read only areas don't take up room
726 *
727 * Running into the gc trigger page will also end up here...
728 */
729 #ifndef SOLARIS
730 void segv_handler(HANDLER_ARGS, caddr_t addr)
731 #else
732 void segv_handler(HANDLER_ARGS)
733 #endif /* SOLARIS */
734 {
735 #ifdef SOLARIS
736 caddr_t addr = code->si_addr;
737 #endif
738
739 SAVE_CONTEXT();
740
741 if (CODE(code) == OS_PROTERR) { /* allow writes to this chunk */
742 struct segment *seg=seg_find(addr);
743
744 if((caddr_t)last_fault==addr){
745 if(seg!=NULL && maybe_gc(signal, code, context))
746 /* we just garbage collected */
747 return;
748 else{
749 /* a *real* protection fault */
750 fprintf(stderr,
751 "segv_handler: Real protection violation: 0x%08x\n",
752 addr);
753 interrupt_handle_now(signal,code,context);
754 }
755 }else
756 last_fault=(os_vm_address_t) addr;
757
758 if(seg!=NULL){
759 int err;
760 /* round down to a page */
761 os_vm_address_t block=(os_vm_address_t)((long)addr&~SPARSE_SIZE_MASK);
762 os_vm_size_t length=SPARSE_BLOCK_SIZE;
763
764 if(block < seg->start){
765 length-=(seg->start - block);
766 block=seg->start;
767 }
768 if(block+length > seg->start+seg->length)
769 length=seg->start+seg->length-block;
770
771 #if 0
772 /* unmap it. probably redundant. */
773 if(munmap((caddr_t)block,length) == -1)
774 perror("segv_handler: munmap");
775 #endif
776
777 /* and remap it with more permissions */
778 err=(int)
779 mmap((caddr_t)block,
780 length,
781 seg->protection,
782 MAP_PRIVATE|MAP_FIXED,
783 seg->mapped_fd,
784 seg->file_offset==OFFSET_NONE
785 ? 0
786 : seg->file_offset+(block-seg->start));
787
788 if (err == -1) {
789 perror("segv_handler: mmap");
790 interrupt_handle_now(signal,code,context);
791 }
792 }
793 else{
794 fprintf(stderr, "segv_handler: 0x%08x not in any segment\n",addr);
795 interrupt_handle_now(signal,code,context);
796 }
797 }
798 /*
799 * note that we check for a gc-trigger hit even if it's not a PROT error
800 */
801 else if(!maybe_gc(signal, code, context)){
802 static int nomap_count=0;
803
804 if(CODE(code)==OS_MAPERR){
805 if(nomap_count==0){
806 fprintf(stderr,
807 "segv_handler: No mapping fault: 0x%08x\n",addr);
808 nomap_count++;
809 }else{
810 /*
811 * There should be higher-level protection against stack
812 * overflow somewhere, but at least this prevents infinite
813 * puking of error messages...
814 */
815 fprintf(stderr,
816 "segv_handler: Recursive no mapping fault (stack overflow?)\n");
817 exit(-1);
818 }
819 } else if(OS_HASERRNO(code)) {
820 errno=OS_ERRNO(code);
821 perror("segv_handler: Object error");
822 }
823
824 interrupt_handle_now(signal,code,context);
825
826 if(CODE(code)==OS_MAPERR)
827 nomap_count--;
828 }
829 }
830
831 void os_install_interrupt_handlers()
832 {
833 interrupt_install_low_level_handler(SIGSEGV,segv_handler);
834 }
835
836
837 #ifdef SOLARIS
838
839
840 /* function defintions for register lvalues */
841
842 int * solaris_register_address(struct ucontext *context, int reg)
843 {
844 if (reg == 0) {
845 static int zero;
846
847 zero = 0;
848
849 return &zero;
850 } else if (reg < 16) {
851 return &context->uc_mcontext.gregs[reg+3];
852 } else if (reg < 32) {
853 int *sp = (int*) context->uc_mcontext.gregs[REG_SP];
854 return &sp[reg-16];
855 } else
856 return 0;
857 }
858 /* function defintions for backward compatibilty and static linking */
859
860 #if 0
861 void * dlopen(const char * file, int flag) { return 0; }
862 void * dlsym(void *obj, const char *sym) { return 0; }
863 int dlclose(void *obj) { return 0; }
864 char * dlerror(void) { return "no dynamic linking"; }
865 #endif
866
867 /* For now we put in some porting functions */
868
869 #ifndef SOLARIS25
870 int
871 getdtablesize(void)
872 {
873 return sysconf(_SC_OPEN_MAX);
874 }
875
876 char *
877 getwd(char *path)
878 {
879 return getcwd(path, MAXPATHLEN);
880 }
881
882 int
883 getpagesize(void)
884 {
885 return sysconf(_SC_PAGESIZE);
886 }
887
888
889 #include <sys/procfs.h>
890 /* Old rusage definition */
891 struct rusage {
892 struct timeval ru_utime; /* user time used */
893 struct timeval ru_stime; /* system time used */
894 long ru_maxrss;
895 #define ru_first ru_ixrss
896 long ru_ixrss; /* XXX: 0 */
897 long ru_idrss; /* XXX: sum of rm_asrss */
898 long ru_isrss; /* XXX: 0 */
899 long ru_minflt; /* any page faults not requiring I/O */
900 long ru_majflt; /* any page faults requiring I/O */
901 long ru_nswap; /* swaps */
902 long ru_inblock; /* block input operations */
903 long ru_oublock; /* block output operations */
904 long ru_msgsnd; /* messages sent */
905 long ru_msgrcv; /* messages received */
906 long ru_nsignals; /* signals received */
907 long ru_nvcsw; /* voluntary context switches */
908 long ru_nivcsw; /* involuntary " */
909 #define ru_last ru_nivcsw
910 };
911
912
913 int
914 getrusage(int who, struct rusage *rp)
915 {
916 memset(rp, 0, sizeof(struct rusage));
917 return 0;
918 }
919
920 int
921 setreuid()
922 {
923 fprintf(stderr,"setreuid unimplemented\n");
924 errno = ENOSYS;
925 return -1;
926 }
927
928 int
929 setregid()
930 {
931 fprintf(stderr,"setregid unimplemented\n");
932 errno = ENOSYS;
933 return -1;
934 }
935
936 int
937 gethostid()
938 {
939 fprintf(stderr,"gethostid unimplemented\n");
940 errno = ENOSYS;
941 return -1;
942 }
943
944 int
945 killpg(int pgrp, int sig)
946 {
947 if (pgrp < 0) {
948 errno = ESRCH;
949 return -1;
950 }
951 return kill(-pgrp, sig);
952 }
953 #endif
954
955 int
956 sigblock(int mask)
957 {
958 sigset_t old, new;
959
960 sigemptyset(&new);
961 new.__sigbits[0] = mask;
962
963 sigprocmask(SIG_BLOCK, &new, &old);
964
965 return old.__sigbits[0];
966 }
967
968 #ifndef SOLARIS25
969 int
970 wait3(int *status, int options, struct rusage *rp)
971 {
972 if (rp)
973 memset(rp, 0, sizeof(struct rusage));
974 return waitpid(-1, status, options);
975 }
976 #endif
977
978 int
979 sigsetmask(int mask)
980 {
981 sigset_t old, new;
982
983 sigemptyset(&new);
984 new.__sigbits[0] = mask;
985
986 sigprocmask(SIG_SETMASK, &new, &old);
987
988 return old.__sigbits[0];
989
990 }
991
992 #endif /* SOLARIS */
993
994 os_vm_address_t
995 round_up_sparse_size(os_vm_address_t addr)
996 {
997 return (addr + SPARSE_BLOCK_SIZE - 1) & ~SPARSE_SIZE_MASK;
998 }
999
1000 /*
1001 * An array of the start of the spaces which should have holes placed
1002 * after them. Must not include the dynamic spaces because the size
1003 * of the dynamic space can be controlled from the command line.
1004 */
1005 static os_vm_address_t spaces[] =
1006 {
1007 READ_ONLY_SPACE_START, STATIC_SPACE_START,
1008 BINDING_STACK_START, CONTROL_STACK_START
1009 };
1010
1011 /*
1012
1013 * The corresponding array for the size of each space. Be sure that
1014 * the spaces and holes don't overlap! The sizes MUST be on
1015 * SPARSE_BLOCK_SIZE boundaries.
1016
1017 */
1018 static unsigned long space_size[] =
1019 {
1020 READ_ONLY_SPACE_SIZE, STATIC_SPACE_SIZE,
1021 BINDING_STACK_SIZE, CONTROL_STACK_SIZE
1022 };
1023
1024 /*
1025 * The size of the hole to make. It should be strictly smaller than
1026 * SPARSE_BLOCK_SIZE.
1027 */
1028
1029 #define HOLE_SIZE 0x2000
1030
1031 void make_holes(void)
1032 {
1033 int k;
1034 os_vm_address_t hole;
1035
1036 /* Make holes of the appropriate size for desired spaces */
1037
1038 for (k = 0; k < sizeof(spaces)/sizeof(spaces[0]); ++k)
1039 {
1040
1041 hole = spaces[k] + space_size[k];
1042
1043 if (os_validate(hole, HOLE_SIZE) == NULL) {
1044 fprintf(stderr,
1045 "ensure_space: Failed to validate hole of %ld bytes at 0x%08X\n",
1046 HOLE_SIZE,
1047 (unsigned long)hole);
1048 exit(1);
1049 }
1050 /* Make it inaccessible */
1051 os_protect(hole, HOLE_SIZE, 0);
1052 }
1053
1054 /* Round up the dynamic_space_size to the nearest SPARSE_BLOCK_SIZE */
1055 dynamic_space_size = round_up_sparse_size(dynamic_space_size);
1056
1057 /* Now make a hole for the dynamic spaces */
1058 hole = dynamic_space_size + (os_vm_address_t) dynamic_0_space;
1059
1060 if (os_validate(hole, HOLE_SIZE) == NULL)
1061 {
1062 fprintf(stderr,
1063 "ensure_space: Failed to validate hold of %ld bytes at 0x%08X\n",
1064 HOLE_SIZE,
1065 (unsigned long)hole);
1066 exit(1);
1067 }
1068 os_protect(hole, HOLE_SIZE, 0);
1069
1070 hole = dynamic_space_size + (os_vm_address_t) dynamic_1_space;
1071 if (os_validate(hole, HOLE_SIZE) == NULL)
1072 {
1073 fprintf(stderr,
1074 "ensure_space: Failed to validate hole of %ld bytes at 0x%08X\n",
1075 HOLE_SIZE,
1076 (unsigned long)hole);
1077 exit(1);
1078 }
1079 os_protect(hole, HOLE_SIZE, 0);
1080 }
1081

  ViewVC Help
Powered by ViewVC 1.1.5