~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to o/sgbc.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  Copyright William Schelter. All rights reserved.
 
2
    
 
3
    Stratified Garbage Collection  (SGC)
 
4
    
 
5
    Write protects pages to tell which ones have been written
 
6
    to recently, for more efficient garbage collection.
 
7
    
 
8
*/
 
9
 
 
10
static void
 
11
sgc_mark_object1(object);
 
12
 
 
13
static void
 
14
sgc_mprotect(long, long, int);
 
15
 
 
16
 
 
17
#ifdef BSD
 
18
/* ulong may have been defined in mp.h but the define is no longer needed */
 
19
#undef ulong
 
20
#include <sys/mman.h>
 
21
#define PROT_READ_WRITE_EXEC (PROT_READ | PROT_WRITE |PROT_EXEC)
 
22
#define PROT_READ_EXEC (PROT_READ|PROT_EXEC)
 
23
#endif
 
24
#ifdef AIX3
 
25
#include <sys/vmuser.h>
 
26
#define PROT_READ_EXEC RDONLY /*FIXME*/
 
27
#define  PROT_READ_WRITE_EXEC UDATAKEY
 
28
int mprotect();
 
29
#endif
 
30
 
 
31
#ifdef __MINGW32__
 
32
#include <windows.h>
 
33
#define PROT_READ_WRITE_EXEC PAGE_EXECUTE_READWRITE
 
34
#define PROT_READ_EXEC PAGE_READONLY /*FIXME*/
 
35
 
 
36
int gclmprotect ( void *addr, size_t len, int prot ) {
 
37
    int old, rv;
 
38
    rv = VirtualProtect ( (LPVOID) addr, len, prot, &old );
 
39
    if ( 0 == rv ) {
 
40
        fprintf ( stderr, "mprotect: VirtualProtect %x %d %d failed\n", addr, len, prot );
 
41
        rv = -1;
 
42
    } else {
 
43
        rv =0;
 
44
    }    
 
45
    return (rv);
 
46
}
 
47
/* Avoid clash with libgcc's mprotect */
 
48
#define mprotect gclmprotect
 
49
 
 
50
#endif
 
51
 
 
52
#if defined(DARWIN)
 
53
#include <sys/ucontext.h>
 
54
#endif
 
55
 
 
56
#include <signal.h>
 
57
 
 
58
/*  void segmentation_catcher(void); */
 
59
 
 
60
 
 
61
#define sgc_mark_pack_list(u)      \
 
62
do {register object xtmp = u;  \
 
63
 while (xtmp != Cnil) \
 
64
   {if (ON_WRITABLE_PAGE(xtmp)) xtmp->d.m = TRUE; \
 
65
     sgc_mark_object(xtmp->c.c_car); \
 
66
    xtmp=xtmp->c.c_cdr;}}while(0) 
 
67
 
 
68
 
 
69
#ifdef SDEBUG
 
70
object sdebug;
 
71
joe1(){;}
 
72
joe() {;}     
 
73
#endif
 
74
 
 
75
static void
 
76
sgc_mark_cons(object x) {
 
77
  
 
78
  cs_check(x);
 
79
  
 
80
  /*  x is already marked.  */
 
81
  
 
82
 BEGIN:
 
83
#ifdef SDEBUG
 
84
  if(x==sdebug) joe1();
 
85
#endif
 
86
  sgc_mark_object(x->c.c_car);
 
87
#ifdef OLD
 
88
  IF_WRITABLE(x->c.c_car, goto MARK_CAR;);
 
89
  goto MARK_CDR;
 
90
  
 
91
 MARK_CAR:
 
92
  if (x->c.c_car->c.m ==0) {
 
93
    if (type_of(x->c.c_car) == t_cons) {
 
94
      x->c.c_car->c.m = TRUE;
 
95
      sgc_mark_cons(x->c.c_car);
 
96
    } else
 
97
      sgc_mark_object1(x->c.c_car);}
 
98
 MARK_CDR:  
 
99
#endif
 
100
  x = x->c.c_cdr;
 
101
  IF_WRITABLE(x, goto WRITABLE_CDR;);
 
102
  return;
 
103
 WRITABLE_CDR:
 
104
  if (x->d.m) return;
 
105
  if (type_of(x) == t_cons) {
 
106
    x->c.m = TRUE;
 
107
    goto BEGIN;
 
108
  }
 
109
  sgc_mark_object1(x);
 
110
}
 
111
 
 
112
 
 
113
/* Whenever two arrays are linked together by displacement,
 
114
   if one is live, the other will be made live */
 
115
#define sgc_mark_displaced_field(ar) sgc_mark_object(ar->a.a_displaced)
 
116
 
 
117
 
 
118
/* structures and arrays of type t, need to be marked if their
 
119
   bodies are not write protected even if the headers are.
 
120
   So we should keep these on pages particular to them.
 
121
   Actually we will change structure sets to touch the structure
 
122
   header, that way we won't have to keep the headers in memory.
 
123
   This takes only 1.47 as opposed to 1.33 microseconds per set.
 
124
*/
 
125
static void
 
