gnu_java_nio_EpollSelectorImpl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /* gnu_java_nio_EpollSelectorImpl.c --
  2. Copyright (C) 2006 Free Software Foundation, Inc.
  3. This file is a part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or (at
  7. your option) any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  15. USA
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. #ifdef HAVE_CONFIG_H
  32. #include <config.h>
  33. #endif /* HAVE_CONFIG_H */
  34. #ifdef HAVE_SYS_EPOLL_H
  35. #include <sys/epoll.h>
  36. #endif /* HAVE_SYS_EPOLL_H */
  37. #include <config-int.h>
  38. #include <gnu_java_nio_EpollSelectorImpl.h>
  39. #include <jcl.h>
  40. #include <errno.h>
  41. #include <string.h>
  42. #define IO_EXCEPTION "java/io/IOException"
  43. /* #define TRACE_EPOLL 1 */
  44. /*
  45. * Class: gnu_java_nio_EpollSelectorImpl
  46. * Method: epoll_supported
  47. * Signature: ()Z
  48. */
  49. JNIEXPORT jboolean JNICALL
  50. Java_gnu_java_nio_EpollSelectorImpl_epoll_1supported (JNIEnv *e __attribute__((unused)),
  51. jclass c __attribute__((unused)))
  52. {
  53. #ifdef HAVE_EPOLL_CREATE
  54. return JNI_TRUE;
  55. #else
  56. return JNI_FALSE;
  57. #endif /* HAVE_EPOLL_CREATE */
  58. }
  59. /*
  60. * Class: gnu_java_nio_EpollSelectorImpl
  61. * Method: sizeof_struct
  62. * Signature: ()I
  63. */
  64. JNIEXPORT jint JNICALL
  65. Java_gnu_java_nio_EpollSelectorImpl_sizeof_1struct (JNIEnv *env,
  66. jclass c __attribute__((unused)))
  67. {
  68. #ifdef HAVE_EPOLL_CREATE
  69. (void) env;
  70. #ifdef TRACE_EPOLL
  71. fprintf (stderr, "%s: sizeof is %d\n", __FUNCTION__, sizeof (struct epoll_event));
  72. #endif /* TRACE_EPOLL */
  73. return sizeof (struct epoll_event);
  74. #else
  75. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  76. return -1;
  77. #endif /* HAVE_EPOLL_CREATE */
  78. }
  79. /*
  80. * Class: gnu_java_nio_EpollSelectorImpl
  81. * Method: epoll_create
  82. * Signature: (I)I
  83. */
  84. JNIEXPORT jint JNICALL
  85. Java_gnu_java_nio_EpollSelectorImpl_epoll_1create (JNIEnv *env,
  86. jclass c __attribute__((unused)),
  87. jint size)
  88. {
  89. #ifdef HAVE_EPOLL_CREATE
  90. int fd = epoll_create (size);
  91. #ifdef TRACE_EPOLL
  92. fprintf (stderr, "%s: epoll_create returns %d\n", __FUNCTION__, fd);
  93. #endif /* TRACE_EPOLL */
  94. if (fd == -1)
  95. {
  96. if (ENOSYS == errno)
  97. JCL_ThrowException (env, "java/lang/InternalError",
  98. strerror (errno));
  99. else
  100. JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
  101. }
  102. return fd;
  103. #else
  104. (void) size;
  105. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  106. return -1;
  107. #endif /* HAVE_EPOLL_CREATE */
  108. }
  109. /*
  110. * Class: gnu_java_nio_EpollSelectorImpl
  111. * Method: epoll_add
  112. * Signature: (III)V
  113. */
  114. JNIEXPORT void JNICALL
  115. Java_gnu_java_nio_EpollSelectorImpl_epoll_1add (JNIEnv *env,
  116. jclass c __attribute__((unused)),
  117. jint efd, jint fd, jint ops)
  118. {
  119. #ifdef HAVE_EPOLL_CREATE
  120. struct epoll_event event;
  121. memset (&event, 0, sizeof (struct epoll_event));
  122. if ((ops & gnu_java_nio_EpollSelectorImpl_OP_ACCEPT) != 0
  123. || (ops & gnu_java_nio_EpollSelectorImpl_OP_READ) != 0)
  124. event.events = EPOLLIN;
  125. if ((ops & gnu_java_nio_EpollSelectorImpl_OP_CONNECT) != 0
  126. || (ops & gnu_java_nio_EpollSelectorImpl_OP_WRITE) != 0)
  127. event.events |= EPOLLOUT;
  128. event.data.fd = fd;
  129. #ifdef TRACE_EPOLL
  130. fprintf (stderr, "%s: adding struct epoll_event { events: %o; data.fd: %d } to %d\n",
  131. __FUNCTION__, event.events, event.data.fd, efd);
  132. #endif /* TRACE_EPOLL */
  133. if (epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event) == -1)
  134. {
  135. if (ENOSYS == errno)
  136. JCL_ThrowException (env, "java/lang/InternalError",
  137. strerror (errno));
  138. else
  139. JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
  140. }
  141. #else
  142. (void) efd;
  143. (void) fd;
  144. (void) ops;
  145. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  146. #endif /* HAVE_EPOLL_CREATE */
  147. }
  148. /*
  149. * Class: gnu_java_nio_EpollSelectorImpl
  150. * Method: epoll_modify
  151. * Signature: (III)V
  152. */
  153. JNIEXPORT void JNICALL
  154. Java_gnu_java_nio_EpollSelectorImpl_epoll_1modify (JNIEnv *env,
  155. jclass c __attribute__((unused)),
  156. jint efd, jint fd, jint ops)
  157. {
  158. #ifdef HAVE_EPOLL_CREATE
  159. struct epoll_event event;
  160. memset (&event, 0, sizeof (struct epoll_event));
  161. if ((ops & gnu_java_nio_EpollSelectorImpl_OP_ACCEPT) != 0
  162. || (ops & gnu_java_nio_EpollSelectorImpl_OP_READ) != 0)
  163. event.events = EPOLLIN;
  164. if ((ops & gnu_java_nio_EpollSelectorImpl_OP_CONNECT) != 0
  165. || (ops & gnu_java_nio_EpollSelectorImpl_OP_WRITE) != 0)
  166. event.events |= EPOLLOUT;
  167. event.data.fd = fd;
  168. #ifdef TRACE_EPOLL
  169. fprintf (stderr, "%s: modding struct epoll_event { events: %o; data.fd: %d } on %d\n",
  170. __FUNCTION__, event.events, event.data.fd, efd);
  171. #endif /* TRACE_EPOLL */
  172. if (epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event) == -1)
  173. {
  174. if (ENOSYS == errno)
  175. JCL_ThrowException (env, "java/lang/InternalError",
  176. strerror (errno));
  177. else
  178. JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
  179. }
  180. #else
  181. (void) efd;
  182. (void) fd;
  183. (void) ops;
  184. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  185. #endif /* HAVE_EPOLL_CREATE */
  186. }
  187. /*
  188. * Class: gnu_java_nio_EpollSelectorImpl
  189. * Method: epoll_delete
  190. * Signature: (II)V
  191. */
  192. JNIEXPORT void JNICALL
  193. Java_gnu_java_nio_EpollSelectorImpl_epoll_1delete (JNIEnv *env,
  194. jclass c __attribute__((unused)),
  195. jint efd, jint fd)
  196. {
  197. #ifdef HAVE_EPOLL_CREATE
  198. struct epoll_event event;
  199. memset (&event, 0, sizeof (struct epoll_event));
  200. event.data.fd = fd;
  201. #ifdef TRACE_EPOLL
  202. fprintf (stderr, "%s: delete events on fd %d for %d\n", __FUNCTION__, fd, efd);
  203. #endif /* TRACE_EPOLL */
  204. /* Older kernel versions require a non-null `event' parameter,
  205. * even though it is ignored by this call.
  206. */
  207. if (epoll_ctl (efd, EPOLL_CTL_DEL, fd, &event) == -1)
  208. {
  209. if (ENOSYS == errno)
  210. JCL_ThrowException (env, "java/lang/InternalError",
  211. strerror (errno));
  212. /* XXX the docs here seem a little strange. If `fd' is closed,
  213. epoll_ctl returns EBADF; but the docs say that this happens
  214. only when efd is invalid. Go figure.
  215. */
  216. else if (ENOENT == errno || EBADF == errno)
  217. return; /* fd is closed; it's already removed. */
  218. else
  219. JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
  220. }
  221. #else
  222. (void) efd;
  223. (void) fd;
  224. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  225. #endif /* HAVE_EPOLL_CREATE */
  226. }
  227. /*
  228. * Class: gnu_java_nio_EpollSelectorImpl
  229. * Method: epoll_wait
  230. * Signature: (ILjava/nio/ByteBuffer;II)I
  231. */
  232. JNIEXPORT jint JNICALL
  233. Java_gnu_java_nio_EpollSelectorImpl_epoll_1wait (JNIEnv *env,
  234. jclass c __attribute__((unused)),
  235. jint efd, jobject nstate,
  236. jint num_events, jint timeout)
  237. {
  238. #ifdef HAVE_EPOLL_CREATE
  239. void *p = (*env)->GetDirectBufferAddress (env, nstate);
  240. struct epoll_event *events = (struct epoll_event *) p;
  241. int ret;
  242. if (p == NULL)
  243. {
  244. if (!(*env)->ExceptionCheck (env))
  245. JCL_ThrowException (env, IO_EXCEPTION, "getting native state failed");
  246. return -1;
  247. }
  248. #ifdef TRACE_EPOLL
  249. fprintf (stderr, "%s: events: %p; num_events: %d; timeout: %d; efd: %d\n",
  250. __FUNCTION__, p, num_events, timeout, efd);
  251. #endif /* TRACE_EPOLL */
  252. ret = epoll_wait (efd, events, num_events, timeout);
  253. if (ret == -1)
  254. {
  255. if (ENOSYS == errno)
  256. JCL_ThrowException (env, "java/lang/InternalError",
  257. strerror (errno));
  258. else if (EINTR == errno)
  259. ret = 0;
  260. else
  261. JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
  262. }
  263. #ifdef TRACE_EPOLL
  264. fprintf (stderr, " epoll_wait returns %d\n", ret);
  265. {
  266. int i;
  267. for (i = 0; i < ret; i++)
  268. {
  269. fprintf (stderr, " [%4i]: events: %o; data.fd: %d\n", i, events[i].events,
  270. events[i].data.fd);
  271. }
  272. }
  273. fflush (stderr);
  274. #endif /* TRACE_EPOLL */
  275. return ret;
  276. #else
  277. (void) efd;
  278. (void) nstate;
  279. (void) num_events;
  280. (void) timeout;
  281. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  282. return -1;
  283. #endif /* HAVE_EPOLL_CREATE */
  284. }
  285. /*
  286. * Class: gnu_java_nio_EpollSelectorImpl
  287. * Method: selected_fd
  288. * Signature: (Ljava/nio/ByteBuffer;)I
  289. */
  290. JNIEXPORT jint JNICALL
  291. Java_gnu_java_nio_EpollSelectorImpl_selected_1fd (JNIEnv *env,
  292. jclass c __attribute__((unused)),
  293. jobject value)
  294. {
  295. #ifdef HAVE_EPOLL_CREATE
  296. void *p = (*env)->GetDirectBufferAddress (env, value);
  297. struct epoll_event *event = (struct epoll_event *) p;
  298. #ifdef TRACE_EPOLL
  299. fprintf (stderr, "%s: event: %p\n", __FUNCTION__, p);
  300. #endif /* TRACE_EPOLL */
  301. if (p == NULL)
  302. {
  303. if (!(*env)->ExceptionCheck (env))
  304. JCL_ThrowException (env, "java/lang/InternalError",
  305. "getting native state failed");
  306. return -1;
  307. }
  308. #ifdef TRACE_EPOLL
  309. fprintf (stderr, " data.fd: %d\n", event->data.fd);
  310. fflush (stderr);
  311. #endif /* TRACE_EPOLL */
  312. return event->data.fd;
  313. #else
  314. (void) value;
  315. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  316. return -1;
  317. #endif /* HAVE_EPOLL_CREATE */
  318. }
  319. /*
  320. * Class: gnu_java_nio_EpollSelectorImpl
  321. * Method: selected_ops
  322. * Signature: (Ljava/nio/ByteBuffer;)I
  323. */
  324. JNIEXPORT jint JNICALL
  325. Java_gnu_java_nio_EpollSelectorImpl_selected_1ops (JNIEnv *env,
  326. jclass c __attribute__((unused)),
  327. jobject value)
  328. {
  329. #ifdef HAVE_EPOLL_CREATE
  330. void *p = (*env)->GetDirectBufferAddress (env, value);
  331. struct epoll_event *event = (struct epoll_event *) p;
  332. int ret = 0;
  333. #ifdef TRACE_EPOLL
  334. fprintf (stderr, "%s: event: %p\n", __FUNCTION__, p);
  335. #endif /* TRACE_EPOLL */
  336. if (p == NULL)
  337. {
  338. if (!(*env)->ExceptionCheck (env))
  339. JCL_ThrowException (env, "java/lang/InternalError",
  340. "getting native state failed");
  341. return -1;
  342. }
  343. if ((event->events & EPOLLIN) != 0)
  344. ret |= gnu_java_nio_EpollSelectorImpl_OP_ACCEPT | gnu_java_nio_EpollSelectorImpl_OP_READ;
  345. if ((event->events & EPOLLOUT) != 0)
  346. ret |= gnu_java_nio_EpollSelectorImpl_OP_CONNECT | gnu_java_nio_EpollSelectorImpl_OP_WRITE;
  347. #ifdef TRACE_EPOLL
  348. fprintf (stderr, " events: %o\n", event->events);
  349. fflush (stderr);
  350. #endif /* TRACE_EPOLL */
  351. return ret;
  352. #else
  353. (void) value;
  354. JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available");
  355. return -1;
  356. #endif /* HAVE_EPOLL_CREATE */
  357. }