~ubuntu-branches/ubuntu/hoary/cdrtools/hoary

« back to all changes in this revision

Viewing changes to cdrecord/fifo.c

  • Committer: Bazaar Package Importer
  • Author(s): Eduard Bloch
  • Date: 2002-04-09 10:03:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020409100306-t4hagiv7gm0fhggv
Tags: upstream-1.10
ImportĀ upstreamĀ versionĀ 1.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* @(#)fifo.c   1.28 01/04/11 Copyright 1989,1997 J. Schilling */
 
2
#ifndef lint
 
3
static  char sccsid[] =
 
4
        "@(#)fifo.c     1.28 01/04/11 Copyright 1989,1997 J. Schilling";
 
5
#endif
 
6
/*
 
7
 *      A "fifo" that uses shared memory between two processes
 
8
 *
 
9
 *      The actual code is a mixture of borrowed code from star's fifo.c
 
10
 *      and a proposal from Finn Arne Gangstad <finnag@guardian.no>
 
11
 *      who had the idea to use a ring buffer to handle average size chunks.
 
12
 *
 
13
 *      Copyright (c) 1989,1997 J. Schilling
 
14
 */
 
15
/*
 
16
 * This program is free software; you can redistribute it and/or modify
 
17
 * it under the terms of the GNU General Public License as published by
 
18
 * the Free Software Foundation; either version 2, or (at your option)
 
19
 * any later version.
 
20
 *
 
21
 * This program is distributed in the hope that it will be useful,
 
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
24
 * GNU General Public License for more details.
 
25
 *
 
26
 * You should have received a copy of the GNU General Public License
 
27
 * along with this program; see the file COPYING.  If not, write to
 
28
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
29
 */
 
30
 
 
31
#define DEBUG
 
32
/*#define       XDEBUG*/
 
33
#include <mconfig.h>
 
34
#if     !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM)
 
35
#undef  FIFO                    /* We cannot have a FIFO on this platform */
 
36
#endif
 
37
#ifdef  FIFO
 
38
#if !defined(USE_MMAP) && !defined(USE_USGSHM)
 
39
#define USE_MMAP
 
40
#endif
 
41
#ifndef HAVE_SMMAP
 
42
#       undef   USE_MMAP
 
43
#       define  USE_USGSHM      /* now SYSV shared memory is the default*/
 
44
#endif
 
45
#ifdef  USE_MMAP                /* Only want to have one implementation */
 
46
#       undef   USE_USGSHM      /* mmap() is preferred                  */
 
47
#endif
 
48
 
 
49
#ifdef  HAVE_DOSALLOCSHAREDMEM  /* This is for OS/2 */
 
50
#       undef   USE_MMAP
 
51
#       undef   USE_USGSHM
 
52
#       define  USE_OS2SHM
 
53
#endif
 
54
 
 
55
#include <fctldefs.h>
 
56
#include <sys/types.h>
 
57
#if defined(HAVE_SMMAP) && defined(USE_MMAP)
 
58
#include <mmapdefs.h>
 
59
#endif
 
60
#include <stdio.h>
 
61
#include <stdxlib.h>
 
62
#include <unixstd.h>
 
63
#include <waitdefs.h>
 
64
#include <utypes.h>
 
65
#include <standard.h>
 
66
#include <errno.h>
 
67
#include <signal.h>
 
68
#include <libport.h>
 
69
#include <schily.h>
 
70
 
 
71
#include "cdrecord.h"
 
72
 
 
73
#ifdef DEBUG
 
74
#ifdef XDEBUG
 
75
FILE    *ef;
 
76
#define USDEBUG1        if (debug) {if(s == owner_reader)fprintf(ef, "r");else fprintf(ef, "w");fflush(ef);}
 
77
#define USDEBUG2        if (debug) {if(s == owner_reader)fprintf(ef, "R");else fprintf(ef, "W");fflush(ef);}
 
78
#else
 
79
#define USDEBUG1
 
80
#define USDEBUG2
 
81
#endif
 
82
#define EDEBUG(a)       if (debug) error a
 
83
#else
 
84
#define EDEBUG(a)
 
85
#define USDEBUG1
 
86
#define USDEBUG2
 
87
#endif
 
88
 
 
89
#define palign(x, a)    (((char *)(x)) + ((a) - 1 - (((unsigned)((x)-1))%(a))))
 
90
 
 
91
typedef enum faio_owner {
 
92
        owner_none,             /* Unused in real life                       */
 
93
        owner_writer,           /* owned by process that writes into FIFO    */
 
94
        owner_faio,             /* Intermediate state when buf still in use  */
 
95
        owner_reader            /* owned by process that reads from FIFO     */
 
96
} fowner_t;
 
97
 
 
98
char    *onames[] = {
 
99
        "none",
 
100
        "writer",
 
101
        "faio",
 
102
        "reader",
 
103
};
 
104
 
 
105
typedef struct faio {
 
106
        int     len;
 
107
        volatile fowner_t owner;
 
108
        volatile int users;
 
109
        short   fd;
 
110
        short   saved_errno;
 
111
        char    *bufp;
 
112
} faio_t;
 
113
 
 
114
struct faio_stats {
 
115
        long    puts;
 
116
        long    gets;
 
117
        long    empty;
 
118
        long    full;
 
119
        long    done;
 
120
        long    cont_low;
 
121
        int     users;
 
122
} *sp;
 
123
 
 
124
#define MIN_BUFFERS     3
 
125
 
 
126
#define MSECS   1000
 
127
#define SECS    (1000*MSECS)
 
128
 
 
129
/*
 
130
 * Note: WRITER_MAXWAIT & READER_MAXWAIT need to be greater than the SCSI
 
131
 * timeout for commands that write to the media. This is currently 200s
 
132
 * if we are in SAO mode.
 
133
 */
 
134
/* microsecond delay between each buffer-ready probe by writing process */
 
135
#define WRITER_DELAY    (20*MSECS)
 
136
#define WRITER_MAXWAIT  (240*SECS)      /* 240 seconds max wait for data */
 
137
 
 
138
/* microsecond delay between each buffer-ready probe by reading process */
 
139
#define READER_DELAY    (80*MSECS)
 
140
#define READER_MAXWAIT  (240*SECS)      /* 240 seconds max wait for reader */
 
141
 
 
142
LOCAL   char    *buf;
 
143
LOCAL   char    *bufbase;
 
144
LOCAL   char    *bufend;
 
145
LOCAL   long    buflen;
 
146
 
 
147
extern  int     debug;
 
148
extern  int     lverbose;
 
149
 
 
150
EXPORT  void    init_fifo       __PR((long));
 
151
#ifdef  USE_MMAP
 
152
LOCAL   char*   mkshare         __PR((int size));
 
153
#endif
 
154
#ifdef  USE_USGSHM
 
155
LOCAL   char*   mkshm           __PR((int size));
 
156
#endif
 
157
#ifdef  USE_OS2SHM
 
158
LOCAL   char*   mkos2shm        __PR((int size));
 
159
#endif
 
160
 
 
161
EXPORT  BOOL    init_faio       __PR((int tracks, track_t *track, int));
 
162
EXPORT  BOOL    await_faio      __PR((void));
 
163
EXPORT  void    kill_faio       __PR((void));
 
164
EXPORT  int     wait_faio       __PR((void));
 
165
LOCAL   void    faio_reader     __PR((int tracks, track_t *track));
 
166
LOCAL   void    faio_read_track __PR((track_t *trackp));
 
167
LOCAL   void    faio_wait_on_buffer __PR((faio_t *f, fowner_t s,
 
168
                                          unsigned long delay,
 
169
                                          unsigned long max_wait));
 
170
LOCAL   int     faio_read_segment __PR((int fd, faio_t *f, int len));
 
171
LOCAL   faio_t  *faio_ref       __PR((int n));
 
172
EXPORT  int     faio_read_buf   __PR((int f, char *bp, int size));
 
173
EXPORT  int     faio_get_buf    __PR((int f, char **bpp, int size));
 
174
EXPORT  void    fifo_stats      __PR((void));
 
175
EXPORT  int     fifo_percent    __PR((BOOL addone));
 
176
 
 
177
 
 
178
EXPORT void
 
179
init_fifo(fs)
 
180
        long    fs;
 
181
{
 
182
        int     pagesize;
 
183
 
 
184
        if (fs == 0L)
 
185
                return;
 
186
 
 
187
#ifdef  _SC_PAGESIZE
 
188
        pagesize = sysconf(_SC_PAGESIZE);
 
189
#else
 
190
        pagesize = getpagesize();
 
191
#endif
 
192
        buflen = roundup(fs, pagesize) + pagesize;
 
193
        EDEBUG(("fs: %ld buflen: %ld\n", fs, buflen));
 
194
 
 
195
#if     defined(USE_MMAP)
 
196
        buf = mkshare(buflen);
 
197
#endif
 
198
#if     defined(USE_USGSHM)
 
199
        buf = mkshm(buflen);
 
200
#endif
 
201
#if     defined(USE_OS2SHM)
 
202
        buf = mkos2shm(buflen);
 
203
#endif
 
204
 
 
205
        bufbase = buf;
 
206
        bufend = buf + buflen;
 
207
        EDEBUG(("buf: %p bufend: %p, buflen: %ld\n", buf, bufend, buflen));
 
208
        buf = palign(buf, pagesize);
 
209
        buflen -= buf - bufbase;
 
210
        EDEBUG(("buf: %p bufend: %p, buflen: %ld (align %ld)\n", buf, bufend, buflen, (long)(buf - bufbase)));
 
211
 
 
212
        /*
 
213
         * Dirty the whole buffer. This can die with various signals if
 
214
         * we're trying to lock too much memory
 
215
         */
 
216
        fillbytes(buf, buflen, '\0');
 
217
 
 
218
#ifdef  XDEBUG
 
219
        if (debug)
 
220
                ef = fopen("/tmp/ef", "w");
 
221
#endif
 
222
}
 
223
 
 
224
#ifdef  USE_MMAP
 
225
LOCAL char *
 
226
mkshare(size)
 
227
        int     size;
 
228
{
 
229
        int     f;
 
230
        char    *addr;
 
231
 
 
232
#ifdef  MAP_ANONYMOUS   /* HP/UX */
 
233
        f = -1;
 
234
        addr = mmap(0, mmap_sizeparm(size),
 
235
                        PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
 
236
#else
 
237
        if ((f = open("/dev/zero", O_RDWR)) < 0)
 
238
                comerr("Cannot open '/dev/zero'.\n");
 
239
        addr = mmap(0, mmap_sizeparm(size),
 
240
                        PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
 
241
#endif
 
242
        if (addr == (char *)-1)
 
243
                comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size);
 
244
        close(f);
 
245
 
 
246
        if (debug) errmsgno(EX_BAD, "shared memory segment attached: %p\n", (void *)addr);
 
247
 
 
248
        return (addr);
 
249
}
 
250
#endif
 
251
 
 
252
#ifdef  USE_USGSHM
 
253
#include <sys/ipc.h>
 
254
#include <sys/shm.h>
 
255
LOCAL char *
 
256
mkshm(size)
 
257
        int     size;
 
258
{
 
259
        int     id;
 
260
        char    *addr;
 
261
        /*
 
262
         * Unfortunately, a declaration of shmat() is missing in old
 
263
         * implementations such as AT&T SVr0 and SunOS.
 
264
         * We cannot add this definition here because the return-type
 
265
         * changed on newer systems.
 
266
         *
 
267
         * We will get a warning like this:
 
268
         *
 
269
         * warning: assignment of pointer from integer lacks a cast
 
270
         * or
 
271
         * warning: illegal combination of pointer and integer, op =
 
272
         */
 
273
/*      extern  char *shmat();*/
 
274
 
 
275
        if ((id = shmget(IPC_PRIVATE, size, IPC_CREAT|0600)) == -1)
 
276
                comerr("shmget failed\n");
 
277
 
 
278
        if (debug) errmsgno(EX_BAD, "shared memory segment allocated: %d\n", id);
 
279
 
 
280
        if ((addr = shmat(id, (char *)0, 0600)) == (char *)-1)
 
281
                comerr("shmat failed\n");
 
282
 
 
283
        if (debug) errmsgno(EX_BAD, "shared memory segment attached: %p\n", addr);
 
284
 
 
285
        if (shmctl(id, IPC_RMID, 0) < 0)
 
286
                comerr("shmctl failed to detach shared memory segment\n");
 
287
 
 
288
#ifdef  SHM_LOCK
 
289
        /*
 
290
         * Although SHM_LOCK is standard, it seems that all versions of AIX
 
291
         * ommit this definition.
 
292
         */
 
293
        if (shmctl(id, SHM_LOCK, 0) < 0)
 
294
                comerr("shmctl failed to lock shared memory segment\n");
 
295
#endif
 
296
 
 
297
        return (addr);
 
298
}
 
299
#endif
 
300
 
 
301
#ifdef  USE_OS2SHM
 
302
LOCAL char *
 
303
mkos2shm(size)
 
304
        int     size;
 
305
{
 
306
        char    *addr;
 
307
 
 
308
        /*
 
309
         * The OS/2 implementation of shm (using shm.dll) limits the size of one shared
 
310
         * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we have
 
311
         * no such restriction so I decided to use it allowing fifos of arbitrary size.
 
312
         */
 
313
        if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L))
 
314
                comerr("DosAllocSharedMem() failed\n");
 
315
 
 
316
        if (debug)
 
317
                errmsgno(EX_BAD, "shared memory allocated at address: %x\n", addr);
 
318
 
 
319
        return (addr);
 
320
}
 
