/[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 - (show annotations) (download)
Mon Sep 4 17:07:51 2006 UTC (6 years, 8 months ago) by blade
File MIME type: text/plain
File size: 20576 byte(s)
Force FIFO define for now
1 /* @(#)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
36 /* XXX Force use of FIFO untill we fixed the detection */
37 #ifndef FIFO
38 #define FIFO
39 #endif
40
41 #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