event.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. /* Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees.
  2. See file COPYING. */
  3. #include <signal.h> /* for sigaction(), pthread_sigmask() / sigprocmask() (POSIX.1) */
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <sys/time.h>
  9. #include <sys/times.h>
  10. #include <errno.h> /* for errno, (POSIX?/ANSI) */
  11. #include <string.h> /* FD_ZERO sometimes needs this */
  12. #include "sysdep.h"
  13. #ifdef HAVE_PTHREAD_H
  14. #include <pthread.h>
  15. #endif
  16. #ifdef HAVE_POLL_H
  17. #include <poll.h>
  18. #endif
  19. #ifdef HAVE_GLIB
  20. #include <glib.h>
  21. #endif
  22. #include "c-mods.h"
  23. #include "scheme48vm.h"
  24. #include "event.h"
  25. /* turning interrupts and I/O readiness into events */
  26. static sigset_t interrupt_mask;
  27. /*
  28. * They're basically the same, but the behavior of sigprocmask is
  29. * undefined in the presence of Pthreads.
  30. */
  31. #ifdef HAVE_PTHREAD_H
  32. #define SIGMASK pthread_sigmask
  33. #else
  34. /* sigprocmask can be interrupted, while pthread_sigmask cannot */
  35. static int
  36. our_sigmask(int how, const sigset_t *set, sigset_t *oset)
  37. {
  38. int retval;
  39. while ((retval = sigprocmask(how, set, oset))
  40. && (errno == EINTR))
  41. ;
  42. return retval;
  43. }
  44. #define SIGMASK our_sigmask
  45. #endif
  46. static void
  47. block_keyboard_n_alarm_interrupts(void)
  48. {
  49. if (SIGMASK(SIG_BLOCK, &interrupt_mask, NULL))
  50. {
  51. fprintf(stderr,
  52. "Failed to block SIGINT/SIGALRM, errno = %d\n",
  53. errno);
  54. exit(1);
  55. }
  56. }
  57. static void
  58. allow_keyboard_n_alarm_interrupts(void)
  59. {
  60. if (SIGMASK(SIG_UNBLOCK, &interrupt_mask, NULL))
  61. {
  62. fprintf(stderr,
  63. "Failed to unblock SIGINT/SIGALRM, errno = %d\n",
  64. errno);
  65. exit(1);
  66. }
  67. }
  68. /*
  69. * Unless a signal is being ignored, set up the handler.
  70. * If we return PSFALSE, something went wrong and errno is set to what.
  71. */
  72. psbool
  73. s48_setcatcher(int signum, void (*catcher)(int))
  74. {
  75. struct sigaction sa;
  76. if (sigaction(signum, (struct sigaction *)NULL, &sa) != 0)
  77. return (PSFALSE);
  78. if (sa.sa_handler == SIG_IGN)
  79. return (PSTRUE);
  80. sa.sa_handler = catcher;
  81. sigemptyset(&sa.sa_mask);
  82. #ifdef HAVE_SIGALTSTACK
  83. sa.sa_flags = SA_ONSTACK;
  84. #else
  85. sa.sa_flags = 0;
  86. #endif
  87. if (sigaction(signum, &sa, (struct sigaction *)NULL) != 0)
  88. return (PSFALSE);
  89. return (PSTRUE);
  90. }
  91. static long keyboard_interrupt_count = 0;
  92. void
  93. s48_when_keyboard_interrupt(int ign)
  94. {
  95. keyboard_interrupt_count += 1;
  96. NOTE_EVENT;
  97. return;
  98. }
  99. /*
  100. We turn off SIGPIPE interrupts by installing a handler that does nothing.
  101. Turning them off affects exec()'ed programs, so we don't want to do that.
  102. Any actual pipe problems are caught when we try to read or write to them.
  103. We thank Olin Shivers for this hack.
  104. */
  105. static void
  106. when_sigpipe_interrupt(int ign)
  107. {
  108. return;
  109. }
  110. /* ticks since last timer-interrupt request */
  111. long s48_current_time = 0;
  112. static long alarm_time = -1;
  113. static long poll_time = -1;
  114. static long poll_interval = 5;
  115. void
  116. s48_when_alarm_interrupt(int ign)
  117. {
  118. s48_current_time += 1;
  119. /* fprintf(stderr, "[tick]"); */
  120. if ((alarm_time >= 0 && alarm_time <= s48_current_time) ||
  121. (poll_time >= 0 && poll_time <= s48_current_time)) {
  122. NOTE_EVENT;
  123. };
  124. return;
  125. }
  126. #define USEC_PER_POLL (1000000 / POLLS_PER_SECOND)
  127. /* delta is in ticks, 0 cancels current alarm */
  128. long
  129. s48_schedule_alarm_interrupt(long delta)
  130. {
  131. long old;
  132. /*
  133. fprintf(stderr, "<scheduling alarm for %ld + %ld>\n", s48_current_time,
  134. delta/TICKS_PER_POLL); */
  135. /* get remaining time */
  136. if (alarm_time == -1)
  137. old = -1;
  138. else
  139. old = (alarm_time - s48_current_time) * TICKS_PER_POLL;
  140. /* decrement poll_time and reset current_time */
  141. if (poll_time != -1)
  142. poll_time -= s48_current_time;
  143. s48_current_time = 0;
  144. /* set alarm_time */
  145. if (delta == 0) {
  146. NOTE_EVENT;
  147. alarm_time = 0; }
  148. else
  149. alarm_time = delta / TICKS_PER_POLL;
  150. return old;
  151. }
  152. /* The next two procedures return times in seconds and ticks */
  153. long
  154. s48_real_time(long *ticks)
  155. {
  156. struct timeval tv;
  157. static struct timeval tv_orig;
  158. static int initp = PSFALSE;
  159. if (!initp) {
  160. gettimeofday(&tv_orig, NULL);
  161. initp = PSTRUE;
  162. };
  163. gettimeofday(&tv, NULL);
  164. *ticks = (tv.tv_usec - tv_orig.tv_usec)/(1000000/TICKS_PER_SECOND);
  165. return tv.tv_sec - tv_orig.tv_sec;
  166. }
  167. long
  168. s48_run_time(long *ticks)
  169. {
  170. struct tms time_buffer;
  171. static long clock_tick = 0;
  172. long cpu_time;
  173. if (clock_tick == 0)
  174. clock_tick = sysconf(_SC_CLK_TCK); /* POSIX.1, POSIX.2 */
  175. times(&time_buffer); /* On Sun, getrusage() would be better */
  176. cpu_time = time_buffer.tms_utime + time_buffer.tms_stime;
  177. *ticks = (cpu_time % clock_tick) * TICKS_PER_SECOND / clock_tick;
  178. return cpu_time / clock_tick;
  179. }
  180. void
  181. s48_start_alarm_interrupts(void)
  182. {
  183. struct itimerval newv, old;
  184. newv.it_value.tv_sec = 0;
  185. newv.it_value.tv_usec = USEC_PER_POLL;
  186. newv.it_interval.tv_sec = 0;
  187. newv.it_interval.tv_usec = USEC_PER_POLL;
  188. if (0 != setitimer(ITIMER_REAL, &newv, &old)) {
  189. perror("setitimer");
  190. exit(-1); }
  191. }
  192. void
  193. s48_stop_alarm_interrupts(void)
  194. {
  195. struct itimerval newv, old;
  196. newv.it_value.tv_sec = 0;
  197. newv.it_value.tv_usec = 0;
  198. newv.it_interval.tv_sec = 0;
  199. newv.it_interval.tv_usec = 0;
  200. if (0 != setitimer(ITIMER_REAL, &newv, &old)) {
  201. perror("setitimer");
  202. exit(-1); }
  203. }
  204. /*
  205. * We ensure single-threadedness by sending a signal to the main
  206. * thread, and doing everthing critical there. This is all probably
  207. * quite useless without OS threads.
  208. */
  209. #ifdef HAVE_PTHREAD_H
  210. static pthread_mutex_t external_event_mutex = PTHREAD_MUTEX_INITIALIZER;
  211. static pthread_t main_thread;
  212. #define LOCK_EXTERNAL_EVENTS pthread_mutex_lock(&external_event_mutex)
  213. #define UNLOCK_EXTERNAL_EVENTS pthread_mutex_unlock(&external_event_mutex)
  214. #else
  215. #define LOCK_EXTERNAL_EVENTS
  216. #define UNLOCK_EXTERNAL_EVENTS
  217. #endif
  218. long
  219. s48_dequeue_external_event(char* readyp)
  220. {
  221. long retval;
  222. LOCK_EXTERNAL_EVENTS;
  223. retval = s48_dequeue_external_eventBUunsafe(readyp);
  224. UNLOCK_EXTERNAL_EVENTS;
  225. return retval;
  226. }
  227. static char
  228. external_event_pending()
  229. {
  230. char retval;
  231. LOCK_EXTERNAL_EVENTS;
  232. retval = s48_external_event_pendingPUunsafe();
  233. UNLOCK_EXTERNAL_EVENTS;
  234. return retval;
  235. }
  236. /* no side effect */
  237. static char
  238. external_event_ready()
  239. {
  240. char retval;
  241. LOCK_EXTERNAL_EVENTS;
  242. retval = s48_external_event_readyPUunsafe();
  243. UNLOCK_EXTERNAL_EVENTS;
  244. return retval;
  245. }
  246. void
  247. s48_note_external_event(long uid)
  248. {
  249. LOCK_EXTERNAL_EVENTS;
  250. s48_note_external_eventBUunsafe(uid);
  251. UNLOCK_EXTERNAL_EVENTS;
  252. NOTE_EVENT;
  253. #ifdef HAVE_PTHREAD_H
  254. pthread_kill(main_thread, SIG_EXTERNAL_EVENT);
  255. #else
  256. /* pretty useless probably */
  257. raise(SIG_EXTERNAL_EVENT);
  258. #endif
  259. }
  260. void
  261. s48_when_external_event_interrupt(int ign)
  262. {
  263. /* do nothing, except possibly interrupt the running select */
  264. }
  265. /*
  266. * ; Scheme version of the get-next-event procedure
  267. * ;
  268. * ; 1. If there has been a keyboard interrupt, return it.
  269. * ; 2. Check for ready ports if enough time has passed since the last check.
  270. * ; 3. If there is a ready port, return it.
  271. * ; 4. If an alarm is due, return it.
  272. * ; 5. If no events are pending, clear the event flags.
  273. * (define (get-next-event)
  274. * (cond ((> *keyboard-interrupt-count* 0)
  275. * (without-interrupts
  276. * (lambda ()
  277. * (set! *keyboard-interrupt-count*
  278. * (- *keyboard-interrupt-count* 1))))
  279. * (values (enum event-type keyboard-interrupt) #f #f))
  280. * (else
  281. * (cond ((>= *current_time* *poll-time*)
  282. * (queue-ready-ports)
  283. * (set! *poll-time* (+ *time* *poll-interval*))))
  284. * (cond ((not (queue-empty? ready-ports))
  285. * (values (enum event-type i/o-completion)
  286. * (dequeue! ready-ports)))
  287. * ((>= *current_time* *alarm-time*)
  288. * (set! *alarm-time* max-integer)
  289. * (values (enum event-type alarm-interrupt) #f))
  290. * (else
  291. * (without-interrupts
  292. * (lambda ()
  293. * (if (and (= *keyboard-interrupt-count* 0)
  294. * (> *alarm-time* *current_time*)
  295. * (> *poll-time* *current_time*))
  296. * (set! *pending-event?* #f))))
  297. * (values (enum event-type no-event) #f))))))
  298. */
  299. static psbool there_are_ready_ports(void);
  300. static int next_ready_port(void);
  301. static int queue_ready_ports(psbool wait, long seconds, long ticks);
  302. int
  303. s48_get_next_event(long *ready_fd, long *status)
  304. {
  305. int io_poll_status;
  306. /*
  307. fprintf(stderr, "[poll at %d (waiting for %d)]\n", s48_current_time, alarm_time);
  308. */
  309. if (keyboard_interrupt_count > 0) {
  310. block_keyboard_n_alarm_interrupts();
  311. --keyboard_interrupt_count;
  312. allow_keyboard_n_alarm_interrupts();
  313. /* fprintf(stderr, "[keyboard interrupt]\n"); */
  314. return (KEYBOARD_INTERRUPT_EVENT);
  315. }
  316. if (poll_time != -1 && s48_current_time >= poll_time) {
  317. io_poll_status = queue_ready_ports(PSFALSE, 0, 0);
  318. if (io_poll_status == NO_ERRORS)
  319. poll_time = s48_current_time + poll_interval;
  320. else {
  321. *status = io_poll_status;
  322. return (ERROR_EVENT);
  323. }
  324. }
  325. if (there_are_ready_ports()) {
  326. *ready_fd = next_ready_port();
  327. *status = 0; /* chars read or written */
  328. /* fprintf(stderr, "[i/o completion]\n"); */
  329. return (IO_COMPLETION_EVENT);
  330. }
  331. if (alarm_time != -1 && s48_current_time >= alarm_time) {
  332. alarm_time = -1;
  333. /* fprintf(stderr, "[alarm %ld]\n", ticks); */
  334. return (ALARM_EVENT);
  335. }
  336. if (s48_os_signal_pending())
  337. return (OS_SIGNAL_EVENT);
  338. if (external_event_pending())
  339. return (EXTERNAL_EVENT);
  340. block_keyboard_n_alarm_interrupts();
  341. if ((keyboard_interrupt_count == 0)
  342. && (alarm_time == -1 || s48_current_time < alarm_time)
  343. && (poll_time == -1 || s48_current_time < poll_time))
  344. s48_Spending_eventsPS = PSFALSE;
  345. allow_keyboard_n_alarm_interrupts();
  346. return (NO_EVENT);
  347. }
  348. /*
  349. * We keep two queues of ports: those that have a pending operation, and
  350. * those whose operation has completed. Periodically, we call select() on
  351. * the pending ports and move any that are ready onto the other queue and
  352. * signal an event.
  353. */
  354. #define FD_QUIESCENT 0 /* idle */
  355. #define FD_READY 1 /* I/O ready to be performed */
  356. #define FD_PENDING 2 /* waiting */
  357. typedef struct fd_struct {
  358. int fd, /* file descriptor */
  359. status; /* one of the FD_* constants */
  360. psbool is_input; /* iff input */
  361. struct fd_struct *next; /* next on same queue */
  362. } fd_struct;
  363. /*
  364. * A queue of fd_structs is empty iff the first field is NULL. In
  365. * that case, lastp points to first.
  366. */
  367. typedef struct fdque {
  368. long count;
  369. fd_struct *first,
  370. **lastp;
  371. } fdque;
  372. static long fd_setsize;
  373. static fd_struct **fds;
  374. static fdque ready = {
  375. 0,
  376. NULL,
  377. &ready.first
  378. },
  379. pending = {
  380. 0,
  381. NULL,
  382. &pending.first
  383. };
  384. static void findrm(fd_struct *entry, fdque *que);
  385. static fd_struct *rmque(fd_struct **link, fdque *que);
  386. static void addque(fd_struct *entry, fdque *que);
  387. static fd_struct *add_fd(int fd, psbool is_input);
  388. /*
  389. * Find a fd_struct in a queue, and remove it.
  390. */
  391. static void
  392. findrm(fd_struct *entry, fdque *que)
  393. {
  394. fd_struct **fp,
  395. *f;
  396. for (fp = &que->first; (f = *fp) != entry; fp = &f->next)
  397. if (f == NULL) {
  398. fprintf(stderr, "ERROR: findrm fd %d, status %d not on queue.\n",
  399. entry->fd, entry->status);
  400. return;
  401. }
  402. rmque(fp, que);
  403. }
  404. /*
  405. * Given a pointer to the link of a fd_struct, and a pointer to
  406. * the queue it is on, remove the entry from the queue.
  407. * The entry removed is returned.
  408. */
  409. static fd_struct *
  410. rmque(fd_struct **link, fdque *que)
  411. {
  412. fd_struct *res;
  413. res = *link;
  414. *link = res->next;
  415. if (res->next == NULL)
  416. que->lastp = link;
  417. que->count--;
  418. return (res);
  419. }
  420. /*
  421. * Add a fd_struct to a queue.
  422. */
  423. static void
  424. addque(fd_struct *entry, fdque *que)
  425. {
  426. *que->lastp = entry;
  427. entry->next = NULL;
  428. que->lastp = &entry->next;
  429. que->count++;
  430. }
  431. static psbool
  432. there_are_ready_ports(void)
  433. {
  434. return (ready.first != NULL);
  435. }
  436. static int
  437. next_ready_port(void)
  438. {
  439. fd_struct *p;
  440. p = rmque(&ready.first, &ready);
  441. p->status = FD_QUIESCENT;
  442. return (p->fd);
  443. }
  444. /*
  445. * Put fd on to the queue of ports with pending operations.
  446. * Return PSTRUE if successful, and PSFALSE otherwise.
  447. */
  448. psbool
  449. s48_add_pending_fd(int fd, psbool is_input)
  450. {
  451. fd_struct *data;
  452. if (! (0 <= fd && fd < fd_setsize)) {
  453. fd_setsize *= 2;
  454. fds = (fd_struct **) realloc (fds, sizeof (fd_struct *) * fd_setsize);
  455. if (fds == NULL)
  456. fprintf(stderr, "ERROR: realloc of fds to %ld elements failed, errno = %d\n",
  457. fd_setsize,
  458. errno);
  459. return (PSFALSE);
  460. }
  461. data = fds[fd];
  462. if (data == NULL) {
  463. data = add_fd(fd, is_input);
  464. if (data == NULL)
  465. return (PSFALSE); } /* no more memory */
  466. data->is_input = is_input;
  467. if (data->status == FD_PENDING)
  468. return (PSTRUE); /* fd is already pending */
  469. if (data->status == FD_READY)
  470. findrm(data, &ready);
  471. data->status = FD_PENDING;
  472. addque(data, &pending);
  473. if (poll_time == -1)
  474. poll_time = s48_current_time + poll_interval;
  475. return PSTRUE;
  476. }
  477. /*
  478. * Add a new fd_struct for fd.
  479. */
  480. static fd_struct *
  481. add_fd(int fd, psbool is_input)
  482. {
  483. struct fd_struct *new_fd;
  484. new_fd = (struct fd_struct *)malloc(sizeof(struct fd_struct));
  485. if (new_fd != NULL) {
  486. new_fd->fd = fd;
  487. new_fd->status = FD_QUIESCENT;
  488. new_fd->is_input = is_input;
  489. new_fd->next = NULL;
  490. fds[fd] = new_fd;
  491. }
  492. return (new_fd);
  493. }
  494. /*
  495. * Remove fd from any queues it is on. Returns true if the FD was on a queue
  496. * and false if it wasn't.
  497. */
  498. psbool
  499. s48_remove_fd(int fd)
  500. {
  501. struct fd_struct *data;
  502. if (! (0 <= fd && fd < fd_setsize)) {
  503. fprintf(stderr, "ERROR: s48_remove_fd fd %d not in [0, %ld)\n",
  504. fd,
  505. fd_setsize);
  506. return PSFALSE;
  507. }
  508. data = fds[fd];
  509. if (data == NULL)
  510. return PSFALSE;
  511. if (data->status == FD_PENDING) {
  512. findrm(data, &pending);
  513. if (pending.first == NULL)
  514. poll_time = -1;
  515. } else if (data->status == FD_READY)
  516. findrm(data, &ready);
  517. free((void *)data);
  518. fds[fd] = NULL;
  519. return PSTRUE;
  520. }
  521. int
  522. s48_wait_for_event(long max_wait, psbool is_minutes)
  523. {
  524. int status;
  525. long seconds,
  526. ticks;
  527. /* fprintf(stderr, "[waiting]\n"); */
  528. s48_stop_alarm_interrupts();
  529. ticks = 0;
  530. if (max_wait == -1)
  531. seconds = -1;
  532. else if (is_minutes)
  533. seconds = max_wait * 60;
  534. else {
  535. seconds = max_wait / TICKS_PER_SECOND;
  536. ticks = max_wait % TICKS_PER_SECOND;
  537. }
  538. if (keyboard_interrupt_count > 0)
  539. status = NO_ERRORS;
  540. else {
  541. status = queue_ready_ports(PSTRUE, seconds, ticks);
  542. if (there_are_ready_ports()
  543. || external_event_ready())
  544. NOTE_EVENT;
  545. }
  546. s48_start_alarm_interrupts();
  547. return (status);
  548. }
  549. #if defined HAVE_GLIB
  550. static GMainContext *g_main_context;
  551. typedef struct S48_GSource {
  552. GSource g_source;
  553. psbool wait;
  554. long seconds;
  555. long ticks;
  556. } S48_GSource;
  557. static S48_GSource *g_source;
  558. static guint g_source_id;
  559. static GPollFD *g_pollfds;
  560. static long g_pollfds_size;
  561. static gboolean
  562. s48_g_source_prepare(GSource *source, gint *timeout_) {
  563. fd_struct *fdp,
  564. **fdpp;
  565. int g_npollfds;
  566. S48_GSource *src = (S48_GSource *) source;
  567. if ((! src->wait)
  568. && (pending.first == NULL))
  569. return TRUE;
  570. if (pending.count > g_pollfds_size) {
  571. g_pollfds_size *= 2;
  572. g_pollfds = (GPollFD *) realloc (g_pollfds,
  573. sizeof (GPollFD) * g_pollfds_size);
  574. if (g_pollfds == NULL) {
  575. fprintf(stderr,
  576. "Failed to realloc array of file descriptors to poll, errno = %d\n",
  577. errno);
  578. exit(1);
  579. }
  580. }
  581. for (fdp = pending.first, g_npollfds = 0;
  582. fdp != NULL;
  583. fdp = fdp->next, g_npollfds++) {
  584. g_pollfds[g_npollfds].fd = fdp->fd;
  585. g_pollfds[g_npollfds].events = fdp->is_input?
  586. (G_IO_IN | G_IO_HUP | G_IO_ERR) : (G_IO_OUT | G_IO_ERR);
  587. g_source_add_poll(source, &g_pollfds[g_npollfds]);
  588. }
  589. if (src->wait && timeout_)
  590. if (src->seconds == -1)
  591. *timeout_ = -1;
  592. else
  593. *timeout_ = (gint) src->seconds;
  594. else
  595. *timeout_ = 0;
  596. return FALSE;
  597. }
  598. static gboolean
  599. s48_g_source_check(GSource *source) {
  600. fd_struct *fdp,
  601. **fdpp;
  602. int g_npollfds;
  603. fdpp = &pending.first;
  604. for (fdp = *fdpp, g_npollfds = 0;
  605. (fdp != NULL);
  606. fdp = *fdpp, g_npollfds++) {
  607. if ((g_pollfds[g_npollfds].revents
  608. & (fdp->is_input? G_IO_IN : G_IO_OUT))
  609. | G_IO_HUP | G_IO_ERR)
  610. return TRUE;
  611. else
  612. fdpp = &fdp->next;
  613. }
  614. return FALSE;
  615. }
  616. static gboolean
  617. s48_g_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) {
  618. fd_struct *fdp,
  619. **fdpp;
  620. int g_npollfds;
  621. fdpp = &pending.first;
  622. for (fdp = *fdpp, g_npollfds = 0;
  623. (fdp != NULL);
  624. fdp = *fdpp, g_npollfds++) {
  625. if ((g_pollfds[g_npollfds].revents
  626. & (fdp->is_input? G_IO_IN : G_IO_OUT))
  627. | G_IO_HUP | G_IO_ERR) {
  628. g_source_remove_poll(source, &g_pollfds[g_npollfds]);
  629. rmque(fdpp, &pending);
  630. fdp->status = FD_READY;
  631. addque(fdp, &ready);
  632. }
  633. else
  634. fdpp = &fdp->next;
  635. }
  636. if (pending.first == NULL)
  637. poll_time = -1;
  638. return TRUE;
  639. }
  640. static GSourceFuncs s48_g_source_funcs = {
  641. s48_g_source_prepare,
  642. s48_g_source_check,
  643. s48_g_source_dispatch,
  644. NULL,
  645. NULL,
  646. NULL
  647. };
  648. /*
  649. * Use the glib event loop.
  650. */
  651. static int
  652. queue_ready_ports(psbool wait, long seconds, long ticks)
  653. {
  654. g_source->wait = wait;
  655. g_source->seconds = seconds;
  656. g_source->ticks = ticks;
  657. g_main_context_iteration(g_main_context, wait);
  658. return NO_ERRORS;
  659. }
  660. #elif defined HAVE_POLL
  661. static struct pollfd *pollfds;
  662. static long pollfds_size;
  663. /*
  664. * Call poll() on the pending ports and move any ready ones to the ready
  665. * queue. If wait is true, seconds is either -1 (wait forever) or the
  666. * maximum number of seconds to wait (with ticks any additional ticks).
  667. * The returned value is a status code.
  668. */
  669. static int
  670. queue_ready_ports(psbool wait, long seconds, long ticks)
  671. {
  672. int npollfds;
  673. int timeout;
  674. fd_struct *fdp,
  675. **fdpp;
  676. int left;
  677. if ((! wait)
  678. && (pending.first == NULL))
  679. return (NO_ERRORS);
  680. if (pending.count > pollfds_size) {
  681. pollfds_size *= 2;
  682. pollfds = (struct pollfd *) realloc (pollfds,
  683. sizeof (struct pollfd) * pollfds_size);
  684. if (pollfds == NULL) {
  685. fprintf(stderr,
  686. "Failed to realloc array of file descriptors to poll, errno = %d\n",
  687. errno);
  688. exit(1);
  689. }
  690. }
  691. for (fdp = pending.first, npollfds = 0; fdp != NULL; fdp = fdp->next, npollfds++) {
  692. pollfds[npollfds].fd = fdp->fd;
  693. pollfds[npollfds].events = fdp->is_input? POLLIN : POLLOUT;
  694. }
  695. if (wait)
  696. if (seconds == -1)
  697. timeout = -1;
  698. else
  699. timeout = (int) seconds;
  700. else
  701. timeout = 0;
  702. while(1) {
  703. left = poll(pollfds, pending.count, timeout);
  704. if (left > 0) {
  705. fdpp = &pending.first;
  706. for (fdp = *fdpp, npollfds = 0;
  707. (left > 0) && (fdp != NULL);
  708. fdp = *fdpp, npollfds++) {
  709. if (pollfds[npollfds].revents & (fdp->is_input? POLLIN : POLLOUT)
  710. | POLLHUP | POLLERR) {
  711. rmque(fdpp, &pending);
  712. fdp->status = FD_READY;
  713. addque(fdp, &ready);
  714. }
  715. else
  716. fdpp = &fdp->next;
  717. }
  718. if (pending.first == NULL)
  719. poll_time = -1;
  720. return NO_ERRORS;
  721. }
  722. else if (left == 0)
  723. return NO_ERRORS;
  724. else if (errno == EINTR) {
  725. if (external_event_ready())
  726. return NO_ERRORS;
  727. timeout = 0; /* turn off blocking and try again */
  728. }
  729. else
  730. return errno;
  731. }
  732. }
  733. #elif defined HAVE_SELECT
  734. /*
  735. * Call select() on the pending ports and move any ready ones to the ready
  736. * queue. If wait is true, seconds is either -1 (wait forever) or the
  737. * maximum number of seconds to wait (with ticks any additional ticks).
  738. * The returned value is a status code.
  739. */
  740. static int
  741. queue_ready_ports(psbool wait, long seconds, long ticks)
  742. {
  743. fd_set reads,
  744. writes,
  745. alls;
  746. int limfd;
  747. fd_struct *fdp,
  748. **fdpp;
  749. int left;
  750. struct timeval tv,
  751. *tvp;
  752. if ((! wait)
  753. && (pending.first == NULL))
  754. return (NO_ERRORS);
  755. FD_ZERO(&reads);
  756. FD_ZERO(&writes);
  757. FD_ZERO(&alls);
  758. limfd = 0;
  759. for (fdp = pending.first; fdp != NULL; fdp = fdp->next) {
  760. FD_SET(fdp->fd, fdp->is_input ? &reads : &writes);
  761. FD_SET(fdp->fd, &alls);
  762. if (limfd <= fdp->fd)
  763. limfd = fdp->fd + 1;
  764. }
  765. tvp = &tv;
  766. if (wait)
  767. if (seconds == -1)
  768. tvp = NULL;
  769. else {
  770. tv.tv_sec = seconds;
  771. tv.tv_usec = ticks * (1000000 / TICKS_PER_SECOND);
  772. }
  773. else
  774. timerclear(&tv);
  775. while(1) {
  776. left = select(limfd, &reads, &writes, &alls, tvp);
  777. if (left > 0) {
  778. fdpp = &pending.first;
  779. while (left > 0 && (fdp = *fdpp) != NULL)
  780. if ((FD_ISSET(fdp->fd, &alls))
  781. || (FD_ISSET(fdp->fd, fdp->is_input ? &reads : &writes))) {
  782. --left;
  783. rmque(fdpp, &pending);
  784. fdp->status = FD_READY;
  785. addque(fdp, &ready);
  786. } else
  787. fdpp = &fdp->next;
  788. if (pending.first == NULL)
  789. poll_time = -1;
  790. return NO_ERRORS;
  791. }
  792. else if (left == 0)
  793. return NO_ERRORS;
  794. else if (errno == EINTR) {
  795. if (external_event_ready())
  796. return NO_ERRORS;
  797. tvp = &tv; /* turn off blocking and try again */
  798. timerclear(tvp);
  799. }
  800. else
  801. return errno;
  802. }
  803. }
  804. #endif /* HAVE_SELECT */
  805. void
  806. s48_sysdep_init(void)
  807. {
  808. #ifdef HAVE_PTHREAD_H
  809. main_thread = pthread_self();
  810. #endif
  811. #ifdef HAVE_SIGALTSTACK
  812. stack_t ss;
  813. ss.ss_sp = malloc(SIGSTKSZ);
  814. if (ss.ss_sp == NULL)
  815. fprintf(stderr,
  816. "Failed to malloc alt stack, errno = %d\n",
  817. errno);
  818. ss.ss_size = SIGSTKSZ;
  819. ss.ss_flags = 0;
  820. if (sigaltstack(&ss, NULL) == -1)
  821. fprintf(stderr,
  822. "Failed to sigaltstack, errno = %d\n",
  823. errno);
  824. #endif
  825. #if defined HAVE_GLIB
  826. g_main_context = g_main_context_default();
  827. g_main_context_ref(g_main_context);
  828. g_source = (S48_GSource *) g_source_new(&s48_g_source_funcs, sizeof (S48_GSource));
  829. g_source_id = g_source_attach((GSource *) g_source, g_main_context);
  830. g_pollfds_size = FD_SETSIZE;
  831. g_pollfds = (GPollFD *) calloc (sizeof (GPollFD), g_pollfds_size);
  832. if (g_pollfds == NULL) {
  833. fprintf(stderr,
  834. "Failed to alloc array of file descriptors to poll with %d elements, errno = %d\n",
  835. g_pollfds_size,
  836. errno);
  837. exit(1);
  838. }
  839. #elif defined HAVE_POLL
  840. pollfds_size = FD_SETSIZE;
  841. pollfds = (struct pollfd *) calloc (sizeof (struct pollfd), pollfds_size);
  842. if (pollfds == NULL) {
  843. fprintf(stderr,
  844. "Failed to alloc array of file descriptors to poll with %ld elements, errno = %d\n",
  845. pollfds_size,
  846. errno);
  847. exit(1);
  848. }
  849. #endif /* HAVE_POLL */
  850. fd_setsize = FD_SETSIZE;
  851. fds = (fd_struct **) calloc (sizeof (fd_struct *), fd_setsize);
  852. if (fds == NULL) {
  853. fprintf(stderr,
  854. "Failed to alloc fds with %ld elements, errno = %d\n",
  855. fd_setsize,
  856. errno);
  857. exit(1);
  858. }
  859. if (!s48_setcatcher(SIGINT, s48_when_keyboard_interrupt)
  860. || !s48_setcatcher(SIGALRM, s48_when_alarm_interrupt)
  861. || !s48_setcatcher(SIGPIPE, when_sigpipe_interrupt)
  862. || !s48_setcatcher(SIG_EXTERNAL_EVENT, s48_when_external_event_interrupt)) {
  863. fprintf(stderr,
  864. "Failed to install signal handlers, errno = %d\n",
  865. errno);
  866. exit(1);
  867. }
  868. sigemptyset(&interrupt_mask);
  869. sigaddset(&interrupt_mask, SIGINT);
  870. sigaddset(&interrupt_mask, SIGALRM);
  871. s48_start_alarm_interrupts();
  872. }