~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to erts/emulator/sys/unix/erl_check_io.c

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ``The contents of this file are subject to the Erlang Public License,
 
2
 * Version 1.1, (the "License"); you may not use this file except in
 
3
 * compliance with the License. You should have received a copy of the
 
4
 * Erlang Public License along with this software. If not, it can be
 
5
 * retrieved via the world wide web at http://www.erlang.org/.
 
6
 * 
 
7
 * Software distributed under the License is distributed on an "AS IS"
 
8
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
9
 * the License for the specific language governing rights and limitations
 
10
 * under the License.
 
11
 * 
 
12
 * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
 
13
 * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
 
14
 * AB. All Rights Reserved.''
 
15
 * 
 
16
 *     $Id$
 
17
 */
 
18
 
 
19
/*
 
20
 * Description: Check I/O
 
21
 *
 
22
 * Author:      Rickard Green
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#  include "config.h"
 
27
#endif
 
28
 
 
29
#define ERTS_WANT_BREAK_HANDLING
 
30
#define WANT_NONBLOCKING 
 
31
#include "sys.h"
 
32
#include "global.h"
 
33
#include "erl_driver.h"
 
34
#include "erl_poll.h"
 
35
#include "erl_check_io.h"
 
36
#include "erl_alloc.h"
 
37
 
 
38
#define ERTS_EV_FLG_IGNORE              (((short) 1) << 0)
 
39
 
 
40
#define ERTS_EV_TYPE_NONE               ((short) 0)
 
41
#define ERTS_EV_TYPE_DRV_SEL            ((short) 1)
 
42
#define ERTS_EV_TYPE_DRV_EV             ((short) 2)
 
43
 
 
44
#define ERTS_DRV_EV_STATE_EXTRA_SIZE 128
 
45
 
 
46
#if defined(ERTS_KERNEL_POLL_VERSION)
 
47
#  define ERTS_CIO_EXPORT(FUNC) FUNC ## _kp
 
48
#elif defined(ERTS_NO_KERNEL_POLL_VERSION)
 
49
#  define ERTS_CIO_EXPORT(FUNC) FUNC ## _nkp
 
50
#else
 
51
#  define ERTS_CIO_EXPORT(FUNC) FUNC
 
52
#endif
 
53
 
 
54
#define ERTS_CIO_HAVE_DRV_EVENT \
 
55
  (ERTS_POLL_USE_POLL && !ERTS_POLL_USE_KERNEL_POLL)
 
56
 
 
57
#define ERTS_CIO_POLL_CTL       ERTS_POLL_EXPORT(erts_poll_control)
 
58
#define ERTS_CIO_POLL_WAIT      ERTS_POLL_EXPORT(erts_poll_wait)
 
59
#define ERTS_CIO_POLL_INTR      ERTS_POLL_EXPORT(erts_poll_interrupt)
 
60
#define ERTS_CIO_NEW_POLLSET    ERTS_POLL_EXPORT(erts_poll_create_pollset)
 
61
#define ERTS_CIO_FREE_POLLSET   ERTS_POLL_EXPORT(erts_poll_destroy_pollset)
 
62
#define ERTS_CIO_POLL_MAX_FDS   ERTS_POLL_EXPORT(erts_poll_max_fds)
 
63
#define ERTS_CIO_POLL_INIT      ERTS_POLL_EXPORT(erts_poll_init)
 
64
#define ERTS_CIO_POLL_INFO      ERTS_POLL_EXPORT(erts_poll_info)
 
65
 
 
66
static ErtsPollSet pollset;
 
67
 
 
68
/*
 
69
 * ErtsDrvEventDataState is used by driver_event() which is almost never
 
70
 * used. We allocate ErtsDrvEventDataState separate since we dont wan't
 
71
 * the size of ErtsDrvEventState to increase due to driver_event()
 
72
 * information.
 
73
 */
 
74
typedef struct {
 
75
    int port;
 
76
    ErlDrvEventData data;
 
77
    ErtsPollEvents removed_events;
 
78
} ErtsDrvEventDataState;
 
79
 
 
80
typedef struct {
 
81
    union {
 
82
        ErtsDrvEventDataState *event;
 
83
        struct {
 
84
            int inport;
 
85
            int outport;
 
86
        } select;
 
87
    } driver;
 
88
    ErtsPollEvents events;
 
89
    short flags;
 
90
    short type;
 
91
} ErtsDrvEventState;
 
92
 
 
93
struct erts_fd_list {
 
94
    struct erts_fd_list *next;
 
95
    int fd;
 
96
};
 
97
 
 
98
static int max_fds = -1;
 
99
static erts_smp_mtx_t drv_ev_state_mtx;
 
100
static int drv_ev_state_len;
 
101
static ErtsDrvEventState *drv_ev_state;
 
102
 
 
103
static erts_smp_atomic_t in_poll_wait;
 
104
 
 
105
struct erts_fd_list *ignored_list;
 
106
 
 
107
static void select_large_fd_error(ErlDrvPort, int, int, int);
 
108
#if ERTS_CIO_HAVE_DRV_EVENT
 
109
static void event_large_fd_error(ErlDrvPort, int, ErlDrvEventData);
 
110
#endif
 
111
 
 
112
 
 
113
ERTS_QUALLOC_IMPL(fd_list, struct erts_fd_list, 64, ERTS_ALC_T_FD_LIST)
 
114
#if ERTS_CIO_HAVE_DRV_EVENT
 
115
ERTS_QUALLOC_IMPL(drv_ev_data, ErtsDrvEventDataState, 16,
 
116
                  ERTS_ALC_T_DRV_EV_D_STATE)
 
117
#endif
 
118
 
 
119
static ERTS_INLINE void
 
