sigio.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  3. * Licensed under the GPL
  4. */
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <termios.h>
  8. #include <pty.h>
  9. #include <signal.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <sched.h>
  13. #include <sys/socket.h>
  14. #include <sys/poll.h>
  15. #include "init.h"
  16. #include "user.h"
  17. #include "kern_util.h"
  18. #include "user_util.h"
  19. #include "sigio.h"
  20. #include "os.h"
  21. /* Protected by sigio_lock(), also used by sigio_cleanup, which is an
  22. * exitcall.
  23. */
  24. static int write_sigio_pid = -1;
  25. /* These arrays are initialized before the sigio thread is started, and
  26. * the descriptors closed after it is killed. So, it can't see them change.
  27. * On the UML side, they are changed under the sigio_lock.
  28. */
  29. static int write_sigio_fds[2] = { -1, -1 };
  30. static int sigio_private[2] = { -1, -1 };
  31. struct pollfds {
  32. struct pollfd *poll;
  33. int size;
  34. int used;
  35. };
  36. /* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
  37. * synchronizes with it.
  38. */
  39. struct pollfds current_poll = {
  40. .poll = NULL,
  41. .size = 0,
  42. .used = 0
  43. };
  44. struct pollfds next_poll = {
  45. .poll = NULL,
  46. .size = 0,
  47. .used = 0
  48. };
  49. static int write_sigio_thread(void *unused)
  50. {
  51. struct pollfds *fds, tmp;
  52. struct pollfd *p;
  53. int i, n, respond_fd;
  54. char c;
  55. signal(SIGWINCH, SIG_IGN);
  56. fds = &current_poll;
  57. while(1){
  58. n = poll(fds->poll, fds->used, -1);
  59. if(n < 0){
  60. if(errno == EINTR) continue;
  61. printk("write_sigio_thread : poll returned %d, "
  62. "errno = %d\n", n, errno);
  63. }
  64. for(i = 0; i < fds->used; i++){
  65. p = &fds->poll[i];
  66. if(p->revents == 0) continue;
  67. if(p->fd == sigio_private[1]){
  68. n = os_read_file(sigio_private[1], &c, sizeof(c));
  69. if(n != sizeof(c))
  70. printk("write_sigio_thread : "
  71. "read failed, err = %d\n", -n);
  72. tmp = current_poll;
  73. current_poll = next_poll;
  74. next_poll = tmp;
  75. respond_fd = sigio_private[1];
  76. }
  77. else {
  78. respond_fd = write_sigio_fds[1];
  79. fds->used--;
  80. memmove(&fds->poll[i], &fds->poll[i + 1],
  81. (fds->used - i) * sizeof(*fds->poll));
  82. }
  83. n = os_write_file(respond_fd, &c, sizeof(c));
  84. if(n != sizeof(c))
  85. printk("write_sigio_thread : write failed, "
  86. "err = %d\n", -n);
  87. }
  88. }
  89. return 0;
  90. }
  91. static int need_poll(int n)
  92. {
  93. if(n <= next_poll.size){
  94. next_poll.used = n;
  95. return(0);
  96. }
  97. kfree(next_poll.poll);
  98. next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
  99. if(next_poll.poll == NULL){
  100. printk("need_poll : failed to allocate new pollfds\n");
  101. next_poll.size = 0;
  102. next_poll.used = 0;
  103. return(-1);
  104. }
  105. next_poll.size = n;
  106. next_poll.used = n;
  107. return(0);
  108. }
  109. /* Must be called with sigio_lock held, because it's needed by the marked
  110. * critical section. */
  111. static void update_thread(void)
  112. {
  113. unsigned long flags;
  114. int n;
  115. char c;
  116. flags = set_signals(0);
  117. n = os_write_file(sigio_private[0], &c, sizeof(c));
  118. if(n != sizeof(c)){
  119. printk("update_thread : write failed, err = %d\n", -n);
  120. goto fail;
  121. }
  122. n = os_read_file(sigio_private[0], &c, sizeof(c));
  123. if(n != sizeof(c)){
  124. printk("update_thread : read failed, err = %d\n", -n);
  125. goto fail;
  126. }
  127. set_signals(flags);
  128. return;
  129. fail:
  130. /* Critical section start */
  131. if(write_sigio_pid != -1)
  132. os_kill_process(write_sigio_pid, 1);
  133. write_sigio_pid = -1;
  134. close(sigio_private[0]);
  135. close(sigio_private[1]);
  136. close(write_sigio_fds[0]);
  137. close(write_sigio_fds[1]);
  138. /* Critical section end */
  139. set_signals(flags);
  140. }
  141. int add_sigio_fd(int fd, int read)
  142. {
  143. int err = 0, i, n, events;
  144. sigio_lock();
  145. for(i = 0; i < current_poll.used; i++){
  146. if(current_poll.poll[i].fd == fd)
  147. goto out;
  148. }
  149. n = current_poll.used + 1;
  150. err = need_poll(n);
  151. if(err)
  152. goto out;
  153. for(i = 0; i < current_poll.used; i++)
  154. next_poll.poll[i] = current_poll.poll[i];
  155. if(read) events = POLLIN;
  156. else events = POLLOUT;
  157. next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd,
  158. .events = events,
  159. .revents = 0 });
  160. update_thread();
  161. out:
  162. sigio_unlock();
  163. return(err);
  164. }
  165. int ignore_sigio_fd(int fd)
  166. {
  167. struct pollfd *p;
  168. int err = 0, i, n = 0;
  169. sigio_lock();
  170. for(i = 0; i < current_poll.used; i++){
  171. if(current_poll.poll[i].fd == fd) break;
  172. }
  173. if(i == current_poll.used)
  174. goto out;
  175. err = need_poll(current_poll.used - 1);
  176. if(err)
  177. goto out;
  178. for(i = 0; i < current_poll.used; i++){
  179. p = &current_poll.poll[i];
  180. if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i];
  181. }
  182. if(n == i){
  183. printk("ignore_sigio_fd : fd %d not found\n", fd);
  184. err = -1;
  185. goto out;
  186. }
  187. update_thread();
  188. out:
  189. sigio_unlock();
  190. return(err);
  191. }
  192. static struct pollfd *setup_initial_poll(int fd)
  193. {
  194. struct pollfd *p;
  195. p = um_kmalloc(sizeof(struct pollfd));
  196. if (p == NULL) {
  197. printk("setup_initial_poll : failed to allocate poll\n");
  198. return NULL;
  199. }
  200. *p = ((struct pollfd) { .fd = fd,
  201. .events = POLLIN,
  202. .revents = 0 });
  203. return p;
  204. }
  205. void write_sigio_workaround(void)
  206. {
  207. unsigned long stack;
  208. struct pollfd *p;
  209. int err;
  210. int l_write_sigio_fds[2];
  211. int l_sigio_private[2];
  212. int l_write_sigio_pid;
  213. /* We call this *tons* of times - and most ones we must just fail. */
  214. sigio_lock();
  215. l_write_sigio_pid = write_sigio_pid;
  216. sigio_unlock();
  217. if (l_write_sigio_pid != -1)
  218. return;
  219. err = os_pipe(l_write_sigio_fds, 1, 1);
  220. if(err < 0){
  221. printk("write_sigio_workaround - os_pipe 1 failed, "
  222. "err = %d\n", -err);
  223. return;
  224. }
  225. err = os_pipe(l_sigio_private, 1, 1);
  226. if(err < 0){
  227. printk("write_sigio_workaround - os_pipe 2 failed, "
  228. "err = %d\n", -err);
  229. goto out_close1;
  230. }
  231. p = setup_initial_poll(l_sigio_private[1]);
  232. if(!p)
  233. goto out_close2;
  234. sigio_lock();
  235. /* Did we race? Don't try to optimize this, please, it's not so likely
  236. * to happen, and no more than once at the boot. */
  237. if(write_sigio_pid != -1)
  238. goto out_unlock;
  239. write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
  240. CLONE_FILES | CLONE_VM, &stack, 0);
  241. if (write_sigio_pid < 0)
  242. goto out_clear;
  243. if (write_sigio_irq(l_write_sigio_fds[0]))
  244. goto out_kill;
  245. /* Success, finally. */
  246. memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
  247. memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
  248. current_poll = ((struct pollfds) { .poll = p,
  249. .used = 1,
  250. .size = 1 });
  251. sigio_unlock();
  252. return;
  253. out_kill:
  254. l_write_sigio_pid = write_sigio_pid;
  255. write_sigio_pid = -1;
  256. sigio_unlock();
  257. /* Going to call waitpid, avoid holding the lock. */
  258. os_kill_process(l_write_sigio_pid, 1);
  259. goto out_free;
  260. out_clear:
  261. write_sigio_pid = -1;
  262. out_unlock:
  263. sigio_unlock();
  264. out_free:
  265. kfree(p);
  266. out_close2:
  267. close(l_sigio_private[0]);
  268. close(l_sigio_private[1]);
  269. out_close1:
  270. close(l_write_sigio_fds[0]);
  271. close(l_write_sigio_fds[1]);
  272. return;
  273. }
  274. void sigio_cleanup(void)
  275. {
  276. if(write_sigio_pid != -1){
  277. os_kill_process(write_sigio_pid, 1);
  278. write_sigio_pid = -1;
  279. }
  280. }