/[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.3 - (hide annotations)
Tue Oct 25 00:19:13 1994 UTC (19 years, 5 months ago) by ram
Branch: MAIN
Changes since 1.2: +234 -30 lines
File MIME type: text/plain
Solaris patches.
1 wlott 1.1 /*
2 ram 1.3 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/sunos-os.c,v 1.3 1994/10/25 00:19:13 ram Exp $
3 wlott 1.1 *
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 ram 1.3 #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 wlott 1.1 #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 ram 1.2 #define INITIAL_MAX_SEGS 32
52     #define GROW_MAX_SEGS 16
53 wlott 1.1
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 ram 1.3 static long os_real_page_size=(-1);
62 wlott 1.1
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 ram 1.2 } *segments;
70 wlott 1.1
71 ram 1.2 static int n_segments=0, max_segments=0;
72 wlott 1.1
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 ram 1.2 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 wlott 1.1 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 ram 1.2 if(empty_fd<0)
96     os_init_bailout(empty_file);
97 wlott 1.1 unlink(empty_file);
98    
99     zero_fd=open(ZEROFILE,O_RDONLY);
100 ram 1.2 if(zero_fd<0)
101     os_init_bailout(ZEROFILE);
102 wlott 1.1
103 ram 1.3
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 wlott 1.1
110 ram 1.2 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 wlott 1.1 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 ram 1.2 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 wlott 1.1 }
185    
186 ram 1.2 for(n=n_segments, seg=segments; n>0; n--, seg++)
187 wlott 1.1 if(addr<seg->start){
188 ram 1.2 seg=(&segments[n_segments]);
189 wlott 1.1 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 ram 1.2 #if 1
208 wlott 1.1 /* 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 ram 1.2 for(n=n_segments, seg=segments; n>0; n--, seg++)
216 wlott 1.1 if(seg->start<=addr && seg->start+seg->length>addr)
217     return seg;
218    
219     return NULL;
220     }
221 ram 1.2 #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 wlott 1.1
229 ram 1.2 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 wlott 1.1 /* 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 ram 1.2 for(n=n_segments, seg=segments; n>0; n--, seg++)
255 wlott 1.1 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 ram 1.3 #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 ram 1.2 #define seg_last_p(seg) (((seg)-segments)>=n_segments-1)
283 wlott 1.1
284     static void seg_destroy(seg)
285     struct segment *seg;
286     {
287     if(seg!=NULL){
288     int n;
289    
290 ram 1.2 for(n=seg-segments+1; n<n_segments; n++){
291 wlott 1.1 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 ram 1.2 if(seg>segments)
341 wlott 1.1 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 ram 1.3 munmap((caddr_t)real,addr-real);
506 wlott 1.1
507     overflow=real_page_size_difference-(addr-real);
508     if(overflow!=0)
509 ram 1.3 munmap((caddr_t)(addr+len-real_page_size_difference),overflow);
510 wlott 1.1
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 ram 1.3 munmap((caddr_t)real,len);
538 wlott 1.1 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 ram 1.3 if(munmap((caddr_t)addr,len)!=0)
591 wlott 1.1 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 ram 1.3 static boolean maybe_gc(HANDLER_ARGS)
670 wlott 1.1 {
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 ram 1.3 SAVE_CONTEXT();
684    
685     #ifdef POSIX_SIGS
686     sigprocmask(SIG_SETMASK, &context->uc_sigmask,0);
687     #else
688 wlott 1.1 sigsetmask(context->sc_mask);
689 ram 1.3 #endif
690 wlott 1.1
691     already_trying=TRUE;
692 ram 1.3 did_gc=interrupt_maybe_gc(signal, code, context);
693 wlott 1.1 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 ram 1.3 #ifndef SOLARIS
707     void segv_handler(HANDLER_ARGS, caddr_t addr)
708     #else
709     void segv_handler(HANDLER_ARGS)
710     #endif /* SOLARIS */
711 wlott 1.1 {
712 ram 1.3 #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 wlott 1.1 struct segment *seg=seg_find(addr);
720    
721 ram 1.3 if((caddr_t)last_fault==addr){
722     if(seg!=NULL && maybe_gc(signal, code, context))
723 wlott 1.1 /* 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 ram 1.3 interrupt_handle_now(signal,code,context);
731 wlott 1.1 }
732     }else
733 ram 1.3 last_fault=(os_vm_address_t) addr;
734 wlott 1.1
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 ram 1.3 if(munmap((caddr_t)block,length) == -1)
751 wlott 1.1 perror("segv_handler: munmap");
752     #endif
753    
754     /* and remap it with more permissions */
755     err=(int)
756 ram 1.3 mmap((caddr_t)block,
757 wlott 1.1 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 ram 1.3 interrupt_handle_now(signal,code,context);
768 wlott 1.1 }
769     }
770     else{
771     fprintf(stderr, "segv_handler: 0x%08x not in any segment\n",addr);
772 ram 1.3 interrupt_handle_now(signal,code,context);
773 wlott 1.1 }
774     }
775     /*
776     * note that we check for a gc-trigger hit even if it's not a PROT error
777     */
778 ram 1.3 else if(!maybe_gc(signal, code, context)){
779 wlott 1.1 static int nomap_count=0;
780    
781 ram 1.3 if(CODE(code)==OS_MAPERR){
782 wlott 1.1 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 ram 1.3 } else if(OS_HASERRNO(code)) {
797     errno=OS_ERRNO(code);
798 wlott 1.1 perror("segv_handler: Object error");
799     }
800    
801 ram 1.3 interrupt_handle_now(signal,code,context);
802 wlott 1.1
803 ram 1.3 if(CODE(code)==OS_MAPERR)
804 wlott 1.1 nomap_count--;
805     }
806     }
807    
808     void os_install_interrupt_handlers()
809     {
810     interrupt_install_low_level_handler(SIGSEGV,segv_handler);
811     }
812 ram 1.3
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