aio_readwrite.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #include <aio.h>
  2. #include <fcntl.h>
  3. #include "pthread_impl.h"
  4. static void dummy(void)
  5. {
  6. }
  7. weak_alias(dummy, __aio_wake);
  8. static void notify_signal(struct sigevent *sev)
  9. {
  10. siginfo_t si = {
  11. .si_signo = sev->sigev_signo,
  12. .si_value = sev->sigev_value,
  13. .si_code = SI_ASYNCIO,
  14. .si_pid = __pthread_self()->pid,
  15. .si_uid = getuid()
  16. };
  17. __syscall(SYS_rt_sigqueueinfo, si.si_pid, si.si_signo, &si);
  18. }
  19. static void *io_thread(void *p)
  20. {
  21. struct aiocb *cb = p;
  22. int fd = cb->aio_filedes;
  23. void *buf = (void *)cb->aio_buf;
  24. size_t len = cb->aio_nbytes;
  25. off_t off = cb->aio_offset;
  26. int op = cb->aio_lio_opcode;
  27. struct sigevent sev = cb->aio_sigevent;
  28. ssize_t ret;
  29. if (op == LIO_WRITE) {
  30. if ( (fcntl(fd, F_GETFL) & O_APPEND)
  31. ||((ret = pwrite(fd, buf, len, off))<0 && errno==ESPIPE) )
  32. ret = write(fd, buf, len);
  33. } else if (op == LIO_READ) {
  34. if ( (ret = pread(fd, buf, len, off))<0 && errno==ESPIPE )
  35. ret = read(fd, buf, len);
  36. } else {
  37. ret = 0;
  38. }
  39. cb->__ret = ret;
  40. if (ret < 0) a_store(&cb->__err, errno);
  41. else a_store(&cb->__err, 0);
  42. __aio_wake();
  43. switch (cb->aio_sigevent.sigev_notify) {
  44. case SIGEV_SIGNAL:
  45. notify_signal(&sev);
  46. break;
  47. case SIGEV_THREAD:
  48. sev.sigev_notify_function(sev.sigev_value);
  49. break;
  50. }
  51. return 0;
  52. }
  53. static int new_req(struct aiocb *cb)
  54. {
  55. int ret = 0;
  56. pthread_attr_t a;
  57. sigset_t set;
  58. pthread_t td;
  59. if (cb->aio_sigevent.sigev_notify == SIGEV_THREAD) {
  60. if (cb->aio_sigevent.sigev_notify_attributes)
  61. a = *cb->aio_sigevent.sigev_notify_attributes;
  62. else
  63. pthread_attr_init(&a);
  64. } else {
  65. pthread_attr_init(&a);
  66. pthread_attr_setstacksize(&a, PAGE_SIZE);
  67. pthread_attr_setguardsize(&a, 0);
  68. }
  69. pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
  70. sigfillset(&set);
  71. pthread_sigmask(SIG_BLOCK, &set, &set);
  72. cb->__err = EINPROGRESS;
  73. if (pthread_create(&td, &a, io_thread, cb)) {
  74. errno = EAGAIN;
  75. ret = -1;
  76. }
  77. pthread_sigmask(SIG_SETMASK, &set, 0);
  78. cb->__td = td;
  79. return ret;
  80. }
  81. ssize_t aio_read(struct aiocb *cb)
  82. {
  83. cb->aio_lio_opcode = LIO_READ;
  84. return new_req(cb);
  85. }
  86. ssize_t aio_write(struct aiocb *cb)
  87. {
  88. cb->aio_lio_opcode = LIO_WRITE;
  89. return new_req(cb);
  90. }