~ubuntu-branches/ubuntu/intrepid/mit-scheme/intrepid-updates

« back to all changes in this revision

Viewing changes to src/microcode/bchdrn.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Hanson
  • Date: 2002-03-14 17:04:07 UTC
  • Revision ID: james.westby@ubuntu.com-20020314170407-m5lg1d6bdsl9lv0s
Tags: upstream-7.7.0
ImportĀ upstreamĀ versionĀ 7.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- C -*-
 
2
 
 
3
$Id: bchdrn.c,v 1.10 2000/12/05 21:23:42 cph Exp $
 
4
 
 
5
Copyright (c) 1991-2000 Massachusetts Institute of Technology
 
6
 
 
7
This program is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2 of the License, or (at
 
10
your option) any later version.
 
11
 
 
12
This program is distributed in the hope that it will be useful, but
 
13
WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with this program; if not, write to the Free Software
 
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
*/
 
21
 
 
22
/* Drone program for overlapped I/O in bchscheme. */
 
23
 
 
24
#include "ux.h"
 
25
#include "bchdrn.h"
 
26
#if 0
 
27
/* ux.h includes <setjmp.h> indirectly */
 
28
#  include <setjmp.h>
 
29
#endif
 
30
 
 
31
#define DEBUG
 
32
/* #define DEBUG_1 */
 
33
/* #define DEBUG_2 */
 
34
 
 
35
extern char * EXFUN (error_name, (int));
 
36
extern int EXFUN (retrying_file_operation,
 
37
                  (ssize_t EXFUN ((*), (int, char *, int)),
 
38
                   int, char *, long, long, char *, char *, long *,
 
39
                   int EXFUN ((*), (char *, char *))));
 
40
 
 
41
#ifdef USE_SYSV_SHARED_MEMORY
 
42
 
 
43
static struct
 
44
{
 
45
  char * program_name;
 
46
  char * file_name;             /* gc file name */
 
47
  int shmid;                    /* shared memory descriptor */
 
48
  int tdron;                    /* total number of drones */
 
49
  int nbuf;                     /* total number of buffers */
 
50
  long bufsiz;                  /* size of each buffer in bytes */
 
51
  int sdron;                    /* index of first drone to start */
 
52
  int ndron;                    /* number of drones to start */
 
53
  int keep_p;                   /* keep the gc file if Scheme dies? */
 
54
} arguments;
 
55
 
 
56
struct argdesc
 
57
{
 
58
  char * name;
 
59
  char * format;
 
60
  PTR location;
 
61
};
 
62
 
 
63
static char string_a[] = "%s";
 
64
#define STRING_FMT &string_a[0]
 
65
 
 
66
static char decimal_int_a[] = "%d";
 
67
#define DECIMAL_INT_FMT &decimal_int_a[0]
 
68
 
 
69
static char decimal_long_a[] = "%ld";
 
70
#define DECIMAL_LONG_FMT &decimal_long_a[0]
 
71
 
 
72
static struct argdesc command_line[] =
 
73
{
 
74
  { "program_name",     STRING_FMT,             &arguments.program_name },
 
75
  { "file_name",        STRING_FMT,             &arguments.file_name },
 
76
  { "shmid",            DECIMAL_INT_FMT,        &arguments.shmid },
 
77
  { "tdron",            DECIMAL_INT_FMT,        &arguments.tdron },
 
78
  { "nbuf",             DECIMAL_INT_FMT,        &arguments.nbuf },
 
79
  { "bufsiz",           DECIMAL_LONG_FMT,       &arguments.bufsiz },
 
80
  { "sdron",            DECIMAL_INT_FMT,        &arguments.sdron },
 
81
  { "ndron",            DECIMAL_INT_FMT,        &arguments.ndron },
 
82
  { "keep_gc_file",     DECIMAL_INT_FMT,        &arguments.keep_p }
 
83
};
 
84
 
 
85
static int gc_fid = -1;
 
