Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
3.8 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. #define _GNU_SOURCE
  2. #include <errno.h>
  3. #define my_extern
  4. #include "io_internal.h"
  5. #undef my_extern
  6. #include "byte.h"
  7. #ifdef HAVE_SIGIO
  8. #include <signal.h>
  9. #include <fcntl.h>
  10. #endif
  11. #include <sys/types.h>
  12. #include <fcntl.h>
  13. #ifdef HAVE_KQUEUE
  14. #include <sys/event.h>
  15. #endif
  16. #ifdef HAVE_EPOLL
  17. #include <inttypes.h>
  18. #include <sys/epoll.h>
  19. #endif
  20. #include <unistd.h>
  21. #ifdef HAVE_DEVPOLL
  22. #include <sys/types.h>
  23. #include <sys/socket.h>
  24. #include <sys/devpoll.h>
  25. #endif
  26. #ifdef __dietlibc__
  27. #include <sys/atomic.h>
  28. #else
  29. #define __CAS(ptr,oldval,newval) __sync_val_compare_and_swap(ptr,oldval,newval)
  30. #endif
  31. #ifdef __MINGW32__
  32. #include <stdio.h>
  33. extern HANDLE io_comport;
  34. #endif
  35. iarray io_fds;
  36. static int io_fds_inited;
  37. uint64 io_wanted_fds;
  38. array io_pollfds;
  39. enum __io_waitmode io_waitmode;
  40. #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) || defined(HAVE_DEVPOLL)
  41. int io_master;
  42. #endif
  43. #if defined(HAVE_SIGIO)
  44. int io_signum;
  45. sigset_t io_ss;
  46. long alt_firstread;
  47. long alt_firstwrite;
  48. #endif
  49. /* put d on internal data structure, return 1 on success, 0 on error */
  50. static io_entry* io_fd_internal(int64 d) {
  51. io_entry* e;
  52. #ifndef __MINGW32__
  53. long r;
  54. if ((r=fcntl(d,F_GETFL,0)) == -1)
  55. return 0; /* file descriptor not open */
  56. #endif
  57. /* Problem: we might be the first to use io_fds. We need to make sure
  58. * we are the only ones to initialize it. So set io_fds_inited to 2
  59. * and not to 1. We know we are done when it is 1. We know we need
  60. * to do something when it is 0. We know somebody else is doing it
  61. * when it is 2. */
  62. if (__CAS(&io_fds_inited,0,2)==0) {
  63. iarray_init(&io_fds,sizeof(io_entry));
  64. io_fds_inited=1;
  65. } else
  66. do { asm("" : : : "memory"); } while (io_fds_inited!=1);
  67. if (!(e=iarray_allocate(&io_fds,d))) return 0;
  68. if (e->inuse) return e;
  69. byte_zero(e,sizeof(io_entry));
  70. e->inuse=1;
  71. #ifdef __MINGW32__
  72. e->mh=0;
  73. #else
  74. if (r&O_NDELAY) e->nonblock=1;
  75. #endif
  76. e->next_read=e->next_write=-1;
  77. if (io_waitmode==UNDECIDED) {
  78. first_readable=first_writeable=-1;
  79. #if defined(HAVE_EPOLL)
  80. io_master=epoll_create(1000);
  81. if (io_master!=-1) io_waitmode=EPOLL;
  82. #endif
  83. #if defined(HAVE_KQUEUE)
  84. if (io_waitmode==UNDECIDED) { /* who knows, maybe someone supports both one day */
  85. io_master=kqueue();
  86. if (io_master!=-1) io_waitmode=KQUEUE;
  87. }
  88. #endif
  89. #if defined(HAVE_DEVPOLL)
  90. if (io_waitmode==UNDECIDED) {
  91. io_master=open("/dev/poll",O_RDWR);
  92. if (io_master!=-1) io_waitmode=DEVPOLL;
  93. }
  94. #endif
  95. #if defined(HAVE_SIGIO)
  96. alt_firstread=alt_firstwrite=-1;
  97. if (io_waitmode==UNDECIDED) {
  98. io_signum=SIGRTMIN+1;
  99. if (sigemptyset(&io_ss)==0 &&
  100. sigaddset(&io_ss,io_signum)==0 &&
  101. sigaddset(&io_ss,SIGIO)==0 &&
  102. sigprocmask(SIG_BLOCK,&io_ss,0)==0)
  103. io_waitmode=_SIGIO;
  104. }
  105. #endif
  106. #ifdef __MINGW32__
  107. io_comport=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
  108. if (io_comport) {
  109. io_waitmode=COMPLETIONPORT;
  110. fprintf(stderr,"Initialized completion port: %p\n",io_comport);
  111. } else {
  112. fprintf(stderr,"ARGH! Could not init completion port!\n");
  113. errno=EINVAL;
  114. return 0;
  115. }
  116. #endif
  117. }
  118. #if defined(HAVE_SIGIO)
  119. if (io_waitmode==_SIGIO) {
  120. fcntl(d,F_SETOWN,getpid());
  121. fcntl(d,F_SETSIG,io_signum);
  122. #if defined(O_ONESIGFD) && defined(F_SETAUXFL)
  123. fcntl(d, F_SETAUXFL, O_ONESIGFD);
  124. #endif
  125. fcntl(d,F_SETFL,fcntl(d,F_GETFL)|O_NONBLOCK|O_ASYNC);
  126. }
  127. #endif
  128. #ifdef __MINGW32__
  129. if (io_comport) {
  130. fprintf(stderr,"Queueing %p at completion port %p...",d,io_comport);
  131. if (CreateIoCompletionPort((HANDLE)d,io_comport,(ULONG_PTR)d,0)==0) {
  132. fprintf(stderr," failed!\n");
  133. errno=EBADF;
  134. return 0;
  135. }
  136. fprintf(stderr," OK!\n");
  137. }
  138. #endif
  139. return e;
  140. }
  141. int io_fd(int64 d) {
  142. io_entry* e=io_fd_internal(d);
  143. return !!e;
  144. }
  145. int io_fd_canwrite(int64 d) {
  146. io_entry* e=io_fd_internal(d);
  147. if (e) e->canwrite=1;
  148. return !!e;
  149. }