event.c 23 KB

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