[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / runtime / main / Select.lc
1 %
2 % (c) The AQUA Project, Glasgow University, 1995
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[Select.lc]{Select Available File Descriptors}
7 %*                                                                      *
8 %************************************************************************
9
10 \begin{code}
11
12 #ifdef CONCURRENT
13
14 /* #define STK_CHK_DEBUG */
15
16 #define NULL_REG_MAP
17 #define NON_POSIX_SOURCE
18 /* Should there be a POSIX alternative based on poll()? */
19 #include "stgdefs.h"
20
21 # if defined(HAVE_SYS_TYPES_H)
22 #  include <sys/types.h>
23 # endif
24
25 # ifdef HAVE_SYS_TIME_H
26 #  include <sys/time.h>
27 # endif
28
29 void
30 AwaitEvent(delta)
31 I_ delta;
32 {
33     P_ tso, prev, next;
34     rtsBool ready;
35     fd_set rfd;
36     I_ us;
37     I_ min;
38     struct timeval tv;
39
40     min = delta == 0 ? 0x7fffffff : 0;
41
42     /* 
43      * Collect all of the fd's that we're interested in, and capture
44      * the minimum waiting time for the delayed threads.
45      */
46     FD_ZERO(&rfd);
47     for(tso = WaitingThreadsHd; tso != Nil_closure; tso = TSO_LINK(tso)) {
48         us = (I_) TSO_EVENT(tso);
49         if (us > 0) {
50             /* Looking at a delay event */
51             if (us < min)
52                 min = us;
53         } else {
54             /* Looking at a wait event */
55             FD_SET((-us), &rfd);
56         }
57     }
58
59     /* Check for any interesting events */
60
61     tv.tv_sec = min / 1000000;
62     tv.tv_usec = min % 1000000;
63
64     while (select(FD_SETSIZE, &rfd, NULL, NULL, &tv) < 0) {
65         if (errno != EINTR) {
66             fflush(stdout);
67             fprintf(stderr, "AwaitEvent: select failed\n");
68             EXIT(EXIT_FAILURE);
69         }
70     }   
71
72     if (delta == 0)
73         delta = min;
74
75     prev = NULL;
76     for(tso = WaitingThreadsHd; tso != Nil_closure; tso = next) {
77         next = TSO_LINK(tso);
78         us = (I_) TSO_EVENT(tso);
79         if (us > 0) {
80             /* Looking at a delay event */
81             us -= delta;
82             ready = (us <= 0);
83             if (!ready)
84                 TSO_EVENT(tso) = (W_) us;
85         } else {
86             /* Looking at a wait event */
87             ready = FD_ISSET((-us), &rfd);
88         }
89         if (ready) {
90
91 #if defined(GRAN)
92             if (ThreadQueueTl == Nil_closure)
93                 ThreadQueueHd = tso;
94             else
95                 TSO_LINK(ThreadQueueTl) = tso;
96             ThreadQueueTl = tso;
97             TSO_LINK(tso) = Nil_closure;
98 #else
99             if (RunnableThreadsTl == Nil_closure)
100                 RunnableThreadsHd = tso;
101             else
102                 TSO_LINK(RunnableThreadsTl) = tso;
103             RunnableThreadsTl = tso;
104             TSO_LINK(tso) = Nil_closure;
105 #endif
106         } else {
107             if (prev == NULL)
108                 WaitingThreadsHd = tso;
109             else
110                 TSO_LINK(prev) = tso;
111             prev = tso;
112         }
113     }
114     if (prev == NULL)
115         WaitingThreadsHd = WaitingThreadsTl = Nil_closure;
116     else {
117         TSO_LINK(prev) = Nil_closure;
118         WaitingThreadsTl = prev;
119     }
120 }
121
122 #endif /* CONCURRENT */
123 \end{code}