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

« back to all changes in this revision

Viewing changes to o/usig2.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
/*
 
2
 Copyright (C) 1994  W. Schelter
 
3
 
 
4
This file is part of GNU Common Lisp, herein referred to as GCL
 
5
 
 
6
GCL is free software; you can redistribute it and/or modify it under
 
7
the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE as published by
 
8
the Free Software Foundation; either version 2, or (at your option)
 
9
any later version.
 
10
 
 
11
GCL is distributed in the hope that it will be useful, but WITHOUT
 
12
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public 
 
14
License for more details.
 
15
 
 
16
You should have received a copy of the GNU Library General Public License 
 
17
along with GCL; see the file COPYING.  If not, write to the Free Software
 
18
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 
 
20
*/
 
21
 
 
22
 
 
23
#ifndef IN_UNIXINT
 
24
#define NEED_MP_H
 
25
#include <unistd.h>
 
26
#include <string.h>
 
27
#include <stdlib.h>
 
28
#include "include.h"
 
29
 
 
30
static void
 
31
invoke_handler(int,int);
 
32
 
 
33
 
 
34
#ifndef USIG2
 
35
#include <signal.h>
 
36
#include "usig.h"
 
37
/*  #include "arith.h" */
 
38
#endif
 
39
#endif
 
40
 
 
41
#ifdef USIG2
 
42
#include USIG2
 
43
#else
 
44
 
 
45
 
 
46
 
 
47
/* these sstructure pointers would need their structures provided...
 
48
   so we just call them void */
 
49
void * sfaslp;
 
50
 
 
51
#ifdef CMAC
 
52
EXTER
 
53
unsigned long s4_neg_int[4],small_neg_int[3],small_pos_int[3];
 
54
#endif
 
55
 
 
56
 
 
57
/* 
 
58
   We have two mechanisms for protecting against interrupts.  1] We have a
 
59
   facility for delaying certain signals during critical regions of code.
 
60
   This facility will involve BEGIN_NO_INTERRUPT and END_NO_INTERRUPT
 
61
 
 
62
*/   
 
63
 
 
64
handler_function_type our_signal_handler[32];
 
65
 
 
66
struct save_for_interrupt{
 
67
   object free1[32];
 
68
   object free2[32];
 
69
   object altfree1[32];
 
70
   object altfree2[32];
 
71
   union lispunion buf[32];
 
72
   struct call_data fcall;
 
73
   object  *vs_top,vs_topVAL,*vs_base;
 
74
   struct bds_bd  *bds_top,bds_topVAL;
 
75
   struct  invocation_history *ihs_top,ihs_topVAL;
 
76
   char *token_bufp;
 
77
   char token_buf [4*INITIAL_TOKEN_LENGTH];
 
78
   int token_st_dim;
 
79
   /* for storing the XS objects in te usig2_aux.c */
 
80
   void *save_objects[75];
 
81
   
 
82
 };
 
83
 
 
84
 
 
85
/* note these are the reverse of the ones in unixint.c
 
86
   ... uggghhh*/
 
87
 
 
88
 
 
89
#undef SS1
 
90
#undef RS1
 
91
#define SS1(a,b) a =  b ;
 
92
#define RS1(a,b) b = a ;
 
93
 
 
94
           /* save objects in save_objects list  */   
 
95
 
 
96
 
 
97
 
 
98
char signals_handled [] = {SIGINT,SIGUSR2,SIGUSR1,SIGIO,SIGALRM,
 
99
#ifdef OTHER_SIGNALS_HANDLED                       
 
100
                           OTHER_SIGNALS_HANDLED
 
101
#endif                     
 
102
                           0};
 
103
 
 
104
/* * in_signal_handler:   if not zero indicates we are running inside a signal
 
105
     handler, which may have been invoked at a random intruction, and so
 
106
     it is not safe to do a relocatable gc.   
 
107
 
 
108
   * signals_pending:   if (signals_pending & signal_mask(signo)) then this
 
109
     signo 's handler is waiting to be run.
 
110
 
 
111
   * signals_allowed:  indicates the state we think we were in when
 
112
      checking to invoke a signal.  Values:
 
113
      
 
114
      sig_none:    definitely dont run handler
 
115
      sig_normal:  In principle `ok', but if desiring maximum safety dont run here.
 
116
      sig_safe:    safe point to run a function (eg make_cons,...)
 
117
      sig_at_read: interrupting the getc function in read.  Should be safe.
 
118
 
 
119
 
 
120
      unwind (used by throw,return etc) resets this to sig_normal just as it
 
121
      does the longjmp.
 
122
 
 
123
 
 
124
   If we invoke signal handling routines at a storage
 
125
   allocation pt, it is completely safe:  we should save
 
126
   some of the globals, but the freelists etc dont need
 
127
   to be saved.   pass: sig_safe to raise_pending.
 
128
 
 
129
   If we invoke it at end of a No interrupts
 
130
   region, then it we must look at whether these were nested.
 
131
   We should probably have two endings for END_NO_INTERRUPTS,
 
132
   one for when we want to raise, and one for where we are sure
 
133
   we are at safe place.  pass sig_use_signals_allowed_value
 
134
   
 
135
   If we invoke a handler when at
 
136
   signals_allowed == sig_at_read, then we are safe.
 
137
   */
 
