1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1996-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 __BIF_H__
22 #define __BIF_H__
23 
24 #include "erl_process.h"
25 #include "export.h"
26 
27 extern Export *erts_await_result;
28 extern Export* erts_format_cpu_topology_trap;
29 extern Export *erts_convert_time_unit_trap;
30 
31 #define BIF_RETTYPE Eterm
32 
33 #define BIF_P A__p
34 
35 #define BIF_ALIST Process* A__p, Eterm* BIF__ARGS, ErtsCodePtr A__I
36 #define BIF_CALL_ARGS A__p, BIF__ARGS, A__I
37 
38 #define BIF_ALIST_0 BIF_ALIST
39 #define BIF_ALIST_1 BIF_ALIST
40 #define BIF_ALIST_2 BIF_ALIST
41 #define BIF_ALIST_3 BIF_ALIST
42 #define BIF_ALIST_4 BIF_ALIST
43 
44 #define BIF_ARG_1  (BIF__ARGS[0])
45 #define BIF_ARG_2  (BIF__ARGS[1])
46 #define BIF_ARG_3  (BIF__ARGS[2])
47 #define BIF_ARG_4  (BIF__ARGS[3])
48 
49 #define BIF_I A__I
50 
51 /* NBIF_* is for bif calls from native code... */
52 
53 #define NBIF_ALIST Process* A__p, Eterm* BIF__ARGS
54 #define NBIF_CALL_ARGS A__p, BIF__ARGS
55 
56 #define NBIF_ALIST_0 NBIF_ALIST
57 #define NBIF_ALIST_1 NBIF_ALIST
58 #define NBIF_ALIST_2 NBIF_ALIST
59 #define NBIF_ALIST_3 NBIF_ALIST
60 #define NBIF_ALIST_4 NBIF_ALIST
61 
62 typedef BIF_RETTYPE (*ErtsBifFunc)(BIF_ALIST);
63 
64 #ifdef BEAMASM
65 #define ERTS_REDS_LEFT(p, FCalls) (FCalls)
66 
67 #define ERTS_IS_PROC_OUT_OF_REDS(p)	((p)->fcalls == 0)
68 
69 #define BUMP_REDS(p, gc) do {			   \
70      ASSERT(p);		 			   \
71      ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));\
72      (p)->fcalls -= (gc); 			   \
73      if ((p)->fcalls < 0) { 			   \
74            (p)->fcalls = 0; 			   \
75      } 						   \
76 } while(0)
77 
78 #define BUMP_ALL_REDS(p) do {			\
79     (p)->fcalls = 0; 			\
80     ASSERT(ERTS_BIF_REDS_LEFT((p)) == 0);	\
81 } while(0)
82 
83 #define ERTS_VBUMP_REDS(p, reds)					\
84 do {									\
85 	if ((p)->fcalls >= reds) {					\
86 	    (p)->fcalls -= reds;					\
87 	    erts_proc_sched_data((p))->virtual_reds += reds;		\
88 	}								\
89 	else {								\
90 	    if ((p)->fcalls > 0)					\
91 		erts_proc_sched_data((p))->virtual_reds += (p)->fcalls;	\
92 	    (p)->fcalls = 0;						\
93 	}								\
94 } while(0)
95 
96 
97 #define ERTS_VBUMP_ALL_REDS_INTERNAL(p, fcalls)				\
98 do {									\
99 	if ((fcalls) > 0)						\
100 	    erts_proc_sched_data((p))->virtual_reds += (fcalls);	\
101 	(fcalls) = 0;							\
102 } while(0)
103 
104 #define ERTS_VBUMP_LEAVE_REDS_INTERNAL(P, Reds, FCalls)			\
105     do {								\
106 	    if ((FCalls) > (Reds)) {					\
107 		erts_proc_sched_data((P))->virtual_reds			\
108 		    += (FCalls) - (Reds);				\
109 		(FCalls) = (Reds);					\
110 	    }								\
111     } while (0)
112 
113 #else
114 
115 #define ERTS_REDS_LEFT(p, FCalls)					\
116   (ERTS_PROC_GET_SAVED_CALLS_BUF((p))					\
117    ? ((FCalls) > -CONTEXT_REDS ? ((FCalls) - (-CONTEXT_REDS)) : 0)	\
118    : ((FCalls) > 0 ? (FCalls) : 0))
119 
120 #define ERTS_IS_PROC_OUT_OF_REDS(p)		\
121     ((p)->fcalls > 0				\
122      ? 0					\
123      : (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))	\
124 	? (p)->fcalls == 0			\
125 	: ((p)->fcalls == -CONTEXT_REDS)))
126 
127 #define BUMP_REDS(p, gc) do {			   \
128      ASSERT(p);		 			   \
129      ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));\
130      (p)->fcalls -= (gc); 			   \
131      if ((p)->fcalls < 0) { 			   \
132 	if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p)))   \
133            (p)->fcalls = 0; 			   \
134 	else if ((p)->fcalls < -CONTEXT_REDS)      \
135            (p)->fcalls = -CONTEXT_REDS; 	   \
136      } 						   \
137 } while(0)
138 
139 #define BUMP_ALL_REDS(p) do {			\
140     if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) 	\
141 	(p)->fcalls = 0; 			\
142     else 					\
143 	(p)->fcalls = -CONTEXT_REDS;		\
144     ASSERT(ERTS_BIF_REDS_LEFT((p)) == 0);	\
145 } while(0)
146 
147 #define ERTS_VBUMP_REDS(p, reds)					\
148 do {									\
149     if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) {				\
150 	if ((p)->fcalls >= reds) {					\
151 	    (p)->fcalls -= reds;					\
152 	    erts_proc_sched_data((p))->virtual_reds += reds;		\
153 	}								\
154 	else {								\
155 	    if ((p)->fcalls > 0)					\
156 		erts_proc_sched_data((p))->virtual_reds += (p)->fcalls;	\
157 	    (p)->fcalls = 0;						\
158 	}								\
159     }									\
160     else {								\
161 	if ((p)->fcalls >= reds - CONTEXT_REDS) {			\
162 	    (p)->fcalls -= reds;					\
163 	    erts_proc_sched_data((p))->virtual_reds += reds;		\
164 	}								\
165 	else {								\
166 	    if ((p)->fcalls > -CONTEXT_REDS)				\
167 		erts_proc_sched_data((p))->virtual_reds			\
168 		    += (p)->fcalls - (-CONTEXT_REDS);			\
169 	    (p)->fcalls = -CONTEXT_REDS;				\
170 	}								\
171     }									\
172 } while(0)
173 
174 #define ERTS_VBUMP_ALL_REDS_INTERNAL(p, fcalls)				\
175 do {									\
176     if (!ERTS_PROC_GET_SAVED_CALLS_BUF((p))) {				\
177 	if ((fcalls) > 0)						\
178 	    erts_proc_sched_data((p))->virtual_reds += (fcalls);	\
179 	(fcalls) = 0;							\
180     }									\
181     else {								\
182 	if ((fcalls) > -CONTEXT_REDS)					\
183 	    erts_proc_sched_data((p))->virtual_reds			\
184 		+= ((fcalls) - (-CONTEXT_REDS));			\
185 	(fcalls) = -CONTEXT_REDS;					\
186     }									\
187 } while(0)
188 
189 #define ERTS_VBUMP_LEAVE_REDS_INTERNAL(P, Reds, FCalls)			\
190     do {								\
191 	if (ERTS_PROC_GET_SAVED_CALLS_BUF((P))) {			\
192 	    int nreds__ = ((int)(Reds)) - CONTEXT_REDS;			\
193 	    if ((FCalls) > nreds__) {					\
194 		erts_proc_sched_data((P))->virtual_reds			\
195 		    += (FCalls) - nreds__;				\
196 		(FCalls) = nreds__;					\
197 	    }								\
198 	}								\
199 	else {								\
200 	    if ((FCalls) > (Reds)) {					\
201 		erts_proc_sched_data((P))->virtual_reds			\
202 		    += (FCalls) - (Reds);				\
203 		(FCalls) = (Reds);					\
204 	    }								\
205 	}								\
206     } while (0)
207 
208 #endif
209 
210 #define ERTS_VBUMP_ALL_REDS(p) \
211     ERTS_VBUMP_ALL_REDS_INTERNAL((p), (p)->fcalls)
212 
213 #define ERTS_VBUMP_LEAVE_REDS(P, Reds) \
214     ERTS_VBUMP_LEAVE_REDS_INTERNAL(P, Reds, (P)->fcalls)
215 
216 #define ERTS_BIF_REDS_LEFT(p) \
217     ERTS_REDS_LEFT(p, p->fcalls)
218 
219 #define BIF_RET2(x, gc) do {			\
220     BUMP_REDS(BIF_P, (gc));			\
221     return (x);					\
222 } while(0)
223 
224 #define BIF_RET(x) return (x)
225 
226 #define ERTS_BIF_PREP_RET(Ret, Val) ((Ret) = (Val))
227 
228 #define BIF_ERROR(p,r) do { 			\
229     (p)->freason = r; 				\
230     return THE_NON_VALUE; 			\
231 } while(0)
232 
233 #define ERTS_BIF_ERROR_TRAPPED0(Proc, Reason, Bif)		\
234 do {								\
235     (Proc)->freason = (Reason);					\
236     (Proc)->current = &(Bif)->info.mfa;                         \
237     return THE_NON_VALUE; 					\
238 } while (0)
239 
240 #define ERTS_BIF_ERROR_TRAPPED1(Proc, Reason, Bif, A0)		\
241 do {								\
242     Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;	\
243     (Proc)->freason = (Reason);					\
244     (Proc)->current = &(Bif)->info.mfa;                         \
245     reg[0] = (Eterm) (A0);					\
246     return THE_NON_VALUE; 					\
247 } while (0)
248 
249 #define ERTS_BIF_ERROR_TRAPPED2(Proc, Reason, Bif, A0, A1)	\
250 do {								\
251     Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;	\
252     (Proc)->freason = (Reason);					\
253     (Proc)->current = &(Bif)->info.mfa;                         \
254     reg[0] = (Eterm) (A0);					\
255     reg[1] = (Eterm) (A1);					\
256     return THE_NON_VALUE; 					\
257 } while (0)
258 
259 #define ERTS_BIF_ERROR_TRAPPED3(Proc, Reason, Bif, A0, A1, A2)	\
260 do {								\
261     Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;	\
262     (Proc)->freason = (Reason);					\
263     (Proc)->current = &(Bif)->info.mfa;                         \
264     reg[0] = (Eterm) (A0);					\
265     reg[1] = (Eterm) (A1);					\
266     reg[2] = (Eterm) (A2);					\
267     return THE_NON_VALUE; 					\
268 } while (0)
269 
270 #define ERTS_BIF_PREP_ERROR(Ret, Proc, Reason)	\
271 do {						\
272     (Proc)->freason = (Reason);			\
273     (Ret) = THE_NON_VALUE;			\
274 } while (0)
275 
276 #define ERTS_BIF_PREP_ERROR_TRAPPED0(Ret, Proc, Reason, Bif)	\
277 do {								\
278     (Proc)->freason = (Reason);					\
279     (Proc)->current = &(Bif)->info.mfa;                         \
280     (Ret) = THE_NON_VALUE;					\
281 } while (0)
282 
283 #define ERTS_BIF_PREP_ERROR_TRAPPED1(Ret, Proc, Reason, Bif, A0) \
284 do {								\
285     Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;	\
286     (Proc)->freason = (Reason);					\
287     (Proc)->current = &(Bif)->info.mfa;                         \
288     reg[0] = (Eterm) (A0);					\
289     (Ret) = THE_NON_VALUE;					\
290 } while (0)
291 
292 #define ERTS_BIF_PREP_ERROR_TRAPPED2(Ret, Proc, Reason, Bif, A0, A1) \
293 do {								\
294     Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;	\
295     (Proc)->freason = (Reason);					\
296     (Proc)->current = &(Bif)->info.mfa;                         \
297     reg[0] = (Eterm) (A0);					\
298     reg[1] = (Eterm) (A1);					\
299     (Ret) = THE_NON_VALUE;					\
300 } while (0)
301 
302 #define ERTS_BIF_PREP_ERROR_TRAPPED3(Ret, Proc, Reason, Bif, A0, A1, A2) \
303 do {								\
304     Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;	\
305     (Proc)->freason = (Reason);					\
306     (Proc)->current = &(Bif)->info.mfa;                         \
307     reg[0] = (Eterm) (A0);					\
308     reg[1] = (Eterm) (A1);					\
309     reg[2] = (Eterm) (A2);					\
310     (Ret) = THE_NON_VALUE;					\
311 } while (0)
312 
313 
314 #ifdef BEAMASM
315 
316 /* See `emit_bif_export_trap` for details. */
317 extern ErtsCodePtr beam_bif_export_trap;
318 #define ERTS_BIF_PREP_TRAP(Export, Proc, Arity)                               \
319     do {                                                                      \
320         (Proc)->i = beam_bif_export_trap;                                     \
321         (Proc)->arity = (Arity);                                              \
322         (Proc)->freason = TRAP;                                               \
323         (Proc)->current = &(Export)->info.mfa;                                \
324     } while(0);
325 
326 #else /* defined(BEAMASM) */
327 
328 #define ERTS_BIF_PREP_TRAP(Export, Proc, Arity)                               \
329     do {                                                                      \
330         (Proc)->i = (Export)->addresses[erts_active_code_ix()];               \
331         (Proc)->arity = (Arity);                                              \
332         (Proc)->freason = TRAP;                                               \
333     } while(0);
334 
335 #endif /* !defined(BEAMASM) */
336 
337 #define ERTS_BIF_PREP_TRAP0(Ret, Trap, Proc)                                  \
338     do {                                                                      \
339         ERTS_BIF_PREP_TRAP((Trap), (Proc), 0);                                \
340         (Ret) = THE_NON_VALUE;                                                \
341     } while (0)
342 
343 #define ERTS_BIF_PREP_TRAP1(Ret, Trap, Proc, A0)                              \
344     do {                                                                      \
345         Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;  \
346         ERTS_BIF_PREP_TRAP((Trap), (Proc), 1);                                \
347         reg[0] = (Eterm) (A0);                                                \
348         (Ret) = THE_NON_VALUE;                                                \
349     } while (0)
350 
351 #define ERTS_BIF_PREP_TRAP2(Ret, Trap, Proc, A0, A1)                          \
352     do {                                                                      \
353         Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;  \
354         ERTS_BIF_PREP_TRAP((Trap), (Proc), 2);                                \
355         reg[0] = (Eterm) (A0);                                                \
356         reg[1] = (Eterm) (A1);                                                \
357         (Ret) = THE_NON_VALUE;                                                \
358     } while (0)
359 
360 #define ERTS_BIF_PREP_TRAP3(Ret, Trap, Proc, A0, A1, A2)                      \
361     do {                                                                      \
362         Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;  \
363         ERTS_BIF_PREP_TRAP((Trap), (Proc), 3);                                \
364         reg[0] = (Eterm) (A0);                                                \
365         reg[1] = (Eterm) (A1);                                                \
366         reg[2] = (Eterm) (A2);                                                \
367         (Ret) = THE_NON_VALUE;                                                \
368     } while (0)
369 
370 #define ERTS_BIF_PREP_TRAP4(Ret, Trap, Proc, A0, A1, A2, A3)                  \
371     do {                                                                      \
372         Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;  \
373         ERTS_BIF_PREP_TRAP((Trap), (Proc), 4);                                \
374         reg[0] = (Eterm) (A0);                                                \
375         reg[1] = (Eterm) (A1);                                                \
376         reg[2] = (Eterm) (A2);                                                \
377         reg[3] = (Eterm) (A3);                                                \
378         (Ret) = THE_NON_VALUE;                                                \
379     } while (0)
380 
381 #define ERTS_BIF_PREP_TRAP3_NO_RET(Trap, Proc, A0, A1, A2)                    \
382     do {                                                                      \
383         Eterm* reg = erts_proc_sched_data((Proc))->registers->x_reg_array.d;  \
384         ERTS_BIF_PREP_TRAP((Trap), (Proc), 3);                                \
385         reg[0] = (Eterm) (A0);                                                \
386         reg[1] = (Eterm) (A1);                                                \
387         reg[2] = (Eterm) (A2);                                                \
388     } while (0)
389 
390 #define BIF_TRAP0(Trap_, p)                                                   \
391     do {                                                                      \
392         ERTS_BIF_PREP_TRAP((Trap_), (p), 0);                                  \
393         return THE_NON_VALUE;                                                 \
394     } while(0)
395 
396 #define BIF_TRAP1(Trap_, p, A0)                                               \
397     do {                                                                      \
398         Eterm* reg = erts_proc_sched_data((p))->registers->x_reg_array.d;     \
399         ERTS_BIF_PREP_TRAP((Trap_), (p), 1);                                  \
400         reg[0] = (A0);                                                        \
401         return THE_NON_VALUE;                                                 \
402     } while(0)
403 
404 #define BIF_TRAP2(Trap_, p, A0, A1)                                           \
405     do {                                                                      \
406         Eterm* reg = erts_proc_sched_data((p))->registers->x_reg_array.d;     \
407         ERTS_BIF_PREP_TRAP((Trap_), (p), 2);                                  \
408         reg[0] = (A0);                                                        \
409         reg[1] = (A1);                                                        \
410         return THE_NON_VALUE;                                                 \
411     } while(0)
412 
413 #define BIF_TRAP3(Trap_, p, A0, A1, A2)                                       \
414         do {                                                                  \
415         Eterm* reg = erts_proc_sched_data((p))->registers->x_reg_array.d;     \
416         ERTS_BIF_PREP_TRAP((Trap_), (p), 3);                                  \
417         reg[0] = (A0);                                                        \
418         reg[1] = (A1);                                                        \
419         reg[2] = (A2);                                                        \
420         return THE_NON_VALUE;                                                 \
421     } while(0)
422 
423 #define BIF_TRAP4(Trap_, p, A0, A1, A2, A3)                                   \
424     do {                                                                      \
425         Eterm* reg = erts_proc_sched_data((p))->registers->x_reg_array.d;     \
426         ERTS_BIF_PREP_TRAP((Trap_), (p), 4);                                  \
427         reg[0] = (A0);                                                        \
428         reg[1] = (A1);                                                        \
429         reg[2] = (A2);                                                        \
430         reg[3] = (A3);                                                        \
431         return THE_NON_VALUE;                                                 \
432     } while(0)
433 
434 #define BIF_TRAP_CODE_PTR(p, Code_, Arity_)                                   \
435     do {                                                                      \
436         (p)->arity = (Arity_);                                                \
437         (p)->i = (Code_);                                                     \
438         (p)->freason = TRAP;                                                  \
439         return THE_NON_VALUE;                                                 \
440     } while(0)
441 
442 extern Export bif_return_trap_export;
443 #define ERTS_BIF_PREP_YIELD_RETURN_X(RET, P, VAL, OP)			\
444 do {									\
445     ERTS_VBUMP_ALL_REDS(P);						\
446     ERTS_BIF_PREP_TRAP2(RET, &bif_return_trap_export, (P), (VAL), (OP));\
447 } while (0)
448 
449 #define ERTS_BIF_PREP_YIELD_RETURN(RET, P, VAL) \
450   ERTS_BIF_PREP_YIELD_RETURN_X(RET, (P), (VAL), am_undefined)
451 
452 #define ERTS_BIF_YIELD_RETURN_X(P, VAL, OP)				\
453 do {									\
454     ERTS_VBUMP_ALL_REDS(P);						\
455     BIF_TRAP2(&bif_return_trap_export, (P), (VAL), (OP));		\
456 } while (0)
457 
458 #define ERTS_BIF_RETURN_YIELD(P) ERTS_VBUMP_ALL_REDS((P))
459 
460 #define ERTS_BIF_YIELD_RETURN(P, VAL) \
461   ERTS_BIF_YIELD_RETURN_X((P), (VAL), am_undefined)
462 
463 #define ERTS_BIF_PREP_YIELD0(RET, TRP, P)				\
464 do {									\
465     ERTS_VBUMP_ALL_REDS((P));						\
466     ERTS_BIF_PREP_TRAP0(RET, (TRP), (P));				\
467 } while (0)
468 
469 #define ERTS_BIF_PREP_YIELD1(RET, TRP, P, A0)				\
470 do {									\
471     ERTS_VBUMP_ALL_REDS((P));						\
472     ERTS_BIF_PREP_TRAP1(RET, (TRP), (P), (A0));				\
473 } while (0)
474 
475 #define ERTS_BIF_PREP_YIELD2(RET, TRP, P, A0, A1)			\
476 do {									\
477     ERTS_VBUMP_ALL_REDS((P));						\
478     ERTS_BIF_PREP_TRAP2(RET, (TRP), (P), (A0), (A1));			\
479 } while (0)
480 
481 #define ERTS_BIF_PREP_YIELD3(RET, TRP, P, A0, A1, A2)			\
482 do {									\
483     ERTS_VBUMP_ALL_REDS((P));						\
484     ERTS_BIF_PREP_TRAP3(RET, (TRP), (P), (A0), (A1), (A2));		\
485 } while (0)
486 
487 #define ERTS_BIF_PREP_YIELD4(RET, TRP, P, A0, A1, A2, A3)		\
488 do {									\
489     ERTS_VBUMP_ALL_REDS((P));						\
490     ERTS_BIF_PREP_TRAP4(RET, (TRP), (P), (A0), (A1), (A2), (A3));       \
491 } while (0)
492 
493 #define ERTS_BIF_YIELD0(TRP, P)						\
494 do {									\
495     ERTS_VBUMP_ALL_REDS((P));						\
496     BIF_TRAP0((TRP), (P));                                              \
497 } while (0)
498 
499 #define ERTS_BIF_YIELD1(TRP, P, A0)					\
500 do {									\
501     ERTS_VBUMP_ALL_REDS((P));						\
502     BIF_TRAP1((TRP), (P), (A0));					\
503 } while (0)
504 
505 #define ERTS_BIF_YIELD2(TRP, P, A0, A1)					\
506 do {									\
507     ERTS_VBUMP_ALL_REDS((P));						\
508     BIF_TRAP2((TRP), (P), (A0), (A1));					\
509 } while (0)
510 
511 #define ERTS_BIF_YIELD3(TRP, P, A0, A1, A2)				\
512 do {									\
513     ERTS_VBUMP_ALL_REDS((P));						\
514     BIF_TRAP3((TRP), (P), (A0), (A1), (A2));				\
515 } while (0)
516 
517 #define ERTS_BIF_YIELD4(TRP, P, A0, A1, A2, A3)				\
518 do {									\
519     ERTS_VBUMP_ALL_REDS((P));						\
520     BIF_TRAP4((TRP), (P), (A0), (A1), (A2), (A3));                      \
521 } while (0)
522 
523 extern Export erts_bif_handle_signals_return_export;
524 
525 #define ERTS_BIF_HANDLE_SIGNALS_RETURN(P, VAL)                          \
526     BIF_TRAP1(&erts_bif_handle_signals_return_export, (P), (VAL))
527 
528 #define ERTS_BIF_PREP_HANDLE_SIGNALS_RETURN(Ret, P, Val)                \
529     ERTS_BIF_PREP_TRAP1((Ret), &erts_bif_handle_signals_return_export,  \
530                         (P), (Val))
531 
532 #define ERTS_BIF_PREP_EXITED(RET, PROC)	                                \
533 do {                                                                    \
534     KILL_CATCHES((PROC));                                               \
535     ERTS_BIF_PREP_ERROR((RET), (PROC), EXTAG_EXIT);                     \
536 } while (0)
537 
538 #define ERTS_BIF_EXITED(PROC)		\
539 do {					\
540     KILL_CATCHES((PROC));		\
541     BIF_ERROR((PROC), EXTAG_EXIT);	\
542 } while (0)
543 
544 #define ERTS_BIF_CHK_EXITED(PROC)	\
545 do {					\
546     if (ERTS_PROC_IS_EXITING((PROC)))	\
547 	ERTS_BIF_EXITED((PROC));	\
548 } while (0)
549 
550 int erts_call_dirty_bif(ErtsSchedulerData *esdp, Process *c_p,
551                         ErtsCodePtr I, Eterm *reg);
552 
553 BIF_RETTYPE
554 erts_schedule_bif(Process *proc,
555 		  Eterm *argv,
556 		  ErtsCodePtr i,
557 		  const ErtsCodeMFA *mfa,
558 		  ErtsBifFunc dbf,
559 		  ErtsSchedType sched_type,
560 		  Eterm mod,
561 		  Eterm func,
562 		  int argc);
563 
564 ERTS_GLB_INLINE BIF_RETTYPE
565 erts_reschedule_bif(Process *proc,
566 		    Eterm *argv,
567 		    ErtsCodePtr i,
568 		    const ErtsCodeMFA *mfa,
569 		    ErtsBifFunc dbf,
570 		    ErtsSchedType sched_type);
571 
572 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
573 
574 ERTS_GLB_INLINE BIF_RETTYPE
erts_reschedule_bif(Process * proc,Eterm * argv,ErtsCodePtr i,const ErtsCodeMFA * mfa,ErtsBifFunc dbf,ErtsSchedType sched_type)575 erts_reschedule_bif(Process *proc,
576 		    Eterm *argv,
577 		    ErtsCodePtr i,
578 		    const ErtsCodeMFA *mfa,
579 		    ErtsBifFunc dbf,
580 		    ErtsSchedType sched_type)
581 {
582     return erts_schedule_bif(proc, argv, i, mfa, dbf, sched_type,
583 			     THE_NON_VALUE, THE_NON_VALUE, -1);
584 }
585 
586 #endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
587 
588 Uint16 erts_monitor_opts(Eterm opts, Eterm *tag);
589 
590 #include "erl_bif_table.h"
591 
592 #endif
593