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/.
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
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.''
20
* Description: Check I/O
22
* Author: Rickard Green
29
#define ERTS_WANT_BREAK_HANDLING
30
#define WANT_NONBLOCKING
33
#include "erl_driver.h"
35
#include "erl_check_io.h"
36
#include "erl_alloc.h"
38
#define ERTS_EV_FLG_IGNORE (((short) 1) << 0)
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)
44
#define ERTS_DRV_EV_STATE_EXTRA_SIZE 128
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
51
# define ERTS_CIO_EXPORT(FUNC) FUNC
54
#define ERTS_CIO_HAVE_DRV_EVENT \
55
(ERTS_POLL_USE_POLL && !ERTS_POLL_USE_KERNEL_POLL)
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)
66
static ErtsPollSet pollset;
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()
77
ErtsPollEvents removed_events;
78
} ErtsDrvEventDataState;
82
ErtsDrvEventDataState *event;
88
ErtsPollEvents events;
94
struct erts_fd_list *next;
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;
103
static erts_smp_atomic_t in_poll_wait;
105
struct erts_fd_list *ignored_list;
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);
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)
119
static ERTS_INLINE void
120
check_ignore(int fd, ErtsPollEvents new_evs, ErtsPollEvents 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();
129
fdlp->next = ignored_list;
131
drv_ev_state[fd].flags |= ERTS_EV_FLG_IGNORE;
136
static ERTS_INLINE void
139
struct erts_fd_list *fdlp = ignored_list;
142
struct erts_fd_list *ffdlp = fdlp;
143
drv_ev_state[fdlp->fd].flags &= ~ERTS_EV_FLG_IGNORE;
151
grow_drv_ev_state(int min_ix)
154
int new_len = min_ix + 1 + ERTS_DRV_EV_STATE_EXTRA_SIZE;
155
if (new_len > max_fds)
157
drv_ev_state = (drv_ev_state_len
158
? erts_realloc(ERTS_ALC_T_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;
172
drv_ev_state_len = new_len;
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);
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);
198
ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix,
204
ErtsPollEvents ctl_events = (ErtsPollEvents) 0;
205
ErtsPollEvents new_events, old_events;
211
select_large_fd_error(ix, fd, mode, on);
215
erts_smp_mtx_lock(&drv_ev_state_mtx);
217
if (fd >= drv_ev_state_len)
218
grow_drv_ev_state(fd);
220
#if ERTS_CIO_HAVE_DRV_EVENT
221
if (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_EV)
226
ctl_events |= ERTS_POLL_EV_IN;
228
ctl_events |= ERTS_POLL_EV_OUT;
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));
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);
240
old_events = drv_ev_state[fd].events;
243
? (new_events == (drv_ev_state[fd].events | ctl_events))
244
: (new_events == (drv_ev_state[fd].events & ~ctl_events)));
246
drv_ev_state[fd].events = new_events;
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;
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;
265
check_ignore(fd, new_events, old_events);
266
erts_smp_mtx_unlock(&drv_ev_state_mtx);
272
ERTS_CIO_EXPORT(driver_event)(ErlDrvPort ix,
274
ErlDrvEventData event_data)
276
#if !ERTS_CIO_HAVE_DRV_EVENT
280
ErtsPollEvents events;
281
ErtsPollEvents add_events;
282
ErtsPollEvents remove_events;
288
event_large_fd_error(ix, fd, event_data);
292
erts_smp_mtx_lock(&drv_ev_state_mtx);
294
if (fd >= drv_ev_state_len)
295
grow_drv_ev_state(fd);
297
if (drv_ev_state[fd].type == ERTS_EV_TYPE_DRV_SEL)
300
events = drv_ev_state[fd].events;
303
remove_events = events;
307
remove_events = ~event_data->events & events;
308
add_events = ~events & event_data->events;
313
events = ERTS_CIO_POLL_CTL(pollset, fd, add_events, 1);
314
if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL))
318
events = ERTS_CIO_POLL_CTL(pollset, fd, remove_events, 0);
319
if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL))
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;
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;
333
drv_ev_state[fd].driver.event->data = event_data;
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;
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);
351
erts_smp_mtx_unlock(&drv_ev_state_mtx);
358
large_fd_error_common(erts_dsprintf_buf_t *dsbufp)
360
erts_dsprintf(dsbufp,
361
"fd=%d is larger than the largest allowed fd=%d\n",
366
select_error_common(erts_dsprintf_buf_t *dsbufp,
367
ErlDrvPort ix, int fd, int mode, int on)
369
erts_dsprintf(dsbufp,
370
"driver_select(%p, %d, %s%s%s, %d) "
371
"by driver %s port=%T failed: ",
374
mode & DO_READ ? "DO_READ" : "",
375
(mode & (DO_READ|DO_WRITE)) == (DO_READ|DO_WRITE) ? "|" : "",
376
mode & DO_WRITE ? "DO_WRITE" : "",
378
erts_port[(int) ix].drv_ptr->driver_name,
379
erts_port[(int) ix].id);
383
select_large_fd_error(ErlDrvPort ix, int fd, int mode, int on)
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);
391
#if ERTS_CIO_HAVE_DRV_EVENT
394
event_error_common(erts_dsprintf_buf_t *dsbufp,
395
ErlDrvPort ix, int fd, ErlDrvEventData event_data)
397
erts_dsprintf(dsbufp, "driver_event(%p, %d, ", ix, fd);
399
erts_dsprintf(dsbufp, "NULL");
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);
411
event_large_fd_error(ErlDrvPort ix, int fd, ErlDrvEventData event_data)
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);
422
static ERTS_INLINE void
425
#ifndef ERTS_TIMER_THREAD
426
long dt = do_time_read_and_reset();
428
erts_smp_io_unlock();
436
static ERTS_INLINE void
437
iready(int ix, int fd)
439
erts_smp_mtx_unlock(&drv_ev_state_mtx);
441
erts_smp_mtx_lock(&drv_ev_state_mtx);
444
static ERTS_INLINE void
445
oready(int ix, int fd)
447
erts_smp_mtx_unlock(&drv_ev_state_mtx);
448
output_ready(ix, fd);
449
erts_smp_mtx_lock(&drv_ev_state_mtx);
452
#if ERTS_CIO_HAVE_DRV_EVENT
454
static ERTS_INLINE void
455
eready(int ix, int fd, ErlDrvEventData event_data)
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);
464
static void bad_fd_in_pollset(int, int, int, short);
467
ERTS_CIO_EXPORT(erts_check_io)(int do_wait)
469
ErtsPollResFd pollres[256];
471
SysTimeval wait_time;
477
ERTS_CIO_POLL_INTR(pollset, 0);
480
/* Figure out timeout value */
482
erts_time_remaining(&wait_time);
483
} else { /* poll only */
484
wait_time.tv_sec = 0;
485
wait_time.tv_usec = 0;
489
erts_smp_io_unlock();
491
#ifdef ERTS_ENABLE_LOCK_CHECK
492
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
494
erts_smp_activity_change(ERTS_ACTIVITY_IO,
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);
504
#ifdef ERTS_ENABLE_LOCK_CHECK
505
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
507
erts_smp_activity_change(ERTS_ACTIVITY_WAIT,
514
erts_deliver_time(); /* sync the machine's idea of time */
520
if (erts_break_requested)
521
erts_do_break_handling();
524
erts_smp_atomic_set(&in_poll_wait, 0);
526
if (poll_ret == EAGAIN)
529
if (poll_ret != ETIMEDOUT
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);
541
erts_smp_mtx_lock(&drv_ev_state_mtx);
542
erts_smp_atomic_set(&in_poll_wait, 0);
544
for (i = 0; i < pollres_len; i++) {
545
int fd = pollres[i].fd;
547
if (drv_ev_state[fd].flags & ERTS_EV_FLG_IGNORE)
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;
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;
559
if (revents & ERTS_POLL_EV_ERR) {
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.
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);
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
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);
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);
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;
604
event_data->events = drv_ev_state[fd].events;
605
event_data->revents = revents;
607
eready(drv_ev_state[fd].driver.event->port, fd, event_data);
613
case ERTS_EV_TYPE_NONE: /* Deselected ... */
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);
633
erts_smp_mtx_unlock(&drv_ev_state_mtx);
637
bad_fd_in_pollset(int fd, int inport, int outport, short events)
639
erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
641
if (events & (ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) {
645
if ((events & ERTS_POLL_EV_IN) && (events & ERTS_POLL_EV_OUT)) {
646
io_str = "input/output";
650
if (events & ERTS_POLL_EV_IN) {
658
erts_dsprintf(dsbufp,
659
"Bad %s fd in erts_poll()! fd=%d, ",
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);
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);
673
erts_dsprintf(dsbufp, "Bad fd in erts_poll()! fd=%d\n", fd);
675
erts_send_error_to_logger_nogl(dsbufp);
682
ERTS_CIO_EXPORT(erts_init_check_io)(void)
684
init_fd_list_alloc();
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;
693
#if ERTS_CIO_HAVE_DRV_EVENT
694
init_drv_ev_data_alloc();
699
ERTS_CIO_EXPORT(erts_check_io_max_files)(void)
705
ERTS_CIO_EXPORT(erts_check_io_size)(void)
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);
718
ERTS_CIO_EXPORT(erts_check_io_info)(void *proc)
720
Process *p = (Process *) proc;
721
Eterm tags[12], values[12], res;
722
Uint sz, *szp, *hp, **hpp, memory_size;
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);
739
tags[i] = erts_bld_atom(hpp, szp, "name");
740
values[i++] = erts_bld_atom(hpp, szp, "erts_poll");
742
tags[i] = erts_bld_atom(hpp, szp, "primary");
743
values[i++] = erts_bld_atom(hpp, szp, pi.primary);
745
tags[i] = erts_bld_atom(hpp, szp, "fallback");
746
values[i++] = erts_bld_atom(hpp, szp, pi.fallback ? pi.fallback : "false");
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");
752
tags[i] = erts_bld_atom(hpp, szp, "memory_size");
753
values[i++] = erts_bld_uint(hpp, szp, memory_size);
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);
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);
763
tags[i] = erts_bld_atom(hpp, szp, "lazy_updates");
764
values[i++] = pi.lazy_updates ? am_true : am_false;
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);
771
tags[i] = erts_bld_atom(hpp, szp, "batch_updates");
772
values[i++] = pi.batch_updates ? am_true : am_false;
774
tags[i] = erts_bld_atom(hpp, szp, "concurrent_updates");
775
values[i++] = pi.concurrent_updates ? am_true : am_false;
777
tags[i] = erts_bld_atom(hpp, szp, "max_fds");
778
values[i++] = erts_bld_uint(hpp, szp, (Uint) pi.max_fds);
780
res = erts_bld_2tup_list(hpp, szp, i, tags, values);
792
static ERTS_INLINE ErtsPollEvents
793
print_events(ErtsPollEvents ev)
796
if(ev & ERTS_POLL_EV_IN) {
797
ev &= ~ERTS_POLL_EV_IN;
798
erts_printf("%s%s", first ? "" : "|", "IN");
801
if(ev & ERTS_POLL_EV_OUT) {
802
ev &= ~ERTS_POLL_EV_OUT;
803
erts_printf("%s%s", first ? "" : "|", "OUT");
806
/* The following should not appear... */
807
if(ev & ERTS_POLL_EV_NVAL) {
808
erts_printf("%s%s", first ? "" : "|", "NVAL");
811
if(ev & ERTS_POLL_EV_ERR) {
812
erts_printf("%s%s", first ? "" : "|", "ERR");
815
if(ev & ERTS_POLL_EV_1SHOT) {
816
erts_printf("%s%s", first ? "" : "|", "1SHOT");
819
if(ev & ERTS_POLL_EV_FULL_1SHOT) {
820
erts_printf("%s%s", first ? "" : "|", "FULL_1SHOT");
824
erts_printf("%s0x%b32x", first ? "" : "|", (Uint32) ev);
829
ERTS_CIO_EXPORT(erts_check_io_debug)(void)
834
int internal_fds = 0;
835
ErtsPollEvents *epep;
836
ErtsDrvEventState null_des;
838
null_des.driver.select.inport = -1;
839
null_des.driver.select.outport = -1;
842
null_des.type = ERTS_EV_TYPE_NONE;
844
erts_smp_mtx_lock(&drv_ev_state_mtx);
846
erts_printf("--- fds in pollset --------------------------------------\n");
848
epep = erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsPollEvents)*max_fds);
850
ERTS_POLL_EXPORT(erts_poll_get_selected_events)(pollset, epep, max_fds);
852
for (fd = 0; fd < max_fds; fd++) {
854
ErtsDrvEventState *desp = ((fd < drv_ev_state_len)
857
ErtsPollEvents cio_events = desp->events;
858
ErtsPollEvents ep_events = epep[fd];
861
struct stat stat_buf;
864
if (desp->events || ep_events) {
865
if (ep_events & ERTS_POLL_EV_NVAL) {
866
ep_events &= ~ERTS_POLL_EV_NVAL;
873
erts_printf("fd=%d ", fd);
876
if (fstat(fd, &stat_buf) < 0)
877
erts_printf("type=unknown ");
879
erts_printf("type=");
881
if (S_ISSOCK(stat_buf.st_mode))
882
erts_printf("sock ");
886
if (S_ISFIFO(stat_buf.st_mode))
887
erts_printf("fifo ");
891
if (S_ISCHR(stat_buf.st_mode))
896
if (S_ISDIR(stat_buf.st_mode))
901
if (S_ISBLK(stat_buf.st_mode))
906
if (S_ISREG(stat_buf.st_mode))
911
if (S_ISLNK(stat_buf.st_mode))
916
if (S_ISDOOR(stat_buf.st_mode))
917
erts_printf("door ");
921
if (S_ISWHT(stat_buf.st_mode))
926
if (S_ISXATTR(stat_buf.st_mode))
927
erts_printf("xattr ");
930
erts_printf("unknown ");
934
if (desp->type == ERTS_EV_TYPE_DRV_SEL) {
935
erts_printf("driver_select ");
938
erts_printf("internal ");
942
if (cio_events == ep_events) {
944
if (print_events(cio_events) != 0)
949
erts_printf("cio_ev=");
950
print_events(cio_events);
951
erts_printf(" ep_ev=");
952
print_events(ep_events);
955
if (cio_events & ERTS_POLL_EV_IN) {
956
int ix = desp->driver.select.inport;
958
erts_printf("inport=none indrv=none ");
962
erts_printf("inport=%T indrv=%s ",
964
erts_port[ix].drv_ptr->driver_name);
967
if (cio_events & ERTS_POLL_EV_OUT) {
968
int ix = desp->driver.select.outport;
970
erts_printf("outport=none outdrv=none ");
974
erts_printf("outport=%T outdrv=%s ",
976
erts_port[ix].drv_ptr->driver_name);
980
else if (desp->type == ERTS_EV_TYPE_DRV_EV) {
982
erts_printf("driver_event ");
984
erts_printf("internal ");
987
if (cio_events == ep_events) {
988
erts_printf("ev=0x%b32x", (Uint32) cio_events);
992
erts_printf("cio_ev=0x%b32x", (Uint32) cio_events);
993
erts_printf(" ep_ev=0x%b32x", (Uint32) ep_events);
995
ix = desp->driver.event->port;
997
erts_printf(" port=none drv=none ");
1001
erts_printf(" port=%T drv=%s ",
1003
erts_port[ix].drv_ptr->driver_name);
1006
else if (internal) {
1007
erts_printf("internal ");
1010
erts_printf("cio_ev=");
1011
print_events(cio_events);
1014
erts_printf("ep_ev=");
1015
print_events(ep_events);
1020
erts_printf("control_type=%d ", desp->type);
1021
if (cio_events == ep_events) {
1022
erts_printf("ev=0x%b32x", (Uint32) cio_events);
1025
erts_printf("cio_ev=0x%b32x", (Uint32) cio_events);
1026
erts_printf(" ep_ev=0x%b32x", (Uint32) ep_events);
1032
erts_printf(" ERROR");
1038
erts_printf("used fds=%d\n", used_fds);
1039
erts_printf("internal fds=%d\n", internal_fds);
1040
erts_printf("---------------------------------------------------------\n");
1042
erts_free(ERTS_ALC_T_TMP, (void *) epep);
1043
erts_smp_mtx_unlock(&drv_ev_state_mtx);
1051
ERTS_CIO_EXPORT(erts_wake_io_thread)(void)
1053
ERTS_CIO_POLL_INTR(pollset, 1);
1056
#endif /* #ifdef ERTS_SMP */