321
#endif
 
322
 
 
323
LOCAL   int     faio_buffers;
 
324
LOCAL   int     faio_buf_size;
 
325
LOCAL   int     buf_idx;
 
326
LOCAL   pid_t   faio_pid;
 
327
LOCAL   BOOL    faio_didwait;
 
328
 
 
329
/*#define       faio_ref(n)     (&((faio_t *)buf)[n])*/
 
330
 
 
331
 
 
332
EXPORT BOOL
 
333
init_faio(tracks, track, bufsize)
 
334
        int     tracks;
 
335
        track_t *track;
 
336
        int     bufsize;
 
337
{
 
338
        int     n;
 
339
        faio_t  *f;
 
340
        int     pagesize;
 
341
        char    *base;
 
342
 
 
343
        if (buflen == 0L)
 
344
                return (FALSE);
 
345
 
 
346
#ifdef  _SC_PAGESIZE
 
347
        pagesize = sysconf(_SC_PAGESIZE);
 
348
#else
 
349
        pagesize = getpagesize();
 
350
#endif
 
351
 
 
352
        faio_buf_size = bufsize;
 
353
        f = (faio_t *)buf;
 
354
 
 
355
        /*
 
356
         * Compute space for buffer headers.
 
357
         * Round bufsize up to pagesize to make each FIFO segment
 
358
         * properly page aligned.
 
359
         */
 
360
        bufsize = roundup(bufsize, pagesize);
 
361
        faio_buffers = (buflen - sizeof(*sp)) / bufsize;
 
362
        EDEBUG(("bufsize: %d buffers: %d hdrsize %ld\n", bufsize, faio_buffers, (long)faio_buffers * sizeof(struct faio)));
 
363
 
 
364
        /*
 
365
         * Reduce buffer space by header space.
 
366
         */
 
367
        n = sizeof(*sp) + faio_buffers * sizeof(struct faio);
 
368
        n = roundup(n, pagesize);
 
369
        faio_buffers = (buflen-n) / bufsize;
 
370
        EDEBUG(("bufsize: %d buffers: %d hdrsize %ld\n", bufsize, faio_buffers, (long)faio_buffers * sizeof(struct faio)));
 
371
 
 
372
        if (faio_buffers < MIN_BUFFERS) {
 
373
                errmsgno(EX_BAD,
 
374
                        "write-buffer too small, minimum is %dk. Disabling.\n",
 
375
                                                MIN_BUFFERS*bufsize/1024);
 
376
                return (FALSE);
 
377
        }
 
378
 
 
379
        if (debug)
 
380
                printf("Using %d buffers of %d bytes.\n", faio_buffers, faio_buf_size);
 
381
 
 
382
        f = (faio_t *)buf;
 
383
        base = buf + roundup(sizeof(*sp) + faio_buffers * sizeof(struct faio),
 
384
                                pagesize);
 
385
 
 
386
        for (n = 0; n < faio_buffers; n++, f++, base += bufsize) {
 
387
                /* Give all the buffers to the file reader process */
 
388
                f->owner = owner_writer;
 
389
                f->users = 0;
 
390
                f->bufp = base;
 
391
                f->fd = -1;
 
392
        }
 
393
        sp = (struct faio_stats *)f;    /* point past headers */
 
394
        sp->gets = sp->puts = sp->done = 0L;
 
395
        sp->users = 1;
 
396
 
 
397
        faio_pid = fork();
 
398
        if (faio_pid < 0)
 
399
                comerr("fork(2) failed");
 
400
 
 
401
        if (faio_pid == 0) {
 
402
                /*
 
403
                 * child (background) process that fills the FIFO.
 
404
                 */
 
405
                raisepri(1);            /* almost max priority */
 
406
 
 
407
#ifdef USE_OS2SHM
 
408
                DosGetSharedMem(buf,3); /* PAG_READ|PAG_WRITE */
 
409
#endif
 
410
                /* Ignoring SIGALRM cures the SCO usleep() bug */
 
411
/*              signal(SIGALRM, SIG_IGN);*/
 
412
                faio_reader(tracks, track);
 
413
                /* NOTREACHED */
 
414
        } else {
 
415
                faio_didwait = FALSE;
 
416
 
 
417
                /* close all file-descriptors that only the child will use */
 
418
                for (n = 1; n <= tracks; n++)
 
419
                        close(track[n].f);
 
420
        }
 
421
 
 
422
        return (TRUE);
 
423
}
 