86
static char * shared_memory;
 
87
static struct buffer_info * gc_buffers;
 
88
static struct drone_info * myself;
 
89
static unsigned long * drone_version, * wait_mask;
 
90
static jmp_buf abort_point;
 
91
static pid_t boss_pid;
 
92
 
 
93
static void EXFUN (kill_program, (int sig));
 
94
 
 
95
static void 
 
96
DEFUN (posix_signal, (signum, handler),
 
97
       int signum AND void EXFUN ((*handler), ()))
 
98
{
 
99
  struct sigaction new;
 
100
 
 
101
  new.sa_handler = handler;
 
102
  UX_sigemptyset (&new.sa_mask);
 
103
  UX_sigaddset ((&new.sa_mask), SIGCONT);
 
104
  UX_sigaddset ((&new.sa_mask), SIGQUIT);
 
105
  new.sa_flags = SA_NOCLDSTOP;
 
106
  
 
107
  if ((UX_sigaction (signum, &new, 0)) == -1)
 
108
  {
 
109
    fprintf (stderr, "%s (%d, posix_signal): sigaction failed. errno = %s.\n",
 
110
             arguments.program_name, myself->index, (error_name (errno)));
 
111
    fflush (stderr);
 
112
    kill_program (0);
 
113
    /*NOTREACHED*/
 
114
  }
 
115
  return;
 
116
}
 
117
 
 
118
static void
 
119
DEFUN (kill_program, (sig), int sig)
 
120
{
 
121
  myself->state = drone_dead;
 
122
  if (gc_fid != -1)
 
123
    close (gc_fid);
 
124
  shmdt (shared_memory);
 
125
  if (sig == -1)
 
126
  {
 
127
    shmctl (arguments.shmid, IPC_RMID, ((struct shmid_ds *) 0));
 
128
    if (!arguments.keep_p)
 
129
      unlink (arguments.file_name);
 
130
  }
 
131
  exit (0);
 
132
  /*NOTREACHED*/
 
133
}
 
134
 
 
135
static void
 
136
DEFUN (abort_operation, (sig), int sig)
 
137
{
 
138
  RE_INSTALL_HANDLER (SIGQUIT, abort_operation);
 
139
  myself->state = drone_aborting;
 
140
  longjmp (abort_point, 1);
 
141
  /*NOTREACHED*/
 
142
}
 
143
 
 
144
static void
 
145
DEFUN (continue_running, (sig), int sig)
 
146
{
 
147
  RE_INSTALL_HANDLER (SIGCONT, continue_running);
 
148
  longjmp (abort_point, 1);
 
149
  /*NOTREACHED*/
 
150
}
 
151
 
 
152
static int
 
153
DEFUN (always_one, (operation_name, noise),
 
154
       char * operation_name AND char * noise)
 
155
{
 
156
  return (1);
 
157
}
 
158
 
 
159
static void
 
160
DEFUN (process_requests, (drone), struct drone_info * drone)
 