120
check_ignore(int fd, ErtsPollEvents new_evs, ErtsPollEvents old_evs)
 
121
{
 
122
 
 
123
    if (!new_evs
 
124
        && old_evs
 
125
        && !(drv_ev_state[fd].flags & ERTS_EV_FLG_IGNORE)
 
126
        && erts_smp_atomic_read(&in_poll_wait)) {
 
127
        struct erts_fd_list *fdlp = fd_list_alloc();
 
128
        fdlp->fd = fd;
 
129
        fdlp->next = ignored_list;
 
130
        ignored_list = fdlp;
 
131
        drv_ev_state[fd].flags |= ERTS_EV_FLG_IGNORE;
 
132
    }
 
133
 
 
134
}
 
135
 
 
136
static ERTS_INLINE void
 
137
reset_ignores(void)
 
138
{
 
139
    struct erts_fd_list *fdlp = ignored_list;
 
140
 
 
141
    while (fdlp) {
 
142
        struct erts_fd_list *ffdlp = fdlp;
 
143
        drv_ev_state[fdlp->fd].flags &= ~ERTS_EV_FLG_IGNORE;
 
144
        fdlp = fdlp->next;
 
145
        fd_list_free(ffdlp);
 
146
    }
 
147
    ignored_list = NULL;
 
148
}
 
149
 
 
150
static void
 
151
grow_drv_ev_state(int min_ix)
 
152
{
 
153
    int i;
 
154
    int new_len = min_ix + 1 + ERTS_DRV_EV_STATE_EXTRA_SIZE;
 
155
    if (new_len > max_fds)
 
156
        new_len = max_fds;
 
157
    drv_ev_state = (drv_ev_state_len
 
158
                     ? erts_realloc(ERTS_ALC_T_DRV_EV_STATE,
 
159
                                    drv_ev_state,
 
160
                                    sizeof(ErtsDrvEventState)*new_len)
 
161
                     : erts_alloc(ERTS_ALC_T_DRV_EV_STATE,
 
162
                                  sizeof(ErtsDrvEventState)*new_len));
 
163
    for (i = drv_ev_state_len; i < new_len; i++) {
 
164
        /* driver_select() depends on inport/outport being < 0
 
165
           when not selected... */
 
166
        drv_ev_state[i].driver.select.inport = -1;
 
167
        drv_ev_state[i].driver.select.outport = -1;
 
168
        drv_ev_state[i].events = 0;
 
169
        drv_ev_state[i].flags = 0;
 
170
        drv_ev_state[i].type = ERTS_EV_TYPE_NONE;
 
171
    }
 
172
    drv_ev_state_len = new_len;
 
173
}
 
174
 
 
175
static void
 
176
deselect(int fd)
 
177
{
 
178
    ErtsPollEvents old_events = drv_ev_state[fd].events;
 
179
    ERTS_SMP_LC_ASSERT(erts_smp_lc_mtx_is_locked(&drv_ev_state_mtx));
 
180
    ASSERT(drv_ev_state[fd].events);
 
181
    drv_ev_state[fd].events
 
182
        = ERTS_CIO_POLL_CTL(pollset, fd, drv_ev_state[fd].events, 0);
 
183
    ASSERT(drv_ev_state[fd].events == 0);
 
184
#if ERTS_CIO_HAVE_DRV_EVENT
 
185
    if (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_EV)
 
186
        drv_ev_data_free(drv_ev_state[fd].driver.event);
 
187
#endif
 
188
    drv_ev_state[fd].type = ERTS_EV_TYPE_NONE;
 
189
    drv_ev_state[fd].flags = 0;
 
190
    /* driver_select() depends on inport/outport being < 0
 
191
       when not selected... */
 
192
    drv_ev_state[fd].driver.select.inport = -1;
 
193
    drv_ev_state[fd].driver.select.outport = -1;
 
194
    check_ignore(fd, (ErtsPollEvents) 0, old_events);
 
195
}
 
196
 
 
197
int
 
198
ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
 
199
                               ErlDrvEvent e,
 
200
                               int mode,
 
201
                               int on)
 
202
{
 
203
    int fd = (int) e;
 
204
    ErtsPollEvents ctl_events = (ErtsPollEvents) 0;
 
205
    ErtsPollEvents new_events, old_events;
 
206
 
 
207
    if (fd < 0)
 
208
        return -1;
 
209
 
 
210
    if (fd >= max_fds) {
 
211
        select_large_fd_error(ix, fd, mode, on);
 
212
        return -1;
 
213
    }
 
214
 
 
215
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
216
 
 
217
    if (fd >= drv_ev_state_len)
 
218
        grow_drv_ev_state(fd);
 
219
 
 
220
#if ERTS_CIO_HAVE_DRV_EVENT
 
221
    if (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_EV)
 
222
        deselect(fd);
 
223
#endif
 
224
 
 
225
    if (mode & DO_READ)
 
226
        ctl_events |= ERTS_POLL_EV_IN;
 
227
    if (mode & DO_WRITE)
 
228
        ctl_events |= ERTS_POLL_EV_OUT;
 
229
 
 
230
    ASSERT(drv_ev_state[fd].events
 
231
           ? (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_SEL)
 
232
           : (drv_ev_state[fd].type == ERTS_EV_TYPE_NONE));
 
233
 
 
234
    new_events = ERTS_CIO_POLL_CTL(pollset, fd, ctl_events, on);
 
235
    if (new_events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL)) {
 
236
        erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
237
        return -1;
 
238
    }
 
239
 
 
240
    old_events = drv_ev_state[fd].events;
 
241
 
 
242
    ASSERT(on
 
243
           ? (new_events == (drv_ev_state[fd].events | ctl_events))
 
244
           : (new_events == (drv_ev_state[fd].events & ~ctl_events)));
 
