4fdcaa45ecf5b33583e5563a9c852550b5a75135
[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(I_ delta)
31 {
32     P_ tso, prev, next;
33     rtsBool ready;
34     fd_set rfd;
35     I_ us;
36     I_ min;
37     I_ maxfd=0;
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      * (I_)TSO_EVENT(tso) < 0 => thread waiting on fd (-(I_)TSO_EVENT(tso))
47      *
48      */
49     FD_ZERO(&rfd);
50     for(tso = WaitingThreadsHd; tso != Nil_closure; tso = TSO_LINK(tso)) {
51         us = (I_) TSO_EVENT(tso);
52         if (us > 0) {
53             /* Looking at a delay event */
54             if (us < min)
55                 min = us;
56         } else {
57             /* Looking at a wait event */
58             maxfd = ((-us)> maxfd) ? (-us) : maxfd;
59             FD_SET((-us), &rfd);
60         }
61     }
62
63     /* Check for any interesting events */
64
65     tv.tv_sec = min / 1000000;
66     tv.tv_usec = min % 1000000;
67
68     while (select((maxfd==0 ? 0 : (maxfd+1)), &rfd, NULL, NULL, &tv) < 0) {
69         if (errno != EINTR) {
70             fflush(stdout);
71             fprintf(stderr, "AwaitEvent: select failed\n");
72             EXIT(EXIT_FAILURE);
73         }
74     }   
75  
76     if (delta == 0)
77         delta=min;
78
79     prev = NULL;
80     for(tso = WaitingThreadsHd; tso != Nil_closure; tso = next) {
81         next = TSO_LINK(tso);
82         us = (I_) TSO_EVENT(tso);
83         if (us > 0) {
84             /* Looking at a delay event */
85             us -= delta;
86             ready = (us <= 0);
87             if (!ready)
88                 TSO_EVENT(tso) = (W_) us;
89         } else {
90             /* Looking at a wait event */
91             ready = FD_ISSET((-us), &rfd);
92         }
93         if (ready) {
94
95 #if defined(GRAN)
96             if (ThreadQueueTl == Nil_closure)
97                 ThreadQueueHd = tso;
98             else
99                 TSO_LINK(ThreadQueueTl) = tso;
100             ThreadQueueTl = tso;
101             TSO_LINK(tso) = Nil_closure;
102 #else
103             if (RunnableThreadsTl == Nil_closure)
104                 RunnableThreadsHd = tso;
105             else
106                 TSO_LINK(RunnableThreadsTl) = tso;
107             RunnableThreadsTl = tso;
108             TSO_LINK(tso) = Nil_closure;
109 #endif
110         } else {
111             if (prev == NULL)
112                 WaitingThreadsHd = tso;
113             else
114                 TSO_LINK(prev) = tso;
115             prev = tso;
116         }
117     }
118     if (prev == NULL)
119         WaitingThreadsHd = WaitingThreadsTl = Nil_closure;
120     else {
121         TSO_LINK(prev) = Nil_closure;
122         WaitingThreadsTl = prev;
123     }
124 }
125
126 #endif /* CONCURRENT */
127 \end{code}