161
{
 
162
  sigset_t non_blocking_signal_mask, blocking_signal_mask;
 
163
  int result, count, buffer_index, flags;
 
164
  long current_position = -1;
 
165
  struct timeval timeout;
 
166
  struct stat file_info;
 
167
  unsigned long read_mask, my_mask;
 
168
 
 
169
  myself = drone;
 
170
  my_mask = (((unsigned long) 1) << drone->index);
 
171
  drone->DRONE_PID = (getpid ());
 
172
  gc_fid = (open (arguments.file_name, O_RDWR, 0644));
 
173
  if (gc_fid == -1)
 
174
  {
 
175
    fprintf (stderr,
 
176
             "%s (%d, process_requests): open failed. errno = %s.\n",   
 
177
             arguments.program_name, drone->index, (error_name (errno)));
 
178
    fflush (stderr);
 
179
    if (drone->DRONE_PPID == boss_pid)
 
180
      (void) (kill (boss_pid, SIGCONT));
 
181
    kill_program (0);
 
182
    /*NOTREACHED*/
 
183
  }
 
184
#ifdef DEBUG_1
 
185
  printf ("%s (%d, process_requests): Starting (pid = %d, ppid = %d).\n",
 
186
          arguments.program_name, drone->index,
 
187
          drone->DRONE_PID, drone->DRONE_PPID);
 
188
  fflush (stdout);
 
189
#endif
 
190
  if ((result = (fstat (gc_fid, &file_info))) == -1)
 
191
  {
 
192
    fprintf (stderr,
 
193
             "%s (%d, process_requests): fstat failed. errno = %s.\n",
 
194
             arguments.program_name, drone->index, (error_name (errno)));
 
195
    fflush (stderr);
 
196
  }
 
197
  /* Force O_SYNC only if we are dealing with a raw device. */
 
198
    
 
199
  if ((result == -1) || ((file_info.st_mode & S_IFMT) == S_IFCHR))
 
200
  {
 
201
    if ((flags = (fcntl (gc_fid, F_GETFL, 0))) == -1)
 
202
    {
 
203
      fprintf
 
204
        (stderr,
 
205
         "%s (%d, process_requests): fcntl (F_GETFL) failed. errno = %s.\n",
 
206
         arguments.program_name, drone->index, (error_name (errno)));
 
207
      fflush (stderr);
 
208
    }
 
209
    else
 
210
    {
 
211
      flags |= O_SYNC;
 
212
      if ((fcntl (gc_fid, F_SETFL, flags)) == -1)
 
213
      {
 
214
        fprintf
 
215
          (stderr,
 
216
           "%s (%d, process_requests): fcntl (F_SETFL) failed. errno = %s.\n",
 
217
           arguments.program_name, drone->index, (error_name (errno)));
 
218
        fflush (stderr);
 
219
      }
 
220
    }
 
221
  }
 
222
 
 
223
  UX_sigemptyset (&non_blocking_signal_mask);
 
224
  UX_sigemptyset (&blocking_signal_mask);
 
225
  UX_sigaddset ((&blocking_signal_mask), SIGCONT);
 
226
  UX_sigaddset ((&blocking_signal_mask), SIGQUIT);
 
227
  UX_sigprocmask (SIG_SETMASK, (&blocking_signal_mask), 0);
 
228
  posix_signal (SIGQUIT, abort_operation);
 
229
  posix_signal (SIGCONT, continue_running);
 
230
 
 
231
  if ((setjmp (abort_point)) == 0)
 
232
  {
 
233
    count = drone->index; 
 
234
    drone->state = drone_idle;
 
235
    if (drone->DRONE_PPID == boss_pid)
 
236
      (void) (kill (boss_pid, SIGCONT));
 
237
  }
 
238
  else
 
239
    goto redo_dispatch;
 
240
 
 
241
  for (; 1; count++)
 
242
  {
 
243
    timeout.tv_sec = 6;
 
244
    timeout.tv_usec = 0;
 
245
 
 
246
    UX_sigprocmask (SIG_SETMASK, (&non_blocking_signal_mask), 0);
 
247
    result = (select (0, 0, 0, 0, &timeout));
 
248
    UX_sigprocmask (SIG_SETMASK, (&blocking_signal_mask), 0);
 
249
 
 
250
    if ((drone->state != drone_idle)
 
251
        || ((result == -1) && (errno == EINTR)))
 
252
    {
 
253
      if (result != -1)
 
254
      {
 
255
        fprintf (stderr,
 
256
                 "\n%s (%d, process_requests): request after timeout %d.\n",
 
257
                 arguments.program_name, drone->index, drone->state);
 
258
        fflush (stderr);
 
259
      }
 
260
redo_dispatch:
 
261
      switch (drone->state)
 
262
      {
 
263
        default:
 
264
          fprintf (stderr,
 
265
                   "\n%s (%d, process_requests): Unknown/bad operation %d.\n",
 
266
                   arguments.program_name, drone->index, drone->state);
 
267
          fflush (stderr);
 
268
          kill_program (0);
 
269
          /*NOTREACHED*/
 
270
 
 
271
        case drone_idle:
 
272
          break;
 
273
 
 
274
        case drone_aborting:
 
275
#ifdef DEBUG_1
 
276
          printf ("\n%s (%d, process_requests): Aborting.",
 
277
                  arguments.program_name, drone->index);
 
278
          fflush (stdout);
 
279
#endif
 
280
          drone->buffer_index = -1;
 
281
          current_position = -1;
 
282
          break;
 
283
 
 
284
        case drone_reading:
 
285
        case drone_writing:
 
286
        {
 
287
          /* Can't use buffer->bottom because the shared memory may be
 
288
             attached at a different address!
 
289
           */
 
290
 
 
291
          int saved_errno;
 
292
          enum drone_state operation;
 
293
          char * operation_name, * buffer_address;
 
294
          struct buffer_info * buffer;
 
295
          struct gc_queue_entry * entry;
 
296
 
 
297
          operation = drone->state;
 
298
          buffer_index = (drone->buffer_index);
 
299
          buffer = (gc_buffers + buffer_index);
 
300
 
 
301
          entry = ((struct gc_queue_entry *)
 
302
                   (((char *) drone) + (drone->entry_offset)));
 
303
          entry->error_code = 0;
 
304
 
 
305
          operation_name = ((operation == drone_reading) ? "read" : "write");
 
306
          buffer_address = (shared_memory + (arguments.bufsiz * buffer_index));
 
307
#ifdef DEBUG_1
 
308
          printf ("\n%s (%d, process_requests %s): Buffer index = %d.\n",
 
309
                  arguments.program_name, drone->index, operation_name,
 
310
                  buffer_index);
 
311
          printf ("\tBuffer address = 0x%lx; Position = 0x%lx; Size = 0x%lx.",
 
312
                  buffer_address, buffer->position, buffer->size);
 
313
          fflush (stdout);
 
314
#endif
 
315
 
 
316
          UX_sigprocmask (SIG_SETMASK, (&non_blocking_signal_mask), 0);
 
317
          result = (retrying_file_operation
 
318
                    (((operation == drone_reading) ? read : write),
 
319
                     gc_fid, buffer_address,
 
320
                     buffer->position, buffer->size, operation_name, NULL,
 
321
                     &current_position, always_one));
 
322
          saved_errno = errno;
 
323
          UX_sigprocmask (SIG_SETMASK, (&blocking_signal_mask), 0);
 
324
 
 
325
          if (result == -1)
 
326
          {
 
327
            buffer->state = ((operation == drone_reading)
 
328
                             ? buffer_read_error
 
329
                             : buffer_write_error);
 
330
            drone->buffer_index = -1;
 
331
            entry->drone_index = -1;
 
332
            entry->error_code = saved_errno;
 
333
            entry->state = entry_error;
 
334
            current_position = -1;
 
335
#ifdef DEBUG
 
336
            printf ("\n%s (%d, process_requests): %s error (errno = %s).\n",
 
337
                    arguments.program_name, drone->index, operation_name,
 
338
                    (error_name (saved_errno)));
 
339
            fflush (stdout);
 
340
#endif
 
341
          }
 
342
 
 
343
          else
 
344
          {
 
345
            buffer->state = ((operation == drone_reading)
 
346
                             ? buffer_ready
 
347
                             : buffer_idle);
 
348
            drone->buffer_index = -1;
 
349
            entry->drone_index = -1;
 
350
            if (operation == drone_writing)
 
351
            {
 
352
              entry->retry_count = 0;
 
353
              entry->state = entry_idle;
 
354
            }
 
355
 
 
356
#ifdef DEBUG_1
 
357
          printf ("\n%s (%d, process_requests %s): Done.",
 
358
                  arguments.program_name, drone->index, operation_name);
 
359
          fflush (stdout);
 
360
#endif
 
361
          }
 
362
        }
 
363
      }
 
364
 
 
365
      count = 0;
 
366
      drone->state = drone_idle;
 
367
      read_mask = (* wait_mask);
 
368
      if ((read_mask & my_mask) == my_mask)
 
369
        (void) (kill (boss_pid, SIGCONT));
 
370
    }
 
371
    else if (result == 0)
 
372
    {
 
373
      if (count == arguments.tdron)
 
374
      {
 
375
        count = 0;
 
376
        if ((kill (boss_pid, 0)) == -1)
 
377
          kill_program (-1);
 
378
      }
 
379
      read_mask = (* wait_mask);
 
380
      if ((read_mask & my_mask) == my_mask)
 
381
      {
 
382
        fprintf (stderr,
 
383
                 "\n%s (%d, process_requests): signal deadlock (%s)!\n",
 
384
                 arguments.program_name, drone->index,
 
385
                 ((read_mask == ((unsigned long) -1)) ? "any" : "me"));
 
386
        fflush (stderr);
 
387
        drone->state = drone_idle; /* !! */
 
388
        (void) (kill (boss_pid, SIGCONT));
 
389
      }
 
390
    }
 
391
  }
 
392
}
 