245
 
 
246
    drv_ev_state[fd].events = new_events;
 
247
    if (on) {
 
248
        drv_ev_state[fd].type = ERTS_EV_TYPE_DRV_SEL;
 
249
        if (ctl_events & ERTS_POLL_EV_IN)
 
250
            drv_ev_state[fd].driver.select.inport = (int) ix;
 
251
        if (ctl_events & ERTS_POLL_EV_OUT)
 
252
            drv_ev_state[fd].driver.select.outport = (int) ix;
 
253
    }
 
254
    else {
 
255
        if (ctl_events & ERTS_POLL_EV_IN)
 
256
            drv_ev_state[fd].driver.select.inport = -1;
 
257
        if (ctl_events & ERTS_POLL_EV_OUT)
 
258
            drv_ev_state[fd].driver.select.outport = -1;
 
259
        if (new_events == 0) {
 
260
            drv_ev_state[fd].flags = 0;
 
261
            drv_ev_state[fd].type = ERTS_EV_TYPE_NONE;
 
262
        }
 
263
    }
 
264
 
 
265
    check_ignore(fd, new_events, old_events);
 
266
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
267
 
 
268
    return 0;
 
269
}
 
270
 
 
271
int
 
272
ERTS_CIO_EXPORT(driver_event)(ErlDrvPort ix,
 
273
                              ErlDrvEvent e,
 
274
                              ErlDrvEventData event_data)
 
275
{
 
276
#if !ERTS_CIO_HAVE_DRV_EVENT
 
277
    return -1;
 
278
#else
 
279
    int fd = (int) e;
 
280
    ErtsPollEvents events;
 
281
    ErtsPollEvents add_events;
 
282
    ErtsPollEvents remove_events;
 
283
 
 
284
   if (fd < 0)
 
285
        return -1;
 
286
 
 
287
    if (fd >= max_fds) {
 
288
        event_large_fd_error(ix, fd, event_data);
 
289
        return -1;
 
290
    }
 
291
 
 
292
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
293
 
 
294
    if (fd >= drv_ev_state_len)
 
295
        grow_drv_ev_state(fd);
 
296
 
 
297
    if (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_SEL)
 
298
        deselect(fd);
 
299
 
 
300
    events = drv_ev_state[fd].events;
 
301
 
 
302
    if (!event_data) {
 
303
        remove_events = events;
 
304
        add_events = 0;
 
305
    }
 
306
    else {
 
307
        remove_events = ~event_data->events & events;
 
308
        add_events = ~events & event_data->events;
 
309
 
 
310
    }
 
311
 
 
312
    if (add_events) {
 
313
        events = ERTS_CIO_POLL_CTL(pollset, fd, add_events, 1);
 
314
        if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL))
 
315
            goto error;
 
316
    }
 
317
    if (remove_events) {
 
318
        events = ERTS_CIO_POLL_CTL(pollset, fd, remove_events, 0);
 
319
        if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL))
 
320
            goto error;
 
321
    }
 
322
    if (event_data) {
 
323
        if (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_EV) {
 
324
            drv_ev_state[fd].driver.event->removed_events &= ~add_events;
 
325
            drv_ev_state[fd].driver.event->removed_events |= remove_events;
 
326
        }
 
327
        else {
 
328
            drv_ev_state[fd].driver.event = drv_ev_data_alloc();
 
329
            drv_ev_state[fd].driver.event->port = ix;
 
330
            drv_ev_state[fd].driver.event->removed_events = (ErtsPollEvents) 0;
 
331
            drv_ev_state[fd].type = ERTS_EV_TYPE_DRV_EV;
 
332
        }
 
333
        drv_ev_state[fd].driver.event->data = event_data;
 
334
    }
 
335
    else {
 
336
        if (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_EV)
 
337
            drv_ev_data_free(drv_ev_state[fd].driver.event);
 
338
        /* driver_select() depends on inport/outport being < 0
 
339
           when not selected... */
 
340
        drv_ev_state[fd].driver.select.inport = -1;
 
341
        drv_ev_state[fd].driver.select.outport = -1;
 
342
        drv_ev_state[fd].flags = 0;
 
343
        drv_ev_state[fd].type = ERTS_EV_TYPE_NONE;
 
344
    }
 
345
    check_ignore(fd, events, drv_ev_state[fd].events);
 
346
    drv_ev_state[fd].events = events;
 
347
    ASSERT(event_data ? events == event_data->events : events == 0); 
 
348
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
349
    return 0;
 
350
 error:
 
351
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
352
    return -1;
 
353
#endif
 
354
}
 
355
 
 
356
 
 
357
static void
 
358
large_fd_error_common(erts_dsprintf_buf_t *dsbufp)
 
359
{
 
360
    erts_dsprintf(dsbufp,
 
361
                  "fd=%d is larger than the largest allowed fd=%d\n",
 
362
                  max_fds - 1);
 
363
}
 
364
 
 
365
static void
 
366
select_error_common(erts_dsprintf_buf_t *dsbufp,
 
367
                    ErlDrvPort ix, int fd, int mode, int on)
 
368
{
 
369
    erts_dsprintf(dsbufp,
 
370
                  "driver_select(%p, %d, %s%s%s, %d) "
 
371
                  "by driver %s port=%T failed: ",
 
372
                  ix,
 
373
                  fd,
 
374
                  mode & DO_READ ? "DO_READ" : "",
 
375
                  (mode & (DO_READ|DO_WRITE)) == (DO_READ|DO_WRITE) ? "|" : "",
 
376
                  mode & DO_WRITE ? "DO_WRITE" : "",
 
377
                  on,
 
378
                  erts_port[(int) ix].drv_ptr->driver_name,
 
379
                  erts_port[(int) ix].id);
 
380
}
 
