aispoll.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /*
  2. * Copyright (c) 2003-2004 MontaVista Software, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Steven Dake (sdake@mvista.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <errno.h>
  35. #include <pthread.h>
  36. #include <sys/poll.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <stdio.h>
  40. #include "aispoll.h"
  41. #include "../include/list.h"
  42. #include "../include/hdb.h"
  43. #include "tlist.h"
  44. typedef int (*dispatch_fn_t) (poll_handle poll_handle, int fd, int revents, void *data);
  45. struct poll_entry {
  46. struct pollfd ufd;
  47. dispatch_fn_t dispatch_fn;
  48. void *data;
  49. };
  50. struct poll_instance {
  51. struct poll_entry *poll_entries;
  52. struct pollfd *ufds;
  53. int poll_entry_count;
  54. struct timerlist timerlist;
  55. void (*serialize_lock_fn) (void);
  56. void (*serialize_unlock_fn) (void);
  57. };
  58. /*
  59. * All instances in one database
  60. */
  61. static struct hdb_handle_database poll_instance_database = {
  62. .handle_count = 0,
  63. .handles = 0,
  64. .iterator = 0
  65. };
  66. poll_handle poll_create (
  67. void (*serialize_lock_fn) (void),
  68. void (*serialize_unlock_fn) (void))
  69. {
  70. poll_handle handle;
  71. struct poll_instance *poll_instance;
  72. unsigned int res;
  73. res = hdb_handle_create (&poll_instance_database,
  74. sizeof (struct poll_instance), &handle);
  75. if (res != 0) {
  76. goto error_exit;
  77. }
  78. res = hdb_handle_get (&poll_instance_database, handle,
  79. (void *)&poll_instance);
  80. if (res != 0) {
  81. goto error_destroy;
  82. }
  83. poll_instance->poll_entries = 0;
  84. poll_instance->ufds = 0;
  85. poll_instance->poll_entry_count = 0;
  86. poll_instance->serialize_lock_fn = serialize_unlock_fn;
  87. poll_instance->serialize_unlock_fn = serialize_unlock_fn;
  88. timerlist_init (&poll_instance->timerlist);
  89. return (handle);
  90. error_destroy:
  91. hdb_handle_destroy (&poll_instance_database, handle);
  92. error_exit:
  93. return (-1);
  94. }
  95. int poll_destroy (poll_handle handle)
  96. {
  97. struct poll_instance *poll_instance;
  98. int res = 0;
  99. res = hdb_handle_get (&poll_instance_database, handle,
  100. (void *)&poll_instance);
  101. if (res != 0) {
  102. res = -ENOENT;
  103. goto error_exit;
  104. }
  105. if (poll_instance->poll_entries) {
  106. free (poll_instance->poll_entries);
  107. }
  108. if (poll_instance->ufds) {
  109. free (poll_instance->ufds);
  110. }
  111. hdb_handle_destroy (&poll_instance_database, handle);
  112. hdb_handle_put (&poll_instance_database, handle);
  113. error_exit:
  114. return (res);
  115. }
  116. int poll_dispatch_add (
  117. poll_handle handle,
  118. int fd,
  119. int events,
  120. void *data,
  121. int (*dispatch_fn) (
  122. poll_handle poll_handle,
  123. int fd,
  124. int revents,
  125. void *data))
  126. {
  127. struct poll_instance *poll_instance;
  128. struct poll_entry *poll_entries;
  129. struct pollfd *ufds;
  130. int found = 0;
  131. int install_pos;
  132. int res = 0;
  133. res = hdb_handle_get (&poll_instance_database, handle,
  134. (void *)&poll_instance);
  135. if (res != 0) {
  136. res = -ENOENT;
  137. goto error_exit;
  138. }
  139. for (found = 0, install_pos = 0; install_pos < poll_instance->poll_entry_count; install_pos++) {
  140. if (poll_instance->poll_entries[install_pos].ufd.fd == -1) {
  141. found = 1;
  142. break;
  143. }
  144. }
  145. if (found == 0) {
  146. /*
  147. * Grow pollfd list
  148. */
  149. poll_entries = (struct poll_entry *)realloc (poll_instance->poll_entries,
  150. (poll_instance->poll_entry_count + 1) *
  151. sizeof (struct poll_entry));
  152. if (poll_entries == 0) {
  153. res = -ENOMEM;
  154. goto error_put;
  155. }
  156. poll_instance->poll_entries = poll_entries;
  157. ufds = (struct pollfd *)realloc (poll_instance->ufds,
  158. (poll_instance->poll_entry_count + 1) *
  159. sizeof (struct pollfd));
  160. if (ufds == 0) {
  161. res = -ENOMEM;
  162. goto error_put;
  163. }
  164. poll_instance->ufds = ufds;
  165. poll_instance->poll_entry_count += 1;
  166. install_pos = poll_instance->poll_entry_count - 1;
  167. }
  168. /*
  169. * Install new dispatch handler
  170. */
  171. poll_instance->poll_entries[install_pos].ufd.fd = fd;
  172. poll_instance->poll_entries[install_pos].ufd.events = events;
  173. poll_instance->poll_entries[install_pos].ufd.revents = 0;
  174. poll_instance->poll_entries[install_pos].dispatch_fn = dispatch_fn;
  175. poll_instance->poll_entries[install_pos].data = data;
  176. error_put:
  177. hdb_handle_put (&poll_instance_database, handle);
  178. error_exit:
  179. return (res);
  180. }
  181. int poll_dispatch_modify (
  182. poll_handle handle,
  183. int fd,
  184. int events,
  185. int (*dispatch_fn) (
  186. poll_handle poll_handle,
  187. int fd,
  188. int revents,
  189. void *data))
  190. {
  191. struct poll_instance *poll_instance;
  192. int i;
  193. int res = 0;
  194. res = hdb_handle_get (&poll_instance_database, handle,
  195. (void *)&poll_instance);
  196. if (res != 0) {
  197. res = -ENOENT;
  198. goto error_exit;
  199. }
  200. /*
  201. * Find file descriptor to modify events and dispatch function
  202. */
  203. for (i = 0; i < poll_instance->poll_entry_count; i++) {
  204. if (poll_instance->poll_entries[i].ufd.fd == fd) {
  205. poll_instance->poll_entries[i].ufd.events = events;
  206. poll_instance->poll_entries[i].dispatch_fn = dispatch_fn;
  207. goto error_put;
  208. }
  209. }
  210. res = -EBADF;
  211. error_put:
  212. hdb_handle_put (&poll_instance_database, handle);
  213. error_exit:
  214. return (res);
  215. }
  216. int poll_dispatch_delete (
  217. poll_handle handle,
  218. int fd)
  219. {
  220. struct poll_instance *poll_instance;
  221. int i;
  222. int res = 0;
  223. res = hdb_handle_get (&poll_instance_database, handle,
  224. (void *)&poll_instance);
  225. if (res != 0) {
  226. res = -ENOENT;
  227. goto error_exit;
  228. }
  229. /*
  230. * Find dispatch fd to delete
  231. */
  232. res = -EBADF;
  233. for (i = 0; i < poll_instance->poll_entry_count; i++) {
  234. if (poll_instance->poll_entries[i].ufd.fd == fd) {
  235. poll_instance->poll_entries[i].ufd.fd = -1;
  236. poll_instance->poll_entries[i].ufd.revents = 0;
  237. break;
  238. }
  239. }
  240. hdb_handle_put (&poll_instance_database, handle);
  241. error_exit:
  242. return (res);
  243. }
  244. int poll_timer_add (
  245. poll_handle handle,
  246. int msec_in_future, void *data,
  247. void (*timer_fn) (void *data),
  248. poll_timer_handle *timer_handle_out)
  249. {
  250. struct poll_instance *poll_instance;
  251. int res = 0;
  252. res = hdb_handle_get (&poll_instance_database, handle,
  253. (void *)&poll_instance);
  254. if (res != 0) {
  255. res = -ENOENT;
  256. goto error_exit;
  257. }
  258. if (timer_handle_out == 0) {
  259. res = -ENOENT;
  260. }
  261. timerlist_add_future (&poll_instance->timerlist,
  262. timer_fn, data, msec_in_future, timer_handle_out);
  263. hdb_handle_put (&poll_instance_database, handle);
  264. error_exit:
  265. return (res);
  266. }
  267. int poll_timer_delete (
  268. poll_handle handle,
  269. poll_timer_handle timer_handle)
  270. {
  271. struct poll_instance *poll_instance;
  272. int res = 0;
  273. if (timer_handle == 0) {
  274. return (0);
  275. }
  276. res = hdb_handle_get (&poll_instance_database, handle,
  277. (void *)&poll_instance);
  278. if (res != 0) {
  279. res = -ENOENT;
  280. goto error_exit;
  281. }
  282. timerlist_del (&poll_instance->timerlist, (void *)timer_handle);
  283. hdb_handle_put (&poll_instance_database, handle);
  284. error_exit:
  285. return (res);
  286. }
  287. int poll_timer_delete_data (
  288. poll_handle handle,
  289. poll_timer_handle timer_handle) {
  290. struct poll_instance *poll_instance;
  291. int res = 0;
  292. if (timer_handle == 0) {
  293. return (0);
  294. }
  295. res = hdb_handle_get (&poll_instance_database, handle,
  296. (void *)&poll_instance);
  297. if (res != 0) {
  298. res = -ENOENT;
  299. goto error_exit;
  300. }
  301. timerlist_del_data (&poll_instance->timerlist, (void *)timer_handle);
  302. hdb_handle_put (&poll_instance_database, handle);
  303. error_exit:
  304. return (res);
  305. }
  306. int poll_run (
  307. poll_handle handle)
  308. {
  309. struct poll_instance *poll_instance;
  310. int i;
  311. int timeout = -1;
  312. int res;
  313. int poll_entry_count;
  314. res = hdb_handle_get (&poll_instance_database, handle,
  315. (void *)&poll_instance);
  316. if (res != 0) {
  317. goto error_exit;
  318. }
  319. for (;;) {
  320. for (i = 0; i < poll_instance->poll_entry_count; i++) {
  321. memcpy (&poll_instance->ufds[i],
  322. &poll_instance->poll_entries[i].ufd,
  323. sizeof (struct pollfd));
  324. }
  325. timeout = timerlist_timeout_msec (&poll_instance->timerlist);
  326. retry_poll:
  327. res = poll (poll_instance->ufds,
  328. poll_instance->poll_entry_count, timeout);
  329. if (errno == EINTR && res == -1) {
  330. goto retry_poll;
  331. } else
  332. if (res == -1) {
  333. goto error_exit;
  334. }
  335. poll_entry_count = poll_instance->poll_entry_count;
  336. for (i = 0; i < poll_entry_count; i++) {
  337. if (poll_instance->ufds[i].fd != -1 &&
  338. poll_instance->ufds[i].revents) {
  339. poll_instance->serialize_lock_fn();
  340. res = poll_instance->poll_entries[i].dispatch_fn (handle,
  341. poll_instance->ufds[i].fd,
  342. poll_instance->ufds[i].revents,
  343. poll_instance->poll_entries[i].data);
  344. poll_instance->serialize_unlock_fn();
  345. /*
  346. * Remove dispatch functions that return -1
  347. */
  348. if (res == -1) {
  349. poll_instance->poll_entries[i].ufd.fd = -1; /* empty entry */
  350. }
  351. }
  352. }
  353. poll_instance->serialize_lock_fn();
  354. timerlist_expire (&poll_instance->timerlist);
  355. poll_instance->serialize_unlock_fn();
  356. } /* for (;;) */
  357. hdb_handle_put (&poll_instance_database, handle);
  358. error_exit:
  359. return (-1);
  360. }
  361. int poll_stop (
  362. poll_handle handle);
  363. #ifdef COMPILE_OUT
  364. void poll_print_state (
  365. poll_handle handle,
  366. int fd)
  367. {
  368. struct poll_instance *poll_instance;
  369. int i;
  370. int res = 0;
  371. res = hdb_handle_get (&poll_instance_database, handle,
  372. (void *)&poll_instance);
  373. if (res != 0) {
  374. res = -ENOENT;
  375. exit (1);
  376. }
  377. for (i = 0; i < poll_instance->poll_entry_count; i++) {
  378. if (poll_instance->poll_entries[i].ufd.fd == fd) {
  379. printf ("fd %d\n", poll_instance->poll_entries[i].ufd.fd);
  380. printf ("events %d\n", poll_instance->poll_entries[i].ufd.events);
  381. printf ("dispatch_fn %p\n", poll_instance->poll_entries[i].dispatch_fn);
  382. }
  383. }
  384. }
  385. #endif