int
do_test (int argc, char *argv[])
{
  struct aiocb cbs[10];
  struct aiocb cbs_fsync;
  struct aiocb *cbp[10];
  struct aiocb *cbp_fsync[1];
  char buf[1000];
  size_t cnt;
  int result = 0;

  /* Preparation.  */
  for (cnt = 0; cnt < 10; ++cnt)
    {
      cbs[cnt].aio_fildes = fd;
      cbs[cnt].aio_reqprio = 0;
      cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100);
      cbs[cnt].aio_nbytes = 100;
      cbs[cnt].aio_offset = cnt * 100;
      cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;

      cbp[cnt] = &cbs[cnt];
    }

  /* First a simple test.  */
  for (cnt = 10; cnt > 0; )
    if (aio_write (cbp[--cnt]) < 0 && errno == ENOSYS)
      {
	error (0, 0, "no aio support in this configuration");
	return 0;
      }
  /* Wait 'til the results are there.  */
  result |= do_wait (cbp, 10, 0);
  /* Test this.  */
  result |= test_file (buf, sizeof (buf), fd, "aio_write");

  /* Read now as we've written it.  */
  memset (buf, '\0', sizeof (buf));
  /* Issue the commands.  */
  for (cnt = 10; cnt > 0; )
    {
      --cnt;
      cbp[cnt] = &cbs[cnt];
      aio_read (cbp[cnt]);
    }
  /* Wait 'til the results are there.  */
  result |= do_wait (cbp, 10, 0);
  /* Test this.  */
  for (cnt = 0; cnt < 1000; ++cnt)
    if (buf[cnt] != '0' + (cnt / 100))
      {
	result = 1;
	error (0, 0, "comparison failed for aio_read test");
	break;
      }

  if (cnt == 1000)
    puts ("aio_read test ok");

  /* Remove the test file contents.  */
  if (ftruncate (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Test lio_listio.  */
  for (cnt = 0; cnt < 10; ++cnt)
    {
      cbs[cnt].aio_lio_opcode = LIO_WRITE;
      cbp[cnt] = &cbs[cnt];
    }
  /* Issue the command.  */
  lio_listio (LIO_WAIT, cbp, 10, NULL);
  /* ...and immediately test it since we started it in wait mode.  */
  result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)");

  /* Test aio_fsync.  */
  cbs_fsync.aio_fildes = fd;
  cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE;
  cbp_fsync[0] = &cbs_fsync;

  /* Remove the test file contents first.  */
  if (ftruncate (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Write again.  */
  for (cnt = 10; cnt > 0; )
    aio_write (cbp[--cnt]);

  if (aio_fsync (O_SYNC, &cbs_fsync) < 0)
    {
      error (0, errno, "aio_fsync failed\n");
      result = 1;
    }
  result |= do_wait (cbp_fsync, 1, 0);

  /* ...and test since all data should be on disk now.  */
  result |= test_file (buf, sizeof (buf), fd, "aio_fsync (aio_write)");

  /* Test aio_cancel.  */
  /* Remove the test file contents first.  */
  if (ftruncate (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Write again.  */
  for (cnt = 10; cnt > 0; )
    aio_write (cbp[--cnt]);

  /* Cancel all requests.  */
  if (aio_cancel (fd, NULL) == -1)
    printf ("aio_cancel (fd, NULL) cannot cancel anything\n");

  result |= do_wait (cbp, 10, ECANCELED);

  /* Another test for aio_cancel.  */
  /* Remove the test file contents first.  */
  if (ftruncate (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Write again.  */
  for (cnt = 10; cnt > 0; )
    {
      --cnt;
      cbp[cnt] = &cbs[cnt];
      aio_write (cbp[cnt]);
    }
  puts ("finished3");

  /* Cancel all requests.  */
  for (cnt = 10; cnt > 0; )
    if (aio_cancel (fd, cbp[--cnt]) == -1)
      /* This is not an error.  The request can simply be finished.  */
      printf ("aio_cancel (fd, cbp[%Zd]) cannot be canceled\n", cnt);
  puts ("finished2");

  result |= do_wait (cbp, 10, ECANCELED);

  puts ("finished");

  return result;
}
Exemplo n.º 2
0
static int
do_test (int argc, char *argv[])
{
  char name[] = "/tmp/aio3.XXXXXX";
  int fd;
  struct aiocb *arr[1];
  struct aiocb cb;
  static const char buf[] = "Hello World\n";

  fd = mkstemp (name);
  if (fd == -1)
    {
      printf ("cannot open temp name: %m\n");
      return 1;
    }

  unlink (name);

  if (pthread_barrier_init (&b, NULL, 2) != 0)
    {
      puts ("barrier_init failed");
      return 1;
    }

  arr[0] = &cb;

  cb.aio_fildes = fd;
  cb.aio_lio_opcode = LIO_WRITE;
  cb.aio_reqprio = 0;
  cb.aio_buf = (void *) buf;
  cb.aio_nbytes = sizeof (buf) - 1;
  cb.aio_offset = 0;
  cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
  cb.aio_sigevent.sigev_notify_function = thrfct;
  cb.aio_sigevent.sigev_notify_attributes = NULL;
  cb.aio_sigevent.sigev_value.sival_ptr = NULL;

  if (lio_listio (LIO_NOWAIT, arr, 1, NULL) < 0)
    {
      if (errno == ENOSYS)
	{
	  puts ("no aio support in this configuration");
	  return 0;
	}
      printf ("lio_listio failed: %m\n");
      return 1;
    }

  if (aio_suspend ((const struct aiocb *const *) arr, 1, NULL) < 0)
    {
      printf ("aio_suspend failed: %m\n");
      return 1;
    }

  int e = pthread_barrier_wait (&b);
  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
    {
      puts ("parent: barrier_wait failed");
      return 1;
    }

  puts ("all OK");

  return 0;
}
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
{
    int rc = VINF_SUCCESS;
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;

    /* Parameter checks */
    AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE);
    AssertReturn(cReqs != 0, VERR_INVALID_POINTER);
    AssertPtrReturn(pahReqs,  VERR_INVALID_PARAMETER);

    rtFileAioCtxDump(pCtxInt);

    /* Check that we don't exceed the limit */
    if (ASMAtomicUoReadS32(&pCtxInt->cRequests) + cReqs > pCtxInt->cMaxRequests)
        return VERR_FILE_AIO_LIMIT_EXCEEDED;

    PRTFILEAIOREQINTERNAL pHead = NULL;

    do
    {
        int rcPosix = 0;
        size_t cReqsSubmit = 0;
        size_t i = 0;
        PRTFILEAIOREQINTERNAL pReqInt;

        while (   (i < cReqs)
               && (i < AIO_LISTIO_MAX))
        {
            pReqInt = pahReqs[i];
            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
            {
                /* Undo everything and stop submitting. */
                for (size_t iUndo = 0; iUndo < i; iUndo++)
                {
                    pReqInt = pahReqs[iUndo];
                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    pReqInt->pCtxInt = NULL;

                    /* Unlink from the list again. */
                    PRTFILEAIOREQINTERNAL pNext, pPrev;
                    pNext = pReqInt->pNext;
                    pPrev = pReqInt->pPrev;
                    if (pNext)
                        pNext->pPrev = pPrev;
                    if (pPrev)
                        pPrev->pNext = pNext;
                    else
                        pHead = pNext;
                }
                rc = VERR_INVALID_HANDLE;
                break;
            }

            pReqInt->pCtxInt = pCtxInt;

            if (pReqInt->fFlush)
                break;

            /* Link them together. */
            pReqInt->pNext = pHead;
            if (pHead)
                pHead->pPrev = pReqInt;
            pReqInt->pPrev = NULL;
            pHead = pReqInt;
            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

            cReqsSubmit++;
            i++;
        }

        if (cReqsSubmit)
        {
            rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
            if (RT_UNLIKELY(rcPosix < 0))
            {
                size_t cReqsSubmitted = cReqsSubmit;

                if (errno == EAGAIN)
                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                else
                    rc = RTErrConvertFromErrno(errno);

                /* Check which ones were not submitted. */
                for (i = 0; i < cReqsSubmit; i++)
                {
                    pReqInt = pahReqs[i];

                    rcPosix = aio_error(&pReqInt->AioCB);

                    if ((rcPosix != EINPROGRESS) && (rcPosix != 0))
                    {
                        cReqsSubmitted--;

#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
                        if (errno == EINVAL)
#else
                        if (rcPosix == EINVAL)
#endif
                        {
                            /* Was not submitted. */
                            RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        }
                        else
                        {
                            /* An error occurred. */
                            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);

                            /*
                             * Looks like Apple and glibc interpret the standard in different ways.
                             * glibc returns the error code which would be in errno but Apple returns
                             * -1 and sets errno to the appropriate value
                             */
#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
                            Assert(rcPosix == -1);
                            pReqInt->Rc = RTErrConvertFromErrno(errno);
#elif defined(RT_OS_LINUX)
                            pReqInt->Rc = RTErrConvertFromErrno(rcPosix);
#endif
                            pReqInt->cbTransfered = 0;
                        }
                        /* Unlink from the list. */
                        PRTFILEAIOREQINTERNAL pNext, pPrev;
                        pNext = pReqInt->pNext;
                        pPrev = pReqInt->pPrev;
                        if (pNext)
                            pNext->pPrev = pPrev;
                        if (pPrev)
                            pPrev->pNext = pNext;
                        else
                            pHead = pNext;

                        pReqInt->pNext = NULL;
                        pReqInt->pPrev = NULL;
                    }
                }
                ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted);
                AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n"));
                break;
            }

            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
            AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n"));
            cReqs   -= cReqsSubmit;
            pahReqs += cReqsSubmit;
        }

        /*
         * Check if we have a flush request now.
         * If not we hit the AIO_LISTIO_MAX limit
         * and will continue submitting requests
         * above.
         */
        if (cReqs && RT_SUCCESS_NP(rc))
        {
            pReqInt = pahReqs[0];

            if (pReqInt->fFlush)
            {
                /*
                 * lio_listio does not work with flush requests so
                 * we have to use aio_fsync directly.
                 */
                rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB);
                if (RT_UNLIKELY(rcPosix < 0))
                {
                    if (errno == EAGAIN)
                    {
                        rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    }
                    else
                    {
                        rc = RTErrConvertFromErrno(errno);
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                        pReqInt->Rc = rc;
                    }
                    pReqInt->cbTransfered = 0;
                    break;
                }

                /* Link them together. */
                pReqInt->pNext = pHead;
                if (pHead)
                    pHead->pPrev = pReqInt;
                pReqInt->pPrev = NULL;
                pHead = pReqInt;
                RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

                ASMAtomicIncS32(&pCtxInt->cRequests);
                AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n"));
                cReqs--;
                pahReqs++;
            }
        }
    } while (   cReqs
             && RT_SUCCESS_NP(rc));

    if (pHead)
    {
        /*
         * Forward successfully submitted requests to the thread waiting for requests.
         * We search for a free slot first and if we don't find one
         * we will grab the first one and append our list to the existing entries.
         */
        unsigned iSlot = 0;
        while (  (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead))
               && !ASMAtomicCmpXchgPtr(&pCtxInt->apReqsNewHead[iSlot], pHead, NULL))
            iSlot++;

        if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead))
        {
            /* Nothing found. */
            PRTFILEAIOREQINTERNAL pOldHead = ASMAtomicXchgPtrT(&pCtxInt->apReqsNewHead[0], NULL, PRTFILEAIOREQINTERNAL);

            /* Find the end of the current head and link the old list to the current. */
            PRTFILEAIOREQINTERNAL pTail = pHead;
            while (pTail->pNext)
                pTail = pTail->pNext;

            pTail->pNext = pOldHead;

            ASMAtomicWritePtr(&pCtxInt->apReqsNewHead[0], pHead);
        }

        /* Set the internal wakeup flag and wakeup the thread if possible. */
        bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true);
        if (!fWokenUp)
            rtFileAioCtxWakeup(pCtxInt);
    }

    rtFileAioCtxDump(pCtxInt);

    return rc;
}
Exemplo n.º 4
0
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
{
    /*
     * Parameter validation.
     */
    int rc = VINF_SUCCESS;
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
    AssertReturn(cReqs > 0,  VERR_INVALID_PARAMETER);
    AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);

    do
    {
        int rcBSD = 0;
        size_t cReqsSubmit = 0;
        size_t i = 0;
        PRTFILEAIOREQINTERNAL pReqInt;

        while (   (i < cReqs)
               && (i < AIO_LISTIO_MAX))
        {
            pReqInt = pahReqs[i];
            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
            {
                /* Undo everything and stop submitting. */
                for (size_t iUndo = 0; iUndo < i; iUndo++)
                {
                    pReqInt = pahReqs[iUndo];
                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    pReqInt->pCtxInt = NULL;
                    pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = 0;
                }
                rc = VERR_INVALID_HANDLE;
                break;
            }

            pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = pCtxInt->iKQueue;
            pReqInt->pCtxInt                                = pCtxInt;
            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

            if (pReqInt->fFlush)
                break;

            cReqsSubmit++;
            i++;
        }

        if (cReqsSubmit)
        {
            rcBSD = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
            if (RT_UNLIKELY(rcBSD < 0))
            {
                if (errno == EAGAIN)
                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                else
                    rc = RTErrConvertFromErrno(errno);

                /* Check which requests got actually submitted and which not. */
                for (i = 0; i < cReqs; i++)
                {
                    pReqInt = pahReqs[i];
                    rcBSD = aio_error(&pReqInt->AioCB);
                    if (   rcBSD == -1
                        && errno == EINVAL)
                    {
                        /* Was not submitted. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        pReqInt->pCtxInt = NULL;
                    }
                    else if (rcBSD != EINPROGRESS)
                    {
                        /* The request encountered an error. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                        pReqInt->Rc = RTErrConvertFromErrno(rcBSD);
                        pReqInt->pCtxInt      = NULL;
                        pReqInt->cbTransfered = 0;
                    }
                }
                break;
            }

            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
            cReqs   -= cReqsSubmit;
            pahReqs += cReqsSubmit;
        }

        /* Check if we have a flush request now. */
        if (cReqs && RT_SUCCESS_NP(rc))
        {
            pReqInt = pahReqs[0];
            RTFILEAIOREQ_VALID_RETURN(pReqInt);

            if (pReqInt->fFlush)
            {
                /*
                 * lio_listio does not work with flush requests so
                 * we have to use aio_fsync directly.
                 */
                 rcBSD = aio_fsync(O_SYNC, &pReqInt->AioCB);
                 if (RT_UNLIKELY(rcBSD < 0))
                 {
                    if (rcBSD == EAGAIN)
                    {
                        /* Was not submitted. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        pReqInt->pCtxInt = NULL;
                        return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                    }
                    else
                    {
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                        pReqInt->Rc = RTErrConvertFromErrno(errno);
                        pReqInt->cbTransfered = 0;
                        return pReqInt->Rc;
                    }
                 }

                ASMAtomicIncS32(&pCtxInt->cRequests);
                cReqs--;
                pahReqs++;
            }
        }
    } while (cReqs);

    return rc;
}
Exemplo n.º 5
0
void *POSIX_Init(
  void *argument
)
{
  int             sc;

  TEST_BEGIN();

  puts( "lio_listio -- ENOSYS" );
  sc = lio_listio( 0, NULL, 0, NULL );
  check_enosys( sc );

  puts( "aio_suspend -- ENOSYS" );
  sc = aio_suspend( NULL, 0, NULL );
  check_enosys( sc );

  puts( "clock_getcpuclockid -- ENOSYS" );
  sc = clock_getcpuclockid( 0, NULL );
  check_enosys( sc );

  puts( "clock_getenable_attr -- ENOSYS" );
  sc = clock_getenable_attr( 0, NULL );
  check_enosys( sc );

  puts( "clock_setenable_attr -- ENOSYS" );
  sc = clock_setenable_attr( 0, 0 );
  check_enosys( sc );

  puts( "execl -- ENOSYS" );
  sc = execl( NULL, NULL, (char*)0 );
  check_enosys( sc );

  puts( "execle -- ENOSYS" );
  sc = execle( NULL, NULL, (char*)0, NULL );
  check_enosys( sc );

  puts( "execlp -- ENOSYS" );
  sc = execlp( NULL, NULL, (char*)0 );
  check_enosys( sc );

  puts( "execv -- ENOSYS" );
  sc = execv( NULL, NULL );
  check_enosys( sc );

  puts( "execve -- ENOSYS" );
  sc = execve( NULL, NULL, NULL );
  check_enosys( sc );

  puts( "execvp -- ENOSYS" );
  sc = execvp( NULL, NULL );
  check_enosys( sc );

  puts( "fork -- ENOSYS" );
  sc = fork();
  check_enosys( sc );

  puts( "pthread_atfork -- ENOSYS" );
  sc = pthread_atfork( NULL, NULL, NULL );
  check_enosys( sc );

  puts( "pthread_getcpuclockid -- ENOSYS" );
  sc = pthread_getcpuclockid( 0, NULL );
  check_enosys( sc );

  puts( "sched_setparam -- ENOSYS" );
  sc = sched_setparam( 0, NULL );
  check_enosys( sc );

  puts( "sched_getparam -- ENOSYS" );
  sc = sched_getparam( 0, NULL );
  check_enosys( sc );

  puts( "sched_setscheduler -- ENOSYS" );
  sc = sched_setscheduler( 0, 0, NULL );
  check_enosys( sc );

  puts( "sched_getscheduler -- ENOSYS" );
  sc = sched_getscheduler( 0 );
  check_enosys( sc );

  puts( "wait -- ENOSYS" );
  sc = wait( NULL );
  check_enosys( sc );

  puts( "waitpid -- ENOSYS" );
  sc = waitpid( 0, NULL, 0 );
  check_enosys( sc );

  puts( "mprotect -- stub implementation - OK" );
  sc = mprotect( NULL, 0, 0 );
  posix_service_failed( sc, "mprotect" );

  puts( "vfork -- stub implementation - OK" );
  sc = vfork();
  if ( sc != -1 ) {
    puts( "vfork did not return -1" );
    rtems_test_exit( 0 );
  }

  TEST_END();
  rtems_test_exit( 0 );

  return NULL; /* just so the compiler thinks we returned something */
}
Exemplo n.º 6
0
int main(void)
{
	char tmpfname[256];
	int fd;

	struct aiocb **aiocbs;
	struct aiocb *plist[2];
	char *bufs;
	struct sigaction action;
	struct sigevent event;
	struct timespec ts = {0, 1000}; /* 10 ms */
	int errors = 0;
	int ret;
	int err;
	int i;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
		return PTS_UNSUPPORTED;

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_suspend_7_1_%d",
		  getpid());
	unlink(tmpfname);

	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);

	if (fd == -1) {
		printf(TNAME " Error at open(): %s\n",
		       strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	bufs = malloc(NUM_AIOCBS*BUF_SIZE);

	if (bufs == NULL) {
		printf(TNAME " Error at malloc(): %s\n", strerror(errno));
		close(fd);
		exit(PTS_UNRESOLVED);
	}

	if (write (fd, bufs, NUM_AIOCBS*BUF_SIZE) != (NUM_AIOCBS*BUF_SIZE)) {
		printf(TNAME " Error at write(): %s\n", strerror(errno));
		free(bufs);
		close(fd);
		exit(PTS_UNRESOLVED);
	}

	aiocbs = malloc(sizeof(struct aiocb *) * NUM_AIOCBS);

	/* Queue up a bunch of aio reads */
	for (i = 0; i < NUM_AIOCBS; i++) {

		aiocbs[i] = (struct aiocb*)malloc(sizeof(struct aiocb));
		memset(aiocbs[i], 0, sizeof(struct aiocb));

		aiocbs[i]->aio_fildes = fd;
		aiocbs[i]->aio_offset = i * BUF_SIZE;
		aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE];
		aiocbs[i]->aio_nbytes = BUF_SIZE;
		aiocbs[i]->aio_lio_opcode = LIO_READ;
	}

	/* Use SIGRTMIN + 1 for list completion */
	event.sigev_notify = SIGEV_SIGNAL;
	event.sigev_signo = SIGRTMIN + 1;
	event.sigev_value.sival_ptr = NULL;

	/* Setup handler for list completion */
	action.sa_sigaction = sigrt1_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO|SA_RESTART;
	sigaction(SIGRTMIN + 1, &action, NULL);

	/* Setup suspend list */
	plist[0] = NULL;
	plist[1] = aiocbs[WAIT_FOR_AIOCB];

	/* Submit request list */
	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);

	if (ret) {
		printf(TNAME " Error at lio_listio() %d: %s\n", errno, strerror(errno));
		for (i=0; i<NUM_AIOCBS; i++)
			free(aiocbs[i]);
		free(bufs);
		free(aiocbs);
		close(fd);
		exit(PTS_UNRESOLVED);
	}

	/* Check selected request has not completed yet */
	if (aio_error(aiocbs[WAIT_FOR_AIOCB]) != EINPROGRESS) {
		printf(TNAME " Error : AIOCB %d already completed before suspend\n",
			WAIT_FOR_AIOCB);
		for (i=0; i<NUM_AIOCBS; i++)
			free(aiocbs[i]);
		free(bufs);
		free(aiocbs);
		close(fd);
		exit(PTS_FAIL);
	}

	/* Suspend on selected request */
	ret = aio_suspend((const struct aiocb **)plist, 2, &ts);

	/* Check selected request has not completed */
	if (aio_error(aiocbs[WAIT_FOR_AIOCB]) != EINPROGRESS) {
		printf(TNAME " Error : AIOCB %d should not have completed after timed out suspend\n",
			WAIT_FOR_AIOCB);
		for (i=0; i<NUM_AIOCBS; i++)
			free(aiocbs[i]);
		free(bufs);
		free(aiocbs);
		close(fd);
		exit(PTS_FAIL);
	}

	/* timed out aio_suspend should return -1 and set errno to EAGAIN */
	if (ret != -1) {
		printf(TNAME " aio_suspend() should return -1\n");
		for (i=0; i<NUM_AIOCBS; i++)
			free(aiocbs[i]);
		free(bufs);
		free(aiocbs);
		close(fd);
		exit(PTS_FAIL);
	}

	if (errno != EAGAIN) {
		printf(TNAME " aio_suspend() should set errno to EAGAIN: %d (%s)\n",
			errno, strerror(errno));
		for (i=0; i<NUM_AIOCBS; i++)
			free(aiocbs[i]);
		free(bufs);
		free(aiocbs);
		close(fd);
		exit(PTS_FAIL);
	}

	/* Wait for list processing completion */
	while (!received_all)
		sleep(1);

	/* Check return code and free things */
	for (i = 0; i < NUM_AIOCBS; i++) {
	  	err = aio_error(aiocbs[i]);
		ret = aio_return(aiocbs[i]);

		if ((err != 0) && (ret != BUF_SIZE)) {
			printf(TNAME " req %d: error = %d - return = %d\n", i, err, ret);
			errors++;
		}

		free(aiocbs[i]);
	}

	free(bufs);
	free(aiocbs);

	close(fd);

	if (errors != 0)
		exit(PTS_FAIL);

	printf(TNAME " PASSED\n");

	return PTS_PASS;
}
Exemplo n.º 7
0
static int
do_test (int argc, char *argv[])
{
  char name[] = "/tmp/aio4.XXXXXX";
  int fd;
  struct aiocb *arr[1];
  struct aiocb cb;
  static const char buf[] = "Hello World\n";
  struct aioinit init = {10, 20, 0};
  struct sigaction sa;
  struct sigevent ev;

  if (SIGRTMIN == -1)
  {
      printf ("RT signals not supported.\n");
      return 0;
  }

  /* Select a signal from the middle of the available choices... */
  my_signo = (SIGRTMAX + SIGRTMIN) / 2;

  fd = mkstemp (name);
  if (fd == -1)
    {
      printf ("cannot open temp name: %m\n");
      return 1;
    }

  unlink (name);

  /* Test also aio_init.  */
  aio_init (&init);

  arr[0] = &cb;

  cb.aio_fildes = fd;
  cb.aio_lio_opcode = LIO_WRITE;
  cb.aio_reqprio = 0;
  cb.aio_buf = (void *) buf;
  cb.aio_nbytes = sizeof (buf) - 1;
  cb.aio_offset = 0;
  cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  cb.aio_sigevent.sigev_notify_function = NULL;
  cb.aio_sigevent.sigev_notify_attributes = NULL;
  cb.aio_sigevent.sigev_signo = my_signo;
  cb.aio_sigevent.sigev_value.sival_ptr = NULL;

  ev.sigev_notify = SIGEV_SIGNAL;
  ev.sigev_notify_function = NULL;
  ev.sigev_notify_attributes = NULL;
  ev.sigev_signo = my_signo;

  sa.sa_handler = sighandler;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = SA_RESTART;

  if (sigaction (my_signo, &sa, NULL) < 0)
    {
      printf ("sigaction failed: %m\n");
      return 1;
    }

  flag = 0;
  /* First use aio_write.  */
  if (aio_write (arr[0]) < 0)
    {
      if (errno == ENOSYS)
	{
	  puts ("no aio support in this configuration");
	  return 0;
	}
      printf ("aio_write failed: %m\n");
      return 1;
    }

  if (wait_flag ())
    return 1;

  puts ("aio_write OK");

  flag = 0;
  /* Again with lio_listio.  */
  if (lio_listio (LIO_NOWAIT, arr, 1, &ev) < 0)
    {
      printf ("lio_listio failed: %m\n");
      return 1;
    }

  if (wait_flag ())
    return 1;

  puts ("all OK");

  return 0;
}
Exemplo n.º 8
0
static int
do_test (int argc, char *argv[])
{
  char name[] = "/tmp/aio2.XXXXXX";
  int fd;
  struct aiocb *arr[1];
  struct aiocb cb;
  static const char buf[] = "Hello World\n";

  fd = mkstemp (name);
  if (fd == -1)
    {
      printf ("cannot open temp name: %m\n");
      return 1;
    }

  unlink (name);

  if (pthread_barrier_init (&b, NULL, 2) != 0)
    {
      puts ("barrier_init failed");
      return 1;
    }

  arr[0] = &cb;

  void *p;
  int sz = set_o_direct (fd);
  if (sz != -1)
    {
      int err = posix_memalign (&p, sz, sz);
      if (err)
	{
	  errno = err;
	  printf ("cannot allocate memory: %m\n");
	  return 1;
	}
      memcpy (p, buf, sizeof (buf) - 1);
      memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1);
      printf ("Using O_DIRECT with block size %d\n", sz);
    }
  else
    {
      p = (void *) buf;
      sz = sizeof (buf) - 1;
    }

  cb.aio_fildes = fd;
  cb.aio_lio_opcode = LIO_WRITE;
  cb.aio_reqprio = 0;
  cb.aio_buf = p;
  cb.aio_nbytes = sz;
  cb.aio_offset = 0;
  cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
  cb.aio_sigevent.sigev_notify_function = thrfct;
  cb.aio_sigevent.sigev_notify_attributes = NULL;
  cb.aio_sigevent.sigev_value.sival_ptr = NULL;

  if (lio_listio (LIO_WAIT, arr, 1, NULL) < 0)
    {
      if (errno == ENOSYS)
	{
	  puts ("no aio support in this configuration");
	  return 0;
	}
      printf ("lio_listio failed: %m\n");
      return 1;
    }

  puts ("lio_listio returned");

  int e = pthread_barrier_wait (&b);
  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
    {
      puts ("barrier_wait failed");
      return 1;
    }

  puts ("all OK");

  return 0;
}
Exemplo n.º 9
0
int main(){
	
	struct aiocb a_write, a_read;
	struct aiocb *cblist[MAX];
	int err_r, err_w;
	int read_n = 0;
	int read_fd,write_fd;
	char read_buf[BUFFER_SIZE];
	char write_buf[BUFFER_SIZE];
	
	/* Open Read.txt file for reading */
	read_fd = open("Read.txt", O_RDONLY);

	/* Open Write.txt file for writing */
	write_fd = open("Write.txt", O_CREAT | O_WRONLY, 0644);

	/* Its good practice to clear the aiocbs before 
	 * using them
	 */
	memset(&a_write, 0 , sizeof(struct aiocb));
	memset(&a_read, 0 , sizeof(struct aiocb));


	/* populate aiocbs to defaults */
	populate_aiocb(&a_read, read_fd, 0, BUFFER_SIZE-1, read_buf,LIO_READ);
	populate_aiocb(&a_write, write_fd, 0, BUFFER_SIZE-1, write_buf,LIO_WRITE);

	/* Start async read. The function will read a_read.aio_nbytes bytes
	 * from file a_read.aio_fildes starting from a_read.aio_offset into 
	 * buffer a_read.aio_buf. On success 0 is returned. This function will
	 * return immediately after queueing the request
	 */
	cblist[0] = &a_read;
        cblist[1] = &a_write;

	while(1)
	{
		//aio_read(&a_read);
		lio_listio(LIO_NOWAIT, cblist, 2, NULL);
	
		/* After starting any async operation (read or write), you can get its status
		 * using aio_error function. This function returns EINPROGRESS if the request has not been completed
		 * It  returns ECANCELED if the request was cancelled.It returns 0
        	 * if the request completed successfully.  Otherwise  an  error  value  is returned
		 */
		if((err_r = aio_error(&a_read)) == EINPROGRESS || (err_w = aio_error(&a_write)) == EINPROGRESS){
                        cblist[0] = &a_read;
                        cblist[1] = &a_write;
                        aio_suspend(cblist, 2, NULL);
                }
		/* aio_error returns 0 that is success. Call aio_return to find of number of 
		 * bytes read. The function should be called only once after aio_error returns
		 * something other than EINPROGRESS.
		 */
		read_n  = aio_return(&a_read);
					
		strcpy(write_buf,read_buf);
		/* Setup write control block. Call aio_write to queue write request. The function 
		 * will write a_write.aio_nbytes bytes from buffer a_write.aio_buf to file a_write.aio_fildes
		 * at offset a_write.aio_offset. Returns 0 on success
		 */
		a_write.aio_nbytes = read_n;
		aio_write(&a_write);
		
		if(read_n!=BUFFER_SIZE-1)
			break;
		else
		{
			/* update read & write offset */
			a_read.aio_offset += read_n;
			a_write.aio_offset += aio_return(&a_write);
		}
	}
	close(read_fd);
	close(write_fd);

}
Exemplo n.º 10
0
int main()
{
	char tmpfname[256];
	int fd;

	struct aiocb *aiocbs[NUM_AIOCBS];
	char *bufs;
	int errors = 0;
	int ret;
	int err;
	int i;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
		exit(PTS_UNSUPPORTED);

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_lio_listio_12_1_%d",
		 getpid());
	unlink(tmpfname);

	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);

	if (fd == -1) {
		printf(TNAME " Error at open(): %s\n", strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	bufs = (char *)malloc(NUM_AIOCBS * BUF_SIZE);

	if (bufs == NULL) {
		printf(TNAME " Error at malloc(): %s\n", strerror(errno));
		close(fd);
		exit(PTS_UNRESOLVED);
	}

	/* Queue up a bunch of aio writes */
	for (i = 0; i < NUM_AIOCBS; i++) {

		aiocbs[i] = (struct aiocb *)malloc(sizeof(struct aiocb));
		memset(aiocbs[i], 0, sizeof(struct aiocb));

		aiocbs[i]->aio_fildes = fd;
		aiocbs[i]->aio_offset = 0;
		aiocbs[i]->aio_buf = &bufs[i * BUF_SIZE];
		aiocbs[i]->aio_nbytes = BUF_SIZE;
		aiocbs[i]->aio_lio_opcode = LIO_WRITE;
	}

	/* Submit request list */
	ret = lio_listio(LIO_WAIT, aiocbs, NUM_AIOCBS, NULL);

	if (ret) {
		printf(TNAME " Error at lio_listio() %d: %s\n", errno,
		       strerror(errno));
		for (i = 0; i < NUM_AIOCBS; i++)
			free(aiocbs[i]);
		free(bufs);
		close(fd);
		exit(PTS_FAIL);
	}

	/* Check return code and free things */
	for (i = 0; i < NUM_AIOCBS; i++) {
		err = aio_error(aiocbs[i]);
		ret = aio_return(aiocbs[i]);

		if ((err != 0) && (ret != BUF_SIZE)) {
			printf(TNAME " req %d: error = %d - return = %d\n", i,
			       err, ret);
			errors++;
		}

		free(aiocbs[i]);
	}

	free(bufs);

	close(fd);

	if (errors != 0)
		exit(PTS_FAIL);

	printf(TNAME " PASSED\n");

	return PTS_PASS;
}
Exemplo n.º 11
0
int main()
{
	char tmpfname[256];
	int fd;

	struct aiocb *aiocbs[NUM_AIOCBS];
	char *bufs;
	struct sigaction action;
	struct sigevent event;
	int errors = 0;
	int ret;
	int err;
	int i;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
		exit(PTS_UNSUPPORTED);

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_lio_listio_2_1_%d",
		  getpid());
	unlink(tmpfname);

	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);

	if (fd == -1) {
		printf(TNAME " Error at open(): %s\n",
		       strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	bufs = (char *) malloc (NUM_AIOCBS*BUF_SIZE);

	if (bufs == NULL) {
		printf (TNAME " Error at malloc(): %s\n", strerror (errno));
		close (fd);
		exit(PTS_UNRESOLVED);
	}

	/* Queue up a bunch of aio writes */
	for (i = 0; i < NUM_AIOCBS; i++) {

		aiocbs[i] = (struct aiocb *)malloc(sizeof(struct aiocb));
		memset(aiocbs[i], 0, sizeof(struct aiocb));

		aiocbs[i]->aio_fildes = fd;
		aiocbs[i]->aio_offset = 0;
		aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE];
		aiocbs[i]->aio_nbytes = BUF_SIZE;
		aiocbs[i]->aio_lio_opcode = LIO_WRITE;

		/* Use SIRTMIN+1 for individual completions */
		aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
		aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN+1;
		aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
	}

	/* Use SIGRTMIN+2 for list completion */
	event.sigev_notify = SIGEV_SIGNAL;
	event.sigev_signo = SIGRTMIN+2;
	event.sigev_value.sival_ptr = NULL;

	/* Setup handler for individual operation completion */
	action.sa_sigaction = sigrt1_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO|SA_RESTART;
	sigaction(SIGRTMIN+1, &action, NULL);

	/* Setup handler for list completion */
	action.sa_sigaction = sigrt2_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO|SA_RESTART;
	sigaction(SIGRTMIN+2, &action, NULL);

	/* Submit request list */
	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);

	if (ret) {
		printf(TNAME " Error at lio_listio() %d: %s\n", errno, strerror(errno));
		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		close (fd);
		exit (PTS_FAIL);
	}

	if (received_selected == NUM_AIOCBS-1)
	{
		printf(TNAME " lio_listio() waited\n");
		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		close (fd);
		exit (PTS_FAIL);
	}

	if (received_all != 0)
	{
		printf(TNAME " Error lio_listio() waited for list completion\n");
		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		close (fd);
		exit (PTS_FAIL);
	}

	while (received_all == 0)
		sleep (1);

	/* Check return code and free things */
	for (i = 0; i < NUM_AIOCBS; i++) {
	  	err = aio_error(aiocbs[i]);
		ret = aio_return(aiocbs[i]);

		if ((err != 0) && (ret != BUF_SIZE)) {
			printf(TNAME " req %d: error = %d - return = %d\n", i, err, ret);
			errors++;
		}

		free (aiocbs[i]);
	}

	free (bufs);

	close(fd);

	if (errors != 0)
		exit (PTS_FAIL);

	printf (TNAME " PASSED\n");

	return PTS_PASS;
}
Exemplo n.º 12
0
Arquivo: 18-1.c Projeto: kraj/ltp
int main(void)
{
	char tmpfname[256];
	int fd;

	struct aiocb *aiocbs[NUM_AIOCBS];
	char *bufs;
	int ret;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
		exit(PTS_UNSUPPORTED);

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_lio_listio_18_1_%d",
		 getpid());
	unlink(tmpfname);

	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);

	if (fd == -1) {
		printf(TNAME " Error at open(): %s\n", strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	bufs = malloc(NUM_AIOCBS * BUF_SIZE);

	if (bufs == NULL) {
		printf(TNAME " Error at malloc(): %s\n", strerror(errno));
		close(fd);
		exit(PTS_UNRESOLVED);
	}

	aiocbs[0] = malloc(sizeof(struct aiocb));
	memset(aiocbs[0], 0, sizeof(struct aiocb));

	aiocbs[0]->aio_fildes = fd;
	aiocbs[0]->aio_offset = 0;
	aiocbs[0]->aio_buf = bufs;
	aiocbs[0]->aio_nbytes = BUF_SIZE;
	aiocbs[0]->aio_lio_opcode = LIO_WRITE;

	/* Submit request list */
	ret = lio_listio(-1, aiocbs, NUM_AIOCBS, NULL);

	if (ret != -1) {
		printf(TNAME
		       " Error lio_listio() should have returned -1: %d\n",
		       ret);

		free(aiocbs[0]);
		free(bufs);
		close(fd);
		exit(PTS_FAIL);
	}

	if (errno != EINVAL) {
		printf(TNAME
		       " Error lio_listio() should have set errno to EINVAL: %d (%s)\n",
		       errno, strerror(errno));

		free(aiocbs[0]);
		free(bufs);
		close(fd);
		exit(PTS_FAIL);
	}

	free(aiocbs[0]);
	free(bufs);
	close(fd);

	printf(TNAME " PASSED\n");

	return PTS_PASS;
}
Exemplo n.º 13
0
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
{
    /*
     * Parameter validation.
     */
    int rc = VINF_SUCCESS;
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
    AssertReturn(cReqs > 0,  VERR_INVALID_PARAMETER);
    AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);
    size_t i = cReqs;

    do
    {
        int rcSol = 0;
        size_t cReqsSubmit = 0;
        PRTFILEAIOREQINTERNAL pReqInt;

        while(i-- > 0)
        {
            pReqInt = pahReqs[i];
            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
            {
                /* Undo everything and stop submitting. */
                for (size_t iUndo = 0; iUndo < i; iUndo++)
                {
                    pReqInt = pahReqs[iUndo];
                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    pReqInt->pCtxInt = NULL;
                }
                rc = VERR_INVALID_HANDLE;
                break;
            }

            pReqInt->PortNotifier.portnfy_port = pCtxInt->iPort;
            pReqInt->pCtxInt                   = pCtxInt;
            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

            if (pReqInt->fFlush)
                break;

            cReqsSubmit++;
        }

        if (cReqsSubmit)
        {
            rcSol = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
            if (RT_UNLIKELY(rcSol < 0))
            {
                if (rcSol == EAGAIN)
                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                else
                    rc = RTErrConvertFromErrno(errno);

                /* Check which requests got actually submitted and which not. */
                for (i = 0; i < cReqs; i++)
                {
                    pReqInt = pahReqs[i];
                    rcSol = aio_error(&pReqInt->AioCB);
                    if (rcSol == EINVAL)
                    {
                        /* Was not submitted. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        pReqInt->pCtxInt = NULL;
                    }
                    else if (rcSol != EINPROGRESS)
                    {
                        /* The request encountered an error. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                    }
                }
                break;
            }

            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
            cReqs   -= cReqsSubmit;
            pahReqs += cReqsSubmit;
        }

        if (cReqs)
        {
            pReqInt = pahReqs[0];
            RTFILEAIOREQ_VALID_RETURN(pReqInt);

            /*
             * If there are still requests left we have a flush request.
             * lio_listio does not work with this requests so
             * we have to use aio_fsync directly.
             */
            rcSol = aio_fsync(O_SYNC, &pReqInt->AioCB);
            if (RT_UNLIKELY(rcSol < 0))
            {
                RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                rc = RTErrConvertFromErrno(errno);
                break;
            }

            ASMAtomicIncS32(&pCtxInt->cRequests);
            cReqs--;
            pahReqs++;
        }
    } while (cReqs);

    return rc;
}
Exemplo n.º 14
0
int main(int argc, char *argv[]) {

	if (argc != 3) {
		printf("error syntaxe :%s  source.txt dest.txt \n", argv[0]);
		exit(EXIT_FAILURE);
	}
	const char* source_file = argv[1];
	const char* dest_file = argv[2];

	int desc_source;
	int desc_dest;

	struct aiocb cb_ecr[BUF_SIZE]; /** bloc controle IO **/
	struct aiocb * lio[BUF_SIZE]; /** liste des opérations IO à lancer **/
	struct sigevent lio_sigev; /** événement à déclancher à la fin de toutes les opérations**/

	char buffer[BUF_SIZE] = { 0 };

	/** ouverture des fichiers **/
	if ((desc_source = open(source_file, O_RDONLY | 0666)) < 0) {
		perror("open source_file");
		exit(EXIT_FAILURE);
	}

	if ((desc_dest = open(dest_file, O_CREAT | O_RDWR | O_TRUNC, 0666)) < 0) {
		perror("open dest_file");
		exit(EXIT_FAILURE);
	}

	int i;
	for (i = 0; i < BUF_SIZE; ++i) {
		/**  init l'ecriture **/
		cb_ecr[i].aio_fildes = desc_dest;
		cb_ecr[i].aio_lio_opcode = LIO_WRITE;
		cb_ecr[i].aio_nbytes = 1;
		cb_ecr[i].aio_reqprio = 0;
		cb_ecr[i].aio_sigevent.sigev_notify = SIGEV_NONE;
	}

	/** événement à déclancher à la fin de toutes les opérations**/
	lio_sigev.sigev_notify = SIGEV_NONE;
	long int octet_lus = 0;
	int nb_tour = 0;

	while ((octet_lus = read(desc_source, buffer, BUF_SIZE)) > 0) {
		printf("buffer lu %ld \n", octet_lus);
		for (i = 0; i < octet_lus; ++i) {
			printf("%c \n", buffer[octet_lus - i - 1]);
			cb_ecr[i].aio_buf = &buffer[octet_lus - i - 1];
			cb_ecr[i].aio_offset = nb_tour * BUF_SIZE + i;
			lio[i] = &cb_ecr[i];
		}

		/*** lancer une suite d'AIOs ***/
		if (lio_listio(LIO_WAIT, lio, octet_lus, &lio_sigev) < 0) {
			perror("lio_listio");
			exit(EXIT_FAILURE);
		}
		nb_tour++;
	}

	/**Fermeture des desc **/
	close(desc_source);
	close(desc_dest);
	return EXIT_SUCCESS;
}