aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/common/erl_check_io.h
blob: 777942a473ed4243327304cf7b2cfeec9be9add8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * %CopyrightBegin%
 * 
 * Copyright Ericsson AB 2006-2017. All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * %CopyrightEnd%
 */

/*
 * Description:	Check I/O
 *
 * Author: 	Rickard Green
 */

#ifndef ERL_CHECK_IO_H__
#define ERL_CHECK_IO_H__

#include "sys.h"
#include "erl_sys_driver.h"

#ifdef ERTS_ENABLE_KERNEL_POLL

int driver_select_kp(ErlDrvPort, ErlDrvEvent, int, int);
int driver_select_nkp(ErlDrvPort, ErlDrvEvent, int, int);
int enif_select_kp(ErlNifEnv*, ErlNifEvent, enum ErlNifSelectFlags, void*, const ErlNifPid*, Eterm);
int enif_select_nkp(ErlNifEnv*, ErlNifEvent, enum ErlNifSelectFlags, void*, const ErlNifPid*, Eterm);
int driver_event_kp(ErlDrvPort, ErlDrvEvent, ErlDrvEventData);
int driver_event_nkp(ErlDrvPort, ErlDrvEvent, ErlDrvEventData);
Uint erts_check_io_size_kp(void);
Uint erts_check_io_size_nkp(void);
Eterm erts_check_io_info_kp(void *);
Eterm erts_check_io_info_nkp(void *);
int erts_check_io_max_files_kp(void);
int erts_check_io_max_files_nkp(void);
void erts_check_io_interrupt_kp(int);
void erts_check_io_interrupt_nkp(int);
void erts_check_io_interrupt_timed_kp(int, ErtsMonotonicTime);
void erts_check_io_interrupt_timed_nkp(int, ErtsMonotonicTime);
void erts_check_io_kp(int);
void erts_check_io_nkp(int);
void erts_init_check_io_kp(void);
void erts_init_check_io_nkp(void);
int erts_check_io_debug_kp(ErtsCheckIoDebugInfo *);
int erts_check_io_debug_nkp(ErtsCheckIoDebugInfo *);

#ifdef ERTS_ENABLE_LOCK_COUNT
void erts_lcnt_update_cio_locks_kp(int enable);
void erts_lcnt_update_cio_locks_nkp(int enable);
#endif

#else /* !ERTS_ENABLE_KERNEL_POLL */

Uint erts_check_io_size(void);
Eterm erts_check_io_info(void *);
int erts_check_io_max_files(void);
void erts_check_io_interrupt(int);
void erts_check_io_interrupt_timed(int, ErtsMonotonicTime);
void erts_check_io(int);
void erts_init_check_io(void);

#ifdef ERTS_ENABLE_LOCK_COUNT
void erts_lcnt_update_cio_locks(int enable);
#endif

#endif

extern erts_atomic_t erts_check_io_time;

typedef struct {
    ErtsPortTaskHandle task;
    erts_atomic_t executed_time;
} ErtsIoTask;

ERTS_GLB_INLINE void erts_io_notify_port_task_executed(ErtsPortTaskHandle *pthp);

#if ERTS_GLB_INLINE_INCL_FUNC_DEF

ERTS_GLB_INLINE void
erts_io_notify_port_task_executed(ErtsPortTaskHandle *pthp)
{
    ErtsIoTask *itp = (ErtsIoTask *) (((char *) pthp) - offsetof(ErtsIoTask, task));
    erts_aint_t ci_time = erts_atomic_read_acqb(&erts_check_io_time);
    erts_atomic_set_relb(&itp->executed_time, ci_time);
}

#endif

#endif /*  ERL_CHECK_IO_H__ */

#if !defined(ERL_CHECK_IO_C__) && !defined(ERTS_ALLOC_C__)
#define ERL_CHECK_IO_INTERNAL__
#endif

#ifndef ERL_CHECK_IO_INTERNAL__
#define ERL_CHECK_IO_INTERNAL__
#include "erl_poll.h"
#include "erl_port_task.h"

#ifdef __WIN32__
/*
 * Current erts_poll implementation for Windows cannot handle
 * active events in the set of events polled.
 */
#  define ERTS_CIO_DEFER_ACTIVE_EVENTS 1
#else
#  define ERTS_CIO_DEFER_ACTIVE_EVENTS 0
#endif

/*
 * ErtsDrvEventDataState is used by driver_event() which is almost never
 * used. We allocate ErtsDrvEventDataState separate since we dont wan't
 * the size of ErtsDrvEventState to increase due to driver_event()
 * information.
 */
typedef struct {
    Eterm port;
    ErlDrvEventData data;
    ErtsPollEvents removed_events;
#if ERTS_CIO_DEFER_ACTIVE_EVENTS
    ErtsPollEvents deferred_events;
#endif
    ErtsIoTask iotask;
} ErtsDrvEventDataState;

typedef struct {
    Eterm inport;
    Eterm outport;
    ErtsIoTask iniotask;
    ErtsIoTask outiotask;
} ErtsDrvSelectDataState;

struct erts_nif_select_event {
    Eterm pid;
    Eterm immed;
    Uint32 refn[ERTS_REF_NUMBERS];
    Sint32 ddeselect_cnt; /* 0:  No delayed deselect in progress
                           * 1:  Do deselect before next poll
                           * >1: Countdown of ignored events
                           */
};

typedef struct {
    struct erts_nif_select_event in;
    struct erts_nif_select_event out;
} ErtsNifSelectDataState;

#endif /* #ifndef ERL_CHECK_IO_INTERNAL__ */