126
sgc_mark_object1(object x) {
 
127
 
 
128
  long i;
 
129
  int j;
 
130
  object *p;
 
131
  char *cp;
 
132
  
 
133
  cs_check(x);
 
134
 BEGIN:
 
135
#ifdef SDEBUG
 
136
  if (x == OBJNULL || !ON_WRITABLE_PAGE(x))
 
137
    return;
 
138
  IF_WRITABLE(x,goto OK);
 
139
  joe();
 
140
 OK:
 
141
#endif 
 
142
  if (x->d.m)
 
143
    return;
 
144
#ifdef SDEBUG
 
145
  if(x==sdebug) joe1();
 
146
#endif
 
147
  if (DBEGIN) 
 
148
    if (NULL_OR_ON_C_STACK(x))
 
149
      return;
 
150
  /* otherwise if DBEGIN==0 the IF_WRITABLE test will
 
151
     always fail on x that satisfy (NULL_OR_ON_C_STACK(x))
 
152
  */
 
153
  
 
154
  x->d.m = TRUE;
 
155
  switch (type_of(x)) {
 
156
  case t_fixnum:
 
157
    break;
 
158
    
 
159
  case t_ratio:
 
160
    sgc_mark_object(x->rat.rat_num);
 
161
    x = x->rat.rat_den;
 
162
    IF_WRITABLE(x,if(x->d.m==0) goto BEGIN);
 
163
    
 
164
  case t_shortfloat:
 
165
    break;
 
166
    
 
167
  case t_longfloat:
 
168
    break;
 
169
    
 
170
  case t_complex:
 
171
    sgc_mark_object(x->cmp.cmp_imag);
 
172
    x = x->cmp.cmp_real;
 
173
    IF_WRITABLE(x,if(x->d.m==0) goto BEGIN);
 
174
    
 
175
  case t_character:
 
176
    break;
 
177
    
 
178
  case t_symbol:
 
179
    IF_WRITABLE(x->s.s_plist,if(x->s.s_plist->d.m==0)
 
180
    {x->s.s_plist->d.m=TRUE;
 
181
    sgc_mark_cons(x->s.s_plist);});
 
182
    sgc_mark_object(x->s.s_gfdef);
 
183
    sgc_mark_object(x->s.s_dbind);
 
184
    if (x->s.s_self == NULL)
 
185
      break;
 
186
    /* to do */
 
187
    if ((int)what_to_collect >= (int)t_contiguous) {
 
188
      if (inheap(x->s.s_self)) {
 
189
        if (what_to_collect == t_contiguous)
 
190
          mark_contblock(x->s.s_self,
 
191
                         x->s.s_fillp);
 
192
      } else if(SGC_RELBLOCK_P(x->s.s_self))
 
193
        x->s.s_self =
 
194
          copy_relblock(x->s.s_self, x->s.s_fillp);
 
195
    }
 
196
    break;
 
197
    
 
198
  case t_package:
 
199
    sgc_mark_object(x->p.p_name);
 
200
    sgc_mark_object(x->p.p_nicknames);
 
201
    sgc_mark_object(x->p.p_shadowings);
 
202
    sgc_mark_object(x->p.p_uselist);
 
203
    sgc_mark_object(x->p.p_usedbylist);
 
204
    if (what_to_collect != t_contiguous)
 
205
      break;
 
206
    if (x->p.p_internal != NULL)
 
207
      mark_contblock((char *)(x->p.p_internal),
 
208
                     x->p.p_internal_size*sizeof(object));
 
209
    if (x->p.p_external != NULL)
 
210
      mark_contblock((char *)(x->p.p_external),
 
211
                     x->p.p_external_size*sizeof(object));
 
212
    break;
 
213
    
 
214
  case t_cons:
 
215
    /*
 
216
      sgc_mark_object(x->c.c_car);
 
217
      x = x->c.c_cdr;
 
218
      goto BEGIN;
 
219
    */
 
220
    sgc_mark_cons(x);
 
221
    break;
 
222
    
 
223
  case t_hashtable:
 
224
    sgc_mark_object(x->ht.ht_rhsize);
 
225
    sgc_mark_object(x->ht.ht_rhthresh);
 
226
    if (x->ht.ht_self == NULL)
 
227
      break;
 
228
    for (i = 0, j = x->ht.ht_size;  i < j;  i++) {
 
229
      sgc_mark_object(x->ht.ht_self[i].hte_key);
 
230
      sgc_mark_object(x->ht.ht_self[i].hte_value);
 
231
    }
 
232
    if ((short)what_to_collect >= (short)t_contiguous) {
 
233
      if (inheap(x->ht.ht_self)) {
 
234
        if (what_to_collect == t_contiguous)
 
235
          mark_contblock((char *)(x->ht.ht_self),
 
236
                         j * sizeof(struct htent));
 
237
      } else if(SGC_RELBLOCK_P(x->ht.ht_self))
 
238
        x->ht.ht_self = (struct htent *)
 
239
          copy_relblock((char *)(x->ht.ht_self),
 
240
                        j * sizeof(struct htent));
 
241
    }
 
242
    break;
 
243
    
 
244
  case t_array:
 
245
    if ((x->a.a_displaced) != Cnil)
 
246
      sgc_mark_displaced_field(x);
 
247
    if ((int)what_to_collect >= (int)t_contiguous &&
 
248
        x->a.a_dims != NULL) {
 
249
      if (inheap(x->a.a_dims)) {
 
250
        if (what_to_collect == t_contiguous)
 
251
          mark_contblock((char *)(x->a.a_dims),
 
252
                         sizeof(int)*x->a.a_rank);
 
253
      } else  if(SGC_RELBLOCK_P(x->a.a_dims))
 
254
        x->a.a_dims = (int *)
 
255
          copy_relblock((char *)(x->a.a_dims),
 
256
                        sizeof(int)*x->a.a_rank);
 
257
    }
 
258
    if ((enum aelttype)x->a.a_elttype == aet_ch)
 
259
      goto CASE_STRING;
 
260
    if ((enum aelttype)x->a.a_elttype == aet_bit)
 
261
      goto CASE_BITVECTOR;
 
262
    if ((enum aelttype)x->a.a_elttype == aet_object)
 
263
      goto CASE_GENERAL;
 
264
    
 
265
  CASE_SPECIAL:
 
266
    cp = (char *)(x->fixa.fixa_self);
 
267
    if (cp == NULL)
 
268
      break;
 
269
    /* set j to the size in char of the body of the array */
 
270
    
 
271
    switch((enum aelttype)x->a.a_elttype){
 
272
    case aet_lf:
 
273
      j= sizeof(longfloat)*x->lfa.lfa_dim;
 
274
      if (((int)what_to_collect >= (int)t_contiguous) &&
 
275
          !(inheap(cp)) && SGC_RELBLOCK_P(x->a.a_self))
 
276
        ROUND_RB_POINTERS_DOUBLE;
 
277
      break;
 
278
    case aet_char:
 
279
    case aet_uchar:
 
280
      j=sizeof(char)*x->a.a_dim;
 
281
      break;
 
282
    case aet_short:
 
283
    case aet_ushort:
 
284
      j=sizeof(short)*x->a.a_dim;
 
285
      break;
 
286
    default:
 
287
      j=sizeof(fixnum)*x->fixa.fixa_dim;}
 
288
    
 
289
    goto COPY;
 
290
    
 
291
  CASE_GENERAL:
 
292
    p = x->a.a_self;
 
293
    if (p == NULL
 
294
#ifdef HAVE_ALLOCA
 
295
        || (char *)p >= core_end
 
296
#endif  
 
297
        
 
298
        )
 
299
      break;
 
300
    j=0;
 
301
    if (x->a.a_displaced->c.c_car == Cnil)
 
302
      for (i = 0, j = x->a.a_dim;  i < j;  i++)
 
303
        if (ON_WRITABLE_PAGE(&p[i]))
 
304
          sgc_mark_object(p[i]);
 
305
    cp = (char *)p;
 
306
    j *= sizeof(object);
 
307
  COPY:
 
308
    if ((int)what_to_collect >= (int)t_contiguous) {
 
309
      if (inheap(cp)) {
 
310
        if (what_to_collect == t_contiguous)
 
311
          mark_contblock(cp, j);
 
312
      } else if (!SGC_RELBLOCK_P(cp)) 
 
313
        ;
 
314
      else if (x->a.a_displaced == Cnil) {
 
315
#ifdef HAVE_ALLOCA
 
316
        if (!NULL_OR_ON_C_STACK(cp))  /* only if body of array not on C stack */
 
317
#endif                    
 
318
          x->a.a_self = (object *)copy_relblock(cp, j);
 
319
      }
 
320
      else if (x->a.a_displaced->c.c_car == Cnil) {
 
321
        i = (long)(object *)copy_relblock(cp, j)
 
322
          - (long)(x->a.a_self);
 
323
        adjust_displaced(x, i);
 
324
      }
 
325
    }
 
326
    break;
 
327
    
 
328
  case t_vector:
 
329
    if ((x->v.v_displaced) != Cnil)
 
330
      sgc_mark_displaced_field(x);
 
331
    if ((enum aelttype)x->v.v_elttype == aet_object)
 
332
      goto CASE_GENERAL;
 
333
    else
 
334
      goto CASE_SPECIAL;
 
335
    
 
336
  case t_bignum:
 
337
#ifdef SDEBUG
 
338
    if (type_map[page(x->big.big_self)] < t_contiguous)
 
339
        printf("bad body for %x (%x)\n",x,cp);
 
340
#endif
 
341
#ifndef GMP
 
342
    if ((int)what_to_collect >= (int)t_contiguous) {
 
343
      j = x->big.big_length;
 
344
      cp = (char *)x->big.big_self;
 
345
      if (cp == NULL)
 
346
        break;
 
347
      if  (j != lg(MP(x))  &&
 
348
           /* we don't bother to zero this register,
 
349
              and its contents may get over written */
 
350
           ! (x ==  big_register_1 &&
 
351
              (int)(cp) <= top &&
 
352
              (int) cp >= bot))
 
353
        
 
354
        printf("bad length 0x%x ",x);
 
355
      j = j * sizeof(int);
 
356
      
 
357
      if (inheap(cp)) {
 
358
        if (what_to_collect == t_contiguous)
 
359
          mark_contblock(cp, j);
 
360
      } else {
 
361
        if (SGC_RELBLOCK_P(cp))
 
362
          x->big.big_self = (plong *)copy_relblock(cp, j);}}
 
363
#endif /* no gmp */
 
364
#ifndef GMP_USE_MALLOC
 
365
    if ((int)what_to_collect >= (int)t_contiguous) {
 
366
      j = MP_ALLOCATED(x);
 
367
      cp = (char *)MP_SELF(x);
 
368
      if (cp == 0)
 
369
        break;
 
370
#ifdef PARI
 
371
      if (j != lg(MP(x))  &&
 
372
          /* we don't bother to zero this register,
 
373
             and its contents may get over written */
 
374
          ! (x == big_register_1 &&
 
375
             (int)(cp) <= top &&
 
376
             (int) cp >= bot))
 
377
        printf("bad length 0x%x ",x);
 
378
#endif
 
379
      j = j * MP_LIMB_SIZE;
 
380
      if (inheap(cp)) {
 
381
        if (what_to_collect == t_contiguous)
 
382
          mark_contblock(cp, j);
 
383
      } else 
 
384
        if (SGC_RELBLOCK_P(cp))
 
385
          MP_SELF(x) = (void *) copy_relblock(cp, j);
 
386
    }
 
387
#endif /* not GMP_USE_MALLOC */
 
388
    break;
 
389
    
 
390
    
 
391
  CASE_STRING:
 
392
  case t_string:
 
393
    if ((x->st.st_displaced) != Cnil)
 
394
      sgc_mark_displaced_field(x);
 
395
    j = x->st.st_dim;
 
396
    cp = x->st.st_self;
 
397
    if (cp == NULL)
 
398
      break;
 
399
    
 
400
  COPY_STRING:
 
401
    if ((int)what_to_collect >= (int)t_contiguous) {
 
402
      if (inheap(cp)) {
 
403
        if (what_to_collect == t_contiguous)
 
404
          mark_contblock(cp, j);
 
405
      }
 
406
      else if (!SGC_RELBLOCK_P(cp)) ;
 
407
      else if (x->st.st_displaced == Cnil)
 
408
        x->st.st_self = copy_relblock(cp, j);
 
409
      else if (x->st.st_displaced->c.c_car == Cnil) {
 
410
        i = copy_relblock(cp, j) - cp;
 
411
        adjust_displaced(x, i);
 
412
      }
 
413
    }
 
414
    break;
 
415
    
 
416
  CASE_BITVECTOR:
 
417
  case t_bitvector:
 
418
    if ((x->bv.bv_displaced) != Cnil)
 
419
      sgc_mark_displaced_field(x);
 
420
    /* We make bitvectors multiple of sizeof(int) in size allocated
 
421
       Assume 8 = number of bits in char */
 
422
    
 
423
#define W_SIZE (8*sizeof(int))
 
424
    j= sizeof(int) *
 
425
      ((BV_OFFSET(x) + x->bv.bv_dim + W_SIZE -1)/W_SIZE);
 
426
    cp = x->bv.bv_self;
 
427
    if (cp == NULL)
 
428
      break;
 
429
    goto COPY_STRING;
 
430
    
 
431
  case t_structure:
 
432
    sgc_mark_object(x->str.str_def);
 
433
    p = x->str.str_self;
 
434
    if (p == NULL)
 
435
      break;
 
436
    {
 
437
      object def=x->str.str_def;
 
438
      unsigned char * s_type = &SLOT_TYPE(def,0);
 
439
      unsigned short *s_pos= & SLOT_POS(def,0);
 
440
      for (i = 0, j = S_DATA(def)->length;  i < j;  i++)
 
441
        if (s_type[i]==0 &&
 
442
            ON_WRITABLE_PAGE(& STREF(object,x,s_pos[i]))
 
443
            )
 
444
          sgc_mark_object(STREF(object,x,s_pos[i]));
 
445
      if ((int)what_to_collect >= (int)t_contiguous) {
 
446
        if (inheap(x->str.str_self)) {
 
447
          if (what_to_collect == t_contiguous)
 
448
            mark_contblock((char *)p,
 
449
                           S_DATA(def)->size);
 
450
          
 
451
        } else if(SGC_RELBLOCK_P(p))
 
452
          x->str.str_self = (object *)
 
453
            copy_relblock((char *)p, S_DATA(def)->size);
 
454
      }
 
455
    }
 
456
    break;
 
457
    
 
458
  case t_stream:
 
459
    switch (x->sm.sm_mode) {
 
460
    case smm_input:
 
461
    case smm_output:
 
462
    case smm_io:
 
463
    case smm_socket:  
 
464
    case smm_probe:
 
465
      sgc_mark_object(x->sm.sm_object0);
 
466
      sgc_mark_object(x->sm.sm_object1);
 
467
      if (saving_system) {
 
468
        FILE *fp = x->sm.sm_fp;
 
469
        if (fp != 0 && fp != stdin && fp !=stdout) {
 
470
          fclose(fp);
 
471
          x->sm.sm_fp=0;
 
472
        }
 
473
      }
 
474
      else
 
475
        if (what_to_collect == t_contiguous &&
 
476
            x->sm.sm_fp &&
 
477
            x->sm.sm_buffer)
 
478
          mark_contblock(x->sm.sm_buffer, BUFSIZ);
 
479
      break;
 
480
      
 
481
    case smm_synonym:
 
482
      sgc_mark_object(x->sm.sm_object0);
 
483
      break;
 
484
      
 
485
    case smm_broadcast:
 
486
    case smm_concatenated:
 
487
      sgc_mark_object(x->sm.sm_object0);
 
488
      break;
 
489
      
 
490
    case smm_two_way:
 
491
    case smm_echo:
 
492
      sgc_mark_object(x->sm.sm_object0);
 
493
      sgc_mark_object(x->sm.sm_object1);
 
494
      break;
 
495
      
 
496
    case smm_string_input:
 
497
    case smm_string_output:
 
498
      sgc_mark_object(x->sm.sm_object0);
 
499
      break;
 
500
#ifdef USER_DEFINED_STREAMS
 
501
    case smm_user_defined:
 
502
      sgc_mark_object(x->sm.sm_object0);
 
503
      sgc_mark_object(x->sm.sm_object1);
 
504
      break;
 
505
#endif
 
506
    default:
 
507
      error("mark stream botch");
 
508
    }
 
509
    break;
 
510
    
 
511
  case t_random:
 
512
    break;
 
513
    
 
514
  case t_readtable:
 
515
    if (x->rt.rt_self == NULL)
 
516
      break;
 
517
    if (what_to_collect == t_contiguous)
 
518
      mark_contblock((char *)(x->rt.rt_self),
 
519
                     RTABSIZE*sizeof(struct rtent));
 
520
    for (i = 0;  i < RTABSIZE;  i++) {
 
521
      sgc_mark_object(x->rt.rt_self[i].rte_macro);
 
522
      if (x->rt.rt_self[i].rte_dtab != NULL) {
 
523
        if (what_to_collect == t_contiguous)
 
524
          mark_contblock((char *)(x->rt.rt_self[i].rte_dtab),
 
525
                         RTABSIZE*sizeof(object));
 
526
        for (j = 0;  j < RTABSIZE;  j++)
 
527
          sgc_mark_object(x->rt.rt_self[i].rte_dtab[j]);
 
528
      }
 
529
    }
 
530
    break;
 
531
    
 
532
  case t_pathname:
 
533
    sgc_mark_object(x->pn.pn_host);
 
534
    sgc_mark_object(x->pn.pn_device);
 
535
    sgc_mark_object(x->pn.pn_directory);
 
536
    sgc_mark_object(x->pn.pn_name);
 
537
    sgc_mark_object(x->pn.pn_type);
 
538
    sgc_mark_object(x->pn.pn_version);
 
539
    break;
 
540
    
 
541
  case t_closure:
 
542
    { 
 
543
      int i ;
 
544
      if (what_to_collect == t_contiguous)
 
545
        mark_contblock(x->cc.cc_turbo,x->cc.cc_envdim);
 
546
      for (i= 0 ; i < x->cc.cc_envdim ; i++) 
 
547
        sgc_mark_object(x->cc.cc_turbo[i]);
 
548
    }
 
549
    
 
550
  case t_cfun:
 
551
  case t_sfun:
 
552
  case t_vfun:
 
553
  case t_afun:
 
554
  case t_gfun:
 
555
    sgc_mark_object(x->cf.cf_name);
 
556
    sgc_mark_object(x->cf.cf_data);
 
557
    break;
 
558
    
 
559
  case t_cfdata:
 
560
    
 
561
    if (x->cfd.cfd_self != NULL) {
 
562
      int i=x->cfd.cfd_fillp;
 
563
      while(i-- > 0)
 
564
        sgc_mark_object(x->cfd.cfd_self[i]);
 
565
    }
 
566
    if (x->cfd.cfd_start == NULL)
 
567
      break;
 
568
    if (what_to_collect == t_contiguous) {
 
569
      if (!MAYBE_DATA_P((x->cfd.cfd_start)) ||
 
570
          get_mark_bit((int *)(x->cfd.cfd_start)))
 
571
        break;
 
572
      mark_contblock(x->cfd.cfd_start, x->cfd.cfd_size);
 
573
    }
 
574
    break;
 
575
  case t_cclosure:
 
576
    sgc_mark_object(x->cc.cc_name);
 
577
    sgc_mark_object(x->cc.cc_env);
 
578
    sgc_mark_object(x->cc.cc_data);
 
579
    if (what_to_collect == t_contiguous) {
 
580
      if (x->cc.cc_turbo != NULL)
 
581
        mark_contblock((char *)(x->cc.cc_turbo-1),
 
582
                       (1+fix(*(x->cc.cc_turbo-1)))*sizeof(object));
 
583
    }
 
584
    break;
 
585
    
 
586
  case t_spice:
 
587
    break;
 
588
    
 
589
  default:
 
590
#ifdef DEBUG
 
591
    if (debug)
 
592
      printf("\ttype = %d\n", type_of(x));
 
593
#endif
 
594
    error("mark botch");
 
595
  }
 
596
  
 
597
}
 