381
 
 
382
static void
 
383
select_large_fd_error(ErlDrvPort ix, int fd, int mode, int on)
 
384
{
 
385
    erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
 
386
    select_error_common(dsbufp, ix, fd, mode, on);
 
387
    large_fd_error_common(dsbufp);
 
388
    erts_send_error_to_logger_nogl(dsbufp);
 
389
}
 
390
 
 
391
#if ERTS_CIO_HAVE_DRV_EVENT
 
392
 
 
393
static void
 
394
event_error_common(erts_dsprintf_buf_t *dsbufp,
 
395
                   ErlDrvPort ix, int fd, ErlDrvEventData event_data)
 
396
{
 
397
    erts_dsprintf(dsbufp, "driver_event(%p, %d, ", ix, fd);
 
398
    if (!event_data)
 
399
        erts_dsprintf(dsbufp, "NULL");
 
400
    else
 
401
        erts_dsprintf(dsbufp, "{0x%x, 0x%x}",
 
402
                      (unsigned int) event_data->events,
 
403
                      (unsigned int) event_data->revents);
 
404
    erts_dsprintf(dsbufp,
 
405
                  ") by driver %s port=%T failed: ",
 
406
                  erts_port[(int) ix].drv_ptr->driver_name,
 
407
                  erts_port[(int) ix].id);
 
408
}
 
409
 
 
410
static void
 
411
event_large_fd_error(ErlDrvPort ix, int fd, ErlDrvEventData event_data)
 
412
{
 
413
    erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
 
414
    event_error_common(dsbufp, ix, fd, event_data);
 
415
    large_fd_error_common(dsbufp);
 
416
    erts_send_error_to_logger_nogl(dsbufp);
 
417
}
 
418
 
 
419
#endif
 
420
 
 
421
#ifdef ERTS_SMP
 
422
static ERTS_INLINE void
 
423
bump_timers(void)
 
424
{
 
425
#ifndef ERTS_TIMER_THREAD
 
426
    long dt = do_time_read_and_reset();
 
427
    if (dt) {
 
428
        erts_smp_io_unlock();
 
429
        bump_timer(dt);
 
430
        erts_smp_io_lock();
 
431
    }
 
432
#endif
 
433
}
 
434
#endif
 
435
 
 
436
static ERTS_INLINE void
 
437
iready(int ix, int fd)
 
438
{
 
439
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
440
    input_ready(ix, fd);
 
441
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
442
}
 
443
 
 
444
static ERTS_INLINE void
 
445
oready(int ix, int fd)
 
446
{
 
447
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
448
    output_ready(ix, fd);
 
449
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
450
}
 
451
 
 
452
#if ERTS_CIO_HAVE_DRV_EVENT
 
453
 
 
454
static ERTS_INLINE void
 
455
eready(int ix, int fd, ErlDrvEventData event_data)
 
456
{
 
457
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
458
    event_ready(ix, fd, event_data);
 
459
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
460
}
 
461
 
 
462
#endif
 
463
 
 
464
static void bad_fd_in_pollset(int, int, int, short);
 
465
 
 
466
void
 
467
ERTS_CIO_EXPORT(erts_check_io)(int do_wait)
 