424
 
 
425
EXPORT BOOL
 
426
await_faio()
 
427
{
 
428
        int     n;
 
429
        int     lastfd = -1;
 
430
        faio_t  *f;
 
431
 
 
432
        /*
 
433
         * Wait until the reader is active and has filled the buffer.
 
434
         */
 
435
        if (lverbose || debug) {
 
436
                printf("Waiting for reader process to fill input buffer ... ");
 
437
                flush();
 
438
        }
 
439
 
 
440
        faio_wait_on_buffer(faio_ref(faio_buffers - 1), owner_reader,
 
441
                            500*MSECS, 0);
 
442
 
 
443
        if (lverbose || debug)
 
444
                printf("input buffer ready.\n");
 
445
 
 
446
        sp->empty = sp->full = 0L;      /* set correct stat state */
 
447
        sp->cont_low = faio_buffers;    /* set cont to max value  */
 
448
 
 
449
        f = faio_ref(0);
 
450
        for (n = 0; n < faio_buffers; n++, f++) {
 
451
                if (f->fd != lastfd &&
 
452
                        f->fd == STDIN_FILENO && f->len == 0) {
 
453
                        errmsgno(EX_BAD, "Premature EOF on stdin.\n");
 
454
                        kill(faio_pid, SIGKILL);
 
455
                        return (FALSE);
 
456
                }
 
457
                lastfd = f->fd;
 
458
        }
 
459
        return (TRUE);
 
460
}
 