598
 
 
599
static void
 
600
sgc_mark_stack_carefully(void *topv, void *bottomv, int offset) {
 
601
  
 
602
  long m,pageoffset;
 
603
  unsigned long p;
 
604
  object x;
 
605
  struct typemanager *tm;
 
606
  register long *j;
 
607
  long *top=topv,*bottom=bottomv;
 
608
  
 
609
  /* if either of these happens we are marking the C stack
 
610
     and need to use a local */
 
611
  
 
612
  if (top==0) top = c_stack_where;
 
613
  if (bottom==0) bottom= c_stack_where;
 
614
  
 
615
  /* On machines which align local pointers on multiple of 2 rather
 
616
     than 4 we need to mark twice
 
617
  */
 
618
  
 
619
  if (offset) 
 
620
    sgc_mark_stack_carefully((((char *) top) +offset),bottom,0);
 
621
  for (j=top ; j >= bottom ; j--) {
 
622
    if (VALID_DATA_ADDRESS_P(*j)
 
623
        && type_map[(p=page(*j))]< (char)t_end) {
 
624
      pageoffset=((char *)*j - pagetochar(p));
 
625
      tm=tm_of((enum type) type_map[p]);
 
626
      x= (object)
 
627
        ((char *)(*j) -
 
628
         ((pageoffset=((char *)*j - pagetochar(p))) %
 
629
          tm->tm_size));
 
630
      if ((pageoffset <  (tm->tm_size * tm->tm_nppage))
 
631
          && (m=x->d.m) != FREE) {
 
632
        if (m==TRUE) continue;
 
633
        if (m!=0) {
 
634
          fprintf(stdout,
 
635
                  "**bad value %ld of d.m in gbc page %ld skipping mark**"
 
636
                  ,m,p);fflush(stdout);
 
637
          continue;
 
638
        }
 
639
        sgc_mark_object(x);
 
640
      }
 
641
    }
 
642
  }
 
643
}
 
644
 
 
645
static void
 