393
 
 
394
static void
 
395
DEFUN_VOID (start_drones)
 
396
{
 
397
  pid_t my_pid;
 
398
  int counter, cpid;
 
399
  struct drone_info *gc_drones, *drone;
 
400
 
 
401
  my_pid = (getpid ());
 
402
 
 
403
  shared_memory = (shmat (arguments.shmid, ((char *) 0), 0));
 
404
  if (shared_memory == ((char *) -1))
 
405
  {
 
406
    fprintf (stderr,
 
407
             "\
 
408
%s (start_drones): Unable to attach shared memory segment %d (errno = %s).\n",
 
409
             arguments.program_name, arguments.shmid, (error_name (errno)));
 
410
    fflush (stderr);
 
411
    sleep (10);
 
412
    kill (boss_pid, SIGCONT);
 
413
    exit (1);
 
414
  }
 
415
#ifdef DEBUG_1
 
416
  printf ("%s (start_drones): Attached shared memory at address = 0x%lx.\n",
 
417
          arguments.program_name, ((long) shared_memory));
 
418
  fflush (stdout);
 
419
#endif
 
420
  posix_signal (SIGINT, SIG_IGN);
 
421
  posix_signal (SIGQUIT, SIG_IGN);
 
422
  posix_signal (SIGHUP, kill_program);
 
423
  posix_signal (SIGTERM, kill_program);
 
424
 
 
425
  gc_buffers = ((struct buffer_info *)
 
426
                (shared_memory + (arguments.nbuf * arguments.bufsiz)));
 
427
  gc_drones = ((struct drone_info *) (gc_buffers + arguments.nbuf));
 
428
  drone_version = ((unsigned long *) (gc_drones + arguments.tdron));
 
429
  wait_mask = (drone_version + 1);
 
430
  if ((* drone_version) != ((unsigned long) DRONE_VERSION_NUMBER))
 
431
  {
 
432
    fprintf (stderr,
 
433
             "%s (start_drones): stored drone version != drone version.\n",
 
434
             arguments.program_name);
 
435
    fprintf (stderr, "\t*drone_version = %ld; DRONE_VERSION_NUMBER = %ld.\n",
 
436
             (* drone_version), ((unsigned long) DRONE_VERSION_NUMBER));
 
437
    fflush (stderr);
 
438
    kill (boss_pid, SIGCONT);
 
439
    exit (1);
 
440
  }
 
441
 
 
442
  for (counter = 1, drone = (gc_drones + (arguments.sdron + 1));
 
443
       counter < arguments.ndron;
 
444
       counter++, drone ++)
 
445
  {
 
446
    if ((cpid = (fork ())) == 0)
 
447
    {
 
448
      drone->DRONE_PPID = my_pid;
 
449
      process_requests (drone);
 
450
      /*NOTREACHED*/
 
451
    }
 
452
    else if (cpid == -1)
 
453
    {
 
454
      fprintf (stderr,
 
455
               "%s (start_drones): fork failed; errno = %s.\n",
 
456
               arguments.program_name, (error_name (errno)));
 
457
      fflush (stderr);
 
458
    }
 
459
  }
 
460
  drone = (gc_drones + arguments.sdron);
 
461
  drone->DRONE_PPID = boss_pid;
 
462
  /* This is non-portable behavior to prevent zombies from being created. */
 
463
  if (arguments.ndron != 1)
 
464
    posix_signal (SIGCHLD, SIG_IGN);
 
465
  process_requests (drone);
 
466
  /*NOTREACHED*/
 
467
}
 