461
 
 
462
EXPORT void
 
463
kill_faio()
 
464
{
 
465
        if (faio_pid > 0)
 
466
                kill(faio_pid, SIGKILL);
 
467
}
 
468
 
 
469
EXPORT int
 
470
wait_faio()
 
471
{
 
472
        if (faio_pid > 0 && !faio_didwait)
 
473
                return (wait(0));
 
474
        faio_didwait = TRUE;
 
475
        return (0);
 
476
}
 
477
 
 
478
LOCAL void
 
479
faio_reader(tracks, track)
 
480
        int     tracks;
 
481
        track_t *track;
 
482
{
 
483
        /* This function should not return, but _exit. */
 
484
        int     trackno;
 
485
 
 
486
        if (debug)
 
487
                printf("\nfaio_reader starting\n");
 
488
 
 
489
        for (trackno = 1; trackno <= tracks; trackno++) {
 
490
                if (debug)
 
491
                        printf("\nfaio_reader reading track %d\n", trackno);
 
492
                faio_read_track(&track[trackno]);
 
493
        }
 
494
        sp->done++;
 
495
        if (debug)
 
496
                printf("\nfaio_reader all tracks read, exiting\n");
 
497
 
 
498
        /* Prevent hang if buffer is larger than all the tracks combined */
 
499
        if (sp->gets == 0)
 
500
                faio_ref(faio_buffers - 1)->owner = owner_reader;
 
501
 
 
502
#ifdef  USE_OS2SHM
 
503
        DosFreeMem(buf);
 
504
        sleep(30000);   /* XXX If calling _exit() here the parent process seems to be blocked */
 
505
                        /* XXX This should be fixed soon */
 
506
#endif
 
507
        if (debug)
 
508
                error("\nfaio_reader _exit(0)\n");
 
509
        _exit(0);
 
510
}
 