646
sgc_mark_phase(void) {
 
647
 
 
648
  STATIC long i, j;
 
649
  STATIC struct package *pp;
 
650
  STATIC bds_ptr bdp;
 
651
  STATIC frame_ptr frp;
 
652
  STATIC ihs_ptr ihsp;
 
653
  
 
654
  sgc_mark_object(Cnil);
 
655
  sgc_mark_object(Ct);
 
656
  
 
657
  /* mark all non recent data on writable pages */
 
658
  {
 
659
    long t,i=page(heap_end);
 
660
    struct typemanager *tm;
 
661
    char *p;
 
662
    
 
663
    while (--i >= 0) {
 
664
      if (WRITABLE_PAGE_P(i)
 
665
          && (t=type_map[i]) < (int) t_end)
 
666
        ;
 
667
      else 
 
668
        continue;
 
669
      tm=tm_of(t);
 
670
      p=pagetochar(i);
 
671
      if ( t == t_cons) 
 
672
        for (j = tm->tm_nppage; --j >= 0; p += tm_table[t_cons].tm_size/*  sizeof(struct cons) */) {
 
673
          object x = (object) p; 
 
674
          if (SGC_OR_M(x)) 
 
675
            continue;
 
676
          if (x->d.t==t_cons) {
 
677
            x->d.m = TRUE; 
 
678
            sgc_mark_cons(x);
 
679
          } else
 
680
            sgc_mark_object1(x);
 
681
        }
 
682
      else {
 
683
        int size=tm->tm_size;
 
684
        for (j = tm->tm_nppage; --j >= 0; p += size) {
 
685
          object x = (object) p; 
 
686
          if (SGC_OR_M(x)) continue;
 
687
          sgc_mark_object1(x);
 
688
        }
 
689
      }
 
690
    }
 
691
  }
 
692
  
 
693
  sgc_mark_stack_carefully(vs_top-1,vs_org,0);
 
694
  clear_stack(vs_top,vs_limit);
 
695
  sgc_mark_stack_carefully(MVloc+(sizeof(MVloc)/sizeof(object)),MVloc,0);
 
696
  /* 
 
697
     for (p = vs_org;  p < vs_top;  p++) {
 
698
     if (p && (inheap(*p)))
 
699
     sgc_mark_object(*p);
 
700
     }
 
701
  */
 
702
#ifdef DEBUG
 
703
  if (debug) {
 
704
    printf("value stack marked\n");
 
705
    fflush(stdout);
 
706
  }
 
707
#endif
 
708
  
 
709
  for (bdp = bds_org;  bdp<=bds_top;  bdp++) {
 
710
    sgc_mark_object(bdp->bds_sym);
 
711
    sgc_mark_object(bdp->bds_val);
 
712
  }
 
713
  
 
714
  for (frp = frs_org;  frp <= frs_top;  frp++)
 
715
    sgc_mark_object(frp->frs_val);
 
716
  
 
717
  for (ihsp = ihs_org;  ihsp <= ihs_top;  ihsp++)
 
718
    sgc_mark_object(ihsp->ihs_function);
 
719
  
 
720
  for (i = 0;  i < mark_origin_max;  i++)
 
721
    sgc_mark_object(*mark_origin[i]);
 
722
  for (i = 0;  i < mark_origin_block_max;  i++)
 
723
    for (j = 0;  j < mark_origin_block[i].mob_size;  j++)
 
724
      sgc_mark_object(mark_origin_block[i].mob_addr[j]);
 
725
  
 
726
  for (pp = pack_pointer;  pp != NULL;  pp = pp->p_link)
 
727
    sgc_mark_object((object)pp);
 
728
#ifdef KCLOVM
 
729
  if (ovm_process_created)
 
730
    sgc_mark_all_stacks();
 
731
#endif
 
732
  
 
733
#ifdef DEBUG
 
734
  if (debug) {
 
735
    printf("symbol navigation\n");
 
736
    fflush(stdout);
 
737
  }
 
738
#endif  
 
739
  {
 
740
    int size;
 
741
  
 
742
    for (pp = pack_pointer;  pp != NULL;  pp = pp->p_link) {
 
743
      size = pp->p_internal_size;
 
744
      if (pp->p_internal != NULL)
 
745
        for (i = 0;  i < size;  i++)
 
746
          sgc_mark_pack_list(pp->p_internal[i]);
 
747
      size = pp->p_external_size;
 
748
      if (pp->p_external != NULL)
 
749
        for (i = 0;  i < size;  i++)
 
750
          sgc_mark_pack_list(pp->p_external[i]);
 
751
    }
 
752
  }
 
753
  
 
754
  mark_c_stack(0,N_RECURSION_REQD,sgc_mark_stack_carefully);
 
755
  
 
756
}
 
757
 
 
758
static void
 
759
sgc_sweep_phase(void) {
 
760
  STATIC long i, j, k;
 
761
  STATIC object x;
 
762
  STATIC char *p;
 
763
  STATIC struct typemanager *tm;
 
764
  STATIC object f;
 
765
  int size;
 
766
  
 
767
  Cnil->s.m = FALSE;
 
768
  Ct->s.m = FALSE;
 
769
  
 
770
#ifdef DEBUG
 
771
  if (debug)
 
772
    printf("type map\n");
 
773
#endif
 
774
  for (i = 0;  i < maxpage;  i++) {
 
775
    if (type_map[i] == (int)t_contiguous) {
 
776
      if (debug) {
 
777
        printf("-");
 
778
        /*
 
779
          fflush(stdout);
 
780
        */
 
781
        continue;
 
782
      }
 
783
    }
 
784
    if (type_map[i] >= (int)t_end)
 
785
      continue;
 
786
    
 
787
    tm = tm_of((enum type)type_map[i]);
 
788
    
 
789
    /*
 
790
      general sweeper
 
791
    */
 
792
    
 
793
#ifdef DEBUG
 
794
    if (debug) {
 
795
      printf("%c", tm->tm_name[0]);
 
796
      /*
 
797
        fflush(stdout);
 
798
      */
 
799
    }
 
800
#endif
 
801
    if (!WRITABLE_PAGE_P(i)) 
 
802
      continue;
 
803
    p = pagetochar(i);
 
804
    f = tm->tm_free;
 
805
    k = 0;
 
806
    size=tm->tm_size;
 
807
    if (SGC_PAGE_P(i)) {
 
808
      for (j = tm->tm_nppage; --j >= 0;  p += size) {
 
809
        x = (object)p;
 
810
        
 
811
        if (x->d.m == FREE)
 
812
          continue;
 
813
        else if (x->d.m) {
 
814
          x->d.m = FALSE;
 
815
          continue;
 
816
        }
 
817
        if(x->d.s == SGC_NORMAL)
 
818
          continue;
 
819
        
 
820
        /* it is ok to free x */
 
821
        
 
822
#ifdef OLD_DISPLACE
 
823
        /* old_displace: from might be free, to not */
 
824
        if(x->d.t >=t_array && x->d.t <= t_bitvector) {
 
825
          /*                    case t_array:
 
826
                                case t_vector:
 
827
                                case t_string:
 
828
                                case t_bitvector:
 
829
          */                    
 
830
          if (x->a.a_displaced->c.c_car != Cnil) {
 
831
            undisplace(x);
 
832
            /* The cons x->a.a_displaced cons has been saved,
 
833
               so as to save the pointer to x->a.a_displaced->c.c_car;
 
834
               However any arrays in its cdr, must have been
 
835
               freed, or we would not be freeing x.   To avoid
 
836
               having a cons with trash in the cdr we set the
 
837
               cdr to nil
 
838
            */                              
 
839
            x->a.a_displaced->c.c_cdr = Cnil;
 
840
          }
 
841
        }
 
842
#endif /* OLD_DISPLACE */
 
843
#ifdef GMP_USE_MALLOC                   
 
844
        if (x->d.t == t_bignum) 
 
845
          mpz_clear(MP(x));
 
846
#endif
 
847
        
 
848
        SET_LINK(x,f);
 
849
        x->d.m = FREE;
 
850
        x->d.s = (int)SGC_RECENT;
 
851
        f = x;
 
852
        k++;
 
853
      }
 
854
      tm->tm_free = f;
 
855
      tm->tm_nfree += k;
 
856
    }
 
857
    else /*non sgc_page */
 
858
      for (j = tm->tm_nppage; --j >= 0;  p += size) {
 
859
        x = (object)p;
 
860
        if (x->d.m == TRUE) x->d.m=FALSE;
 
861
      }
 
862
    
 
863
  }
 
864
#ifdef DEBUG
 
865
  if (debug) {
 
866
    putchar('\n');
 
867
    fflush(stdout);
 
868
  }
 
869
#endif
 
870
}
 
871
 
 
872
 
 
873
static void
 
874
sgc_contblock_sweep_phase(void) {
 
875
 
 
876
  STATIC long i, j;
 
877
  STATIC char *s, *e, *p, *q;
 
878
  STATIC struct contblock *cbp;
 
879
  
 
880
  cb_pointer = NULL;
 
881
  ncb = 0;
 
882
  for (i = 0;  i < maxpage;) {
 
883
    if (type_map[i] != (int)t_contiguous
 
884
        || !SGC_PAGE_P(i)) {
 
885
      i++;
 
886
      continue;
 
887
    }
 
888
    for (j = i+1;
 
889
         j < maxpage && type_map[j] == (int)t_contiguous
 
890
           && SGC_PAGE_P(j);
 
891
         j++);
 
892
    s = pagetochar(i);
 
893
    e = pagetochar(j);
 
894
    for (p = s;  p < e;) {
 
895
      if (get_mark_bit((int *)p)) {
 
896
        /* SGC cont pages: cont blocks must be no smaller than
 
897
           sizeof(struct contblock), and must not have a sweep
 
898
           granularity greater than this amount (e.g. CPTR_ALIGN) if
 
899
           contblock leaks are to be avoided.  Used to be aligned at
 
900
           PTR_ALIGN. CM 20030827 */
 
901
        p += CPTR_ALIGN;
 
902
        continue;
 
903
      }
 
904
      q = p + CPTR_ALIGN;
 
905
      while (q < e) {
 
906
        if (!get_mark_bit((int *)q)) {
 
907
          q += CPTR_ALIGN;
 
908
          continue;
 
909
        }
 
910
        break;
 
911
      }
 
912
      insert_contblock(p, q - p);
 
913
      p = q + CPTR_ALIGN;
 
914
    }
 
915
    i = j + 1;
 
916
  }
 
917
#ifdef DEBUG
 
918
  if (debug) {
 
919
    for (cbp = cb_pointer; cbp != NULL; cbp = cbp->cb_link)
 
920
      printf("%d-byte contblock\n", cbp->cb_size);
 
921
    fflush(stdout);
 
922
  }
 
923
#endif
 
924
}
 
