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

  ViewVC Help
Powered by ViewVC 1.1.5