468
 
 
469
int
 
470
DEFUN (main, (argc, argv), int argc AND char ** argv)
 
471
{
 
472
  int count, nargs;
 
473
  static char err_buf[1024];
 
474
#if defined(DEBUG) || defined(DEBUG_1) || defined(DEBUG_2)
 
475
  static char out_buf[1024];
 
476
 
 
477
  setvbuf (stdout, &out_buf[0], _IOFBF, (sizeof (out_buf)));
 
478
#endif
 
479
  setvbuf (stderr, &err_buf[0], _IOFBF, (sizeof (err_buf)));
 
480
 
 
481
#ifdef DEBUG_2
 
482
  printf ("%s (main): Arguments =\n", argv[0]);
 
483
  for (count = 1; count < argc; count++)
 
484
    printf ("\t%s\n", argv[count]);
 
485
  fflush (stdout);
 
486
#endif
 
487
 
 
488
  nargs = ((sizeof (command_line)) / (sizeof (struct argdesc)));
 
489
  boss_pid = (getppid ());
 
490
  if (argc != nargs)
 
491
  {
 
492
    fprintf (stderr,
 
493
             "%s (main): Wrong number of arguments (got %d, expected %d).\n",
 
494
             argv[0], (argc - 1), (nargs - 1));
 
495
    fflush (stderr);
 
496
    kill (boss_pid, SIGCONT);
 
497
    exit (1);
 
498
  }
 
499
  for (count = 0; count < nargs; count++)
 
500
  {
 
501
    if (command_line[count].format == STRING_FMT)
 
502
      (* ((char **) command_line[count].location)) = argv[count];
 
503
    else
 
504
      sscanf (argv[count],
 
505
              command_line[count].format,
 
506
              command_line[count].location);
 
507
  }
 
508
 
 
509
#ifdef DEBUG_2
 
510
  printf ("%s (main): Parsed arguments =\n", argv[0]);
 
511
  for (count = 0; count < nargs; count++)
 
512
  {
 
513
    if (command_line[count].format == STRING_FMT)
 
514
      printf ("\t%s\t= %s\n",
 
515
              command_line[count].name,
 
516
              (* ((char **) (command_line[count].location))));
 
517
    else
 
518
      printf ("\t%s\t= %d\n",
 
519
              command_line[count].name,
 
520
              (* ((int *) (command_line[count].location))));
 
521
  }
 
522
  fflush (stdout);
 
523
#endif
 
524
 
 
525
  start_drones ();
 
526
  /*NOTREACHED*/
 
527
  return (0);
 
528
}
 
529
 
 
530
#define MAIN main
 
531
 
 
532
#endif /* USE_SYSV_SHARED_MEMORY */
 
533
 
 
534
#ifndef MAIN
 
535
 
 
536
int
 
537
DEFUN (main, (argc, argv), int argc AND char ** argv)
 
538
{
 
539
  fprintf (stderr, "%s: Not implemented.\n", (argv[0]));
 
540
  fflush (stderr);
 
541
  exit (1);
 
542
  return (1);
 
543
}
 
544
 
 
545
#endif /* MAIN */