2 * Copyright (c) 2000 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * This file contains several functions to doing reads and writes.
23 * It was written so that a single function could be called in a test
24 * program and only a io type field value would have to change to
25 * do different types of io. There is even a couple of functions that
26 * will allow you to parse a string to determine the iotype.
28 * This file contains functions for writing/reading to/from open files
31 * Functions declared in this module - see individual function code for
34 * int stride_bounds(int offset, int stride, int nstrides,
35 * int bytes_per_stride, int *min, int *max);
37 * int lio_write_buffer(int fd, int method, char *buffer, int size,
38 * char **errmsg, long wrd);
39 * int lio_read_buffer(int fd, int method, char *buffer, int size,
40 * char **errmsg, long wrd);
41 * int lio_parse_io_arg1(char *string)
42 * void lio_help1(char *prefix);
44 * int lio_parse_io_arg2(char *string, char **badtoken)
45 * void lio_help2(char *prefix);
47 * int lio_set_debug(int level);
50 * struct lio_info_type Lio_info1[];
51 * struct lio_info_type Lio_info2[];
53 * Author : Richard Logan
61 #include <sys/types.h>
64 #include <sys/param.h>
66 #include <sys/types.h>
69 #include <sys/uio.h> /* readv(2)/writev(2) */
72 #include <stdlib.h> /* atoi, abs */
74 #include "tlibio.h" /* defines LIO* marcos */
77 #define PATH_MAX MAXPATHLEN
80 #if 0 /* disabled until it's needed -- roehrich 6/11/97 */
81 #define BUG1_workaround 1 /* Work around a condition where aio_return gives
82 * a value of zero but there is no errno followup
83 * and the read/write operation actually did its
90 static void lio_async_signal_handler();
94 * Define the structure as used in lio_parse_arg1 and lio_help1
96 struct lio_info_type Lio_info1[] = {
97 { "s", LIO_IO_SYNC, "sync i/o" },
98 { "p", LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, "async i/o using a loop to wait for a signal" },
99 { "b", LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, "async i/o using pause" },
100 { "a", LIO_IO_ASYNC|LIO_WAIT_RECALL, "async i/o using recall/aio_suspend" },
102 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
104 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
105 { "l", LIO_IO_SLISTIO|LIO_WAIT_RECALL, "single stride sync listio" },
106 { "L", LIO_IO_ALISTIO|LIO_WAIT_RECALL, "single stride async listio using recall" },
107 { "X", LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, "single stride async listio using pause" },
108 { "v", LIO_IO_SYNCV, "single buffer sync readv/writev" },
109 { "P", LIO_IO_SYNCP, "sync pread/pwrite" },
113 * Define the structure used by lio_parse_arg2 and lio_help2
115 struct lio_info_type Lio_info2[] = {
116 { "sync", LIO_IO_SYNC, "sync i/o (read/write)"},
117 { "async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)" },
118 { "slistio", LIO_IO_SLISTIO, "single stride sync listio" },
119 { "alistio", LIO_IO_ALISTIO, "single stride async listio" },
120 { "syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
121 { "syncp", LIO_IO_SYNCP, "pread/pwrite"},
122 { "active", LIO_WAIT_ACTIVE, "spin on status/control values" },
123 { "recall", LIO_WAIT_RECALL, "use recall(2)/aio_suspend(3) to wait for i/o to complete" },
124 { "sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal" },
125 { "sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal" },
126 /* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
127 /* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
128 { "random", LIO_RANDOM, "set random bit" },
130 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES,
131 "all random i/o types and wait methods (except nowait)" },
134 char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */
136 static volatile int Received_signal = 0; /* number of signals received */
137 static volatile int Rec_signal;
138 static char Errormsg[500];
139 static int Debug_level = 0;
143 /***********************************************************************
146 * Determine the bounds of a strided request, normalized to offset. Returns
147 * the number of bytes needed to satisfy the request, and optionally sets
148 * *min and *max to the mininum and maximum bytes referenced, normalized
151 * Returns -1 on error - the only possible error conditions are illegal values
152 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
155 ***********************************************************************/
158 stride_bounds(offset, stride, nstrides, bytes_per_stride, min, max)
162 int bytes_per_stride;
166 int nbytes, min_byte, max_byte;
172 if (nstrides < 0 || bytes_per_stride < 0) {
177 stride = bytes_per_stride;
181 * Determine the # of bytes needed to satisfy the request. This
182 * value, along with the offset argument, determines the min and max
187 nbytes = abs(stride) * (nstrides-1) + bytes_per_stride;
190 max_byte = offset + bytes_per_stride - 1;
191 min_byte = max_byte - nbytes + 1;
194 max_byte = min_byte + nbytes - 1;
208 /***********************************************************************
209 * This function will allow someone to set the debug level.
210 ***********************************************************************/
221 /***********************************************************************
222 * This function will parse a string and return desired io-method.
223 * Only the first character of the string is used.
225 * This function does not provide for meaningful option arguments,
226 * but it supports current growfiles/btlk interface.
229 ***********************************************************************/
231 lio_parse_io_arg1(char *string)
238 * Determine if token is a valid string.
240 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
241 if ( strcmp(string, Lio_info1[ind].token) == 0 ) {
242 mask |= Lio_info1[ind].bits;
256 /***********************************************************************
257 * This function will print a help message describing the characters
258 * that can be parsed by lio_parse_io_arg1().
259 * They will be printed one per line.
261 ***********************************************************************/
263 lio_help1(char *prefix)
267 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
268 printf("%s %s : %s\n", prefix,
269 Lio_info1[ind].token, Lio_info1[ind].desc);
275 /***********************************************************************
276 * This function will parse a string and return the desired io-method.
277 * This function will take a comma separated list of io type and wait
278 * method tokens as defined in Lio_info2[]. If a token does not match
279 * any of the tokens in Lio_info2[], it will be coverted to a number.
280 * If it was a number, those bits are also set.
283 ***********************************************************************/
285 lio_parse_io_arg2(char *string, char **badtoken)
287 char *token = string;
301 for (; ((*cc != ',') && (*cc != '\0')); cc++);
308 * Determine if token is a valid string or number and if
309 * so, add the bits to the mask.
311 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
312 if ( strcmp(token, Lio_info2[ind].token) == 0 ) {
313 mask |= Lio_info2[ind].bits;
320 * If token does not match one of the defined tokens, determine
321 * if it is a number, if so, add the bits.
324 if (sscanf(token, "%i%c", &tmp, &chr) == 1 ) {
332 if (!found) { /* token is not valid */
333 if ( badtoken != NULL)
347 /***********************************************************************
348 * This function will print a help message describing the tokens
349 * that can be parsed by lio_parse_io_arg2().
350 * It will print them one per line.
353 ***********************************************************************/
355 lio_help2(char *prefix)
359 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
360 printf("%s %s : %s\n", prefix,
361 Lio_info2[ind].token, Lio_info2[ind].desc);
367 /***********************************************************************
368 * This is an internal signal handler.
369 * If the handler is called, it will increment the Received_signal
371 ***********************************************************************/
373 lio_async_signal_handler(int sig)
376 printf("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
377 __FILE__, __LINE__, sig, Received_signal+1);
385 /***********************************************************************
387 * This function will randomly choose an io type and wait method
388 * from set of io types and wait methods. Since this information
389 * is stored in a bitmask, it randomly chooses an io type from
390 * the io type bits specified and does the same for wait methods.
393 * This function will return a value with all non choosen io type
394 * and wait method bits cleared. The LIO_RANDOM bit is also
395 * cleared. All other bits are left unchanged.
398 ***********************************************************************/
400 lio_random_methods(long curr_mask)
403 long random_bit(long);
405 /* remove random select, io type, and wait method bits from curr_mask */
406 mask = curr_mask & (~(LIO_IO_TYPES | LIO_WAIT_TYPES | LIO_RANDOM));
408 /* randomly select io type from specified io types */
409 mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
411 /* randomly select wait methods from specified wait methods */
412 mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
417 /***********************************************************************
418 * Generic write function
419 * This function can be used to do a write using write(2), writea(2),
420 * aio_write(3), writev(2), pwrite(2),
421 * or single stride listio(2)/lio_listio(3).
422 * By setting the desired bits in the method
423 * bitmask, the caller can control the type of write and the wait method
424 * that will be used. If no io type bits are set, write will be used.
426 * If async io was attempted and no wait method bits are set then the
427 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
428 * aio_write(3) and lio_listio(3).
430 * If multiple wait methods are specified,
431 * only one wait method will be used. The order is predetermined.
433 * If the call specifies a signal and one of the two signal wait methods,
434 * a signal handler for the signal is set. This will reset an already
435 * set handler for this signal.
437 * If the LIO_RANDOM method bit is set, this function will randomly
438 * choose a io type and wait method from bits in the method argument.
440 * If an error is encountered, an error message will be generated
441 * in a internal static buffer. If errmsg is not NULL, it will
442 * be updated to point to the static buffer, allowing the caller
443 * to print the error message.
446 * If a system call fails, -errno is returned.
447 * If LIO_WAIT_NONE bit is set, the return value is the return value
448 * of the system call.
449 * If the io did not fail, the amount of data written is returned.
450 * If the size the system call say was written is different
451 * then what was asked to be written, errmsg is updated for
452 * this error condition. The return value is still the amount
453 * the system call says was written.
456 ***********************************************************************/
458 lio_write_buffer(fd, method, buffer, size, sig, errmsg, wrd)
459 int fd; /* open file descriptor */
460 int method; /* contains io type and wait method bitmask */
461 char *buffer; /* pointer to buffer */
462 int size; /* the size of the io */
463 int sig; /* signal to use if async io */
464 char **errmsg; /* char pointer that will be updated to point to err message */
465 long wrd; /* to allow future features, use zero for now */
467 int ret = 0; /* syscall return or used to get random method */
468 char *io_type; /* Holds string of type of io */
470 int omethod = method;
471 int listio_cmd; /* Holds the listio/lio_listio cmd */
473 struct iovec iov; /* iovec for writev(2) */
476 * If LIO_RANDOM bit specified, get new method randomly.
478 if ( method & LIO_RANDOM ) {
479 if( Debug_level > 3 )
480 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
481 method = lio_random_methods(method);
482 if ( Debug_level > 2 )
483 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
486 if ( errmsg != NULL )
489 Rec_signal=Received_signal; /* get the current number of signals received */
490 bzero(&iov, sizeof(struct iovec));
491 iov.iov_base = buffer;
495 * If the LIO_USE_SIGNAL bit is not set, only use the signal
496 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
497 * Otherwise there is not necessary a signal handler to trap
500 if ( sig && !(method & LIO_USE_SIGNAL) &&
501 ! (method & LIO_WAIT_SIGTYPES) ){
503 sig=0; /* ignore signal parameter */
507 * only setup signal hander if sig was specified and
508 * a sig wait method was specified.
509 * Doing this will change the handler for this signal. The
510 * old signal handler will not be restored.
511 *** restoring the signal handler could be added ***
515 * Determine the system call that will be called and produce
516 * the string of the system call and place it in Lio_SysCall.
517 * Also update the io_type char pointer to give brief description
518 * of system call. Execute the system call and check for
519 * system call failure. If sync i/o, return the number of
520 * bytes written/read.
523 if ( (method & LIO_IO_SYNC) || (method & LIO_IO_TYPES) == 0 ){
525 * write(2) is used if LIO_IO_SYNC bit is set or not none
526 * of the LIO_IO_TYPES bits are set (default).
530 "write(%d, buf, %d)", fd, size);
534 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
537 if ((ret = write(fd, buffer, size)) == -1) {
538 sprintf(Errormsg, "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
540 fd, size, errno, strerror(errno));
546 "%s/%d write(%d, buf, %d) returned=%d",
550 else if ( Debug_level > 1 )
551 printf("DEBUG %s/%d: write completed without error (ret %d)\n",
552 __FILE__, __LINE__, ret);
558 else if ( method & LIO_IO_SYNCV ) {
562 "writev(%d, &iov, 1) nbyte:%d", fd, size);
565 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
567 if ((ret = writev(fd, &iov, 1)) == -1) {
568 sprintf(Errormsg, "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
570 fd, size, errno, strerror(errno));
576 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
580 else if ( Debug_level > 1 )
581 printf("DEBUG %s/%d: writev completed without error (ret %d)\n",
582 __FILE__, __LINE__, ret);
588 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
593 * If there was an error waiting for async i/o to complete,
594 * return the error value (errno) to the caller.
595 * Note: Errormsg should already have been updated.
602 * If i/o was not waited for (may not have been completed at this time),
603 * return the size that was requested.
609 * check that async io was successful.
610 * Note: if the there was an system call failure, -errno
611 * was returned and Errormsg should already have been updated.
612 * If amount i/o was different than size, Errormsg should already
613 * have been updated but the actual i/o size if returned.
617 } /* end of lio_write_buffer */
619 /***********************************************************************
620 * Generic read function
621 * This function can be used to do a read using read(2), reada(2),
622 * aio_read(3), readv(2), pread(2),
623 * or single stride listio(2)/lio_listio(3).
624 * By setting the desired bits in the method
625 * bitmask, the caller can control the type of read and the wait method
626 * that will be used. If no io type bits are set, read will be used.
628 * If async io was attempted and no wait method bits are set then the
629 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
630 * aio_read(3) and lio_listio(3).
632 * If multiple wait methods are specified,
633 * only one wait method will be used. The order is predetermined.
635 * If the call specifies a signal and one of the two signal wait methods,
636 * a signal handler for the signal is set. This will reset an already
637 * set handler for this signal.
639 * If the LIO_RANDOM method bit is set, this function will randomly
640 * choose a io type and wait method from bits in the method argument.
642 * If an error is encountered, an error message will be generated
643 * in a internal static buffer. If errmsg is not NULL, it will
644 * be updated to point to the static buffer, allowing the caller
645 * to print the error message.
648 * If a system call fails, -errno is returned.
649 * If LIO_WAIT_NONE bit is set, the return value is the return value
650 * of the system call.
651 * If the io did not fail, the amount of data written is returned.
652 * If the size the system call say was written is different
653 * then what was asked to be written, errmsg is updated for
654 * this error condition. The return value is still the amount
655 * the system call says was written.
658 ***********************************************************************/
660 lio_read_buffer(fd, method, buffer, size, sig, errmsg, wrd)
661 int fd; /* open file descriptor */
662 int method; /* contains io type and wait method bitmask */
663 char *buffer; /* pointer to buffer */
664 int size; /* the size of the io */
665 int sig; /* signal to use if async io */
666 char **errmsg; /* char pointer that will be updated to point to err message */
667 long wrd; /* to allow future features, use zero for now */
669 int ret = 0; /* syscall return or used to get random method */
670 char *io_type; /* Holds string of type of io */
672 int listio_cmd; /* Holds the listio/lio_listio cmd */
673 int omethod = method;
675 struct iovec iov; /* iovec for readv(2) */
678 * If LIO_RANDOM bit specified, get new method randomly.
680 if ( method & LIO_RANDOM ) {
681 if( Debug_level > 3 )
682 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
683 method = lio_random_methods(method);
684 if ( Debug_level > 2 )
685 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
688 if ( errmsg != NULL )
691 Rec_signal=Received_signal; /* get the current number of signals received */
692 bzero(&iov, sizeof(struct iovec));
693 iov.iov_base = buffer;
697 * If the LIO_USE_SIGNAL bit is not set, only use the signal
698 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
699 * Otherwise there is not necessarily a signal handler to trap
702 if ( sig && !(method & LIO_USE_SIGNAL) &&
703 ! (method & LIO_WAIT_SIGTYPES) ){
705 sig=0; /* ignore signal parameter */
709 * only setup signal hander if sig was specified and
710 * a sig wait method was specified.
711 * Doing this will change the handler for this signal. The
712 * old signal handler will not be restored.
713 *** restoring the signal handler could be added ***
717 * Determine the system call that will be called and produce
718 * the string of the system call and place it in Lio_SysCall.
719 * Also update the io_type char pointer to give brief description
720 * of system call. Execute the system call and check for
721 * system call failure. If sync i/o, return the number of
722 * bytes written/read.
725 if ( (method & LIO_IO_SYNC) || (method & LIO_IO_TYPES) == 0 ){
727 * read(2) is used if LIO_IO_SYNC bit is set or not none
728 * of the LIO_IO_TYPES bits are set (default).
732 "read(%d, buf, %d)", fd, size);
736 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
739 if ((ret = read(fd, buffer, size)) == -1) {
740 sprintf(Errormsg, "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
742 fd, size, errno, strerror(errno));
748 "%s/%d read(%d, buf, %d) returned=%d",
752 else if ( Debug_level > 1 )
753 printf("DEBUG %s/%d: read completed without error (ret %d)\n",
754 __FILE__, __LINE__, ret);
760 else if ( method & LIO_IO_SYNCV ) {
764 "readv(%d, &iov, 1) nbyte:%d", fd, size);
767 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
769 if ((ret = readv(fd, &iov, 1)) == -1) {
770 sprintf(Errormsg, "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
772 fd, size, errno, strerror(errno));
778 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
782 else if ( Debug_level > 1 )
783 printf("DEBUG %s/%d: readv completed without error (ret %d)\n",
784 __FILE__, __LINE__, ret);
790 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
795 * If there was an error waiting for async i/o to complete,
796 * return the error value (errno) to the caller.
797 * Note: Errormsg should already have been updated.
804 * If i/o was not waited for (may not have been completed at this time),
805 * return the size that was requested.
811 * check that async io was successful.
812 * Note: if the there was an system call failure, -errno
813 * was returned and Errormsg should already have been updated.
814 * If amount i/o was different than size, Errormsg should already
815 * have been updated but the actual i/o size if returned.
819 } /* end of lio_read_buffer */
823 /***********************************************************************
824 * This function will check that async io was successful.
825 * It can also be used to check sync listio since it uses the
829 * If status.sw_error is set, -status.sw_error is returned.
830 * Otherwise sw_count's field value is returned.
833 ***********************************************************************/
835 lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method)
840 /* The I/O may have been synchronous with signal completion. It doesn't
841 * make sense, but the combination could be generated. Release the
842 * completion signal here otherwise it'll hang around and bite us
845 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
846 sigrelse( aiocbp->aio_sigevent.sigev_signo );
848 ret = aio_error( aiocbp );
850 while( ret == EINPROGRESS ){
851 ret = aio_error( aiocbp );
856 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
857 __FILE__, __LINE__, io_type, cnt, method,
858 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
859 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
860 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
867 "%s/%d %s, aio_error = %d %s; random method %#o",
868 __FILE__, __LINE__, io_type,
873 ret = aio_return( aiocbp );
876 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
877 __FILE__, __LINE__, io_type,
880 #ifdef BUG1_workaround
883 if( Debug_level > 1 ){
884 printf("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
885 __FILE__, __LINE__, io_type, ret);
888 #endif /* BUG1_workaround */
891 else if( Debug_level > 1 ){
892 printf("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
893 __FILE__, __LINE__, io_type, ret);
898 } /* end of lio_check_asyncio */
901 /***********************************************************************
903 * This function will wait for async io to complete.
904 * If multiple wait methods are specified, the order is predetermined
905 * to LIO_WAIT_RECALL,
906 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
907 * then LIO_WAIT_NONE.
909 * If no wait method was specified the default wait method is: recall(2)
910 * or aio_suspend(3), as appropriate.
913 * <0: errno of failed recall
914 * 0 : async io was completed
915 * 1 : async was not waited for, io may not have completed.
918 ***********************************************************************/
920 lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp)
924 if ( (method & LIO_WAIT_RECALL)
925 || ((method & LIO_WAIT_TYPES) == 0) ){
927 * If method has LIO_WAIT_RECALL bit set or method does
928 * not have any wait method bits set (default), use recall/aio_suspend.
930 if ( Debug_level > 2 )
931 printf("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n", __FILE__, __LINE__,
932 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
933 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
934 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
938 ret = aio_suspend( aioary, 1, NULL );
939 if( (ret == -1) && (errno == EINTR) ){
940 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ){
941 if( Debug_level > 2 ){
942 printf("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
943 __FILE__, __LINE__ );
947 sprintf(Errormsg, "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
949 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
950 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
951 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
957 sprintf(Errormsg, "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
959 fd, errno, strerror(errno));
962 } else if ( method & LIO_WAIT_ACTIVE ) {
963 if ( Debug_level > 2 )
964 printf("DEBUG %s/%d: wait method : active\n", __FILE__, __LINE__);
966 /* loop while aio_error() returns EINPROGRESS */
969 ret = aio_error( aiocbp );
970 if( (ret == 0) || (ret != EINPROGRESS) ){
976 if ( Debug_level > 5 && cnt && (cnt % 50) == 0 )
977 printf("DEBUG %s/%d: wait active cnt = %d\n",
978 __FILE__, __LINE__, cnt);
980 } else if ( method & LIO_WAIT_SIGPAUSE ) {
981 if ( Debug_level > 2 )
982 printf("DEBUG %s/%d: wait method : sigpause\n", __FILE__, __LINE__);
985 } else if ( method & LIO_WAIT_SIGACTIVE ) {
986 if ( Debug_level > 2 )
987 printf("DEBUG %s/%d: wait method : sigactive\n", __FILE__, __LINE__);
988 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
989 sigrelse( aiocbp->aio_sigevent.sigev_signo );
991 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ );
994 /* loop waiting for signal */
995 while ( Received_signal == Rec_signal ){
996 sigrelse( aiocbp->aio_sigevent.sigev_signo );
999 } else if ( method & LIO_WAIT_NONE ) {
1000 if ( Debug_level > 2 )
1001 printf("DEBUG %s/%d: wait method : none\n", __FILE__, __LINE__);
1002 /* It's broken because the aiocb/iosw is an automatic variable in
1003 * lio_{read,write}_buffer, so when the function returns and the
1004 * I/O completes there will be nowhere to write the I/O status.
1005 * It doesn't cause a problem on unicos--probably because of some
1006 * compiler quirk, or an accident. It causes POSIX async I/O
1007 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1009 sprintf(Errormsg, "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1010 __FILE__, __LINE__ );
1014 if( Debug_level > 2 )
1015 printf("DEBUG %s/%d: no wait method was chosen\n", __FILE__, __LINE__ );
1021 } /* end of lio_wait4asyncio */
1023 #endif /* ifndef linux */
1026 /***********************************************************************
1027 * The following code is provided as unit test.
1028 * Just define add "-DUNIT_TEST=1" to the cc line.
1031 ***********************************************************************/
1032 struct unit_info_t {
1037 { LIO_IO_SYNC, 0, "sync io" },
1038 { LIO_IO_SYNCV, 0, "sync readv/writev" },
1039 { LIO_IO_SYNCP, 0, "sync pread/pwrite" },
1040 { LIO_IO_ASYNC, 0, "async io, def wait" },
1041 { LIO_IO_SLISTIO, 0, "sync listio" },
1042 { LIO_IO_ALISTIO, 0, "async listio, def wait" },
1043 { LIO_IO_ASYNC|LIO_WAIT_ACTIVE, 0, "async active" },
1044 { LIO_IO_ASYNC|LIO_WAIT_RECALL, 0, "async recall/suspend" },
1045 { LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause" },
1046 { LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive" },
1047 { LIO_IO_ALISTIO|LIO_WAIT_ACTIVE, 0, "async listio active" },
1048 { LIO_IO_ALISTIO|LIO_WAIT_RECALL, 0, "async listio recall" },
1049 { LIO_IO_ALISTIO|LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive" },
1050 { LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause" },
1051 { LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2" },
1052 { LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2" },
1060 extern char *optarg;
1071 int exit_status = 0;
1074 char *symbols = NULL;
1077 while( (c = getopt(argc,argv,"s:di:")) != -1 ){
1079 case 's': symbols = optarg; break;
1080 case 'd': ++die_on_err; break;
1081 case 'i': iter = atoi(optarg); break;
1085 if ((fd=open("unit_test_file", O_CREAT|O_RDWR|O_TRUNC, 0777)) == -1 ) {
1086 perror("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
1092 if ( symbols != NULL ) {
1093 if ( (method=lio_parse_io_arg2(symbols, &err)) == -1 ){
1094 printf("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
1100 printf("lio_parse_io_arg2(%s, &err) returned %#o\n", symbols, method);
1103 for(ind=0; ind < iter; ind++ ) {
1104 memset( buffer, 'A', 4096 );
1105 if( lseek(fd, 0, 0) == -1 ){
1106 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1110 if ((ret=lio_write_buffer(fd, method, buffer,
1111 size, SIGUSR1, &err, 0)) != size ) {
1112 printf("lio_write_buffer returned -1, err = %s\n", err);
1114 printf("lio_write_buffer returned %d\n", ret);
1116 memset( buffer, 'B', 4096 );
1117 if( lseek(fd, 0, 0) == -1 ){
1118 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1122 if ((ret=lio_read_buffer(fd, method, buffer,
1123 size, SIGUSR2, &err, 0)) != size ) {
1124 printf("lio_read_buffer returned -1, err = %s\n", err);
1126 printf("lio_read_buffer returned %d\n", ret);
1128 for( i = 0; i < 4096; ++i ){
1129 if( buffer[i] != 'A' ){
1130 printf(" buffer[%d] = %d\n", i, buffer[i] );
1141 unlink("unit_test_file");
1145 for(ind=0; ind < sizeof(Unit_info)/sizeof(struct unit_info_t); ind++ ) {
1147 printf("\n********* write %s ***************\n", Unit_info[ind].str);
1148 if( lseek(fd, 0, 0) == -1 ){
1149 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1154 memset( buffer, 'A', 4096 );
1155 if ((ret=lio_write_buffer(fd, Unit_info[ind].method, buffer,
1156 size, Unit_info[ind].sig, &err, 0)) != size ) {
1157 printf(">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
1158 Unit_info[ind].method, size, Unit_info[ind].sig, err);
1163 printf("lio_write_buffer returned %d\n", ret);
1166 printf("\n********* read %s ***************\n", Unit_info[ind].str);
1167 if( lseek(fd, 0, 0) == -1 ){
1168 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1172 memset( buffer, 'B', 4096 );
1173 if ((ret=lio_read_buffer(fd, Unit_info[ind].method, buffer,
1174 size, Unit_info[ind].sig, &err, 0)) != size ) {
1175 printf(">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
1176 Unit_info[ind].method, size, Unit_info[ind].sig, err);
1181 printf("lio_read_buffer returned %d\n", ret);
1184 for( i = 0; i < 4096; ++i ){
1185 if( buffer[i] != 'A' ){
1186 printf(" buffer[%d] = %d\n", i, buffer[i] );
1200 unlink("unit_test_file");