1/* 2 * Copyright (c) 2004, Bull SA. All rights reserved. 3 * Created by: Laurent.Vivier@bull.net 4 * This file is licensed under the GPL license. For the full content 5 * of this license, see the COPYING file at the top level of this 6 * source tree. 7 */ 8 9/* 10 * assertion: 11 * 12 * The aio_suspend() function shall suspend the calling thread until at 13 * least one of the asynchronous I/O operations referenced by the list 14 * argument has completed, until a signal interrupts the function, or, 15 * if timeout is not NULL, until the time interval specified by timeout 16 * has passed. 17 * 18 * method: Testing for a NULL timeout 19 * 20 * - write to a file 21 * - submit a list of read requests 22 * - check that the selected request has not completed 23 * - suspend on selected request 24 * - check that the selected request has completed using aio_error and 25 * aio_return 26 * 27 */ 28 29#define _XOPEN_SOURCE 600 30#include <stdio.h> 31#include <unistd.h> 32#include <string.h> 33#include <errno.h> 34#include <stdlib.h> 35#include <aio.h> 36 37#include "posixtest.h" 38 39#define TNAME "aio_suspend/8-1.c" 40 41#define NUM_AIOCBS 10 42#define BUF_SIZE 1024*1024 43#define WAIT_FOR_AIOCB 6 44 45int received_selected = 0; 46int received_all = 0; 47 48void 49sigrt1_handler(int signum, siginfo_t *info, void *context) 50{ 51 if (info->si_value.sival_int == WAIT_FOR_AIOCB) 52 received_selected = 1; 53} 54 55void 56sigrt2_handler(int signum, siginfo_t *info, void *context) 57{ 58 received_all = 1; 59} 60 61int 62main () 63{ 64 char tmpfname[256]; 65 int fd; 66 67 struct aiocb **aiocbs; 68 struct aiocb *plist[2]; 69 char *bufs; 70 struct sigaction action; 71 struct sigevent event; 72 int errors = 0; 73 int ret; 74 int err; 75 int i; 76 77#if _POSIX_ASYNCHRONOUS_IO != 200112L 78 exit(PTS_UNSUPPORTED); 79#endif 80 81 snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_suspend_8_1_%d", 82 getpid()); 83 unlink(tmpfname); 84 85 fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); 86 87 if (fd == -1) { 88 printf(TNAME " Error at open(): %s\n", 89 strerror(errno)); 90 exit(PTS_UNRESOLVED); 91 } 92 93 unlink(tmpfname); 94 95 bufs = (char *) malloc (NUM_AIOCBS*BUF_SIZE); 96 97 if (bufs == NULL) { 98 printf (TNAME " Error at malloc(): %s\n", strerror (errno)); 99 close (fd); 100 exit(PTS_UNRESOLVED); 101 } 102 103 if (write (fd, bufs, NUM_AIOCBS*BUF_SIZE) != (NUM_AIOCBS*BUF_SIZE)) { 104 printf(TNAME " Error at write(): %s\n", strerror(errno)); 105 free (bufs); 106 close (fd); 107 exit(PTS_UNRESOLVED); 108 } 109 110 111 112 aiocbs = (struct aiocb**)malloc(sizeof(struct aiocb *) * NUM_AIOCBS); 113 114 /* Queue up a bunch of aio reads */ 115 for (i = 0; i < NUM_AIOCBS; i++) { 116 117 aiocbs[i] = (struct aiocb*)malloc(sizeof(struct aiocb)); 118 memset(aiocbs[i], 0, sizeof(struct aiocb)); 119 120 aiocbs[i]->aio_fildes = fd; 121 aiocbs[i]->aio_offset = i * BUF_SIZE; 122 aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE]; 123 aiocbs[i]->aio_nbytes = BUF_SIZE; 124 aiocbs[i]->aio_lio_opcode = LIO_READ; 125 126 /* Use SIRTMIN+1 for individual completions */ 127 aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL; 128 aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN+1; 129 aiocbs[i]->aio_sigevent.sigev_value.sival_int = i; 130 } 131 132 /* Use SIGRTMIN+2 for list completion */ 133 event.sigev_notify = SIGEV_SIGNAL; 134 event.sigev_signo = SIGRTMIN+2; 135 event.sigev_value.sival_ptr = NULL; 136 137 /* Setup handler for individual operation completion */ 138 action.sa_sigaction = sigrt1_handler; 139 sigemptyset(&action.sa_mask); 140 action.sa_flags = SA_SIGINFO|SA_RESTART; 141 sigaction(SIGRTMIN+1, &action, NULL); 142 143 /* Setup handler for list completion */ 144 action.sa_sigaction = sigrt2_handler; 145 sigemptyset(&action.sa_mask); 146 action.sa_flags = SA_SIGINFO|SA_RESTART; 147 sigaction(SIGRTMIN+2, &action, NULL); 148 149 /* Setup suspend list */ 150 plist[0] = NULL; 151 plist[1] = aiocbs[WAIT_FOR_AIOCB]; 152 153 /* Submit request list */ 154 ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event); 155 156 if (ret) { 157 printf(TNAME " Error at lio_listio() %d: %s\n", errno, strerror(errno)); 158 for (i=0; i<NUM_AIOCBS; i++) 159 free (aiocbs[i]); 160 free (bufs); 161 free (aiocbs); 162 close (fd); 163 exit (PTS_UNRESOLVED); 164 } 165 166 /* Check selected request has not completed yet */ 167 if (received_selected) { 168 printf (TNAME " Error : AIOCB %d already completed before suspend\n", 169 WAIT_FOR_AIOCB); 170 for (i=0; i<NUM_AIOCBS; i++) 171 free (aiocbs[i]); 172 free (bufs); 173 free (aiocbs); 174 close (fd); 175 exit (PTS_FAIL); 176 } 177 178 /* Suspend on selected request */ 179 ret = aio_suspend((const struct aiocb **)plist, 2, NULL); 180 181 if (ret) { 182 printf (TNAME " Error at aio_suspend() %d: %s\n", errno, strerror (errno)); 183 for (i=0; i<NUM_AIOCBS; i++) 184 free (aiocbs[i]); 185 free (bufs); 186 free (aiocbs); 187 close (fd); 188 exit (PTS_FAIL); 189 } 190 191 /* Check selected request has completed */ 192 err = aio_error (aiocbs[WAIT_FOR_AIOCB]); 193 ret = aio_return (aiocbs[WAIT_FOR_AIOCB]); 194 195 if ((err != 0) && (ret != BUF_SIZE)) { 196 printf (TNAME " Error : AIOCB %d should have completed after suspend\n", 197 WAIT_FOR_AIOCB); 198 for (i=0; i<NUM_AIOCBS; i++) 199 free (aiocbs[i]); 200 free (bufs); 201 free (aiocbs); 202 close (fd); 203 exit (PTS_FAIL); 204 } 205 206 207 /* Wait for list processing completion */ 208 while (!received_all) 209 sleep (1); 210 211 /* Check return code and free things */ 212 for (i = 0; i < NUM_AIOCBS; i++) { 213 if (i == WAIT_FOR_AIOCB) 214 continue; 215 216 err = aio_error(aiocbs[i]); 217 ret = aio_return(aiocbs[i]); 218 219 if ((err != 0) && (ret != BUF_SIZE)) { 220 printf(TNAME " req %d: error = %d - return = %d\n", i, err, ret); 221 errors++; 222 } 223 224 free (aiocbs[i]); 225 } 226 227 free (bufs); 228 free (aiocbs); 229 230 close(fd); 231 232 if (errors != 0) 233 exit (PTS_FAIL); 234 235 printf (TNAME " PASSED\n"); 236 237 return PTS_PASS; 238} 239