925
 
 
926
 
 
927
 
 
928
#define PAGE_ROUND_UP(adr) \
 
929
    ((char *)(PAGESIZE*(((long)(adr)+PAGESIZE -1) >> PAGEWIDTH)))
 
930
 
 
931
char *old_rb_start;
 
932
 
 
933
#undef tm
 
934
 
 
935
#ifdef SDEBUG
 
936
sgc_count(object yy) {
 
937
  int count=0;
 
938
  object y=yy;
 
939
  while(y)
 
940
    {count++;
 
941
    y=OBJ_LINK(y);}
 
942
  printf("[length %x = %d]",yy,count);
 
943
  fflush(stdout);
 
944
}
 
945
 
 
946
#endif
 
947
/* count writable pages excluding the hole */
 
948
static int
 
949
sgc_count_writable(int end) { 
 
950
 
 
951
  unsigned long j = first_protectable_page -1;
 
952
  unsigned long count = 0;
 
953
  unsigned long hp_end= page(heap_end)-1;
 
954
  while(j++ < hp_end)
 
955
    if (WRITABLE_PAGE_P(j)) count++;
 
956
  j= page(rb_start);
 
957
  while(j++ < end)
 
958
    if (WRITABLE_PAGE_P(j)) count++;
 
959
  return count;
 
960
}
 
961
 
 
962
 
 
963
int
 
964
sgc_count_type(int t) {
 
965
 
 
966
  unsigned long j = first_protectable_page -1;
 
967
  unsigned long end = page(core_end)-1;
 
968
  unsigned long count=0;
 
969
  /* FIXME  ensure core_end in range for type_map reference below.  CM*/
 
970
  while(j++ < end)
 
971
    if (type_map[j]==t && SGC_PAGE_P(j))
 
972
      count++;
 
973
  return count;
 
974
}
 
975
 
 
976
int
 
977
sgc_count_read_only_type(int t) {
 
978
 
 
979
  unsigned long j = first_protectable_page -1;
 
980
  unsigned long hp_end = page(heap_end)-1;
 
981
  unsigned long end = page(rb_limit)-1;
 
982
  unsigned long count=0;
 
983
  while(j++ < hp_end)
 
984
    if ((type_map[j]==t || (t<0 && type_map[j]!=t_other)) && !WRITABLE_PAGE_P(j))
 
985
      count++;
 
986
  j= page(rb_start)-1;
 
987
  while(j++ < end) /* FIXME: relocatable pages are marked as type t_other */
 
988
    if ((t==t_relocatable || t<0) && !WRITABLE_PAGE_P(j))
 
989
      count++;
 
990
  return count;
 
991
}
 
992
 
 
993
#ifdef SGC_CONT_DEBUG
 
994
void
 
995
overlap_check(struct contblock *t1,struct contblock *t2) {
 
996
 
 
997
  struct contblock *p;
 
998
 
 
999
  for (;t1;t1=t1->cb_link) {
 
1000
 
 
1001
    if (!inheap(t1)) {
 
1002
      fprintf(stderr,"%p not in heap\n",t1);
 
1003
      exit(1);
 
1004
    }
 
1005
 
 
1006
    for (p=t2;p;p=p->cb_link) {
 
1007
 
 
1008
      if (!inheap(p)) {
 
1009
        fprintf(stderr,"%p not in heap\n",t1);
 
1010
        exit(1);
 
1011
      }
 
1012
 
 
1013
      if ((p<=t1 && (void *)p+p->cb_size>(void *)t1) ||
 
1014
          (t1<=p && (void *)t1+t1->cb_size>(void *)p)) {
 
1015
        fprintf(stderr,"Overlap %u %p  %u %p\n",t1->cb_size,t1,p->cb_size,p);
 
1016
        exit(1);
 
1017
      }
 
1018
      
 
1019
      if (p==p->cb_link) {
 
1020
        fprintf(stderr,"circle detected at %p\n",p);
 
1021
        exit(1);
 
1022
      }
 
1023
 
 
1024
    }
 
1025
        
 
1026
    if (t1==t1->cb_link) {
 
1027
      fprintf(stderr,"circle detected at %p\n",t1);
 
1028
      exit(1);
 
1029
    }
 
1030
 
 
1031
  }
 
1032
 
 
1033
}
 
1034
 
 
1035
void
 
1036
tcc(struct contblock *t) {
 
1037
 
 
1038
  for (;t;t=t->cb_link) {
 
1039
 
 
1040
    if (!inheap(t)) {
 
1041
      fprintf(stderr,"%p not in heap\n",t);
 
1042
      break;
 
1043
    }
 
1044
 
 
1045
    fprintf(stderr,"%u at %p\n",t->cb_size,t);
 
1046
 
 
1047
    if (t==t->cb_link) {
 
1048
      fprintf(stderr,"circle detected at %p\n",t);
 
1049
      break;
 
1050
    }
 
1051
 
 
1052
  }
 
1053
 
 
1054
}
 
1055
 
 
1056
#endif    
 
1057
 
 
1058
typedef enum {memprotect_none,memprotect_cannot_protect,memprotect_sigaction,
 
1059
              memprotect_bad_return,memprotect_no_signal,
 
1060
              memprotect_multiple_invocations,memprotect_no_restart,
 
1061
              memprotect_bad_fault_address,memprotect_success} memprotect_enum;
 
1062
static memprotect_enum memprotect_result;
 
1063
static int memprotect_handler_invocations,memprotect_print_enable;
 
1064
static void *memprotect_test_address;
 
1065
 
 
1066
#define MEM_ERR_CASE(a_) \
 
1067
  case a_: \
 
1068
    fprintf(stderr,"The SGC segfault recovery test failed with %s, SGC disabled\n",#a_); \
 
1069
    break
 
1070
 
 
1071
static void
 
1072
memprotect_print(void) {
 
1073
 
 
1074
  if (!memprotect_print_enable)
 
1075
    return;
 
1076
 
 
1077
  switch(memprotect_result) {
 
1078
  case memprotect_none: case memprotect_success:
 
1079
    break;
 
1080
 
 
1081
    MEM_ERR_CASE(memprotect_cannot_protect);
 
1082
    MEM_ERR_CASE(memprotect_sigaction);
 
1083
    MEM_ERR_CASE(memprotect_bad_return);
 
1084
    MEM_ERR_CASE(memprotect_no_signal);
 
1085
    MEM_ERR_CASE(memprotect_no_restart);
 
1086
    MEM_ERR_CASE(memprotect_bad_fault_address);
 
1087
    MEM_ERR_CASE(memprotect_multiple_invocations);
 
1088
 
 
1089
  }
 
1090
 
 
1091
}
 
1092
 
 
1093
 
 
1094
static void
 
1095
memprotect_handler_test(int sig, long code, void *scp, char *addr) {
 
1096
 
 
1097
  char *faddr;
 
1098
  faddr=GET_FAULT_ADDR(sig,code,scp,addr); 
 
1099
 
 
1100
  if (memprotect_handler_invocations) {
 
1101
    memprotect_result=memprotect_multiple_invocations;
 
1102
    exit(-1);
 
1103
  }
 
1104
  memprotect_handler_invocations=1;
 
1105
  if (faddr!=memprotect_test_address)
 
1106
    memprotect_result=memprotect_bad_fault_address;
 
1107
  else
 
1108
    memprotect_result=memprotect_none;
 
1109
  mprotect(memprotect_test_address,PAGESIZE,PROT_READ_WRITE_EXEC);
 
1110
 
 
1111
}
 
1112
 
 
1113
static int
 
1114
memprotect_test(void) {
 
1115
 
 
1116
  char b1[2*PAGESIZE],b2[PAGESIZE];
 
1117
  struct sigaction sa,sao,saob;
 
1118
 
 
1119
  if (memprotect_result!=memprotect_none)
 
1120
    return memprotect_result!=memprotect_success;
 
1121
  if (atexit(memprotect_print)) {
 
1122
    fprintf(stderr,"Cannot setup memprotect_print on exit\n");
 
1123
    exit(-1);
 
1124
  }
 
1125
 
 
1126
  memset(b1,32,sizeof(b1));
 
1127
  memset(b2,0,sizeof(b2));
 
1128
  memprotect_test_address=(void *)(((unsigned long)b1+PAGESIZE-1) & ~(PAGESIZE-1));
 
1129
  if (mprotect(memprotect_test_address,PAGESIZE,PROT_READ_EXEC)) {
 
1130
    memprotect_result=memprotect_cannot_protect;
 
1131
    return -1;
 
1132
  }
 
1133
  sa.sa_sigaction=(void *)memprotect_handler_test;
 
1134
  sa.sa_flags=MPROTECT_ACTION_FLAGS;
 
1135
  if (sigaction(SIGSEGV,&sa,&sao)) {
 
1136
    memprotect_result=memprotect_sigaction;
 
1137
    return -1;
 
1138
  }
 
1139
  if (sigaction(SIGBUS,&sa,&saob)) {
 
1140
    sigaction(SIGSEGV,&sao,NULL);
 
1141
    memprotect_result=memprotect_sigaction;
 
1142
    return -1;
 
1143
  }
 
1144
  memprotect_result=memprotect_bad_return;
 
1145
  memset(memprotect_test_address,0,PAGESIZE);
 
1146
  if (memprotect_result==memprotect_bad_return)
 
1147
    memprotect_result=memprotect_no_signal;
 
1148
  if (memprotect_result!=memprotect_none) {
 
1149
    sigaction(SIGSEGV,&sao,NULL);
 
1150
    sigaction(SIGBUS,&saob,NULL);
 
1151
    return -1;
 
1152
  }
 
1153
  if (memcmp(memprotect_test_address,b2,PAGESIZE)) {
 
1154
    memprotect_result=memprotect_no_restart;
 
1155
    sigaction(SIGSEGV,&sao,NULL);
 
1156
    sigaction(SIGBUS,&saob,NULL);
 
1157
    return -1;
 
1158
  }
 
1159
  memprotect_result=memprotect_success;
 
1160
  sigaction(SIGSEGV,&sao,NULL);
 
1161
    sigaction(SIGBUS,&saob,NULL);
 
1162
  return 0;
 
1163
 
 
1164
}
 
1165
 
 
1166
static int
 
1167
do_memprotect_test(void) {
 
1168
 
 
1169
  int rc=0;
 
1170
 
 
1171
  memprotect_print_enable=1;
 
1172
  if (memprotect_test()) {
 
1173
    memprotect_print();
 
1174
    if (sgc_enabled)
 
1175
      sgc_quit();
 
1176
    rc=-1;
 
1177
  }
 
1178
  memprotect_print_enable=0;
 
1179
  return rc;
 
1180
 
 
1181
}
 
1182
 
 
1183
void
 
1184
memprotect_test_reset(void) {
 
1185
 
 
1186
  memprotect_result=memprotect_none;
 
1187
  memprotect_handler_invocations=0;
 
1188
  memprotect_test_address=NULL;
 
1189
 
 
1190
  if (sgc_enabled)
 
1191
    do_memprotect_test();
 
1192
 
 
1193
}
 
1194
 
 
1195
int
 
1196
sgc_start(void) {
 
1197
 
 
1198
  long i;
 
1199
  long np;
 
1200
  unsigned short free_map[MAXPAGE];
 
1201
  object f;
 
1202
  struct typemanager *tm;
 
1203
  long npages;
 
1204
  unsigned long npp;
 
1205
 
 
1206
  if (memprotect_result!=memprotect_success && do_memprotect_test())
 
1207
    return 0;
 
1208
 
 
1209
  npp=page((&sgc_type_map[0]));
 
1210
  if (npp<MAXPAGE && sgc_type_map[npp] != SGC_PERM_WRITABLE)
 
1211
    perm_writable(&sgc_type_map[0],sizeof(sgc_type_map));
 
1212
  if (sgc_enabled)
 
1213
    return 1;
 
1214
  sgc_type_map[0]=0;
 
1215
  /* FIXME ensure core_end in range for type_map reference below.  CM*/
 
1216
  i=npages=page(core_end);
 
1217
  while (i--> 0)
 
1218
    sgc_type_map[i] = sgc_type_map[i]  & SGC_PERM_WRITABLE ;
 
1219
  
 
1220
  for (i= t_start; i < t_contiguous ; i++)
 
1221
    if (TM_BASE_TYPE_P(i) && (np=(tm=tm_of(i))->tm_sgc)) 
 
1222
      FIND_FREE_PAGES:
 
1223
    {
 
1224
      unsigned long maxp=0;
 
1225
      unsigned long j;
 
1226
      /* SGC cont pages: This used to be simply set to tm_sgc_minfree,
 
1227
         which is a definite bug, as minfree could then be zero,
 
1228
         leading this type to claim SGC pages not of its type as
 
1229
         specified in type_map.  CM 20030827*/
 
1230
      unsigned short minfree = tm->tm_sgc_minfree > 0 ? tm->tm_sgc_minfree : 1 ;
 
1231
      unsigned long count;
 
1232
      bzero(free_map,npages*sizeof(short));
 
1233
      f = tm->tm_free;
 
1234
      count=0;
 
1235
      while (f!=0) {
 
1236
        j=page(f);
 
1237
        if (j>=MAXPAGE)
 
1238
          error("Address in tm freelist out of range");
 
1239
        /* protect against overflow */
 
1240
        free_map[j]=free_map[j]<minfree ? free_map[j]+1 : free_map[j];
 
1241
        if (j>=maxp) maxp=j;
 
1242
#ifdef DEBUG
 
1243
        count++;
 
1244
#endif    
 
1245
        f= OBJ_LINK(f);
 
1246
      }
 
1247
#ifdef DEBUG       
 
1248
      if (count!=tm->tm_nfree) 
 
1249
        printf("[Count differed type(%d)nfree= %ld in freelist %ld]\n"
 
1250
               ,tm->tm_type,tm->tm_nfree,
 
1251
               count);fflush(stdout);
 
1252
#endif       
 
1253
      for(j=0,count=0; j <= maxp ;j++) {
 
1254
        if (free_map[j] >= minfree) {
 
1255
          sgc_type_map[j] |= (SGC_PAGE_FLAG | SGC_TEMP_WRITABLE);
 
1256
          ++count;
 
1257
          if (count >= tm->tm_sgc_max)
 
1258
            break; 
 
1259
          }
 
1260
      }
 
1261
      
 
1262
      /* don't do any more allocations  for this type if saving system */
 
1263
      if (saving_system) 
 
1264
        continue;
 
1265
      
 
1266
      if (count < tm->tm_sgc) {
 
1267
        /* try to get some more free pages of type i */
 
1268
        long n = tm->tm_sgc - count;
 
1269
        long again=0,nfree = tm->tm_nfree;
 
1270
        char *p=alloc_page(n);
 
1271
        if (tm->tm_nfree > nfree) again=1;  /* gc freed some objects */
 
1272
        while (n-- > 0) {
 
1273
          (sgc_enabled=1,add_page_to_freelist(p,tm),sgc_enabled=0);
 
1274
          p += PAGESIZE;
 
1275
        }
 
1276
        if (again) 
 
1277
          goto FIND_FREE_PAGES;  
 
1278
      }
 
1279
    }
 
1280
 
 
1281
/* SGC cont pages: Here we implement the contblock page division into
 
1282
   SGC and non-SGC types.  Unlike the other types, we need *whole*
 
1283
   free pages for contblock SGC, as there is no psersistent data
 
1284
   element (e.g. .m) on an allocated block itself which can indicate
 
1285
   its live status.  If anything on a page which is to be marked
 
1286
   read-only points to a live object on an SGC cont page, it will
 
1287
   never be marked and will be erroneously swept.  It is also possible
 
1288
   for dead objects to unnecessarily mark dead regions on SGC pages
 
1289
   and delay sweeping until the pointing type is GC'ed if SGC is
 
1290
   turned off for the pointing type, e.g. tm_sgc=0. (This was so by
 
1291
   default for a number of types, including bignums, and has now been
 
1292
   corrected in gcl_init_alloc in alloc.c.) We can't get around this
 
1293
   AFAICT, as old data on (writable) SGC pages must be marked lest it
 
1294
   is lost, and (old) data on now writable non-SGC pages might point
 
1295
   to live regions on SGC pages, yet might not themselves be reachable
 
1296
   from the mark origin through an unbroken chain of writable pages.
 
1297
   In any case, the possibility of a lot of garbage marks on contblock
 
1298
   pages, especially when the blocks are small as in bignums, makes
 
1299
   necessary the sweeping of minimal contblocks to prevent leaks. CM
 
1300
   20030827 */
 
1301
  {
 
1302
 
 
1303
    void *p=NULL;
 
1304
    unsigned long i,j,k,count;
 
1305
    struct contblock *new_cb_pointer=NULL,*tmp_cb_pointer=NULL,**cbpp;
 
1306
    
 
1307
    tm=tm_of(t_contiguous);
 
1308
    
 
1309
    /* SGC cont pages:  First count whole free pages available.  CM 20030827 */
 
1310
    for (cbpp=&cb_pointer,count=0;*cbpp;cbpp=&(*cbpp)->cb_link) {
 
1311
      p=PAGE_ROUND_UP((void *)(*cbpp));
 
1312
      k=p-((void *)(*cbpp));
 
1313
      if ((*cbpp)->cb_size<k || (*cbpp)->cb_size-k<PAGESIZE) 
 
1314
        continue;
 
1315
      i=((*cbpp)->cb_size-k)/PAGESIZE;
 
1316
      count+=i;
 
1317
    }
 
1318
    count=tm->tm_sgc>count ? tm->tm_sgc - count : 0;
 
1319
    
 
1320
    if (count>0) {
 
1321
      /* SGC cont pages: allocate more if necessary, dumping possible
 
1322
         GBC freed pages onto the old contblock list.  CM 20030827*/
 
1323
      unsigned long z=count+1;
 
1324
      void *p1=alloc_contblock(z*PAGESIZE);
 
1325
      p=PAGE_ROUND_UP(p1);
 
1326
      if (p>p1) {
 
1327
        z--;
 
1328
        insert_contblock(p1,p-p1);
 
1329
        insert_contblock(p+z*PAGESIZE,PAGESIZE-(p-p1));
 
1330
      }
 
1331
      tmp_cb_pointer=cb_pointer;
 
1332
      cb_pointer=new_cb_pointer;
 
1333
      /* SGC cont pages: add new pages to new contblock list. p is not
 
1334
         already on any list as ensured by alloc_contblock.  CM
 
1335
         20030827 */
 
1336
      insert_contblock(p,PAGESIZE*z);
 
1337
      new_cb_pointer=cb_pointer;
 
1338
      cb_pointer=tmp_cb_pointer;
 
1339
      
 
1340
      i=page(p);
 
1341
      k=i+z;
 
1342
      if (i>=MAXPAGE || k>MAXPAGE)
 
1343
        error("Pages out of range in sgc_start");
 
1344
      for (;i<k;i++) 
 
1345
        sgc_type_map[i]|= SGC_PAGE_FLAG;
 
1346
    }
 
1347
 
 
1348
    for (cbpp=&cb_pointer;*cbpp;) {
 
1349
      p=PAGE_ROUND_UP((void *)(*cbpp));
 
1350
      k=p-((void *)(*cbpp));
 
1351
      if ((*cbpp)->cb_size<k || (*cbpp)->cb_size-k<PAGESIZE) {
 
1352
        cbpp=&(*cbpp)->cb_link;
 
1353
        continue;
 
1354
      }
 
1355
      i=((*cbpp)->cb_size-k)/PAGESIZE;
 
1356
      i*=PAGESIZE;
 
1357
      j=(*cbpp)->cb_size-i-k;
 
1358
      /* SGC contblock pages:  remove this block from old list CM 20030827 */
 
1359
      *cbpp=(*cbpp)->cb_link;
 
1360
      /* SGC contblock pages:  add fragments old list CM 20030827 */
 
1361
      if (k) {
 
1362
        ncb--;
 
1363
        insert_contblock(p-k,k);
 
1364
      }
 
1365
      if (j) {
 
1366
        ncb--;
 
1367
        insert_contblock(p+i,j);
 
1368
      }
 
1369
      tmp_cb_pointer=cb_pointer;
 
1370
      cb_pointer=new_cb_pointer;
 
1371
      /* SGC contblock pages: add whole pages to new list, p p-k, and
 
1372
         p+i are guaranteed to be distinct when used. CM 20030827 */
 
1373
      insert_contblock(p,i);
 
1374
      new_cb_pointer=cb_pointer;
 
1375
      cb_pointer=tmp_cb_pointer;
 
1376
      i/=PAGESIZE;
 
1377
      j=page(p);
 
1378
      i+=j;
 
1379
      if (j>=MAXPAGE || i>MAXPAGE)
 
1380
        error("Pages out of range in sgc_start");
 
1381
      for (;j<i;j++)
 
1382
        sgc_type_map[j]|= SGC_PAGE_FLAG;
 
1383
    }
 
1384
 
 
1385
    /* SGC contblock pages: switch to new free SGC contblock list. CM
 
1386
       20030827 */
 
1387
    old_cb_pointer=cb_pointer;
 
1388
    cb_pointer=new_cb_pointer;
 
1389
 
 
1390
#ifdef SGC_CONT_DEBUG
 
1391
    overlap_check(old_cb_pointer,cb_pointer);
 
1392
#endif
 
1393
 
 
1394
  }
 
1395
 
 
1396
  /* Now  allocate the sgc relblock.   We do this as the tail
 
1397
     end of the ordinary rb.     */  
 
1398
  {
 
1399
    char *new;
 
1400
    tm=tm_of(t_relocatable);
 
1401
    
 
1402
    {
 
1403
      old_rb_start=rb_start;
 
1404
      if(!saving_system) {
 
1405
        new=alloc_relblock(((unsigned long)tm->tm_sgc)*PAGESIZE);
 
1406
        /* the above may cause a gc, shifting the relblock */
 
1407
        old_rb_start=rb_start;
 
1408
        new= PAGE_ROUND_UP(new);
 
1409
        rb_start=rb_pointer=new;
 
1410
      }
 
1411
    }
 
1412
  }
 
1413
  /* the relblock has been allocated */
 
1414
  
 
1415
  /* now move the sgc free lists into place.   alt_free should
 
1416
     contain the others */
 
1417
  
 
1418
  for (i= t_start; i < t_contiguous ; i++)
 
1419
    if (TM_BASE_TYPE_P(i)
 
1420
        && (np=(tm=tm_of(i))->tm_sgc)) {
 
1421
      object f=tm->tm_free ,x,y,next;
 
1422
      int count=0;
 
1423
      x=y=0;
 
1424
      
 
1425
      while (f!=0) {
 
1426
        next=OBJ_LINK(f);
 
1427
#ifdef SDEBUG        
 
1428
        if (f->d.m!=FREE)
 
1429
          printf("Not FREE in freelist f=%d",f);
 
1430
#endif
 
1431
        if (ON_SGC_PAGE(f)) {
 
1432
          SET_LINK(f,x);
 
1433
          f->d.s = SGC_RECENT;
 
1434
          x=f;
 
1435
          count++;
 
1436
        } else {
 
1437
          SET_LINK(f,y);
 
1438
          f->d.s = SGC_NORMAL;
 
1439
          y=f;
 
1440
        }
 
1441
        f=next;
 
1442
      }
 
1443
      tm->tm_free = x;
 
1444
      tm->tm_alt_free = y;
 
1445
      tm->tm_alt_nfree = tm->tm_nfree - count;
 
1446
      tm->tm_nfree=count;
 
1447
    }
 
1448
  
 
1449
  /* Whew.   We have now allocated the sgc space
 
1450
     and modified the tm_table;
 
1451
     Turn  memory protection on for the pages which are writable.
 
1452
  */
 
1453
  memory_protect(1);
 
1454
  sgc_enabled=1;
 
1455
  if (sSAnotify_gbcA->s.s_dbind != Cnil) {
 
1456
    printf("[SGC on]"); 
 
1457
    fflush(stdout);
 
1458
  }
 
1459
 
 
1460
  return 1;
 
1461
  
 
1462
}
 
1463
 
 
1464
int
 
1465
sgc_quit(void) { 
 
1466
 
 
1467
  struct typemanager *tm;
 
1468
  int i,np;
 
1469
 
 
1470
  memory_protect(0);
 
1471
  if(sSAnotify_gbcA->s.s_dbind != Cnil) 
 
1472
    printf("[SGC off]"); fflush(stdout);
 
1473
  if (sgc_enabled==0) 
 
1474
    return 0;
 
1475
  sgc_enabled=0;
 
1476
  rb_start = old_rb_start;
 
1477
 
 
1478
  /* SGC cont pages: restore contblocks, each tmp_cb_pointer coming
 
1479
     from the new list is guaranteed not to be on the old. Need to
 
1480
     grab 'next' before insert_contblock writes is.  CM 20030827 */
 
1481
  {
 
1482
 
 
1483
    struct contblock *tmp_cb_pointer,*next;
 
1484
    if (old_cb_pointer) {
 
1485
#ifdef SGC_CONT_DEBUG
 
1486
      overlap_check(old_cb_pointer,cb_pointer);
 
1487
#endif
 
1488
      tmp_cb_pointer=cb_pointer;
 
1489
      cb_pointer=old_cb_pointer;
 
1490
      for (;tmp_cb_pointer;  tmp_cb_pointer=next) {
 
1491
        next=tmp_cb_pointer->cb_link;
 
1492
        insert_contblock((void *)tmp_cb_pointer,tmp_cb_pointer->cb_size);
 
1493
      }
 
1494
    }
 
1495
  }
 
1496
 
 
1497
  for (i= t_start; i < t_contiguous ; i++)
 
1498
    if (TM_BASE_TYPE_P(i)) {
 
1499
      tm=tm_of(i);
 
1500
      if ((np=tm->tm_sgc)) {
 
1501
        object f,y;
 
1502
        f=tm->tm_free;
 
1503
        if (f==0) 
 
1504
          tm->tm_free=tm->tm_alt_free;
 
1505
        else {
 
1506
          /* tack the alt_free onto the end of free */
 
1507
#ifdef SDEBUG
 
1508
          int count=0;
 
1509
          f=tm->tm_free;
 
1510
          while(y= (object) F_LINK(f)) {
 
1511
            if(y->d.s != SGC_RECENT)
 
1512
              printf("[bad %d]",y);
 
1513
            count++; f=y;
 
1514
          }
 
1515
          
 
1516
          count=0;
 
1517
          if (f=tm->tm_alt_free)
 
1518
            while(y= F_LINK(f)) {
 
1519
              if(y->d.s != SGC_NORMAL)
 
1520
                printf("[alt_bad %d]",y);
 
1521
              count++; f=y;
 
1522
            }
 
1523
          
 
1524
#endif
 
1525
          f=tm->tm_free;
 
1526
          while((y= (object) F_LINK(f)))
 
1527
            f=y;
 
1528
          F_LINK(f)= (long)(tm->tm_alt_free);
 
1529
        }
 
1530
        /* tm->tm_free has all of the free objects */
 
1531
        tm->tm_nfree += tm->tm_alt_nfree;
 
1532
        tm->tm_alt_nfree = 0;
 
1533
        tm->tm_alt_free = 0;
 
1534
        
 
1535
        /* remove the recent flag from any objects on sgc pages */
 
1536
        {
 
1537
          unsigned long hp=page(heap_end);
 
1538
          unsigned long i,j;
 
1539
          char t = (char) tm->tm_type;
 
1540
          char *p;
 
1541
          for (i=0 ; i < hp; i++)
 
1542
            if (type_map[i]==t && (sgc_type_map[i] & SGC_PAGE_FLAG))
 
1543
              for (p= pagetochar(i),j = tm->tm_nppage;
 
1544
                   j > 0; --j, p += tm->tm_size)
 
1545
                ((object) p)->d.s = SGC_NORMAL;
 
1546
        }
 
1547
      }
 
1548
    }
 
1549
 
 
1550
  return 0;
 
1551
 
 
1552
}
 
1553
 
 
1554
void
 
1555
make_writable(unsigned long beg, unsigned long i) {
 
1556
 
 
1557
  if (i > beg) {
 
1558
    beg=ROUND_DOWN_PAGE_NO(beg);
 
1559
    i=ROUND_UP_PAGE_NO(i);
 
1560
    {
 
1561
      unsigned long k=beg;
 
1562
      if (k>=MAXPAGE || i>MAXPAGE)
 
1563
        error("Pages out of range in make_writable");
 
1564
      while(k <i )
 
1565
        sgc_type_map[k++] |= SGC_TEMP_WRITABLE;
 
1566
    }
 
1567
    sgc_mprotect(beg, i-beg, SGC_WRITABLE);
 
1568
  }
 
1569
}
 
1570
 
 
1571
long debug_fault =0;
 
1572
int fault_count =0;
 
1573
extern char etext;
 
1574
static void
 
1575
memprotect_handler(int sig, long code, void *scp, char *addr) {
 
1576
  
 
1577
  unsigned long p;
 
1578
  int j=page_multiple;
 
1579
  char *faddr;  /* Needed because we must not modify signal handler
 
1580
                   arguments on the stack! */
 
1581
#ifdef GET_FAULT_ADDR
 
1582
  faddr=GET_FAULT_ADDR(sig,code,scp,addr); 
 
1583
  debug_fault = (long) faddr;
 
1584
#ifdef DEBUG_MPROTECT
 
1585
  printf("fault:0x%x [%d] (%d)  ",faddr,page(faddr),faddr >= core_end);
 
1586
#endif 
 
1587
  if (faddr >= core_end || (unsigned long)faddr < DBEGIN) {
 
1588
    if (fault_count > 300) error("fault count too high");
 
1589
    fault_count ++;
 
1590
    INSTALL_MPROTECT_HANDLER;
 
1591
    return;
 
1592
  }
 
1593
#else
 
1594
  faddr = addr;
 
1595
#endif 
 
1596
  p = page(faddr);
 
1597
  p = ROUND_DOWN_PAGE_NO(p);
 
1598
  if (p >= first_protectable_page
 
1599
      && faddr < core_end
 
1600
      && !(WRITABLE_PAGE_P(p))) {
 
1601
    /*   CHECK_RANGE(p,1); */
 
1602
#ifdef DEBUG_MPROTECT
 
1603
    printf("mprotect(0x%x,0x%x,0x%x)\n",
 
1604
           pagetochar(p),page_multiple * PAGESIZE, sbrk(0));
 
1605
    fflush(stdout);
 
1606
#endif     
 
1607
    mprotect(pagetochar(p),page_multiple * PAGESIZE, PROT_READ_WRITE_EXEC);
 
1608
    if (p>=MAXPAGE || p+j>MAXPAGE)
 
1609
      error("Pages out of range in memprotect_handler");
 
1610
    while (--j >= 0)
 
1611
      sgc_type_map[p+j] = sgc_type_map[p+j] | SGC_TEMP_WRITABLE;
 
1612
    
 
1613
#ifndef BSD
 
1614
    INSTALL_MPROTECT_HANDLER;
 
1615
#endif
 
1616
    
 
1617
    return;
 
1618
  }
 
1619
  
 
1620
#ifndef  BSD
 
1621
  INSTALL_MPROTECT_HANDLER;
 
1622
#endif
 
1623
 
 
1624
  segmentation_catcher(0);
 
1625
 
 
1626
}
 
1627
 
 
1628
static void
 
1629
sgc_mprotect(long pbeg, long n, int writable) {
 
1630
  /* CHECK_RANGE(pbeg,n);  */
 
1631
#ifdef DEBUG_MPROTECT
 
1632
  printf("prot[%d,%d,(%d),%s]\n",pbeg,pbeg+n,writable & SGC_WRITABLE,
 
1633
         (writable  & SGC_WRITABLE ? "writable" : "not writable"));
 
1634
  printf("mprotect(0x%x,0x%x), sbrk(0)=0x%x\n",
 
1635
         pagetochar(pbeg), n * PAGESIZE, sbrk(0));
 
1636
  fflush(stdout);
 
1637
#endif  
 
1638
  if(mprotect(pagetochar(pbeg),n*PAGESIZE,
 
1639
              (writable & SGC_WRITABLE ? PROT_READ_WRITE_EXEC : PROT_READ_EXEC)))
 
1640
    FEerror("Couldn't protect",0);
 
1641
}
 
1642
 
 
1643
 
 
1644
/* for page numbers from beg below end,
 
1645
   if one page in a a page_multiple grouping is writable,the
 
1646
   rest must be */
 
1647
 
 
1648
static void
 
1649
fix_for_page_multiple(unsigned long beg, unsigned long end) {
 
1650
 
 
1651
  unsigned long i,j;
 
1652
  char *p;
 
1653
  int writable;
 
1654
 
 
1655
  beg = ROUND_DOWN_PAGE_NO(beg);
 
1656
  for (i = beg ; i < end; i = i+ page_multiple){
 
1657
    p = sgc_type_map + i;
 
1658
    j = page_multiple;
 
1659
    writable = ((*p++) & SGC_WRITABLE);
 
1660
    if (writable) {
 
1661
      /* all pages must be */
 
1662
      while (--j)
 
1663
        if (((*p++) & SGC_WRITABLE)  == 0)
 
1664
          goto FIXIT;}
 
1665
    else 
 
1666
      while (--j)
 
1667
        if ((*p++) & SGC_WRITABLE ) 
 
1668
          goto FIXIT;
 
1669
    continue;
 
1670
  FIXIT:
 
1671
    j = page_multiple;
 
1672
    p = sgc_type_map + i;
 
1673
    while (--j >= 0 ) 
 
1674
      (*p++) |= SGC_WRITABLE;
 
1675
  }
 
1676
}
 
1677
 
 
1678
 
 
1679
void
 
1680
memory_protect(int on) {
 
1681
 
 
1682
  unsigned long i,beg,end= page(core_end);
 
1683
  int writable=1;
 
1684
  extern void   install_segmentation_catcher(void);
 
1685
 
 
1686
  if (first_protectable_page==0) {
 
1687
    for (i=page_multiple; i< maxpage ; i++)
 
1688
      if (type_map[i]!=t_other)
 
1689
        break;
 
1690
      else {
 
1691
        /* We want page(0) to be non writable since that
 
1692
           is the only check for 0 pointer in sgc */
 
1693
        sgc_type_map[i] = SGC_PERM_WRITABLE;
 
1694
      }
 
1695
    first_protectable_page= ROUND_DOWN_PAGE_NO(i);
 
1696
  }
 
1697
  if(page_multiple > 1)
 
1698
    fix_for_page_multiple(first_protectable_page,end);
 
1699
  /* turning it off */
 
1700
  if (on==0) {sgc_mprotect((first_protectable_page),
 
1701
                           (end - first_protectable_page), SGC_WRITABLE);
 
1702
  install_segmentation_catcher();
 
1703
  return;
 
1704
  }
 
1705
  /* write protect some pages by first write protecting them
 
1706
     all and then selectively disabling */
 
1707
  /*  sgc_mprotect((first_protectable_page),
 
1708
      (end - first_protectable_page), 0);
 
1709
  */
 
1710
  INSTALL_MPROTECT_HANDLER;
 
1711
  beg=first_protectable_page;
 
1712
  writable = WRITABLE_PAGE_P(beg);
 
1713
  for (i=beg ; ++i<= end; ) {
 
1714
    int wri = WRITABLE_PAGE_P(i);
 
1715
    if ((wri==0 && writable)
 
1716
        || (writable ==0  && wri)
 
1717
        || i == end) {
 
1718
      /* it is changing */
 
1719
      if (writable)
 
1720
        make_writable(beg,i);
 
1721
      else
 
1722
        sgc_mprotect(beg,i-beg,writable);
 
1723
      writable = wri;
 
1724
      beg = i;
 
1725
    }
 
1726
  }
 
1727
}
 
1728
 
 
1729
static void
 
1730
FFN(siLsgc_on)(void) {
 
1731
 
 
1732
  if (vs_base==vs_top) {
 
1733
    vs_base[0]=(sgc_enabled ? Ct :Cnil);
 
1734
    vs_top=vs_base+1; return;
 
1735
  }
 
1736
  check_arg(1);
 
1737
  if(vs_base[0]==Cnil) 
 
1738
    sgc_quit();
 
1739
  else 
 
1740
    vs_base[0]=sgc_start() ? Ct : Cnil;
 
1741
}
 
1742
 
 
1743
/* make permanently writable pages containing pointers p thru p+n-1 */
 
1744
 
 
1745
void
 
1746
perm_writable(char *p, long n) {
 
1747
 
 
1748
  unsigned long beg=page(p);
 
1749
  unsigned long end=page(PAGE_ROUND_UP(p+n));
 
1750
  unsigned long i,must_protect=0;
 
1751
 
 
1752
  beg = ROUND_DOWN_PAGE_NO(beg);
 
1753
  end = ROUND_UP_PAGE_NO(end);
 
1754
  if (beg >= MAXPAGE || end >MAXPAGE)
 
1755
    error("Address supplied to perm_writable out of range");
 
1756
  for (i=beg ; i < end ; i++) {
 
1757
    if (sgc_enabled & !(WRITABLE_PAGE_P(i))) 
 
1758
      must_protect = 1;
 
1759
    sgc_type_map [i] |= SGC_PERM_WRITABLE;
 
1760
  }
 
1761
  if(must_protect) 
 
1762
    make_writable(beg,end);
 
1763
}
 
1764
 
 
1765
void
 
1766
system_error(void) {
 
1767
  FEerror("System error",0);
 
1768
}