1/* BEGIN LICENSE BLOCK
2 * Version: CMPL 1.1
3 *
4 * The contents of this file are subject to the Cisco-style Mozilla Public
5 * License Version 1.1 (the "License"); you may not use this file except
6 * in compliance with the License.  You may obtain a copy of the License
7 * at www.eclipse-clp.org/license.
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11 * the License for the specific language governing rights and limitations
12 * under the License.
13 *
14 * The Original Code is  The ECLiPSe Constraint Logic Programming System.
15 * The Initial Developer of the Original Code is  Cisco Systems, Inc.
16 * Portions created by the Initial Developer are
17 * Copyright (C) 1994-2006 Cisco Systems, Inc.  All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * END LICENSE BLOCK */
22
23/**********************************************************************
24**      System: Parallel ECLiPSe Scheduler
25**        File: sch_macros.h
26**      Author: Liang-Liang Li
27** Description: Macro Definitions
28**
29***********************************************************************/
30
31/**********************************************************************
32** Runtime Consistency Checking
33***********************************************************************/
34
35#if defined(__STDC__)
36/*
37    extern int fprintf(FILE * stream, const char * format, ...);
38    extern int printf(const char * format, ...);
39*/
40#else /* __STDC__ */
41    extern int fprintf();
42    extern int printf();
43#endif /* __STDC__ */
44
45#if defined(PRINTAM)
46
47#define assert(ex) {					\
48    if (!(ex)) {					\
49	void sch_break();				\
50	sch_break();					\
51        (void) fprintf(stderr, "Assertion Failed at ");	\
52        (void) fprintf(stderr, "file \"%s\"", __FILE__);\
53        (void) fprintf(stderr, " line %d\n", __LINE__); \
54	(void) ec_panic("Assertion Failed", "Scheduler");	\
55    }							\
56}
57#else /* PRINTAM */
58#define assert(ex)
59#endif /* PRINTAM */
60
61#define error(err) {                                    \
62        (void) fprintf(stderr, "error: \"%s\"", (err)); \
63        assert(zero());                                 \
64}
65
66
67#if defined(__STDC__)
68int global_flags(int,int);
69#else /* __STDC__ */
70int global_flags();
71#endif /* __STDC__ */
72
73#define SCH_TRACE_FLAG  0x00000008
74#define sch_trace_on (global_flags(0,0)&SCH_TRACE_FLAG)
75
76#if defined(SDEBUG) || defined(NSHDLNOTICE)
77
78#define Sch_Trace_Begin()
79#define Sch_Event_Notify1(name, type, t1)
80#define Sch_Event_Notify2(name, type, t1, t2)
81#define Sch_Event_Notify3(name, type, t1, t2, t3)
82
83#else /* SDEBUG || NSHDLNOTICE */
84
85#define Sch_Trace_Begin() {	\
86	printf("BEGIN\n");	\
87}
88#define Sch_Event_Notify1(name, type, t1) {				\
89    if (sch_trace_on)							\
90	printf( "%s %s ' %" W_MOD "x %" W_MOD "x %" W_MOD "x '\n", name, type,			\
91	   (uword)Site(t1),(uword)Knot(t1),(uword)Edge(t1));	\
92}
93#define Sch_Event_Notify2(name, type, t1, t2) {				\
94    if (sch_trace_on)							\
95	printf("%s %s ' %" W_MOD "x %" W_MOD "x %" W_MOD "x '  ' %" W_MOD "x %" W_MOD "x %" W_MOD "x '\n", name, type,	\
96	   (uword)Site(t1),(uword)Knot(t1),(uword)Edge(t1),	\
97	   (uword)Site(t2),(uword)Knot(t2),(uword)Edge(t2));	\
98}
99#define Sch_Event_Notify3(name, type, t1, t2, t3) {			\
100    if (sch_trace_on)							\
101	printf("%s %s ' %" W_MOD "x %" W_MOD "x %" W_MOD "x '  ' %" W_MOD "x %" W_MOD "x %" W_MOD "x '  ' %" W_MOD "x %" W_MOD "x %" W_MOD "x '\n", name, type, \
102	   (uword)Site(t1),(uword)Knot(t1),(uword)Edge(t1),	\
103	   (uword)Site(t2),(uword)Knot(t2),(uword)Edge(t2),	\
104	   (uword)Site(t3),(uword)Knot(t3),(uword)Edge(t3));	\
105}
106#endif /* SDEBUG || NSHDLNOTICE */
107
108#define Smsg_Hdl_Notify(smsg, recv, send) {		\
109	if (ComnSite((recv),(send)))			\
110	    Scheduler(Site(recv))->smsg_count_intra++;	\
111	Scheduler(Site(recv))->smsg_count_hdl++;	\
112	Scheduler(Site(recv))->smsg_subcount[smsg]++;	\
113	Sch_Event_Notify2("RECV_SMSG",smsg_name[(smsg)], (send), (recv)); \
114}
115#define Smsg_Snd_Notify(smsg, recv, send) {		\
116	Scheduler(Site(send))->smsg_count_snd++;	\
117	Sch_Event_Notify2("SEND_SMSG",smsg_name[(smsg)], (send), (recv)); \
118}
119
120#define InitSchOffset(site) (Scheduler(site)->sch_base = 0)
121#define Scheduler(site)     (&(scheduler[(site)-(site)]))
122#define LeafEngine(leaf)    (Scheduler(Site(leaf))->engine)
123#define SiteLeaf(site)      ((st_id_t *)&(Scheduler(site)->leaf))
124#define NewSiteLeaf(leaf)   {			\
125	Scheduler(Site(leaf))->lmp = 0;		\
126	*SiteLeaf(Site(leaf)) = *(leaf);	\
127}
128
129/* Info about a scheduler branch (subtree) */
130#define INFO_LIFE	0x0f
131#define INFO_LMP	0x10
132#define INFO_RICH	0x20
133#define INFO_POOR_SPINE	0x40
134
135/* Life status of a scheduler branch */
136#define ST_ALIVE        0x1
137#define ST_CHOPPED      0x2
138#define ST_LODGED       0x3
139#define ST_CUT          0x4
140#define ST_BACKTRACK    0x6
141#define ST_DYING        0x7
142#define ST_DEAD         0x8
143#define ST_INIT         0x9
144#define ST_IDLE         0xa
145#define ST_IDLING       0xb
146
147/* (st_id_t *) '(t)' */
148#define PackSite(t,s)	(Site(t) = (s))
149#define PackKnot(t,k) ((t)->knot = (uword)(k)-Scheduler(Site(t))->sch_base)
150#define PackEdge(t,e) ((t)->edge = (uword)(e)-Scheduler(Site(t))->sch_base)
151
152#define Site(t) ((t)->site)
153#define Knot(t) ((st_knot_t *)(Scheduler(Site(t))->sch_base + (t)->knot))
154#define Edge(t) ((st_edge_t *)(Scheduler(Site(t))->sch_base + (t)->edge))
155
156#define ComnSite(t1,t2) (Site(t1)==Site(t2))
157#define ComnKnot(t1,t2) (Knot(t1)==Knot(t2))
158#define ComnEdge(t1,t2) (Edge(t1)==Edge(t2))
159
160/* Trunk: the edge leading to the suptree;
161** Twig : the edge leading to one subtree.
162*/
163#define Trunk(t) (&(Knot(t)->trunk))
164#define Twig(t) Edge(t)
165
166#define SupTree(t) (&(Trunk(t)->tree))
167#define SubTree(t) (&(Twig(t)->tree))
168
169#define K2T(k) ((st_edge_t *) (k))
170#define T2K(b) ((st_knot_t *) (b))
171
172#define IsLeaf(t) (Knot(t)->tip)
173#define IsNode(t) (!IsLeaf(t))
174
175#define SchRoot(t) (Knot(t)==Knot(SupTree(t))&&ComnSite((t),SupTree(t)))
176#define JsRoot(t) (Knot(t)->jroot)
177#define PsRoot(t) (Knot(t)->proot)
178#define Local(t) (Knot(t)->local)
179#define Hybrid(t) (Knot(t)->hybrid)
180#define SetJsRoot(t) (Knot(t)->jroot = 1)
181#define ResetJsRoot(t) (Knot(t)->jroot = 0)
182#define SetPsRoot(t) (Knot(t)->proot = 1)
183#define ResetPsRoot(t) (Knot(t)->proot = 0)
184#define SetLocal(t) (Knot(t)->local = 1)
185#define ResetLocal(t) (Knot(t)->local = 0)
186
187#define Twigless(t) (Trunk(t)==Trunk(t)->next)
188#define SetTwigless(t)  {Trunk(t)->next = Trunk(t); Trunk(t)->prev = Trunk(t);}
189
190#define Exhausted(t) (!Knot(t)->nxtcls)
191#define SetExhausted(t) { Knot(t)->nxtcls = 0; Knot(t)->nxtcls_b = 0; }
192#define Tk_NextClause(t)  (Knot(t)->nxtcls   ? Knot(t)->nxtcls-- : 0)
193#define Bk_NextClause(t)  (Knot(t)->nxtcls_b ? Knot(t)->nxtcls_b-- : 0)
194#define Bk_NextClause0(t) { if (Knot(t)->nxtcls_b) Knot(t)->nxtcls_b--; }
195
196#define AliveTwigs(t) (Knot(t)->alive_twigs)
197#define Monad(t) (AliveTwigs(t)==1)
198#define YoungestTwig(t) (Trunk(t)->prev == Twig(t))
199
200#define Suspended(t) (Knot(t)->suspended)
201
202#define NilTreeId(t) (PackSite(t,0))
203#define IsNilTreeId(t) (Site(t)==0)
204
205/* The super tree area for an incarnated leaf is overloaded to
206** point to its corpse. This is needed only for handling 'cut'.
207*/
208#define Corpse(t) SupTree(t)
209
210#define Life(b)		((b)->info & INFO_LIFE)
211#define Rest(b)		((b)->info & ~INFO_LIFE)
212
213#define Alive(b)	(Life(b) == ST_ALIVE)
214#define Chopped(b)	(Life(b) == ST_CHOPPED)
215#define Lodged(b)	(Life(b) == ST_LODGED)
216#define Idle(b)		(Life(b) == ST_IDLE)
217#define Idling(b)	(Life(b) == ST_IDLING)
218#define Dying(b)	(Life(b) == ST_DYING)
219#define SetAlive(b)	((b)->info = (Rest(b) | ST_ALIVE))
220#define SetNalive(b,s) { (b)->info = (Rest(b) | (s)); SetPoor(b); }
221
222#define PoorSpine(t)	(Trunk(t)->info &  INFO_POOR_SPINE)
223#define SetPoorSpine(t)	(Trunk(t)->info |= INFO_POOR_SPINE)
224#define SetRichSpine(t)	(Trunk(t)->info &= ~INFO_POOR_SPINE)
225
226#define Rich(b)		((b)->info & INFO_RICH)
227#define Eldest(b)	((b)->info & INFO_LMP)
228#define SetRich(b)	((b)->info |= INFO_RICH)
229#define SetEldest(b)	((b)->info |= INFO_LMP)
230#define SetPoor(b)	((b)->info &= ~INFO_RICH)
231#define ResetEldest(b)	((b)->info &= ~INFO_LMP)
232
233
234#define Reincarnat(old,new) {			\
235	*Corpse(new) = *(old);			\
236	SetNalive(Trunk(new), ST_CUT);		\
237	SetNalive(Trunk(old), ST_DYING);	\
238	ResetJsRoot(old);			\
239	assert(!Suspended(old));		\
240	Suspended(new) = (st_susp_t *) 0;	\
241}
242
243#define Quit_Chain(b) {				\
244	(b)->prev->next = (b)->next;		\
245	(b)->next->prev = (b)->prev;		\
246}
247
248#if defined(PRINTAM)
249
250#define check_no_duplicate(b,n) {			\
251	st_edge_t *x = (n);				\
252	do {						\
253	   assert(x != (b));				\
254	   x = x->next;					\
255	} while (x != (n));				\
256}
257#else /* PRINTAM */
258#define check_no_duplicate(b,n)
259#endif /* PRINTAM */
260
261#define Join_Chain_Next(b,n) {			\
262	/* check_no_duplicate((b),(n)); */	\
263	(b)->next = (n)->next;			\
264	(b)->prev = (n);			\
265	(n)->next = (b);			\
266	(b)->next->prev = (b);			\
267}
268
269/* Create an alive twig, leading to a leaf
270** Add_Alive_Twig(st_id_t *, st_id_t *, st_knot_t *)
271*/
272
273#define Add_Alive_Twig_Next(twig,leaf,knot,next) {\
274	Sch_Alloc_Edge(Site(knot),(twig));	\
275	PackKnot((twig),(knot));		\
276	SetAlive(Edge(twig));			\
277        *SubTree(twig) = *(leaf);		\
278	Join_Chain_Next(Edge(twig),(next));	\
279	(knot)->alive_twigs++;			\
280}
281
282/* Add_Lodge_Twig(st_id_t *,st_id_t *,st_knot_t *)
283*/
284#define Add_Lodge_Twig(twig,leaf,knot) {	\
285	Sch_Alloc_Edge(Site(knot),(twig));	\
286	PackKnot((twig),(knot));		\
287						\
288        SetNalive(Edge(twig),ST_LODGED);	\
289        *SubTree(twig) = *(leaf);		\
290						\
291	Join_Chain_Next(Edge(twig),Trunk(twig)->prev);\
292}
293
294/* Intra-Site scheduler message flows are to be short-cut.
295** A special attention is given to the tail-recursive cases.
296** And assume atomic msg handling supported.
297*/
298
299#if !defined(NO_SHORTCUT)
300/*
301** void Smsg_ShortCut_Mid(st_id_t *,st_id_t *,void,void)
302**      this function will not give up holding the 'from'
303*/
304#define Smsg_ShortCut_Mid(from,to,hdl,snd) {	\
305	if ( ComnSite((from),(to)) &&		\
306	     (!Intrasite_Smsg(Site(from))) &&	\
307	     Sch_Lock(to) ) {			\
308	   Inc_ShortCut_Count(Site(from));	\
309	   (hdl);				\
310	} else  {				\
311	   (snd);				\
312	}					\
313}
314
315/*
316** void Smsg_ShortCut_End(st_id_t *, st_id_t *,void,void)
317**      this function will give up holding 'from'
318*/
319#define Smsg_ShortCut_End(from,to,hdl,snd) {	\
320	if ( ComnSite((from),(to)) &&		\
321	     (!Intrasite_Smsg(Site(from))) &&	\
322	     Sch_Lock(to) ) {			\
323	   Sch_Unlock(from);			\
324	   Inc_ShortCut_Count(Site(from));	\
325	   (hdl);				\
326	} else {				\
327           (snd);				\
328           Sch_Unlock(from);			\
329        }					\
330}
331
332#else /* NO_SHORTCUT */
333
334/*
335** void Smsg_ShortCut_Mid(st_id_t *,st_id_t *,void,void)
336**      this function will not give up holding the 'from'
337*/
338#define Smsg_ShortCut_Mid(from,to,hdl,snd) (snd)
339
340/*
341** void Smsg_ShortCut_End(st_id_t *, st_id_t *,void,void)
342**      this function will give up holding 'from'
343*/
344#define Smsg_ShortCut_End(from,to,hdl,snd) {	\
345        (snd);					\
346        Sch_Unlock(from);			\
347}
348
349#endif  /* NO_SHORTCUT */
350
351#define Sch_JS_Install(self, lodg, coma, leaf) {	\
352	st_id_t twig;					\
353	st_edge_t *x = Trunk(self)->prev;		\
354	st_edge_t *y = (st_edge_t *) 0;			\
355	while (x != Trunk(self)) {			\
356	   if (Alive(x)||Idle(x)) {			\
357	      y = x;					\
358	      if (ComnSite(self,&(x->tree)))		\
359		 break;					\
360	   }						\
361           x = x->prev;					\
362	}						\
363	if (y) {					\
364	   twig = *(self);				\
365	   PackEdge(&twig,y);				\
366	   Smsg_ShortCut_End(&twig, SubTree(&twig),	\
367sch_msg_hdl_js_install(SubTree(&twig),&twig,(lodg),(coma),(leaf)),	\
368sch_msg_snd_js_install(SubTree(&twig),&twig,(lodg),(coma),(leaf))	\
369		);					\
370	   return;					\
371	}						\
372}
373
374#if defined(PRINTAM)
375#define CheckAllPoor(x) {				\
376	st_edge_t *y = (x)->next;			\
377	while (y!=(x)) {				\
378	   assert(!Alive(y) || !Rich(y));		\
379	   y = y->next;					\
380	}						\
381}
382#else /* PRINTAM */
383#define CheckAllPoor(x)
384#endif /* PRINTAM */
385
386
387#define Sch_JS_Trav_Up(self,coma,leaf)	{		\
388	if (!Alive(Trunk(self)) ||			\
389	   (!JsRoot(self) && !(Local(self) && ComnSite((self),(leaf))))) { \
390	   st_id_t *ncoma = (coma);			\
391	   if (ComnNode((self),(coma))) {		\
392	      ncoma = SupTree(self);			\
393	      SetPoorSpine(self);			\
394	   }						\
395	   Smsg_ShortCut_End((self), SupTree(self),	\
396		sch_msg_hdl_js_trav_up(SupTree(self),(self),ncoma,(leaf)),\
397		sch_msg_snd_js_trav_up(SupTree(self),(self),ncoma,(leaf))\
398	       );					\
399	} else if (AliveTwigs(self) ||			\
400		  !(Local(self) && ComnSite((self),(leaf)))) { \
401	   st_susp_t *x;				\
402	   CheckAllPoor(Trunk(self));			\
403	   Sch_Alloc_Suspended(Site(self), x);		\
404	   x->next = Suspended(self);			\
405	   x->leaf = *(leaf);				\
406	   x->coma = *(coma);				\
407	   Suspended(self) = x;				\
408	   if (JsRoot(self))				\
409	      SetRich(Trunk(self));			\
410	   Sch_Unlock(self);				\
411	} else {					\
412	   int alt0 = Hybrid(self) ? (-1):0;		\
413	   SetNalive(Trunk(self), ST_DYING);		\
414	   Smsg_ShortCut_End((self),SupTree(self),	\
415		sch_msg_hdl_straighten(SupTree(self),(self),(leaf),(self),alt0),\
416		sch_msg_snd_straighten(SupTree(self),(self),(leaf),(self),alt0) \
417		);					\
418	}						\
419}
420
421#define Next_X(s,x) ((Scheduler(s)->left_first) ? (x)->next : (x)->prev)
422#define Sch_JS_Trav_Down(self,coma,leaf)	{	\
423	if (Rich(Trunk(self))) {			\
424	   st_edge_t *x = Next_X(Site(self),Trunk(self));\
425	   st_id_t twig;				\
426	   while (x != Trunk(self)) {			\
427	      if (Alive(x) && Rich(x)) {		\
428		 twig = *self;				\
429		 PackEdge(&twig,x);			\
430		 Smsg_ShortCut_End(&twig, SubTree(&twig),\
431	      sch_msg_hdl_js_trav_dn(SubTree(&twig),&twig,(coma),(leaf)),\
432	      sch_msg_snd_js_trav_dn(SubTree(&twig),&twig,(coma),(leaf))\
433		      );				\
434		 return;				\
435	      }						\
436	      x = Next_X(Site(self), x);		\
437	   }						\
438	   if (!Knot(self)->nxtcls_b && !JsRoot(self)) {\
439	      SetPoor(Trunk(self));			\
440	   }						\
441	}						\
442}
443
444#define Sch_WakeUp_Suspended(self) {			\
445	   st_susp_t * x;				\
446	   while (x= Suspended(self)) {			\
447	      Smsg_ShortCut_Mid((self),&(x->leaf),	\
448		   sch_msg_hdl_js_in_vain(&(x->leaf),(self)),	\
449		   sch_msg_snd_js_in_vain(&(x->leaf),(self))	\
450	          );					\
451	      Suspended(self) = x->next;		\
452	      Sch_Gc_Suspended(Site(self),x);		\
453	   }						\
454}
455
456#define Sch_Alloc_Knot(s,t) {				\
457	Sch_Alloc_Edge((s),(t))				\
458	PackKnot((t),T2K(Edge(t)));			\
459	*Knot(t) = *knot_template;			\
460	SetTwigless(t);					\
461}
462
463#define Sch_Gc_Knot(t) Sch_Gc_Edge(Site(t),Trunk(t))
464
465#define Sch_Alloc_Edge(site, tree) {			\
466	edge_buffer_t *b = &(Scheduler(site)->edge_buffer); \
467	if (b->count > 20 && Simp_Lock(b)) {		\
468	    b->count--;					\
469	    PackEdge((tree),b->head.trunk.prev);	\
470	    Quit_Chain(Edge(tree));			\
471	    Simp_Unlock(b);				\
472	} else {					\
473	    PackEdge((tree), (st_edge_t *)		\
474			hp_alloc(sizeof(st_knot_t)));	\
475	}						\
476	PackSite((tree),(site));			\
477	Edge(tree)->info = 0;				\
478}
479
480#if !defined(SEPARATE_INSTALL)
481#define None_Install_Req(leaf)
482#else /* SEPARATE_INSTALL */
483#define None_Install_Req(leaf) assert(!Install_Req(Site(leaf)))
484#define Install_Req(site) (Scheduler(site)->install_req)
485#define Sch_Gc_Inst_Req(site, req)   (hp_free((void *)(req)))
486#define Sch_Alloc_Inst_Req(site, req) 			\
487	((req) = (install_req_t *) hp_alloc(sizeof(install_req_t)))
488#endif /* SEPARATE_INSTALL */
489
490
491#define Sch_Gc_Edge(site, edge) {			\
492	edge_buffer_t *b = &(Scheduler(site)->edge_buffer); \
493	if (b->count < 1000 && Simp_Lock(b)) {		\
494	   b->count++;					\
495	   Join_Chain_Next((edge), K2T(&(b->head)));	\
496	   Simp_Unlock(b);				\
497	} else						\
498	hp_free((void *)(edge));			\
499}
500
501#define Sch_Alloc_Suspended(site, susp) {		\
502	susp_buffer_t *b = &(Scheduler(site)->susp_buffer); \
503	if (Simp_Lock(b)) {				\
504	   if (b->count) {				\
505	      b->count--;				\
506	      (susp) = b->next;				\
507	      b->next = (susp)->next;			\
508	   } else {					\
509	      Simp_Unlock(b);				\
510	      (susp) = (st_susp_t *)			\
511			hp_alloc(sizeof(st_susp_t));	\
512	   }						\
513	} else						\
514	   (susp) = (st_susp_t *)			\
515			hp_alloc(sizeof(st_susp_t));	\
516}
517
518#define Sch_Gc_Suspended(site, susp) {		\
519	susp_buffer_t *b = &(Scheduler(site)->susp_buffer); \
520	if (Simp_Lock(b)) {			\
521	   b->count++;				\
522	   (susp)->next = b->next;		\
523	   b->next = (susp);			\
524	   Simp_Unlock(b);			\
525	} else					\
526	hp_free((void *)(susp));		\
527}
528
529#if defined(PROLOG_LMP)
530#define CheckLmp(twig) {				\
531	if (Eldest(Trunk(twig)) && Monad(twig))		\
532	   SetEldest(Twig(twig));			\
533	else 						\
534	   ResetEldest(Twig(twig));			\
535}
536
537#define UpdateLmp(old) {				\
538	if (Eldest(Twig(old)) && !Monad(old)) {		\
539	   st_id_t new;					\
540	   st_edge_t *x = Twig(old)->next;		\
541	   do {						\
542	      if (Alive(x)) {				\
543		 PackSite(&new,(old));			\
544		 PackKnot(&new,Knot(old));		\
545		 PackEdge(&new,x);			\
546		 SetEldest(x);				\
547		 Smsg_ShortCut_Mid(&new, SubTree(&new),	\
548		      sch_msg_hdl_lmp(SubTree(&new), &new),\
549		      sch_msg_snd_lmp(SubTree(&new), &new) \
550		     );					\
551		 break;					\
552	      } else 					\
553	         x = x->next;				\
554	   } while (x!=Trunk(old)) {			\
555	   assert(x!=Trunk(old));			\
556	   ResetEldest(Twig(old));			\
557	}						\
558}
559#else /* PROLOG_LMP */
560#define CheckLmp(twig)
561#define UpdateLmp(twig)
562#endif /* PROLOG_LMP */
563
564#if !defined(NO_SHORTCUT)
565#define Intrasite_Smsg(site)	 (Scheduler(site)->intrasite_smsg.count)
566#define Inc_ShortCut_Count(site) (Scheduler(site)->smsg_count_intra_shortcut++)
567
568#define IntraSiteCheckIn(recv,send) {		\
569	if ((recv)==(send)) {			\
570	   Disable_Int();			\
571	   Intrasite_Smsg(recv) += 1;		\
572	   Enable_Int();			\
573	}					\
574}
575#define IntraSiteCheckOut(recv,send) {		\
576	if ((recv)==(send)) {			\
577	   Disable_Int();			\
578	   Intrasite_Smsg(recv) -= 1;		\
579	   assert(Intrasite_Smsg(recv) >= 0);	\
580	   Enable_Int();			\
581	}					\
582}
583#else /* NO_SHORTCUT */
584#define IntraSiteCheckIn(recv,send)
585#define IntraSiteCheckOut(recv,send)
586#define Intrasite_Smsg(site) 1
587#endif  /* NO_SHORTCUT */
588
589#define LoadReportPublish(site) (Scheduler(site)->load_report_eager)
590
591#define Sch_Initlock(t) Simp_Initlock(Knot(t))
592#define Sch_Unlock(t)   Simp_Unlock(Knot(t))
593#define Sch_Lock(t)     Simp_Lock(Knot(t))
594
595#define Simp_Initlock(obj) ((obj)->lock = 0)
596/* #define Simp_Unlock(obj)   (simp_unlock(&((obj)->lock))) */
597/* #define Simp_Lock(obj)     (simp_lock(&((obj)->lock))) */
598#define Simp_Lock(obj) ((obj)->lock ? 0 : ++((obj)->lock))
599#define Simp_Unlock(obj) {	\
600	assert((obj)->lock);	\
601	(obj)->lock = 0;	\
602}
603