1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2001-2018. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #ifndef ERL_NODE_CONTAINER_UTILS_H__
22 #define ERL_NODE_CONTAINER_UTILS_H__
23 
24 #include "erl_ptab.h"
25 
26 /*
27  * Note regarding node containers:
28  *
29  * The term "node container" is used as a group name (internally in
30  * the emulator) for the Erlang data types that contain a reference
31  * to a node, i.e. pids, ports, and references.
32  *
33  * Node containers are divided into internal and external node containers.
34  * An internal node container refer to the current incarnation of the
35  * node which it reside on. An external node container refer to
36  * either a remote node (i.e. a node with another node name than the
37  * node name of the node on which the node container resides on) or another
38  * incarnation of the node which the node container resides on (i.e
39  * another node with the same node name but another creation).
40  *
41  * External node containers are boxed data types. The data of an
42  * external node container is stored on the heap together with a pointer
43  * to an element in the node table (see erl_term.h and erl_node_tables.h).
44  * The elements of the node table are garbage collected by reference
45  * counting (much like refc binaries, and funs in the separate heap case).
46  *
47  * Internal node containers are stored as they previously were (in R8)
48  * with the exception of changed internal layouts (see erl_term.h), i.e.
49  * internal pid, and internal port are immediate data types and internal
50  * reference is a boxed data type. An internal node container have an
51  * implicit reference to the 'erts_this_node' element in the node table.
52  *
53  * OBSERVE! Pids doesn't use fixed size 'serial' and 'number' fields any
54  * more. Previously the 15 bit 'number' field of a pid was used as index
55  * into the process table, and the 3 bit 'serial' field was used as a
56  * "wrap counter". The needed number of bits for index into the process
57  * table is now calculated at startup and the rest (of the 18 bits used)
58  * are used as 'serial'. In the "emulator interface" (external format,
59  * list_to_pid, etc) the least significant 15 bits are presented as
60  * 'number' and the most significant 3 bits are presented as 'serial',
61  * though. The makro internal_pid_index() can be used for retrieving
62  * index into the process table. Do *not* use the result from
63  * pid_number() as an index into the process table. The pid_number() and
64  * pid_serial() (and friends) fetch the old fixed size 'number' and
65  * 'serial' fields.
66  */
67 
68 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
69  * Node containers                                                         *
70 \*                                                                         */
71 
72 #define node_container_node_name(x)	(is_external(x)			\
73 					 ? external_node_name((x))	\
74 					 : internal_node_name((x)))
75 #define node_container_creation(x) 	(is_external(x)			\
76 					 ? external_creation((x))	\
77 					 : internal_creation((x)))
78 #define node_container_dist_entry(x) 	(is_external(x)			\
79 					 ? external_dist_entry((x))	\
80 					 : internal_dist_entry((x)))
81 #define node_container_channel_no(x)	(is_external((x))		\
82 					 ? external_channel_no((x))	\
83 					 : internal_channel_no((x)))
84 #define is_node_container(x)		(is_external((x)) || is_internal((x)))
85 #define is_not_node_container(x)	(!is_node_container((x)))
86 
87 #define is_internal(x) 			(is_internal_pid((x))		\
88 					 || is_internal_port((x))	\
89 					 || is_internal_ref((x)))
90 #define is_not_internal(x) 		(!is_internal((x)))
91 #define internal_node_name(x)		(erts_this_node->sysname)
92 #define external_node_name(x)		external_node((x))->sysname
93 #define internal_creation(x)		(erts_this_node->creation)
94 #define external_creation(x)		(external_node((x))->creation)
95 #define internal_dist_entry(x)		(erts_this_node->dist_entry)
96 #define external_dist_entry(x)		(external_node((x))->dist_entry)
97 
98 /*
99  * For this node (and previous incarnations of this node), 0 is used as
100  * channel no. For other nodes, the atom index of the atom corresponding
101  * to the node name is used as channel no.
102  *
103  * (We used to assert for correct node names, but we removed that assertion
104  *  as it is possible to sneak in incorrect node names for instance using
105  *  the external format.)
106  */
107 #define dist_entry_channel_no(x)				\
108   ((x) == erts_this_dist_entry					\
109    ? ((Uint) 0)							\
110    : (ASSERT(is_atom((x)->sysname)),			        \
111       (Uint) atom_val((x)->sysname)))
112 #define internal_channel_no(x) ((Uint) ERST_INTERNAL_CHANNEL_NO)
113 #define external_channel_no(x) \
114   (dist_entry_channel_no(external_dist_entry((x))))
115 
116 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
117  * Pids                                                                    *
118 \*                                                                         */
119 
120 extern ErtsPTab erts_proc;
121 
122 #define make_internal_pid(D)		erts_ptab_make_id(&erts_proc, \
123 							  (D), \
124 							  _TAG_IMMED1_PID)
125 
126 #define internal_pid_index(PID)		(ASSERT(is_internal_pid((PID))), \
127 					 erts_ptab_id2pix(&erts_proc, (PID)))
128 
129 #define internal_pid_data(PID)		(ASSERT(is_internal_pid((PID))), \
130 					 erts_ptab_id2data(&erts_proc, (PID)))
131 
132 #define internal_pid_number(x)		_GET_PID_NUM(internal_pid_data((x)))
133 #define internal_pid_serial(x)		_GET_PID_SER(internal_pid_data((x)))
134 
135 #define internal_pid_node_name(x)	(internal_pid_node((x))->sysname)
136 #define external_pid_node_name(x)	(external_pid_node((x))->sysname)
137 #define internal_pid_creation(x)	(internal_pid_node((x))->creation)
138 #define external_pid_creation(x)	(external_pid_node((x))->creation)
139 #define internal_pid_dist_entry(x)	(internal_pid_node((x))->dist_entry)
140 #define external_pid_dist_entry(x)	(external_pid_node((x))->dist_entry)
141 
142 #define internal_pid_channel_no(x)	(internal_channel_no((x)))
143 #define external_pid_channel_no(x)	(external_channel_no((x)))
144 
145 #define pid_data_words(x)		(is_internal_pid((x))		\
146 					 ? internal_pid_data_words((x))	\
147 					 : external_pid_data_words((x)))
148 #define pid_number(x)			(is_internal_pid((x))		\
149 					 ? internal_pid_number((x))	\
150 					 : external_pid_number((x)))
151 #define pid_serial(x)			(is_internal_pid((x))		\
152 					 ? internal_pid_serial((x))	\
153 					 : external_pid_serial((x)))
154 #define pid_node(x)			(is_internal_pid((x))		\
155 					 ? internal_pid_node((x))	\
156 					 : external_pid_node((x)))
157 #define pid_node_name(x)		(is_internal_pid((x))		\
158 					 ? internal_pid_node_name((x))	\
159 					 : external_pid_node_name((x)))
160 #define pid_creation(x)			(is_internal_pid((x))		\
161 					 ? internal_pid_creation((x))	\
162 					 : external_pid_creation((x)))
163 #define pid_dist_entry(x)		(is_internal_pid((x))		\
164 					 ? internal_pid_dist_entry((x))	\
165 					 : external_pid_dist_entry((x)))
166 #define pid_channel_no(x)		(is_internal_pid((x))		\
167 					 ? internal_pid_channel_no((x))	\
168 					 : external_pid_channel_no((x)))
169 #define is_pid(x)			(is_internal_pid((x))		\
170 					 || is_external_pid((x)))
171 #define is_not_pid(x)			(!is_pid(x))
172 
173 /*
174  * Maximum number of processes. We want the number to fit in a SMALL on
175  * 32-bit CPU.
176  */
177 
178 #define ERTS_MAX_PROCESSES		(ERTS_PTAB_MAX_SIZE-1)
179 #define ERTS_MAX_PID_DATA		((1 << _PID_DATA_SIZE) - 1)
180 #define ERTS_MAX_PID_NUMBER		((1 << _PID_NUM_SIZE) - 1)
181 #define ERTS_MAX_PID_SERIAL		((1 << _PID_SER_SIZE) - 1)
182 
183 #define ERTS_PROC_BITS			(_PID_SER_SIZE + _PID_NUM_SIZE)
184 
185 #define ERTS_INVALID_PID		ERTS_PTAB_INVALID_ID(_TAG_IMMED1_PID)
186 
187 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
188  * Ports                                                                   *
189 \*                                                                         */
190 
191 extern ErtsPTab erts_port;
192 
193 #define make_internal_port(D)		erts_ptab_make_id(&erts_port, \
194 							  (D), \
195 							  _TAG_IMMED1_PORT)
196 
197 #define internal_port_index(PRT)	(ASSERT(is_internal_port((PRT))), \
198 					 erts_ptab_id2pix(&erts_port, (PRT)))
199 
200 #define internal_port_data(PRT)		(ASSERT(is_internal_port((PRT))), \
201 					 erts_ptab_id2data(&erts_port, (PRT)))
202 
203 #define internal_port_number(x) _GET_PORT_NUM(internal_port_data((x)))
204 
205 #define internal_port_node_name(x)	(internal_port_node((x))->sysname)
206 #define external_port_node_name(x)	(external_port_node((x))->sysname)
207 #define internal_port_creation(x)	(internal_port_node((x))->creation)
208 #define external_port_creation(x)	(external_port_node((x))->creation)
209 #define internal_port_dist_entry(x)	(internal_port_node((x))->dist_entry)
210 #define external_port_dist_entry(x)	(external_port_node((x))->dist_entry)
211 
212 #define internal_port_channel_no(x)	(internal_channel_no((x)))
213 #define external_port_channel_no(x)	(external_channel_no((x)))
214 
215 #define port_data_words(x)		(is_internal_port((x))		\
216 					 ? internal_port_data_words((x))\
217 					 : external_port_data_words((x)))
218 #define port_number(x)			(is_internal_port((x))		\
219 					 ? internal_port_number((x))	\
220 					 : external_port_number((x)))
221 #define port_node(x)			(is_internal_port((x))		\
222 					 ? internal_port_node((x))	\
223 					 : external_port_node((x)))
224 #define port_node_name(x)		(is_internal_port((x))		\
225 					 ? internal_port_node_name((x))	\
226 					 : external_port_node_name((x)))
227 #define port_creation(x)		(is_internal_port((x))		\
228 					 ? internal_port_creation((x))	\
229 					 : external_port_creation((x)))
230 #define port_dist_entry(x)		(is_internal_port((x))		\
231 					 ? internal_port_dist_entry((x))\
232 					 : external_port_dist_entry((x)))
233 #define port_channel_no(x)		(is_internal_port((x))		\
234 					 ? internal_port_channel_no((x))\
235 					 : external_port_channel_no((x)))
236 
237 #define is_port(x)			(is_internal_port((x))		\
238 					 || is_external_port((x)))
239 #define is_not_port(x)			(!is_port(x))
240 
241 /* Highest port-ID part in a term of type Port
242    Not necessarily the same as current maximum port table size
243    which defines the maximum number of simultaneous Ports
244    in the Erlang node. ERTS_MAX_PORTS is a hard upper limit.
245 */
246 #define ERTS_MAX_PORTS			(ERTS_PTAB_MAX_SIZE-1)
247 #define ERTS_MAX_PORT_DATA		((1 << _PORT_DATA_SIZE) - 1)
248 #define ERTS_MAX_PORT_NUMBER		((1 << _PORT_NUM_SIZE) - 1)
249 
250 #define ERTS_PORTS_BITS			(_PORT_NUM_SIZE)
251 
252 #define ERTS_INVALID_PORT		ERTS_PTAB_INVALID_ID(_TAG_IMMED1_PORT)
253 
254 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
255  * Refs                                                                    *
256 \*                                                                         */
257 
258 #define internal_ref_no_numbers(x)	ERTS_REF_NUMBERS
259 #define internal_ref_numbers(x)		(is_internal_ordinary_ref((x)) \
260 					 ? internal_ordinary_ref_numbers((x)) \
261 					 : (ASSERT(is_internal_magic_ref((x))), \
262 					    internal_magic_ref_numbers((x))))
263 #if defined(ARCH_64)
264 
265 #define external_ref_no_numbers(x)					\
266   (external_ref_data((x))[0])
267 #define external_thing_ref_no_numbers(thing)			        \
268   (external_thing_ref_data(thing)[0])
269 #define external_ref_numbers(x)						\
270   (&external_ref_data((x))[1])
271 #define external_thing_ref_numbers(thing)				\
272   (&external_thing_ref_data(thing)[1])
273 
274 
275 #else
276 
277 #define external_ref_no_numbers(x)	(external_ref_data_words((x)))
278 #define external_thing_ref_no_numbers(t) (external_thing_ref_data_words((t)))
279 #define external_ref_numbers(x)		(external_ref_data((x)))
280 #define external_thing_ref_numbers(t)   (external_thing_ref_data((t)))
281 
282 #endif
283 
284 #define internal_ref_node_name(x)	(internal_ref_node((x))->sysname)
285 #define external_ref_node_name(x)	(external_ref_node((x))->sysname)
286 #define internal_ref_creation(x)	(internal_ref_node((x))->creation)
287 #define external_ref_creation(x)	(external_ref_node((x))->creation)
288 #define internal_ref_dist_entry(x)	(internal_ref_node((x))->dist_entry)
289 #define external_ref_dist_entry(x)	(external_ref_node((x))->dist_entry)
290 
291 
292 #define internal_ref_channel_no(x)	(internal_channel_no((x)))
293 #define external_ref_channel_no(x)	(external_channel_no((x)))
294 
295 #define ref_no_numbers(x)		(is_internal_ref((x))		\
296 					 ? internal_ref_no_numbers((x))\
297 					 : external_ref_no_numbers((x)))
298 #define ref_numbers(x)			(is_internal_ref((x))		\
299 					 ? internal_ref_numbers((x))	\
300 					 : external_ref_numbers((x)))
301 #define ref_node(x)			(is_internal_ref((x))		\
302 					 ? internal_ref_node(x)		\
303 					 : external_ref_node((x)))
304 #define ref_node_name(x)		(is_internal_ref((x))		\
305 					 ? internal_ref_node_name((x))	\
306 					 : external_ref_node_name((x)))
307 #define ref_creation(x)			(is_internal_ref((x))		\
308 					 ? internal_ref_creation((x))	\
309 					 : external_ref_creation((x)))
310 #define ref_dist_entry(x)		(is_internal_ref((x))		\
311 					 ? internal_ref_dist_entry((x))	\
312 					 : external_ref_dist_entry((x)))
313 #define ref_channel_no(x)		(is_internal_ref((x))		\
314 					 ? internal_ref_channel_no((x))	\
315 					 : external_ref_channel_no((x)))
316 #define is_ref(x)			(is_internal_ref((x))		\
317 					 || is_external_ref((x)))
318 #define is_not_ref(x)			(!is_ref(x))
319 
320 #endif
321