138
 
 
139
 
 
140
#define XX sig_safe
 
141
/* min safety level required for invoking a given signal handler  */
 
142
char safety_required[]={XX,XX,XX,XX,XX,XX,XX,XX,
 
143
                        XX,XX,XX,XX,XX,XX,XX,XX,
 
144
                        XX,XX,XX,XX,XX,XX,XX,XX,
 
145
                        XX,XX,XX,XX,XX,XX,XX,XX};
 
146
 
 
147
void
 
148
gcl_init_safety(void)
 
149
{ safety_required[SIGINT]=sig_try_to_delay;
 
150
  safety_required[SIGALRM]=sig_normal;
 
151
}
 
152
  
 
153
DO_INIT(gcl_init_safety();)
 
154
DEFUN_NEW("SIGNAL-SAFETY-REQUIRED",object,sSsignal_safety_required,SI,2,2,
 
155
          NONE,OI,IO,OO,OO,(fixnum signo,fixnum safety),
 
156
      "Set the safety level required for handling SIGNO to SAFETY, or if \
 
157
SAFETY is negative just return the current safety level for that \
 
158
signal number.  Value of 1 means allow interrupt at any place not \
 
159
specifically marked in the code as bad, and value of 2 means allow it \
 
160
only in very SAFE places.")
 
161
 
 
162
{ if (signo > sizeof(safety_required))
 
163
    {FEerror("Illegal signo:~a.",1,make_fixnum(signo));}
 
164
  if (safety >=0) safety_required[signo] = safety;
 
165
  return small_fixnum(safety_required[signo]) ;
 
166
}
 
167
     
 
168
 
 
169
void
 
170
#ifdef __MINGW32__
 
171
main_signal_handler(int signo)
 
172
#else    
 
173
main_signal_handler(int signo, int a, int b)
 
174
#endif    
 
175
{  int allowed = signals_allowed;
 
176
#ifdef NEED_TO_REINSTALL_SIGNALS
 
177
       signal(signo,main_signal_handler);
 
178
#endif
 
179
    if (allowed >= safety_required[signo])
 
180
     { signals_allowed = sig_none;
 
181
       
 
182
       if (signo == SIGUSR1 ||
 
183
           signo == SIGIO)
 
184
         { unblock_sigusr_sigio();}
 
185
           
 
186
       invoke_handler(signo,allowed);
 
187
       signals_allowed = allowed;
 
188
      }
 
189
   else {
 
190
     signals_pending |= signal_mask(signo);
 
191
     alarm(1);}
 
192
   return;
 
193
 
 
194
 }
 
195
 
 
196
static void before_interrupt(struct save_for_interrupt *p, int allowed);
 
197
static void after_interrupt(struct save_for_interrupt *p, int allowed);
 
198
 
 
199
/* caller saves and restores the global signals_allowed; */
 
200
static void
 
201
invoke_handler(int signo, int allowed)
 
202
{struct save_for_interrupt buf;
 
203
 before_interrupt(&buf,allowed);
 
204
 signals_pending &= ~(signal_mask(signo));
 
205
 {int prev_in_handler = in_signal_handler;
 
206
  in_signal_handler |= (allowed <= sig_normal ? 1 : 0);
 
207
  signals_allowed = allowed;
 
208
  our_signal_handler[signo](signo);
 
209
  signals_allowed = 0;
 
210
  in_signal_handler = prev_in_handler;
 
211
  after_interrupt(&buf,allowed); 
 
212
}}
 
213
 
 
214
int tok_leng;
 
215
static void
 
216
before_interrupt(struct save_for_interrupt *p, int allowed)
 
217
{int i;
 
218
 /* all this must be run in no interrupts mode */
 
219
 if ( allowed < sig_safe)
 
220
   {                            /* save tht tops of the free stacks */
 
221
     for(i=0; i < t_end ; i++)
 
222
       { struct typemanager *ad = &tm_table[i];
 
223
         {SS1(p->free1[i],ad->tm_free);
 
224
          if (p->free1[i])
 
225
            { char *beg =  (char *) (p->free1[i]);
 
226
              object x = (object)beg;
 
227
              int amt = ad->tm_size;
 
228
              SS1(p->free2[i],OBJ_LINK(p->free1[i]));
 
229
              ad->tm_nfree --;
 
230
              bcopy(beg ,&(p->buf[i]), amt);
 
231
              bzero(beg+8,amt-8);
 
232
              x->d.m = 0;
 
233
              if (p->free2[i])
 
234
                { x = (object) p->free2[i];
 
235
                  beg = (char *)x;
 
236
                  x->d.m = 0;
 
237
                  bzero(beg+8,amt-8);
 
238
                  SS1(ad->tm_free,OBJ_LINK(p->free2[i]));
 
239
                  ad->tm_nfree --;
 
240
                }
 
241
              else
 
242
                { SS1(ad->tm_free, OBJ_LINK(p->free1[i]));
 
243
                }}
 
244
        }}
 
245
   }
 
246
 SS1(p->fcall,fcall);
 
247
 SS1(p->vs_top,vs_top);
 
248
 SS1(p->vs_topVAL,*vs_top);
 
249
 SS1(p->vs_base,vs_base);
 
250
 SS1(p->bds_top,bds_top);
 
251
 SS1(p->bds_topVAL,*bds_top);
 
252
 SS1(p->ihs_top,ihs_top);
 
253
 SS1(p->ihs_topVAL,*ihs_top);
 
254
 { void **pp = p->save_objects;
 
255
#undef XS
 
256
#undef XSI
 
257
#define XS(a) *pp++ = (void *) (a);
 
258
#define XSI(a) *pp++ = (void *)(long)(a);
 
259
/* #define XS(a) *pp++ =  * (void **) (&a);  */
 
260
#include "usig2_aux.c"
 
261
   if ((pp - (&(p->save_objects)[0])) >= (sizeof(p->save_objects)/sizeof(void *)))
 
262
     abort();
 
263
 }
 
264
#define MINN(a,b) (a<b?a :b)
 
265
 p->token_st_dim = MINN(token->st.st_dim,tok_leng+1);
 
266
 if (p->token_st_dim < sizeof(p->token_buf))
 
267
   p->token_bufp = p->token_buf;
 
268
 else { p->token_bufp= (void *)OUR_ALLOCA(p->token_st_dim);}
 
269
 bcopy(token->st.st_self,p->token_bufp,p->token_st_dim);
 
270
  
 
271
}
 
272
 
 
273
static void
 
274
after_interrupt(struct save_for_interrupt *p, int allowed)
 
275
{int i;
 
276
 /* all this must be run in no interrupts mode */
 
277
 if ( allowed < sig_safe)
 
278
   {
 
279
     for(i=0; i < t_end ; i++)
 
280
       { struct typemanager *ad = &tm_table[i];
 
281
         object current_fl = ad->tm_free;
 
282
         {RS1(p->free1[i],ad->tm_free);
 
283
          if (p->free1[i])
 
284
            { char *beg =  (char *) (p->free1[i]);
 
285
              object x = (object)beg;
 
286
              int amt = ad->tm_size;
 
287
              RS1(p->free2[i],(p->free1[i]));
 
288
              if (x->d.m) error("should not be free");
 
289
              bcopy(&(p->buf[i]),beg, amt);
 
290
              if (p->free2[i])
 
291
                { x = (object) p->free2[i];
 
292
                  if (x->d.m) error("should not be free");
 
293
                  x->d.m = FREE;
 
294
                  F_LINK(F_LINK(ad->tm_free)) = (long )current_fl;
 
295
                  ad->tm_nfree += 2;
 
296
                }
 
297
              else
 
298
                ad->tm_nfree =1;
 
299
            }
 
300
       
 
301
          else     ad->tm_nfree =0;
 
302
        }}
 
303
   }
 
304
  RS1(p->fcall,fcall);
 
305
  RS1(p->vs_top,vs_top);
 
306
  RS1(p->vs_topVAL,*vs_top);
 
307
  RS1(p->vs_base,vs_base);
 
308
  RS1(p->bds_top,bds_top);
 
309
  RS1(p->bds_topVAL,*bds_top);
 
310
  RS1(p->ihs_top,ihs_top);
 
311
  RS1(p->ihs_topVAL,*ihs_top);
 
312
 { void **pp = p->save_objects;
 
313
#undef XS
 
314
#undef XSI
 
315
 
 
316
 /*  #define XS(a) a = (void *)(*pp++)
 
317
     We store back in the location 'a' the value we have saved. 
 
318
  */
 
319
 
 
320
/* #define XS(a) do { void **_p = (void **)(&a); *_p = (void *)(*pp++);}while(0) */
 
321
#define XS(a) a = (void *)(*pp++)
 
322
#define XSI(a) {union {void *v;long l;}u; u.v=*pp++; a = u.l;}
 
323
#include "usig2_aux.c"
 
324
 }
 
325
 
 
326
  bcopy(p->token_bufp,token->st.st_self,p->token_st_dim);
 
327
}
 
328
 
 
329
 
 
330
/* claim the following version of make_cons can be interrupted at any line
 
331
   and is suitable for inlining.
 
332
*/
 
333
 
 
334
/* static object */
 
335
/* MakeCons(object a, object b) */
 
336
/* { struct typemanager*ad = &tm_table[t_cons]; */
 
337
/*   object new = (object) ad->tm_free; */
 
338
/*   if (new == 0) */
 
339
/*     { new = alloc_object(t_cons); */
 
340
/*       new->c.c_car = a; */
 
341
/*       goto END; */
 
342
/*     } */
 
343
      
 
344
/*   new->c.c_car=a; */
 
345
  /* interrupt here and before_interrupt will copy new->c into the
 
346
     C stack, so that a will be protected */
 
347
/*   new->c.t=t_cons; */
 
348
/*   new->c.m= 0; */
 
349
  /*  Make interrupt copy new out to the stack and then zero new.
 
350
      That way new is certainly gc valid, and its contents are protected.
 
351
      So the above three operations can occur in any order.
 
352
      */
 
353
 
 
354
/*   { object tem  = OBJ_LINK(new); */
 
355
    /*
 
356
      interrupt here and we see that before_interrupt must save the top of the
 
357
      free list AND the second thing on the Free list.  That way we will be ok
 
358
      here and an interrupt here could not affect tem.  It is possible that tem
 
359
      == 0, yet a gc happened in between.  An interrupt here when tem = 0 would
 
360
      mean the free list needs to be collected again by second gc.
 
361
      */
 
362
/*     ad->tm_free = tem; */
 
363
/*   } */
 
364
  /* Whew:  we got it safely off so interrupts can't hurt us now.  */
 
365
/*   ad->tm_nfree --; */
 
366
  /* interrupt here and the cdr field will point to a f_link which is
 
367
     a 'free' and so gc valid.   b is still protected since
 
368
     it is in the stack or a regiseter, and a is protected since it is
 
369
     in new, and new is not free
 
370
     */
 
371
/*  END: */
 
372
/*   new->c.c_cdr=b; */
 
373
/*   return new; */
 
374
/* } */
 
375
 
 
376
 
 
377
/* COND is the condition where this is raised.
 
378
   Might be sig_safe (eg at cons). */
 
379
   
 
380
void
 
381
raise_pending_signals(int cond)
 
382
{unsigned int allowed = signals_allowed ;
 
383
 if (cond == sig_use_signals_allowed_value)
 
384
 if (cond == sig_none  || interrupt_enable ==0) return ;
 
385
 
 
386
 
 
387
 AGAIN:
 
388
 { unsigned int pending = signals_pending;
 
389
   char *p = signals_handled;
 
390
   if (pending)
 
391
     while(*p)
 
392
       { if (signal_mask(*p) & pending
 
393
             && cond >= safety_required[(unsigned char)*p])
 
394
           {
 
395
             signals_pending &= ~(signal_mask(*p));
 
396
             if (*p == SIGALRM && cond >= sig_safe)
 
397
               { alarm(0);}
 
398
             else
 
399
               invoke_handler(*p,cond);
 
400
             goto AGAIN;
 
401
           }
 
402
           p++;
 
403
         }
 
404
   signals_allowed = allowed; 
 
405
   return;
 
406
 }}
 
407
 
 
408
 
 
409
DEFUN_NEW("ALLOW-SIGNAL",object,fSallow_signal,SI,1,1,NONE,OI,OO,OO,OO,(fixnum n),
 
410
      "Install the default signal handler on signal N")
 
411
 
 
412
{
 
413
 
 
414
 signals_allowed |= signal_mask(n);
 
415
 unblock_signals(n,n);
 
416
 /* sys v ?? just restore the signal ?? */
 
417
 if (our_signal_handler[n])
 
418
   {gcl_signal(n,our_signal_handler[n]);
 
419
    return make_fixnum(1);
 
420
  }
 
421
 else
 
422
   return make_fixnum(0);
 
423
}
 
424
 
 
425
 
 
426
 
 
427
#endif