511
 
 
512
#ifndef faio_ref
 
513
LOCAL faio_t *
 
514
faio_ref(n)
 
515
        int     n;
 
516
{
 
517
        return (&((faio_t *)buf)[n]);
 
518
}
 
519
#endif
 
520
 
 
521
 
 
522
LOCAL void
 
523
faio_read_track(trackp)
 
524
        track_t *trackp;
 
525
{
 
526
        int     fd = trackp->f;
 
527
        int     bytespt = trackp->secsize * trackp->secspt;
 
528
        int     l;
 
529
        off_t   tracksize = trackp->tracksize;
 
530
        off_t   bytes_read = (off_t)0;
 
531
        long    bytes_to_read;
 
532
 
 
533
        if (bytespt > faio_buf_size) {
 
534
                comerrno(EX_BAD,
 
535
                "faio_read_track fatal: secsize %d secspt %d, bytespt(%d) > %d !!\n",
 
536
                         trackp->secsize, trackp->secspt, bytespt,
 
537
                         faio_buf_size);
 
538
        }
 
539
 
 
540
        do {
 
541
                bytes_to_read = bytespt;
 
542
                if (tracksize > 0) {
 
543
                        if ((tracksize - bytes_read) > bytespt)
 
544
                                bytes_to_read = bytespt;
 
545
                        else
 
546
                                bytes_to_read = tracksize - bytes_read;                         
 
547
                }
 
548
                l = faio_read_segment(fd, faio_ref(buf_idx), bytes_to_read);
 
549
                if (++buf_idx >= faio_buffers)
 
550
                        buf_idx = 0;
 
551
                if (l <= 0)
 
552
                        break;
 
553
                bytes_read += l;
 
554
        } while (tracksize < 0 || bytes_read < tracksize);
 
555
 
 
556
        close(fd);      /* Don't keep files open longer than neccesary */
 
557
}
 