468
{
 
469
    ErtsPollResFd pollres[256];
 
470
    int pollres_len;
 
471
    SysTimeval wait_time;
 
472
    int poll_ret, i;
 
473
 
 
474
 restart:
 
475
 
 
476
#ifdef ERTS_SMP
 
477
    ERTS_CIO_POLL_INTR(pollset, 0);
 
478
#endif
 
479
 
 
480
    /* Figure out timeout value */
 
481
    if (do_wait) {
 
482
        erts_time_remaining(&wait_time);
 
483
    } else {                    /* poll only */
 
484
        wait_time.tv_sec = 0;
 
485
        wait_time.tv_usec = 0;
 
486
    }
 
487
 
 
488
 
 
489
    erts_smp_io_unlock();
 
490
 
 
491
#ifdef ERTS_ENABLE_LOCK_CHECK
 
492
    erts_lc_check_exact(NULL, 0); /* No locks should be locked */
 
493
#endif
 
494
    erts_smp_activity_change(ERTS_ACTIVITY_IO,
 
495
                             ERTS_ACTIVITY_WAIT,
 
496
                             NULL,
 
497
                             NULL,
 
498
                             NULL);
 
499
 
 
500
    pollres_len = sizeof(pollres)/sizeof(ErtsPollResFd);
 
501
    erts_smp_atomic_set(&in_poll_wait, 1);
 
502
    poll_ret = ERTS_CIO_POLL_WAIT(pollset, pollres, &pollres_len, &wait_time);
 
503
 
 
504
#ifdef ERTS_ENABLE_LOCK_CHECK
 
505
    erts_lc_check_exact(NULL, 0); /* No locks should be locked */
 
506
#endif
 
507
    erts_smp_activity_change(ERTS_ACTIVITY_WAIT,
 
508
                             ERTS_ACTIVITY_IO,
 
509
                             NULL,
 
510
                             NULL,
 
511
                             NULL);
 
512
    erts_smp_io_lock();
 
513
 
 
514
    erts_deliver_time(); /* sync the machine's idea of time */
 
515
 
 
516
#ifdef ERTS_SMP
 
517
    bump_timers();
 
518
#endif
 
519
 
 
520
    if (erts_break_requested)
 
521
        erts_do_break_handling();
 
522
 
 
523
    if (poll_ret != 0) {
 
524
        erts_smp_atomic_set(&in_poll_wait, 0);
 
525
 
 
526
        if (poll_ret == EAGAIN)
 
527
            goto restart;
 
528
 
 
529
        if (poll_ret != ETIMEDOUT
 
530
            && poll_ret != EINTR
 
531
            && poll_ret != ERRNO_BLOCK) {
 
532
            erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
 
533
            erts_dsprintf(dsbufp, "erts_poll_wait() failed: %s (%d)\n",
 
534
                          erl_errno_id(poll_ret), poll_ret);
 
535
            erts_send_error_to_logger_nogl(dsbufp);
 
536
        }
 
537
 
 
538
        return;
 
539
    }
 
540
 
 
541
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
542
    erts_smp_atomic_set(&in_poll_wait, 0);
 
543
 
 
544
    for (i = 0; i < pollres_len; i++) {
 
545
        int fd = pollres[i].fd;
 
546
 
 
547
        if (drv_ev_state[fd].flags & ERTS_EV_FLG_IGNORE)
 
548
            continue;
 
549
 
 
550
        switch (drv_ev_state[fd].type) {
 
551
        case ERTS_EV_TYPE_DRV_SEL: { /* Requested via driver_select()... */
 
552
            ErtsPollEvents revents;
 
553
            ErtsPollEvents revent_mask;
 
554
 
 
555
            revent_mask = ~(ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT);
 
556
            revent_mask |= drv_ev_state[fd].events;
 
557
            revents = pollres[i].events & revent_mask;
 
558
 
 
559
            if (revents & ERTS_POLL_EV_ERR) {
 
560
                /*
 
561
                 * Let the driver handle the error condition. Only input,
 
562
                 * only output, or nothing might have been selected.
 
563
                 * We *do not* want to call a callback that corresponds
 
564
                 * to an event not selected. revents might give us a clue
 
565
                 * on which one to call.
 
566
                 */ 
 
567
                if ((revents & ERTS_POLL_EV_IN)
 
568
                    || (!(revents & ERTS_POLL_EV_OUT)
 
569
                        && drv_ev_state[fd].events & ERTS_POLL_EV_IN))
 
570
                    iready(drv_ev_state[fd].driver.select.inport, fd);
 
571
                else if (drv_ev_state[fd].events & ERTS_POLL_EV_OUT)
 
572
                    oready(drv_ev_state[fd].driver.select.outport, fd);
 
573
            }
 
574
            else if (revents & (ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) {
 
575
                if (revents & ERTS_POLL_EV_OUT)
 
576
                    oready(drv_ev_state[fd].driver.select.outport, fd);
 
577
                /* Someone might have deselected input since revents
 
578
                   was read (true also on the non-smp emulator since
 
579
                   oready() may have been called); therefore, update
 
580
                   revents... */
 
581
                revents &= ~(~drv_ev_state[fd].events & ERTS_POLL_EV_IN);
 
582
                if (revents & ERTS_POLL_EV_IN)
 
583
                    iready(drv_ev_state[fd].driver.select.inport, fd);
 
584
            }
 
585
            else if (revents & ERTS_POLL_EV_NVAL) {
 
586
                bad_fd_in_pollset(fd,
 
587
                                  drv_ev_state[fd].driver.select.inport,
 
588
                                  drv_ev_state[fd].driver.select.outport,
 
589
                                  drv_ev_state[fd].events);
 
590
            }
 
591
            break;
 
592
        }
 
593
 
 
594
#if ERTS_CIO_HAVE_DRV_EVENT
 
595
        case ERTS_EV_TYPE_DRV_EV: { /* Requested via driver_event()... */
 
596
            ErlDrvEventData event_data = drv_ev_state[fd].driver.event->data;
 
597
            ErtsPollEvents revents;
 
598
            ASSERT(drv_ev_state[fd].driver.event);
 
599
            ASSERT(drv_ev_state[fd].driver.event->data);
 
600
            revents = pollres[i].events;
 
601
            revents &= ~drv_ev_state[fd].driver.event->removed_events;
 
602
 
 
603
            if (revents) {
 
604
                event_data->events = drv_ev_state[fd].events;
 
605
                event_data->revents = revents;
 
606
 
 
607
                eready(drv_ev_state[fd].driver.event->port, fd, event_data);
 
608
            }
 
609
            break;
 
610
        }
 
611
#endif
 
612
 
 
613
        case ERTS_EV_TYPE_NONE: /* Deselected ... */
 
614
            break;
 
615
 
 
616
        default: { /* Error */
 
617
            erts_dsprintf_buf_t *dsbufp;
 
618
            dsbufp = erts_create_logger_dsbuf();
 
619
            erts_dsprintf(dsbufp,
 
620
                          "Invalid event request type for fd in erts_poll()! "
 
621
                          "fd=%d, event request type=%sd\n", fd,
 
622
                          (int) drv_ev_state[fd].type);
 
623
            ASSERT(0);
 
624
            deselect(fd);
 
625
            break;
 
626
        }
 
627
        }
 
628
 
 
629
    }
 
630
 
 
631
    reset_ignores();
 
632
 
 
633
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
634
}
 
635
 
 
636
static void
 
637
bad_fd_in_pollset(int fd, int inport, int outport, short events)
 
638
{
 
639
    erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
 
640
 
 
641
    if (events & (ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) {
 
642
        char *io_str;
 
643
        int port;
 
644
        int both = 0;
 
645
        if ((events & ERTS_POLL_EV_IN) && (events & ERTS_POLL_EV_OUT)) {
 
646
            io_str = "input/output";
 
647
            port = -1;
 
648
            both = 1;
 
649
        }
 
650
        if (events & ERTS_POLL_EV_IN) {
 
651
            io_str = "input";
 
652
            port = inport;
 
653
        }
 
654
        else {
 
655
            io_str = "output";
 
656
            port = outport;
 
657
        }
 
658
        erts_dsprintf(dsbufp,
 
659
                      "Bad %s fd in erts_poll()! fd=%d, ",
 
660
                      io_str, fd);
 
661
        if (port < 0)
 
662
            erts_dsprintf(dsbufp, "ports=%T/%T",
 
663
                          inport >= 0 ? erts_port[inport].id : am_undefined,
 
664
                          outport >= 0 ? erts_port[outport].id : am_undefined);
 
665
        else
 
666
            erts_dsprintf(dsbufp, "port=%T",
 
667
                          port >= 0 ? erts_port[port].id : am_undefined);
 
668
        erts_dsprintf(dsbufp, ", driver=%s, name=%s\n",
 
669
                      erts_port[port].drv_ptr->driver_name,
 
670
                      erts_port[port].name);
 
671
    }
 
672
    else {
 
673
        erts_dsprintf(dsbufp, "Bad fd in erts_poll()! fd=%d\n", fd);
 
674
    }
 
675
    erts_send_error_to_logger_nogl(dsbufp);
 
676
 
 
677
    /* unmap entry */
 
678
    deselect(fd);
 
679
}
 
680
 
 
681
void
 
682
ERTS_CIO_EXPORT(erts_init_check_io)(void)
 
683
{
 
684
    init_fd_list_alloc();
 
685
    ignored_list = NULL;
 
686
    erts_smp_atomic_init(&in_poll_wait, 0);
 
687
    ERTS_CIO_POLL_INIT();
 
688
    max_fds = ERTS_CIO_POLL_MAX_FDS();
 
689
    pollset = ERTS_CIO_NEW_POLLSET();
 
690
    erts_smp_mtx_init(&drv_ev_state_mtx, "drv_ev_state");
 
691
    drv_ev_state_len = 0;
 
692
    drv_ev_state = NULL;
 
693
#if ERTS_CIO_HAVE_DRV_EVENT
 
694
    init_drv_ev_data_alloc();
 
695
#endif
 
696
}
 
697
 
 
698
int
 
699
ERTS_CIO_EXPORT(erts_check_io_max_files)(void)
 
700
{
 
701
    return max_fds;
 
702
}
 
703
 
 
704
Uint
 
705
ERTS_CIO_EXPORT(erts_check_io_size)(void)
 
706
{
 
707
    Uint res;
 
708
    ErtsPollInfo pi;
 
709
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
710
    ERTS_CIO_POLL_INFO(pollset, &pi);
 
711
    res = pi.memory_size;
 
712
    res += sizeof(ErtsDrvEventState)*drv_ev_state_len;
 
713
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
714
    return res;
 
715
}
 
716
 
 
717
Eterm
 
718
ERTS_CIO_EXPORT(erts_check_io_info)(void *proc)
 
719
{
 
720
    Process *p = (Process *) proc;
 
721
    Eterm tags[12], values[12], res;
 
722
    Uint sz, *szp, *hp, **hpp, memory_size;
 
723
    Sint i;
 
724
    ErtsPollInfo pi;
 
725
 
 
726
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
727
    ERTS_CIO_POLL_INFO(pollset, &pi);
 
728
    memory_size = pi.memory_size;
 
729
    memory_size += sizeof(ErtsDrvEventState)*drv_ev_state_len;
 
730
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
731
 
 
732
    hpp = NULL;
 
733
    szp = &sz;
 
734
    sz = 0;
 
735
 
 
736
 bld_it:
 
737
    i = 0;
 
738
 
 
739
    tags[i] = erts_bld_atom(hpp, szp, "name");
 
740
    values[i++] = erts_bld_atom(hpp, szp, "erts_poll");
 
741
 
 
742
    tags[i] = erts_bld_atom(hpp, szp, "primary");
 
743
    values[i++] = erts_bld_atom(hpp, szp, pi.primary);
 
744
 
 
745
    tags[i] = erts_bld_atom(hpp, szp, "fallback");
 
746
    values[i++] = erts_bld_atom(hpp, szp, pi.fallback ? pi.fallback : "false");
 
747
 
 
748
    tags[i] = erts_bld_atom(hpp, szp, "kernel_poll");
 
749
    values[i++] = erts_bld_atom(hpp, szp,
 
750
                                pi.kernel_poll ? pi.kernel_poll : "false");
 
751
 
 
752
    tags[i] = erts_bld_atom(hpp, szp, "memory_size");
 
753
    values[i++] = erts_bld_uint(hpp, szp, memory_size);
 
754
 
 
755
    tags[i] = erts_bld_atom(hpp, szp, "total_poll_set_size");
 
756
    values[i++] = erts_bld_uint(hpp, szp, (Uint) pi.poll_set_size);
 
757
 
 
758
    if (pi.fallback) {
 
759
        tags[i] = erts_bld_atom(hpp, szp, "fallback_poll_set_size");
 
760
        values[i++] = erts_bld_uint(hpp, szp, (Uint) pi.fallback_poll_set_size);
 
761
    }
 
762
 
 
763
    tags[i] = erts_bld_atom(hpp, szp, "lazy_updates");
 
764
    values[i++] = pi.lazy_updates ? am_true : am_false;
 
765
 
 
766
    if (pi.lazy_updates) {
 
767
        tags[i] = erts_bld_atom(hpp, szp, "pending_updates");
 
768
        values[i++] = erts_bld_uint(hpp, szp, (Uint) pi.pending_updates);
 
769
    }
 
770
 
 
771
    tags[i] = erts_bld_atom(hpp, szp, "batch_updates");
 
772
    values[i++] = pi.batch_updates ? am_true : am_false;
 
773
 
 
774
    tags[i] = erts_bld_atom(hpp, szp, "concurrent_updates");
 
775
    values[i++] = pi.concurrent_updates ? am_true : am_false;
 
776
 
 
777
    tags[i] = erts_bld_atom(hpp, szp, "max_fds");
 
778
    values[i++] = erts_bld_uint(hpp, szp, (Uint) pi.max_fds);
 
779
 
 
780
    res = erts_bld_2tup_list(hpp, szp, i, tags, values);
 
781
 
 
782
    if (!hpp) {
 
783
        hp = HAlloc(p, sz);
 
784
        hpp = &hp;
 
785
        szp = NULL;
 
786
        goto bld_it;
 
787
    }
 
788
 
 
789
    return res;
 
790
}
 
791
 
 
792
static ERTS_INLINE ErtsPollEvents
 
793
print_events(ErtsPollEvents ev)
 
794
{
 
795
    int first = 1;
 
796
    if(ev & ERTS_POLL_EV_IN) {
 
797
        ev &= ~ERTS_POLL_EV_IN;
 
798
        erts_printf("%s%s", first ? "" : "|", "IN");
 
799
        first = 0;
 
800
    }
 
801
    if(ev & ERTS_POLL_EV_OUT) {
 
802
        ev &= ~ERTS_POLL_EV_OUT;
 
803
        erts_printf("%s%s", first ? "" : "|", "OUT");
 
804
        first = 0;
 
805
    }
 
806
    /* The following should not appear... */
 
807
    if(ev & ERTS_POLL_EV_NVAL) {
 
808
        erts_printf("%s%s", first ? "" : "|", "NVAL");
 
809
        first = 0;
 
810
    }
 
811
    if(ev & ERTS_POLL_EV_ERR) {
 
812
        erts_printf("%s%s", first ? "" : "|", "ERR");
 
813
        first = 0;
 
814
    }
 
815
    if(ev & ERTS_POLL_EV_1SHOT) {
 
816
        erts_printf("%s%s", first ? "" : "|", "1SHOT");
 
817
        first = 0;
 
818
    }
 
819
    if(ev & ERTS_POLL_EV_FULL_1SHOT) {
 
820
        erts_printf("%s%s", first ? "" : "|", "FULL_1SHOT");
 
821
        first = 0;
 
822
    }
 
823
    if (ev)
 
824
        erts_printf("%s0x%b32x", first ? "" : "|", (Uint32) ev);
 
825
    return ev;
 
826
}
 
827
 
 
828
int
 
829
ERTS_CIO_EXPORT(erts_check_io_debug)(void)
 
830
{
 
831
    int res = 0;
 
832
    int fd;
 
833
    int used_fds = 0;
 
834
    int internal_fds = 0;
 
835
    ErtsPollEvents *epep;
 
836
    ErtsDrvEventState null_des;
 
837
 
 
838
    null_des.driver.select.inport = -1;
 
839
    null_des.driver.select.outport = -1;
 
840
    null_des.events = 0;
 
841
    null_des.flags = 0;
 
842
    null_des.type = ERTS_EV_TYPE_NONE;
 
843
 
 
844
    erts_smp_mtx_lock(&drv_ev_state_mtx);
 
845
 
 
846
    erts_printf("--- fds in pollset --------------------------------------\n");
 
847
 
 
848
    epep = erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsPollEvents)*max_fds);
 
849
 
 
850
    ERTS_POLL_EXPORT(erts_poll_get_selected_events)(pollset, epep, max_fds);
 
851
 
 
852
    for (fd = 0; fd < max_fds; fd++) {
 
853
        int err = 0;
 
854
        ErtsDrvEventState *desp = ((fd < drv_ev_state_len)
 
855
                                   ? &drv_ev_state[fd]
 
856
                                   : &null_des);
 
857
        ErtsPollEvents cio_events = desp->events;
 
858
        ErtsPollEvents ep_events = epep[fd];
 
859
        int internal = 0;
 
860
#ifdef HAVE_FSTAT
 
861
        struct stat stat_buf;
 
862
#endif
 
863
 
 
864
        if (desp->events || ep_events) {
 
865
            if (ep_events & ERTS_POLL_EV_NVAL) {
 
866
                ep_events &= ~ERTS_POLL_EV_NVAL;
 
867
                internal = 1;
 
868
                internal_fds++;
 
869
            }
 
870
            else
 
871
                used_fds++;
 
872
 
 
873
            erts_printf("fd=%d ", fd);
 
874
 
 
875
#ifdef HAVE_FSTAT
 
876
            if (fstat(fd, &stat_buf) < 0)
 
877
                erts_printf("type=unknown ");
 
878
            else {
 
879
                erts_printf("type=");
 
880
#ifdef S_ISSOCK
 
881
                if (S_ISSOCK(stat_buf.st_mode))
 
882
                    erts_printf("sock ");
 
883
                else
 
884
#endif
 
885
#ifdef S_ISFIFO
 
886
                if (S_ISFIFO(stat_buf.st_mode))
 
887
                    erts_printf("fifo ");
 
888
                else
 
889
#endif
 
890
#ifdef S_ISCHR
 
891
                if (S_ISCHR(stat_buf.st_mode))
 
892
                    erts_printf("chr ");
 
893
                else
 
894
#endif
 
895
#ifdef S_ISDIR
 
896
                if (S_ISDIR(stat_buf.st_mode))
 
897
                    erts_printf("dir ");
 
898
                else
 
899
#endif
 
900
#ifdef S_ISBLK
 
901
                if (S_ISBLK(stat_buf.st_mode))
 
902
                    erts_printf("blk ");
 
903
                else
 
904
#endif
 
905
#ifdef S_ISREG
 
906
                if (S_ISREG(stat_buf.st_mode))
 
907
                    erts_printf("reg ");
 
908
                else
 
909
#endif
 
910
#ifdef S_ISLNK
 
911
                if (S_ISLNK(stat_buf.st_mode))
 
912
                    erts_printf("lnk ");
 
913
                else
 
914
#endif
 
915
#ifdef S_ISDOOR
 
916
                if (S_ISDOOR(stat_buf.st_mode))
 
917
                    erts_printf("door ");
 
918
                else
 
919
#endif
 
920
#ifdef S_ISWHT
 
921
                if (S_ISWHT(stat_buf.st_mode))
 
922
                    erts_printf("wht ");
 
923
                else
 
924
#endif
 
925
#ifdef S_ISXATTR
 
926
                if (S_ISXATTR(stat_buf.st_mode))
 
927
                    erts_printf("xattr ");
 
928
                else
 
929
#endif
 
930
                    erts_printf("unknown ");
 
931
            }
 
932
#endif
 
933
 
 
934
            if (desp->type == ERTS_EV_TYPE_DRV_SEL) {
 
935
                erts_printf("driver_select ");
 
936
                
 
937
                if (internal) {
 
938
                    erts_printf("internal ");
 
939
                    err = 1;                
 
940
                }
 
941
 
 
942
                if (cio_events == ep_events) {
 
943
                    erts_printf("ev=");
 
944
                    if (print_events(cio_events) != 0)
 
945
                        err = 1;
 
946
                }
 
947
                else {
 
948
                    err = 1;
 
949
                    erts_printf("cio_ev=");
 
950
                    print_events(cio_events);
 
951
                    erts_printf(" ep_ev=");
 
952
                    print_events(ep_events);
 
953
                }
 
954
                erts_printf(" ");
 
955
                if (cio_events & ERTS_POLL_EV_IN) {
 
956
                    int ix = desp->driver.select.inport;
 
957
                    if (ix < 0) {
 
958
                        erts_printf("inport=none indrv=none ");
 
959
                        err = 1;
 
960
                    }
 
961
                    else {
 
962
                        erts_printf("inport=%T indrv=%s ",
 
963
                                   erts_port[ix].id,
 
964
                                   erts_port[ix].drv_ptr->driver_name);
 
965
                    }
 
966
                }
 
967
                if (cio_events & ERTS_POLL_EV_OUT) {
 
968
                    int ix = desp->driver.select.outport;
 
969
                    if (ix < 0) {
 
970
                        erts_printf("outport=none outdrv=none ");
 
971
                        err = 1;
 
972
                    }
 
973
                    else {
 
974
                        erts_printf("outport=%T outdrv=%s ",
 
975
                                   erts_port[ix].id,
 
976
                                   erts_port[ix].drv_ptr->driver_name);
 
977
                    }
 
978
                }
 
979
            }
 
980
            else if (desp->type == ERTS_EV_TYPE_DRV_EV) {
 
981
                int ix;
 
982
                erts_printf("driver_event ");
 
983
                if (internal) {
 
984
                    erts_printf("internal ");
 
985
                    err = 1;                
 
986
                }
 
987
                if (cio_events == ep_events) {
 
988
                    erts_printf("ev=0x%b32x", (Uint32) cio_events);
 
989
                }
 
990
                else {
 
991
                    err = 1;
 
992
                    erts_printf("cio_ev=0x%b32x", (Uint32) cio_events);
 
993
                    erts_printf(" ep_ev=0x%b32x", (Uint32) ep_events);
 
994
                }
 
995
                ix = desp->driver.event->port;
 
996
                if (ix < 0) {
 
997
                    erts_printf(" port=none drv=none ");
 
998
                    err = 1;
 
999
                }
 
1000
                else {
 
1001
                    erts_printf(" port=%T drv=%s ",
 
1002
                               erts_port[ix].id,
 
1003
                               erts_port[ix].drv_ptr->driver_name);
 
1004
                }
 
1005
            }
 
1006
            else if (internal) {
 
1007
                erts_printf("internal ");
 
1008
                if (cio_events) {
 
1009
                    err = 1;
 
1010
                    erts_printf("cio_ev=");
 
1011
                    print_events(cio_events);
 
1012
                }
 
1013
                if (ep_events) {
 
1014
                    erts_printf("ep_ev=");
 
1015
                    print_events(ep_events);
 
1016
                }
 
1017
            }
 
1018
            else {
 
1019
                err = 1;
 
1020
                erts_printf("control_type=%d ", desp->type);
 
1021
                if (cio_events == ep_events) {
 
1022
                    erts_printf("ev=0x%b32x", (Uint32) cio_events);
 
1023
                }
 
1024
                else {
 
1025
                    erts_printf("cio_ev=0x%b32x", (Uint32) cio_events);
 
1026
                    erts_printf(" ep_ev=0x%b32x", (Uint32) ep_events);
 
1027
                }
 
1028
            }
 
1029
 
 
1030
            if (err) {
 
1031
                res++;
 
1032
                erts_printf(" ERROR");
 
1033
            }
 
1034
            erts_printf("\n");
 
1035
        }
 
1036
    }
 
1037
    erts_printf("\n");
 
1038
    erts_printf("used fds=%d\n", used_fds);
 
1039
    erts_printf("internal fds=%d\n", internal_fds);
 
1040
    erts_printf("---------------------------------------------------------\n");
 
1041
    fflush(stdout);
 
1042
    erts_free(ERTS_ALC_T_TMP, (void *) epep);
 
1043
    erts_smp_mtx_unlock(&drv_ev_state_mtx);
 
1044
    return res;
 
1045
}
 
1046
 
 
1047
 
 
1048
#ifdef ERTS_SMP
 
1049
 
 
1050
void
 
1051
ERTS_CIO_EXPORT(erts_wake_io_thread)(void)
 
1052
{
 
1053
    ERTS_CIO_POLL_INTR(pollset, 1);
 
1054
}
 
1055
 
 
1056
#endif /* #ifdef ERTS_SMP */