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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5