558
 
 
559
LOCAL void
 
560
faio_wait_on_buffer(f, s, delay, max_wait)
 
561
        faio_t  *f;
 
562
        fowner_t s;
 
563
        unsigned long delay;
 
564
        unsigned long max_wait;
 
565
{
 
566
        unsigned long max_loops;
 
567
 
 
568
        if (f->owner == s)
 
569
                return;         /* return immediately if the buffer is ours */
 
570
 
 
571
        if (s == owner_reader)
 
572
                sp->empty++;
 
573
        else
 
574
                sp->full++;
 
575
 
 
576
        max_loops = max_wait / delay + 1;
 
577
 
 
578
        while (max_wait == 0 || max_loops--) {
 
579
                USDEBUG1;
 
580
                usleep(delay);
 
581
                USDEBUG2;
 
582
 
 
583
                if (f->owner == s)
 
584
                        return;
 
585
        }
 
586
        if (debug) {
 
587
                errmsgno(EX_BAD,
 
588
                "%lu microseconds passed waiting for %d current: %d idx: %ld\n",
 
589
                max_wait, s, f->owner, (long)(f - faio_ref(0))/sizeof(*f));
 
590
        }
 
591
        comerrno(EX_BAD, "faio_wait_on_buffer for %s timed out.\n",
 
592
        (s > owner_reader || s < owner_none) ? "bad_owner" : onames[s-owner_none]);
 
593
}
 
