35
35
#include "global.h"
36
36
#include "erl_check_io.h"
37
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
38
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
39
# define ERTS_DRV_EV_STATE_EXTRA_SIZE 128
41
# include "safe_hash.h"
42
# define DRV_EV_STATE_HTAB_SIZE 1024
41
#define ERTS_EV_FLG_IGNORE (((short) 1) << 0)
43
45
#define ERTS_EV_TYPE_NONE ((short) 0)
44
46
#define ERTS_EV_TYPE_DRV_SEL ((short) 1)
45
47
#define ERTS_EV_TYPE_DRV_EV ((short) 2)
47
#define ERTS_DRV_EV_STATE_EXTRA_SIZE 128
49
49
#if defined(ERTS_KERNEL_POLL_VERSION)
50
50
# define ERTS_CIO_EXPORT(FUNC) FUNC ## _kp
51
51
#elif defined(ERTS_NO_KERNEL_POLL_VERSION)
67
67
#define ERTS_CIO_POLL_INIT ERTS_POLL_EXPORT(erts_poll_init)
68
68
#define ERTS_CIO_POLL_INFO ERTS_POLL_EXPORT(erts_poll_info)
70
static ErtsPollSet pollset;
70
static struct pollset_info
73
erts_smp_atomic_t in_poll_wait; /* set while doing poll */
75
struct removed_fd* removed_list; /* list of deselected fd's*/
76
erts_smp_spinlock_t removed_list_lock;
79
#define NUM_OF_POLLSETS 1
83
struct removed_fd *next;
73
89
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
79
95
ErtsDrvSelectDataState *select;
81
97
ErtsPollEvents events;
98
unsigned short remove_cnt; /* number of removed_fd's referring to this fd */
84
100
} ErtsDrvEventState;
87
struct erts_fd_list *next;
91
102
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
92
103
static int max_fds = -1;
94
static erts_smp_mtx_t drv_ev_state_mtx;
105
#define DRV_EV_STATE_LOCK_CNT 16
108
byte _cache_line_alignment[64];
109
}drv_ev_state_locks[DRV_EV_STATE_LOCK_CNT];
112
static ERTS_INLINE erts_smp_mtx_t* fd_mtx(ErtsSysFdType fd)
115
# ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
118
return &drv_ev_state_locks[hash % DRV_EV_STATE_LOCK_CNT].lck;
121
# define fd_mtx(fd) NULL
96
124
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
98
static int drv_ev_state_len;
126
static erts_smp_atomic_t drv_ev_state_len;
99
127
static ErtsDrvEventState *drv_ev_state;
128
static erts_smp_mtx_t drv_ev_state_grow_lock; /* prevent lock-hogging of racing growers */
102
static Hash drv_ev_state_tab;
131
static SafeHash drv_ev_state_tab;
103
132
static int num_state_prealloc;
104
133
static ErtsDrvEventState *state_prealloc_first;
134
erts_smp_spinlock_t state_prealloc_lock;
106
136
static ERTS_INLINE ErtsDrvEventState *hash_get_drv_ev_state(ErtsSysFdType fd)
108
138
ErtsDrvEventState tmpl;
110
return (ErtsDrvEventState *) hash_get(&drv_ev_state_tab, (void *) &tmpl);
140
return (ErtsDrvEventState *) safe_hash_get(&drv_ev_state_tab, (void *) &tmpl);
113
static ERTS_INLINE ErtsDrvEventState *hash_new_drv_ev_state(ErtsSysFdType fd)
143
static ERTS_INLINE ErtsDrvEventState* hash_new_drv_ev_state(ErtsSysFdType fd)
115
145
ErtsDrvEventState tmpl;
117
147
tmpl.driver.select = NULL;
120
150
tmpl.type = ERTS_EV_TYPE_NONE;
121
return (ErtsDrvEventState *) hash_put(&drv_ev_state_tab, (void *) &tmpl);
151
return (ErtsDrvEventState *) safe_hash_put(&drv_ev_state_tab, (void *) &tmpl);
124
154
static ERTS_INLINE void hash_erase_drv_ev_state(ErtsDrvEventState *state)
126
hash_erase(&drv_ev_state_tab, (void *) state);
156
safe_hash_erase(&drv_ev_state_tab, (void *) state);
131
static erts_smp_atomic_t in_poll_wait;
133
struct erts_fd_list *ignored_list;
159
#endif /* !ERTS_SYS_CONTINOUS_FD_NUMBERS */
135
161
static void stale_drv_select(Eterm id, ErtsDrvEventState *state, int mode);
136
162
static void select_steal(ErlDrvPort ix, ErtsDrvEventState *state,
161
ERTS_QUALLOC_IMPL(fd_list, struct erts_fd_list, 64, ERTS_ALC_T_FD_LIST)
188
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(removed_fd, struct removed_fd, 64, ERTS_ALC_T_FD_LIST)
163
192
static ERTS_INLINE void
164
check_ignore(ErtsDrvEventState *state, ErtsPollEvents new_evs, ErtsPollEvents old_evs)
193
remember_removed(ErtsDrvEventState *state, struct pollset_info* psi)
169
&& !(state->flags & ERTS_EV_FLG_IGNORE)
170
&& erts_smp_atomic_read(&in_poll_wait)) {
171
struct erts_fd_list *fdlp = fd_list_alloc();
196
struct removed_fd *fdlp;
197
ERTS_SMP_LC_ASSERT(erts_smp_lc_mtx_is_locked(fd_mtx(state->fd)));
198
if (erts_smp_atomic_read(&psi->in_poll_wait)) {
200
ASSERT(state->remove_cnt > 0);
201
fdlp = removed_fd_alloc();
172
202
fdlp->fd = state->fd;
173
fdlp->next = ignored_list;
175
state->flags |= ERTS_EV_FLG_IGNORE;
203
erts_smp_spin_lock(&psi->removed_list_lock);
204
fdlp->next = psi->removed_list;
205
psi->removed_list = fdlp;
206
erts_smp_spin_unlock(&psi->removed_list_lock);
212
static ERTS_INLINE int
213
is_removed(ErtsDrvEventState *state)
216
/* Note that there is a possible race here, where an fd is removed
217
(increasing remove_cnt) and then added again just before erts_poll_wait
218
is called by erts_check_io. Any polled event on the re-added fd will then
219
be falsely ignored. But that does not matter, as the event will trigger
220
again next time erl_check_io is called. */
221
return state->remove_cnt > 0;
180
228
static ERTS_INLINE void
229
forget_removed(struct pollset_info* psi)
183
struct erts_fd_list *fdlp = ignored_list;
232
struct removed_fd* fdlp;
233
struct removed_fd* tofree;
235
/* Fast track: if (atomic_ptr(removed_list)==NULL) return; */
237
erts_smp_spin_lock(&psi->removed_list_lock);
238
fdlp = psi->removed_list;
239
psi->removed_list = NULL;
240
erts_smp_spin_unlock(&psi->removed_list_lock);
186
struct erts_fd_list *ffdlp = fdlp;
243
ErtsDrvEventState *state;
244
erts_smp_mtx_t* mtx = fd_mtx(fdlp->fd);
245
erts_smp_mtx_lock(mtx);
187
246
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
188
drv_ev_state[(int) fdlp->fd].flags &= ~ERTS_EV_FLG_IGNORE;
247
state = &drv_ev_state[(int) fdlp->fd];
248
ASSERT(state->remove_cnt > 0);
191
ErtsDrvEventState *state = hash_get_drv_ev_state(fdlp->fd);
193
state->flags &= ~ERTS_EV_FLG_IGNORE;
251
state = hash_get_drv_ev_state(fdlp->fd);
253
ASSERT(state->remove_cnt > 0);
254
if (--state->remove_cnt == 0 && state->type == ERTS_EV_TYPE_NONE) {
255
hash_erase_drv_ev_state(state);
258
erts_smp_mtx_unlock(mtx);
196
260
fdlp = fdlp->next;
261
removed_fd_free(tofree);
263
#endif /* ERTS_SMP */
202
266
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
207
271
int new_len = min_ix + 1 + ERTS_DRV_EV_STATE_EXTRA_SIZE;
208
272
if (new_len > max_fds)
209
273
new_len = max_fds;
210
drv_ev_state = (drv_ev_state_len
211
? erts_realloc(ERTS_ALC_T_DRV_EV_STATE,
213
sizeof(ErtsDrvEventState)*new_len)
214
: erts_alloc(ERTS_ALC_T_DRV_EV_STATE,
215
sizeof(ErtsDrvEventState)*new_len));
216
for (i = drv_ev_state_len; i < new_len; i++) {
217
drv_ev_state[i].fd = (ErtsSysFdType) i;
218
drv_ev_state[i].driver.select = NULL;
219
drv_ev_state[i].events = 0;
220
drv_ev_state[i].flags = 0;
221
drv_ev_state[i].type = ERTS_EV_TYPE_NONE;
275
erts_smp_mtx_lock(&drv_ev_state_grow_lock);
276
if (erts_smp_atomic_read(&drv_ev_state_len) <= min_ix) {
277
for (i=0; i<DRV_EV_STATE_LOCK_CNT; i++) { /* lock all fd's */
278
erts_smp_mtx_lock(&drv_ev_state_locks[i].lck);
280
drv_ev_state = (drv_ev_state
281
? erts_realloc(ERTS_ALC_T_DRV_EV_STATE,
283
sizeof(ErtsDrvEventState)*new_len)
284
: erts_alloc(ERTS_ALC_T_DRV_EV_STATE,
285
sizeof(ErtsDrvEventState)*new_len));
286
for (i = erts_smp_atomic_read(&drv_ev_state_len); i < new_len; i++) {
287
drv_ev_state[i].fd = (ErtsSysFdType) i;
288
drv_ev_state[i].driver.select = NULL;
289
drv_ev_state[i].events = 0;
290
drv_ev_state[i].remove_cnt = 0;
291
drv_ev_state[i].type = ERTS_EV_TYPE_NONE;
293
erts_smp_atomic_set(&drv_ev_state_len, new_len);
294
for (i=0; i<DRV_EV_STATE_LOCK_CNT; i++) {
295
erts_smp_mtx_unlock(&drv_ev_state_locks[i].lck);
223
drv_ev_state_len = new_len;
298
/*else already grown by racing thread */
300
erts_smp_mtx_unlock(&drv_ev_state_grow_lock);
302
#endif /* ERTS_SYS_CONTINOUS_FD_NUMBERS */
227
305
static ERTS_INLINE void
228
306
abort_task(Eterm id, ErtsPortTaskHandle *pthp, short type)
342
418
ErtsPollEvents ctl_events = (ErtsPollEvents) 0;
343
419
ErtsPollEvents new_events, old_events;
344
420
ErtsDrvEventState *state;
346
423
ERTS_SMP_LC_ASSERT(erts_drvport2port(ix)
347
424
&& erts_lc_is_port_locked(erts_drvport2port(ix)));
349
426
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
354
select_large_fd_error(ix, fd, mode, on);
359
erts_smp_mtx_lock(&drv_ev_state_mtx);
361
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
362
if (fd >= drv_ev_state_len)
427
if ((unsigned)fd >= (unsigned)erts_smp_atomic_read(&drv_ev_state_len)) {
431
select_large_fd_error(ix, fd, mode, on);
363
434
grow_drv_ev_state(fd);
438
erts_smp_mtx_lock(fd_mtx(fd));
440
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
364
441
state = &drv_ev_state[(int) fd];
366
443
/* Could use hash_new directly, but want to keep the normal case fast */
369
446
state = hash_new_drv_ev_state(fd);
373
450
#if ERTS_CIO_HAVE_DRV_EVENT
374
451
if (state->type == ERTS_EV_TYPE_DRV_EV)
375
select_steal(ix, state, mode, on);;
452
select_steal(ix, state, mode, on);
378
455
if (mode & DO_READ) {
396
473
? (state->type == ERTS_EV_TYPE_DRV_SEL)
397
474
: (state->type == ERTS_EV_TYPE_NONE));
399
new_events = ERTS_CIO_POLL_CTL(pollset, state->fd, ctl_events, on);
400
if (new_events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL))
476
new_events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, ctl_events, on);
477
if (new_events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL)) {
403
482
old_events = state->events;
444
523
erts_free(ERTS_ALC_T_DRV_SEL_D_STATE,
445
524
state->driver.select);
446
525
state->driver.select = NULL;
448
526
state->type = ERTS_EV_TYPE_NONE;
527
remember_removed(state, &pollset);
452
check_ignore(state, new_events, old_events);
454
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
455
if (state->type == ERTS_EV_TYPE_NONE) {
456
hash_erase_drv_ev_state(state);
460
erts_smp_mtx_unlock(&drv_ev_state_mtx);
466
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
467
if (state->type == ERTS_EV_TYPE_NONE) {
468
hash_erase_drv_ev_state(state);
472
erts_smp_mtx_unlock(&drv_ev_state_mtx);
535
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
536
if (state->type == ERTS_EV_TYPE_NONE && state->remove_cnt == 0) {
537
hash_erase_drv_ev_state(state);
540
erts_smp_mtx_unlock(fd_mtx(fd));
487
555
ErtsPollEvents remove_events;
488
556
Eterm id = drvport2id(ix);
489
557
ErtsDrvEventState *state;
491
560
ERTS_SMP_LC_ASSERT(erts_drvport2port(ix)
492
561
&& erts_lc_is_port_locked(erts_drvport2port(ix)));
494
563
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
499
event_large_fd_error(ix, fd, event_data);
504
erts_smp_mtx_lock(&drv_ev_state_mtx);
506
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
507
if (fd >= drv_ev_state_len)
564
if ((unsigned)fd >= (unsigned)erts_smp_atomic_read(&drv_ev_state_len)) {
568
event_large_fd_error(ix, fd, event_data);
508
571
grow_drv_ev_state(fd);
575
erts_smp_mtx_lock(fd_mtx(fd));
577
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
509
578
state = &drv_ev_state[(int) fd];
511
580
/* Could use hash_new directly, but want to keep the normal case fast */
534
603
remove_events = ~event_data->events & events;
535
604
add_events = ~events & event_data->events;
539
607
if (add_events) {
540
events = ERTS_CIO_POLL_CTL(pollset, state->fd, add_events, 1);
541
if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL))
608
events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, add_events, 1);
609
if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL)) {
544
614
if (remove_events) {
545
events = ERTS_CIO_POLL_CTL(pollset, state->fd, remove_events, 0);
546
if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL))
615
events = ERTS_CIO_POLL_CTL(pollset.ps, state->fd, remove_events, 0);
616
if (events & (ERTS_POLL_EV_ERR|ERTS_POLL_EV_NVAL)) {
621
if (event_data && event_data->events != 0) {
550
622
if (state->type == ERTS_EV_TYPE_DRV_EV) {
551
623
state->driver.event->removed_events &= ~add_events;
552
624
state->driver.event->removed_events |= remove_events;
569
641
state->driver.event);
571
643
state->driver.select = NULL;
573
644
state->type = ERTS_EV_TYPE_NONE;
645
remember_removed(state, &pollset);
575
check_ignore(state, events, state->events);
576
647
state->events = events;
577
648
ASSERT(event_data ? events == event_data->events : events == 0);
579
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
580
if (state->type == ERTS_EV_TYPE_NONE) {
581
hash_erase_drv_ev_state(state);
585
erts_smp_mtx_unlock(&drv_ev_state_mtx);
589
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
590
if (state->type == ERTS_EV_TYPE_NONE) {
591
hash_erase_drv_ev_state(state);
595
erts_smp_mtx_unlock(&drv_ev_state_mtx);
653
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
654
if (state->type == ERTS_EV_TYPE_NONE && state->remove_cnt == 0) {
655
hash_erase_drv_ev_state(state);
658
erts_smp_mtx_unlock(fd_mtx(fd));
846
909
ERTS_CIO_EXPORT(erts_check_io_interrupt)(int set)
848
ERTS_CIO_POLL_INTR(pollset, set);
911
ERTS_CIO_POLL_INTR(pollset.ps, set);
852
915
ERTS_CIO_EXPORT(erts_check_io_interrupt_timed)(int set, long msec)
854
ERTS_CIO_POLL_INTR_TMD(pollset, set, msec);
917
ERTS_CIO_POLL_INTR_TMD(pollset.ps, set, msec);
878
941
erts_smp_activity_begin(ERTS_ACTIVITY_WAIT, NULL, NULL, NULL);
879
942
pollres_len = sizeof(pollres)/sizeof(ErtsPollResFd);
880
erts_smp_atomic_set(&in_poll_wait, 1);
881
poll_ret = ERTS_CIO_POLL_WAIT(pollset, pollres, &pollres_len, &wait_time);
944
erts_smp_atomic_set(&pollset.in_poll_wait, 1);
946
poll_ret = ERTS_CIO_POLL_WAIT(pollset.ps, pollres, &pollres_len, &wait_time);
883
948
#ifdef ERTS_ENABLE_LOCK_CHECK
884
949
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
909
974
erl_errno_id(poll_ret), poll_ret);
910
975
erts_send_error_to_logger_nogl(dsbufp);
916
erts_smp_mtx_lock(&drv_ev_state_mtx);
917
erts_smp_atomic_set(&in_poll_wait, 0);
919
980
for (i = 0; i < pollres_len; i++) {
920
982
ErtsSysFdType fd = (ErtsSysFdType) pollres[i].fd;
921
983
ErtsDrvEventState *state;
985
erts_smp_mtx_lock(fd_mtx(fd));
922
987
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
923
988
state = &drv_ev_state[ (int) fd];
925
990
state = hash_get_drv_ev_state(fd);
931
if (state->flags & ERTS_EV_FLG_IGNORE)
996
/* Skip this fd if it was removed from pollset */
997
if (is_removed(state)) {
934
1001
switch (state->type) {
935
1002
case ERTS_EV_TYPE_DRV_SEL: { /* Requested via driver_select()... */
951
1018
if ((revents & ERTS_POLL_EV_IN)
952
1019
|| (!(revents & ERTS_POLL_EV_OUT)
953
&& state->events & ERTS_POLL_EV_IN))
1020
&& state->events & ERTS_POLL_EV_IN)) {
954
1021
iready(state->driver.select->inport, state);
955
else if (state->events & ERTS_POLL_EV_OUT)
1023
else if (state->events & ERTS_POLL_EV_OUT) {
956
1024
oready(state->driver.select->outport, state);
958
1027
else if (revents & (ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) {
959
if (revents & ERTS_POLL_EV_OUT)
1028
if (revents & ERTS_POLL_EV_OUT) {
960
1029
oready(state->driver.select->outport, state);
961
1031
/* Someone might have deselected input since revents
962
1032
was read (true also on the non-smp emulator since
963
1033
oready() may have been called); therefore, update
965
1035
revents &= ~(~state->events & ERTS_POLL_EV_IN);
966
if (revents & ERTS_POLL_EV_IN)
1036
if (revents & ERTS_POLL_EV_IN) {
967
1037
iready(state->driver.select->inport, state);
969
1040
else if (revents & ERTS_POLL_EV_NVAL) {
970
1041
bad_fd_in_pollset(state,
1086
1160
#ifndef ERTS_SYS_CONTINOUS_FD_NUMBERS
1087
static HashValue drv_ev_state_hash(void *des)
1161
static SafeHashValue drv_ev_state_hash(void *des)
1089
return (HashValue) ((ErtsDrvEventState *) des)->fd;
1163
SafeHashValue val = (SafeHashValue) ((ErtsDrvEventState *) des)->fd;
1164
return val ^ (val >> 8); /* Good enough for aligned pointer values? */
1092
1167
static int drv_ev_state_cmp(void *des1, void *des2)
1098
1173
static void *drv_ev_state_alloc(void *des_tmpl)
1100
1175
ErtsDrvEventState *evstate;
1176
erts_smp_spin_lock(&state_prealloc_lock);
1101
1177
if (state_prealloc_first == NULL) {
1178
erts_smp_spin_unlock(&state_prealloc_lock);
1102
1179
evstate = (ErtsDrvEventState *)
1103
1180
erts_alloc(ERTS_ALC_T_DRV_EV_STATE, sizeof(ErtsDrvEventState));
1105
1182
evstate = state_prealloc_first;
1106
1183
state_prealloc_first = (ErtsDrvEventState *) evstate->hb.next;
1107
1184
--num_state_prealloc;
1185
erts_smp_spin_unlock(&state_prealloc_lock);
1109
1187
/* XXX: Already valid data if prealloced, could ignore template! */
1110
1188
*evstate = *((ErtsDrvEventState *) des_tmpl);
1115
1193
static void drv_ev_state_free(void *des)
1117
((ErtsDrvEventState *) des)->hb.next = (struct hash_bucket *) state_prealloc_first;
1195
erts_smp_spin_lock(&state_prealloc_lock);
1196
((ErtsDrvEventState *) des)->hb.next = &state_prealloc_first->hb;
1118
1197
state_prealloc_first = (ErtsDrvEventState *) des;
1119
1198
++num_state_prealloc;
1199
erts_smp_spin_unlock(&state_prealloc_lock);
1124
1204
ERTS_CIO_EXPORT(erts_init_check_io)(void)
1126
init_fd_list_alloc();
1127
ignored_list = NULL;
1128
erts_smp_atomic_init(&in_poll_wait, 0);
1206
erts_smp_atomic_init(&pollset.in_poll_wait, 0);
1129
1207
ERTS_CIO_POLL_INIT();
1208
pollset.ps = ERTS_CIO_NEW_POLLSET();
1211
init_removed_fd_alloc();
1212
pollset.removed_list = NULL;
1213
erts_smp_spinlock_init(&pollset.removed_list_lock,
1217
for (i=0; i<DRV_EV_STATE_LOCK_CNT; i++) {
1218
erts_smp_mtx_init(&drv_ev_state_locks[i].lck, "drv_ev_state");
1130
1222
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
1131
1223
max_fds = ERTS_CIO_POLL_MAX_FDS();
1133
pollset = ERTS_CIO_NEW_POLLSET();
1134
erts_smp_mtx_init(&drv_ev_state_mtx, "drv_ev_state");
1135
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
1136
drv_ev_state_len = 0;
1224
erts_smp_atomic_init(&drv_ev_state_len, 0);
1137
1225
drv_ev_state = NULL;
1226
erts_smp_mtx_init(&drv_ev_state_grow_lock, "drv_ev_state_grow");
1229
SafeHashFunctions hf;
1141
1230
hf.hash = &drv_ev_state_hash;
1142
1231
hf.cmp = &drv_ev_state_cmp;
1143
1232
hf.alloc = &drv_ev_state_alloc;
1144
1233
hf.free = &drv_ev_state_free;
1145
1234
num_state_prealloc = 0;
1146
1235
state_prealloc_first = NULL;
1236
erts_smp_spinlock_init(&state_prealloc_lock,"state_prealloc");
1148
/* On windows, since io is not initiated, the ERTS_CIO_POLL_MAX_FDS() will return
1149
1024 unconditionally at this point, but the hash table grows if needed, so that's
1151
hash_init(ERTS_ALC_T_DRV_EV_STATE, &drv_ev_state_tab, "drv_ev_state_tab",
1152
ERTS_CIO_POLL_MAX_FDS(), hf);
1238
safe_hash_init(ERTS_ALC_T_DRV_EV_STATE, &drv_ev_state_tab, "drv_ev_state_tab",
1239
DRV_EV_STATE_HTAB_SIZE, hf);
1171
1258
ErtsPollInfo pi;
1172
erts_smp_mtx_lock(&drv_ev_state_mtx);
1173
ERTS_CIO_POLL_INFO(pollset, &pi);
1259
ERTS_CIO_POLL_INFO(pollset.ps, &pi);
1174
1260
res = pi.memory_size;
1175
1261
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
1176
res += sizeof(ErtsDrvEventState)*drv_ev_state_len;
1262
res += sizeof(ErtsDrvEventState) * erts_smp_atomic_read(&drv_ev_state_len);
1178
res += hash_table_sz(&drv_ev_state_tab);
1264
res += safe_hash_table_sz(&drv_ev_state_tab);
1181
hash_get_info(&hi, &drv_ev_state_tab);
1267
safe_hash_get_info(&hi, &drv_ev_state_tab);
1182
1268
res += hi.objs * sizeof(ErtsDrvEventState);
1270
erts_smp_spin_lock(&state_prealloc_lock);
1184
1271
res += num_state_prealloc * sizeof(ErtsDrvEventState);
1272
erts_smp_spin_unlock(&state_prealloc_lock);
1187
erts_smp_mtx_unlock(&drv_ev_state_mtx);
1198
1284
ErtsPollInfo pi;
1200
erts_smp_mtx_lock(&drv_ev_state_mtx);
1201
ERTS_CIO_POLL_INFO(pollset, &pi);
1286
ERTS_CIO_POLL_INFO(pollset.ps, &pi);
1202
1287
memory_size = pi.memory_size;
1203
1288
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
1204
memory_size += sizeof(ErtsDrvEventState)*drv_ev_state_len;
1289
memory_size += sizeof(ErtsDrvEventState) * erts_smp_atomic_read(&drv_ev_state_len);
1206
memory_size += hash_table_sz(&drv_ev_state_tab);
1291
memory_size += safe_hash_table_sz(&drv_ev_state_tab);
1209
hash_get_info(&hi, &drv_ev_state_tab);
1294
safe_hash_get_info(&hi, &drv_ev_state_tab);
1210
1295
memory_size += hi.objs * sizeof(ErtsDrvEventState);
1297
erts_smp_spin_lock(&state_prealloc_lock);
1212
1298
memory_size += num_state_prealloc * sizeof(ErtsDrvEventState);
1299
erts_smp_spin_unlock(&state_prealloc_lock);
1214
erts_smp_mtx_unlock(&drv_ev_state_mtx);
1552
1638
ERTS_CIO_EXPORT(erts_check_io_debug)(void)
1554
1640
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
1557
1643
IterDebugCounters counters;
1558
1644
ErtsDrvEventState null_des;
1560
1646
null_des.driver.select = NULL;
1561
1647
null_des.events = 0;
1648
null_des.remove_cnt = 0;
1563
1649
null_des.type = ERTS_EV_TYPE_NONE;
1565
erts_smp_mtx_lock(&drv_ev_state_mtx);
1567
1651
erts_printf("--- fds in pollset --------------------------------------\n");
1654
# ifdef ERTS_ENABLE_LOCK_CHECK
1655
erts_lc_check_exact(NULL, 0); /* No locks should be locked */
1657
erts_block_system(0); /* stop the world to avoid messy locking */
1569
1660
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
1570
1661
counters.epep = erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsPollEvents)*max_fds);
1571
ERTS_POLL_EXPORT(erts_poll_get_selected_events)(pollset, counters.epep, max_fds);
1662
ERTS_POLL_EXPORT(erts_poll_get_selected_events)(pollset.ps, counters.epep, max_fds);
1572
1663
counters.internal_fds = 0;
1574
1665
counters.used_fds = 0;
1575
1666
counters.num_errors = 0;
1577
1668
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
1578
for (fd = 0; fd < max_fds; fd++) {
1579
ErtsDrvEventState *desp = ((fd < drv_ev_state_len)
1669
len = erts_smp_atomic_read(&drv_ev_state_len);
1670
for (fd = 0; fd < len; fd++) {
1671
doit_erts_check_io_debug((void *) &drv_ev_state[fd], (void *) &counters);
1673
for ( ; fd < max_fds; fd++) {
1582
1674
null_des.fd = fd;
1583
doit_erts_check_io_debug((void *) desp, (void *) &counters);
1675
doit_erts_check_io_debug((void *) &null_des, (void *) &counters);
1586
hash_foreach(&drv_ev_state_tab, &doit_erts_check_io_debug, (void *) &counters);
1678
safe_hash_for_each(&drv_ev_state_tab, &doit_erts_check_io_debug, (void *) &counters);
1682
erts_release_system();
1588
1685
erts_printf("\n");
1589
1686
erts_printf("used fds=%d\n", counters.used_fds);
1590
1687
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS