/[debburn]/nonameyet/trunk/cdrecord/fifo.c
ViewVC logotype

Contents of /nonameyet/trunk/cdrecord/fifo.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5