594
 
 
595
LOCAL int
 
596
faio_read_segment(fd, f, len)
 
597
        int     fd;
 
598
        faio_t  *f;
 
599
        int     len;
 
600
{
 
601
        int l;
 
602
 
 
603
        faio_wait_on_buffer(f, owner_writer, WRITER_DELAY, WRITER_MAXWAIT);
 
604
 
 
605
        f->fd = fd;
 
606
        l = read_buf(fd, f->bufp, len);
 
607
        f->len = l;
 
608
        f->saved_errno = errno;
 
609
        f->owner = owner_reader;
 
610
        f->users = sp->users;
 
611
 
 
612
        sp->puts++;
 
613
 
 
614
        return l;
 
615
}
 
616
 
 
617
EXPORT int
 
618
faio_read_buf(fd, bp, size)
 
619
        int fd;
 
620
        char *bp;
 
621
        int size;
 
622
{
 
623
        char *bufp;
 
624
 
 
625
        int len = faio_get_buf(fd, &bufp, size);
 
626
        if (len > 0) {
 
627
                movebytes(bufp, bp, len);
 
628
        }
 
629
        return len;
 
630
}
 
631
 
 
632
EXPORT int
 
633
faio_get_buf(fd, bpp, size)
 
634
        int fd;
 
635
        char **bpp;
 
636
        int size;
 
637
{
 
638
        faio_t  *f;
 
639
        int     len;
 
640
 
 
641
again:
 
642
        f = faio_ref(buf_idx);
 
643
        if (f->owner == owner_faio) {
 
644
                f->owner = owner_writer;
 
645
                if (++buf_idx >= faio_buffers)
 
646
                        buf_idx = 0;
 
647
                f = faio_ref(buf_idx);
 
648
        }
 
649
 
 
650
        if ((sp->puts - sp->gets) < sp->cont_low && sp->done == 0) {
 
651
                EDEBUG(("gets: %ld puts: %ld cont: %ld low: %ld\n", sp->gets, sp->puts, sp->puts - sp->gets, sp->cont_low));
 
652
                sp->cont_low = sp->puts - sp->gets;
 
653
        }
 
654
        faio_wait_on_buffer(f, owner_reader, READER_DELAY, READER_MAXWAIT);
 
655
        len = f->len;
 
656
        
 
657
        if (f->fd != fd) {
 
658
                if (f->len == 0) {
 
659
                        /*
 
660
                         * If the tracksize for this track was known, and
 
661
                         * the tracksize is 0 mod bytespt, this happens.
 
662
                         */
 
663
                        goto again;
 
664
                }
 
665
                comerrno(EX_BAD,
 
666
                "faio_get_buf fatal: fd=%d, f->fd=%d, f->len=%d f->errno=%d\n",
 
667
                fd, f->fd, f->len, f->saved_errno);
 
668
        }
 
669
        if (size < len) {
 
670
                comerrno(EX_BAD,
 
671
                "unexpected short read-attempt in faio_get_buf. size = %d, len = %d\n",
 
672
                size, len);
 
673
        }
 
674
 
 
675
        if (len < 0)
 
676
                errno = f->saved_errno;
 
677
 
 
678
        sp->gets++;
 
679
 
 
680
        *bpp = f->bufp;
 
681
        if (--f->users <= 0)
 
682
                f->owner = owner_faio;
 
683
        return len;
 
684
}
 
685
 
 
686
EXPORT void
 
687
fifo_stats()
 
688
{
 
689
        if (sp == NULL) /* We might not use a FIFO */
 
690
                return;
 
691
 
 
692
        errmsgno(EX_BAD, "fifo had %ld puts and %ld gets.\n",
 
693
                sp->puts, sp->gets);
 
694
        errmsgno(EX_BAD, "fifo was %ld times empty and %ld times full, min fill was %ld%%.\n",
 
695
                sp->empty, sp->full, (100L*sp->cont_low)/faio_buffers);
 
696
}
 
697
 
 
698
EXPORT int
 
699
fifo_percent(addone)
 
700
        BOOL    addone;
 
701
{
 
702
        int     percent;
 
703
 
 
704
        if (buflen == 0L)
 
705
                return (-1);
 
706
        if (sp->done)
 
707
                return (100);
 
708
        percent = (100*(sp->puts + 1 - sp->gets)/faio_buffers);
 
709
        if (percent > 100)
 
710
                return (100);
 
711
        return (percent);
 
712
}
 
713
#else   /* FIFO */
 
714
 
 
715
#include <standard.h>
 
716
#include <sys/types.h>
 
717
#include <utypes.h>
 
718
 
 
719
#include "cdrecord.h"
 
720
 
 
721
EXPORT  void    init_fifo       __PR((long));
 
722
EXPORT  BOOL    init_faio       __PR((int tracks, track_t *track, int));
 
723
EXPORT  BOOL    await_faio      __PR((void));
 
724
EXPORT  void    kill_faio       __PR((void));
 
725
EXPORT  int     wait_faio       __PR((void));
 
726
EXPORT  int     faio_read_buf   __PR((int f, char *bp, int size));
 
727
EXPORT  int     faio_get_buf    __PR((int f, char **bpp, int size));
 
728
EXPORT  void    fifo_stats      __PR((void));
 
729
EXPORT  int     fifo_percent    __PR((BOOL addone));
 
730
 
 
731
 
 
732
EXPORT void
 
733
init_fifo(fs)
 
734
        long    fs;
 
735
{
 
736
        errmsgno(EX_BAD, "Fifo not supported.\n");
 
737
}
 
738
 
 
739
EXPORT BOOL
 
740
init_faio(tracks, track, bufsize)
 
741
        int     tracks;
 
742
        track_t *track;
 
743
        int     bufsize;
 
744
{
 
745
        return (FALSE);
 
746
}
 
747
 
 
748
EXPORT BOOL
 
749
await_faio()
 
750
{
 
751
        return (TRUE);
 
752
}
 
753
 
 
754
EXPORT void
 
755
kill_faio()
 
756
{
 
757
}
 
758
 
 
759
EXPORT int
 
760
wait_faio()
 
761
{
 
762
        return (0);
 
763
}
 
764
 
 
765
EXPORT int
 
766
faio_read_buf(fd, bp, size)
 
767
        int fd;
 
768
        char *bp;
 
769
        int size;
 
770
{
 
771
        return (0);
 
772
}
 
773
 
 
774
EXPORT int
 
775
faio_get_buf(fd, bpp, size)
 
776
        int fd;
 
777
        char **bpp;
 
778
        int size;
 
779
{
 
780
        return (0);
 
781
}
 
782
 
 
783
EXPORT void
 
784
fifo_stats()
 
785
{
 
786
}
 
787
 
 
788
EXPORT int
 
789
fifo_percent(addone)
 
790
        BOOL    addone;
 
791
{
 
792
        return (-1);
 
793
}
 
794
 
 
795
#endif  /* FIFO */