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: scheduler.c
26**      Author: Liang-Liang Li
27** Description:
28**
29***********************************************************************/
30
31#include <stdio.h>
32
33#include "config.h"
34
35#include "pds.h"        /* The Underlying Message Passing System */
36#include "memman.h"
37#include "trace.h"      /* The tracing events and macros defintions */
38#include "error.h"
39
40#include "sch_types.h"  /* The scheduler tree definitions and macros */
41#include "sch_eng_interface.h" /* interface: scheduler/engine/worker manage */
42#include "sch_macros.h"
43
44/*****  Scheduler sub-functions  *****/
45/*************************************/
46#if defined(__STDC__)
47/* Send scheduler msgs of various sizes:
48**	recv-id, msg-type, send-id
49** is the smallest size.
50** Smsg_sndIJ means the msg sent has extra I tree ids, and J integers.
51** this grouping is subject to change when dealing with newly introduced msgs
52*/
53
54static void smsg_snd00(st_id_t *, int, st_id_t *);
55static void smsg_snd01(st_id_t *, int, st_id_t *, int);
56static void smsg_snd02(st_id_t *, int, st_id_t *, int, int);
57static void smsg_snd10(st_id_t *, int, st_id_t *, st_id_t *);
58static void smsg_snd12(st_id_t *, int, st_id_t *, st_id_t *, int,int);
59static void smsg_snd20(st_id_t *, int, st_id_t *, st_id_t *, st_id_t *);
60static void smsg_snd21(st_id_t *, int, st_id_t *, st_id_t *, st_id_t *, int);
61static void smsg_snd30(st_id_t *, int, st_id_t *, st_id_t *, st_id_t *, st_id_t *);
62
63/* handles scheduler msgs of various types */
64static void sch_port_naive_upcall     (site_id_t);
65static void sch_async_msg_hdls	       (site_id_t, int);
66
67static void sch_msg_hdl_init_lodge    (st_id_t *, st_id_t *, int);
68static void sch_msg_hdl_backtrack     (st_id_t *, st_id_t *);
69static void sch_msg_hdl_withered      (st_id_t *, st_id_t *);
70static void sch_msg_hdl_dec_corpse    (st_id_t *, st_id_t *);
71static void sch_msg_hdl_js_in_vain    (st_id_t *, st_id_t *);
72static void sch_msg_hdl_load_report   (st_id_t *, st_id_t *);
73static void sch_msg_hdl_set_js_root   (st_id_t *, st_id_t *);
74static void sch_msg_hdl_js_again      (st_id_t *, st_id_t *);
75static void sch_msg_hdl_lodged        (st_id_t *, st_id_t *);
76static void sch_msg_hdl_tell_idle     (st_id_t *, st_id_t *);
77static void sch_msg_hdl_idle_told     (st_id_t *, st_id_t *);
78static void sch_msg_hdl_idle_eng      (st_id_t *, st_id_t *);
79static void sch_msg_hdl_wake_eng      (st_id_t *, st_id_t *);
80static void sch_msg_hdl_stop_idle     (st_id_t *, st_id_t *);
81static void sch_msg_hdl_lmp	      (st_id_t *, st_id_t *);
82static void sch_msg_hdl_reduce_wk_up  (st_id_t *, st_id_t *);
83static void sch_msg_hdl_reduce_wk_dn  (st_id_t *, st_id_t *);
84static void sch_msg_hdl_engine_migrate(st_id_t *, st_id_t *);
85
86static void sch_msg_hdl_cut_ok        (st_id_t *, st_id_t *, int);
87
88static void sch_msg_hdl_js_success    (st_id_t *, st_id_t *, int, int);
89
90static void sch_msg_hdl_cut           (st_id_t *, st_id_t *, st_id_t *);
91static void sch_msg_hdl_chop          (st_id_t *, st_id_t *, st_id_t *);
92static void sch_msg_hdl_lodge         (st_id_t *, st_id_t *, st_id_t *);
93static void sch_msg_hdl_lodge_idle    (st_id_t *, st_id_t *, st_id_t *);
94static void sch_msg_hdl_js_prologue   (st_id_t *, st_id_t *, st_id_t *);
95
96static void sch_msg_hdl_js_trust      (st_id_t *, st_id_t *, st_id_t *, int, int);
97
98static void sch_msg_hdl_js_trav_up    (st_id_t *, st_id_t *, st_id_t *, st_id_t *);
99static void sch_msg_hdl_js_trav_dn    (st_id_t *, st_id_t *, st_id_t *, st_id_t *);
100static void sch_msg_hdl_js_install_fl (st_id_t *, st_id_t *, st_id_t *, st_id_t *);
101
102static void sch_msg_hdl_straighten    (st_id_t *, st_id_t *, st_id_t *, st_id_t *, int);
103
104static void sch_msg_hdl_js_install    (st_id_t *, st_id_t *, st_id_t *, st_id_t *, st_id_t *);
105
106/* others */
107#if defined(MULTI_THREADS)
108int simp_lock(char *);
109void simp_unlock(char *);
110#endif /* MULTI_THREADS */
111
112#else /* __STDC__ */
113
114static void smsg_snd00();
115static void smsg_snd01();
116static void smsg_snd02();
117static void smsg_snd10();
118static void smsg_snd12();
119static void smsg_snd20();
120static void smsg_snd21();
121static void smsg_snd30();
122
123static void sch_port_naive_upcall     ();
124static void sch_async_msg_hdls	       ();
125
126static void sch_msg_hdl_init_lodge    ();
127static void sch_msg_hdl_backtrack     ();
128static void sch_msg_hdl_withered      ();
129static void sch_msg_hdl_dec_corpse    ();
130static void sch_msg_hdl_js_in_vain    ();
131static void sch_msg_hdl_load_report   ();
132static void sch_msg_hdl_set_js_root   ();
133
134static void sch_msg_hdl_cut_ok        ();
135static void sch_msg_hdl_js_again      ();
136static void sch_msg_hdl_lodged        ();
137static void sch_msg_hdl_tell_idle     ();
138static void sch_msg_hdl_idle_told     ();
139static void sch_msg_hdl_idle_eng      ();
140static void sch_msg_hdl_wake_eng      ();
141static void sch_msg_hdl_stop_idle     ();
142static void sch_msg_hdl_lmp	      ();
143static void sch_msg_hdl_reduce_wk_up  ();
144static void sch_msg_hdl_reduce_wk_dn  ();
145static void sch_msg_hdl_engine_migrate();
146
147static void sch_msg_hdl_js_success    ();
148
149static void sch_msg_hdl_cut           ();
150static void sch_msg_hdl_chop 	       ();
151static void sch_msg_hdl_lodge         ();
152static void sch_msg_hdl_lodge_idle    ();
153static void sch_msg_hdl_js_prologue   ();
154
155static void sch_msg_hdl_js_trust      ();
156
157static void sch_msg_hdl_js_trav_up    ();
158static void sch_msg_hdl_js_trav_dn    ();
159static void sch_msg_hdl_js_install_fl ();
160
161static void sch_msg_hdl_straighten    ();
162
163static void sch_msg_hdl_js_install    ();
164
165#if defined(MULTI_THREADS)
166int  simp_lock		       ();
167void simp_unlock	       ();
168#endif /* MULTI_THREADS */
169
170#endif /* __STDC__ */
171
172int zero();
173
174/*****  Scheduler Messages Among Nodes/Leaves         *****/
175/**********************************************************/
176
177/* Scheduler Message Listing */
178#define SMSG_INIT_LODGE       0       /* root, leaf, wm_port */
179#define SMSG_BACKTRACK        1       /* parent, leaf */
180#define SMSG_STRAIGHTEN       2       /* parent, child, leaf, parent0, nxtcls */
181#define SMSG_CUT              3       /* (a) parent, leaf */
182#define SMSG_CUT_OK           4       /* leaf, parent, info */
183#define SMSG_CHOP             5       /* child, parent, ancestor */
184#define SMSG_WITHERED         6       /* parent, child */
185#define SMSG_LODGE            7       /* (a) parent, leaf */
186#define SMSG_LODGED           8       /* leaf, parent */
187#define SMSG_DEC_CORPSE       9       /* oldleaf, newleaf */
188#define SMSG_JS_PROLOGUE      10      /* parent, child, leaf */
189#define SMSG_JS_TRAV_UP       11      /* parent, child, leaf, coma */
190#define SMSG_JS_TRAV_DN       12      /* child, parent, leaf, coma */
191#define SMSG_JS_INSTALL       13      /* child, parent, leaf, coma */
192#define SMSG_JS_INSTALL_FL    14      /* lodge,child,coma,leaf */
193#define SMSG_JS_SUCCESS       15      /* leaf, parent, nxtcls, info */
194#define SMSG_JS_TRUST         16      /* leaf, parent, parent0, nxtcls, info */
195#define SMSG_JS_IN_VAIN       17      /* leaf, jsroot */
196#define SMSG_JS_AGAIN         18      /* parent, leaf */
197#define SMSG_LOAD_REPORT      19      /* parent, child */
198#define SMSG_SET_JS_ROOT      20      /* child, parent */
199#define SMSG_WAKE_ENG         21      /* leaf, leaf */
200#define SMSG_IDLE_ENG         22      /* leaf, leaf */
201#define SMSG_TELL_IDLE        23      /* parent, leaf */
202#define SMSG_LODGE_IDLE       24      /* parent, child, leaf */
203#define SMSG_IDLE_TOLD        25      /* leaf, parent */
204#define SMSG_STOP_IDLE        26      /* parent, leaf */
205#define SMSG_LMP              27      /* child, parent */
206#define SMSG_REDUCE_WK_UP     28      /* parent, child */
207#define SMSG_REDUCE_WK_DN     29      /* child, parent */
208#define SMSG_ENGINE_MIGRATE   30      /* parent, leaf */
209#define SMSG_MAXNUM           31      /* last item */
210
211/* Comments
212   1. The argument lists for the handlers of messages are listed as comment.
213   2. Some messages are sent upwards the scheduler tree:
214	parent (or ancestors as future parent) as 1st argument
215   3. Other messages are sent downwards the scheduler tree:
216	 child or leaf as 1st argument.
217   4. A leaf can receive any of downward messages.
218      (of course, a leaf with specific state may not expect all of them).
219   5. All of the arguments are pointers to a sch-tree identifiers, with
220      exceptions: SMSG_JS_SUCCESS needs a next-clause argument,
221   6. coma -> common ancestor
222*/
223
224/* Brief explanations for some of the messages :
225   SMSG_STRAIGHTEN: turns a single threaded subtree into a branch;
226   SMSG_CHOP: chops a subtree
227   SMSG_DEC_CORPSE: decouple the old leaf and its reincarnated new leaf
228   SMSG_JS_PROLOGUE: job-search along the lodging path
229   SMSG_JS_TRAV_UP: job-request from a just searched subtree
230   SMSG_JS_INSTALL: asked to install job-state
231   SMSG_JS_INSTALL_FL: fail acknowledgement of installation
232   SMSG_JS_IN_VAIN: nothing is found in the current job-search tree
233   SMSG_JS_AGAIN: start a new session
234   SMSG_JS_TRUST: coupled with SMSG_STRAIGHTEN (reply)
235   SMSG_LOAD_REPORT: report richness of a subtree
236   SMSG_SET_JS_ROOT: set a smallest tree for job search
237   SMSG_IDLE_ENG: instruct the leaf to let the engine idle
238   SMSG_WAKE_ENG: instruct the leaf to wake up the engine
239   SMSG_LMP: instruct the left-most path to become LM set
240   SMSG_REDUCE_WK_UP:
241   SMSG_REDUCE_WK_DN: wake up suspended job-search message flows.
242   SMSG_ENGINE_MIGRATE: the leaf with the engine just copied oracled wants
243		        migrate to the new parent
244*/
245
246char * smsg_name[SMSG_MAXNUM+1];
247
248static scheduler_t scheduler[1];
249static st_knot_t knot_template[1];
250
251/*****  Data Blocks Packing Messages of various sizes  *****/
252/***********************************************************/
253
254/* smsg_xy_t: a message with x stree ids and y integers */
255
256typedef struct {
257	struct st_id_ds recv;
258	pds_int32    type;
259	struct st_id_ds send;
260} smsg00_t;
261
262typedef struct {
263	struct st_id_ds recv;
264	pds_int32    type;
265	struct st_id_ds send;
266	int i1;
267} smsg01_t;
268
269typedef struct {
270	struct st_id_ds recv;
271	pds_int32    type;
272	struct st_id_ds send;
273	pds_int32 i1;
274	pds_int32 i2;
275} smsg02_t;
276
277typedef struct {
278	struct st_id_ds recv;
279	pds_int32    type;
280	struct st_id_ds send;
281	struct st_id_ds t1;
282} smsg10_t;
283
284typedef struct {
285	struct st_id_ds recv;
286	pds_int32    type;
287	struct st_id_ds send;
288	struct st_id_ds t1;
289	pds_int32 i1;
290	pds_int32 i2;
291} smsg12_t;
292
293typedef struct {
294	struct st_id_ds recv;
295	pds_int32    type;
296	struct st_id_ds send;
297	struct st_id_ds t1;
298	struct st_id_ds t2;
299} smsg20_t;
300
301typedef struct {
302	struct st_id_ds recv;
303	pds_int32    type;
304	struct st_id_ds send;
305	struct st_id_ds t1;
306	struct st_id_ds t2;
307	pds_int32 i1;
308} smsg21_t;
309
310typedef struct {
311	struct st_id_ds recv;
312	pds_int32    type;
313	struct st_id_ds send;
314	struct st_id_ds t1;
315	struct st_id_ds t2;
316	struct st_id_ds t3;
317} smsg30_t;
318
319#define ECLIPSE_SCH_INTFCNO	1217
320
321void smsg_type_init(site)
322site_id_t site;
323{
324  amsg_typedef_t mdt_smsg_type[10];
325  amsg_type_t mdt_st_id;
326
327  mdt_smsg_type[0] = MDT_BEGIN;
328  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
329  mdt_smsg_type[2] = MDT_APORTID;
330  mdt_smsg_type[3] = MDT_UINT32;
331  mdt_smsg_type[4] = MDT_UINT32;
332  mdt_smsg_type[5] = MDT_STRUCT_CLOSE;
333  mdt_smsg_type[6] = MDT_END;
334  if (amsg_type_define(ECLIPSE_SCH_INTFCNO, 10, mdt_smsg_type, &mdt_st_id)
335	!= AMSG_OK) {
336     error("fail to define st_id type");
337  }
338
339  mdt_smsg_type[0] = MDT_BEGIN;
340  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
341  mdt_smsg_type[2] = mdt_st_id;
342  mdt_smsg_type[3] = MDT_INT32;
343  mdt_smsg_type[4] = mdt_st_id;
344  mdt_smsg_type[5] = MDT_STRUCT_CLOSE;
345  mdt_smsg_type[6] = MDT_END;
346  if (amsg_type_define(
347       ECLIPSE_SCH_INTFCNO, 11, mdt_smsg_type, &Scheduler(site)->smsg_type[0][0]
348                      ) != AMSG_OK) {
349     error("fail to define smsg00 type");
350  }
351
352  mdt_smsg_type[0] = MDT_BEGIN;
353  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
354  mdt_smsg_type[2] = mdt_st_id;
355  mdt_smsg_type[3] = MDT_INT32;
356  mdt_smsg_type[4] = mdt_st_id;
357  mdt_smsg_type[5] = MDT_INT32;
358  mdt_smsg_type[6] = MDT_STRUCT_CLOSE;
359  mdt_smsg_type[7] = MDT_END;
360  if (amsg_type_define(
361       ECLIPSE_SCH_INTFCNO, 12, mdt_smsg_type, &Scheduler(site)->smsg_type[0][1]
362		      ) != AMSG_OK) {
363     error("fail to define smsg01 type");
364  }
365
366  mdt_smsg_type[0] = MDT_BEGIN;
367  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
368  mdt_smsg_type[2] = mdt_st_id;
369  mdt_smsg_type[3] = MDT_INT32;
370  mdt_smsg_type[4] = mdt_st_id;
371  mdt_smsg_type[5] = MDT_INT32;
372  mdt_smsg_type[6] = MDT_INT32;
373  mdt_smsg_type[7] = MDT_STRUCT_CLOSE;
374  mdt_smsg_type[8] = MDT_END;
375  if (amsg_type_define(
376       ECLIPSE_SCH_INTFCNO, 13, mdt_smsg_type, &Scheduler(site)->smsg_type[0][2]
377		      ) != AMSG_OK) {
378     error("fail to define smsg02 type");
379  }
380
381  mdt_smsg_type[0] = MDT_BEGIN;
382  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
383  mdt_smsg_type[2] = mdt_st_id;
384  mdt_smsg_type[3] = MDT_INT32;
385  mdt_smsg_type[4] = mdt_st_id;
386  mdt_smsg_type[5] = mdt_st_id;
387  mdt_smsg_type[6] = MDT_STRUCT_CLOSE;
388  mdt_smsg_type[7] = MDT_END;
389  if (amsg_type_define(
390       ECLIPSE_SCH_INTFCNO, 14, mdt_smsg_type, &Scheduler(site)->smsg_type[1][0]
391		      ) != AMSG_OK) {
392     error("fail to define smsg10 type");
393  }
394
395  mdt_smsg_type[0] = MDT_BEGIN;
396  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
397  mdt_smsg_type[2] = mdt_st_id;
398  mdt_smsg_type[3] = MDT_INT32;
399  mdt_smsg_type[4] = mdt_st_id;
400  mdt_smsg_type[5] = mdt_st_id;
401  mdt_smsg_type[6] = MDT_INT32;
402  mdt_smsg_type[7] = MDT_INT32;
403  mdt_smsg_type[8] = MDT_STRUCT_CLOSE;
404  mdt_smsg_type[9] = MDT_END;
405  if (amsg_type_define(
406       ECLIPSE_SCH_INTFCNO, 15, mdt_smsg_type, &Scheduler(site)->smsg_type[1][2]
407		      ) != AMSG_OK) {
408     error("fail to define smsg12 type");
409  }
410
411  mdt_smsg_type[0] = MDT_BEGIN;
412  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
413  mdt_smsg_type[2] = mdt_st_id;
414  mdt_smsg_type[3] = MDT_INT32;
415  mdt_smsg_type[4] = mdt_st_id;
416  mdt_smsg_type[5] = mdt_st_id;
417  mdt_smsg_type[6] = mdt_st_id;
418  mdt_smsg_type[7] = MDT_STRUCT_CLOSE;
419  mdt_smsg_type[8] = MDT_END;
420  if (amsg_type_define(
421       ECLIPSE_SCH_INTFCNO, 16, mdt_smsg_type, &Scheduler(site)->smsg_type[2][0]
422		      ) != AMSG_OK) {
423     error("fail to define smsg20 type");
424  }
425
426  mdt_smsg_type[0] = MDT_BEGIN;
427  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
428  mdt_smsg_type[2] = mdt_st_id;
429  mdt_smsg_type[3] = MDT_INT32;
430  mdt_smsg_type[4] = mdt_st_id;
431  mdt_smsg_type[5] = mdt_st_id;
432  mdt_smsg_type[6] = mdt_st_id;
433  mdt_smsg_type[7] = MDT_INT32;
434  mdt_smsg_type[8] = MDT_STRUCT_CLOSE;
435  mdt_smsg_type[9] = MDT_END;
436  if (amsg_type_define(
437       ECLIPSE_SCH_INTFCNO, 17, mdt_smsg_type, &Scheduler(site)->smsg_type[2][1]
438		      ) != AMSG_OK) {
439     error("fail to define smsg21 type");
440  }
441
442  mdt_smsg_type[0] = MDT_BEGIN;
443  mdt_smsg_type[1] = MDT_STRUCT_OPEN;
444  mdt_smsg_type[2] = mdt_st_id;
445  mdt_smsg_type[3] = MDT_INT32;
446  mdt_smsg_type[4] = mdt_st_id;
447  mdt_smsg_type[5] = mdt_st_id;
448  mdt_smsg_type[6] = mdt_st_id;
449  mdt_smsg_type[7] = mdt_st_id;
450  mdt_smsg_type[8] = MDT_STRUCT_CLOSE;
451  mdt_smsg_type[9] = MDT_END;
452  if (amsg_type_define(
453       ECLIPSE_SCH_INTFCNO, 18, mdt_smsg_type, &Scheduler(site)->smsg_type[3][0]
454		      ) != AMSG_OK) {
455     error("fail to define smsg30 type");
456  }
457}
458
459static void smsg_snd00(recv, type, send)
460int type;
461st_id_t *recv, *send;
462{
463   amsg_t      msg;
464   amsg_ret_t  ret;
465   amsg_size_t datasize = sizeof(smsg00_t);
466   smsg00_t *data;
467
468   Smsg_Snd_Notify(type, recv, send);
469   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
470   assert(ret==AMSG_OK);
471   data->type = type;
472   data->recv = *recv;
473   data->send = *send;
474   IntraSiteCheckIn(Site(recv),Site(send));
475   ret = amsg_send(
476		Site(recv),
477		msg,
478		Scheduler(Site(send))->smsg_type[0][0],
479		1,
480		0);
481   assert(ret==AMSG_OK);
482   return;
483}
484
485static void smsg_snd01(recv, type, send, i)
486int type;
487st_id_t *recv, *send;
488int i;
489{
490   amsg_t      msg;
491   amsg_ret_t  ret;
492   amsg_size_t datasize = sizeof(smsg01_t);
493   smsg01_t *data;
494
495   Smsg_Snd_Notify(type, recv, send);
496   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
497   assert(ret==AMSG_OK);
498   data->type = type;
499   data->recv = *recv;
500   data->send = *send;
501   data->i1   = i;
502   IntraSiteCheckIn(Site(recv),Site(send));
503   ret = amsg_send(
504		Site(recv),
505		msg,
506		Scheduler(Site(send))->smsg_type[0][1],
507		1,
508		0);
509   assert(ret==AMSG_OK);
510   return;
511}
512
513static void smsg_snd02(recv, type, send, i1,i2)
514int type;
515st_id_t *recv, *send;
516int i1,i2;
517{
518   amsg_t      msg;
519   amsg_ret_t  ret;
520   amsg_size_t datasize = sizeof(smsg02_t);
521   smsg02_t *data;
522
523   Smsg_Snd_Notify(type, recv, send);
524   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
525   assert(ret==AMSG_OK);
526   data->type = type;
527   data->recv = *recv;
528   data->send = *send;
529   data->i1   = i1;
530   data->i2   = i2;
531   IntraSiteCheckIn(Site(recv),Site(send));
532   ret = amsg_send(
533		Site(recv),
534		msg,
535		Scheduler(Site(send))->smsg_type[0][2],
536		1,
537		0);
538   assert(ret==AMSG_OK);
539   return;
540}
541
542static void smsg_snd10(recv, type, send, t1)
543int type;
544st_id_t *recv, *send, *t1;
545{
546   amsg_t      msg;
547   amsg_ret_t  ret;
548   amsg_size_t datasize = sizeof(smsg10_t);
549   smsg10_t *data;
550
551   Smsg_Snd_Notify(type, recv, send);
552   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
553   assert(ret==AMSG_OK);
554
555   data->type = type;
556   data->recv = *recv;
557   data->send = *send;
558   data->t1   = *t1;
559   IntraSiteCheckIn(Site(recv),Site(send));
560   ret = amsg_send(
561		Site(recv),
562		msg,
563		Scheduler(Site(send))->smsg_type[1][0],
564		1,
565		0);
566   assert(ret==AMSG_OK);
567   return;
568}
569
570static void smsg_snd12(recv, type, send, t1, i1,i2)
571int type;
572st_id_t *recv, *send, *t1;
573int i1,i2;
574{
575   amsg_t      msg;
576   amsg_ret_t  ret;
577   amsg_size_t datasize = sizeof(smsg12_t);
578   smsg12_t *data;
579
580   Smsg_Snd_Notify(type, recv, send);
581   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
582   assert(ret==AMSG_OK);
583   data->type = type;
584   data->recv = *recv;
585   data->send = *send;
586   data->t1   = *t1;
587   data->i1   = i1;
588   data->i2   = i2;
589   IntraSiteCheckIn(Site(recv),Site(send));
590   ret = amsg_send(
591		Site(recv),
592		msg,
593		Scheduler(Site(send))->smsg_type[1][2],
594		1,
595		0);
596   assert(ret==AMSG_OK);
597   return;
598}
599
600static void smsg_snd20(recv, type, send, t1, t2)
601int type;
602st_id_t *recv, *send, *t1, *t2;
603{
604   amsg_t      msg;
605   amsg_ret_t  ret;
606   amsg_size_t datasize = sizeof(smsg20_t);
607   smsg20_t *data;
608
609   Smsg_Snd_Notify(type, recv, send);
610   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
611   assert(ret==AMSG_OK);
612
613   data->type = type;
614   data->recv = *recv;
615   data->send = *send;
616   data->t1   = *t1;
617   data->t2   = *t2;
618   IntraSiteCheckIn(Site(recv),Site(send));
619   ret = amsg_send(
620		Site(recv),
621		msg,
622		Scheduler(Site(send))->smsg_type[2][0],
623		1,
624		0);
625   assert(ret==AMSG_OK);
626   return;
627}
628
629static void smsg_snd21(recv, type, send, t1, t2, i1)
630int type;
631st_id_t *recv, *send, *t1, *t2;
632int i1;
633{
634   amsg_t      msg;
635   amsg_ret_t  ret;
636   amsg_size_t datasize = sizeof(smsg21_t);
637   smsg21_t *data;
638
639   Smsg_Snd_Notify(type, recv, send);
640   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
641   assert(ret==AMSG_OK);
642
643   data->type = type;
644   data->recv = *recv;
645   data->send = *send;
646   data->t1   = *t1;
647   data->t2   = *t2;
648   data->i1   = i1;
649   IntraSiteCheckIn(Site(recv),Site(send));
650   ret = amsg_send(
651		Site(recv),
652		msg,
653		Scheduler(Site(send))->smsg_type[2][1],
654		1,
655		0);
656   assert(ret==AMSG_OK);
657   return;
658}
659
660static void smsg_snd30(recv, type, send, t1, t2, t3)
661int type;
662st_id_t *recv, *send, *t1, *t2, *t3;
663{
664   amsg_t      msg;
665   amsg_ret_t  ret;
666   amsg_size_t datasize = sizeof(smsg30_t);
667   smsg30_t *data;
668
669   Smsg_Snd_Notify(type, recv, send);
670   ret = amsg_alloc(datasize, (amsg_data_t **)&data, &msg);
671   assert(ret==AMSG_OK);
672
673   data->type = type;
674   data->recv = *recv;
675   data->send = *send;
676   data->t1   = *t1;
677   data->t2   = *t2;
678   data->t3   = *t3;
679   IntraSiteCheckIn(Site(recv),Site(send));
680   ret = amsg_send(
681		Site(recv),
682		msg,
683		Scheduler(Site(send))->smsg_type[3][0],
684		1,
685		0);
686   assert(ret==AMSG_OK);
687   return;
688}
689#define sch_msg_snd_backtrack(parent, leaf)	\
690		smsg_snd00((parent),SMSG_BACKTRACK,(leaf))
691#define sch_msg_snd_lodged(leaf,parent)		\
692		smsg_snd00((leaf),SMSG_LODGED,(parent))
693#define sch_msg_snd_withered(recv,child)		\
694		smsg_snd00((recv),SMSG_WITHERED,(child))
695#define sch_msg_snd_dec_corpse(old,new)		\
696		smsg_snd00((old),SMSG_DEC_CORPSE,(new))
697#define sch_msg_snd_js_in_vain(leaf,jroot)	\
698		smsg_snd00((leaf),SMSG_JS_IN_VAIN,(jroot))
699#define sch_msg_snd_load_report(parent,child)	\
700		smsg_snd00((parent),SMSG_LOAD_REPORT,(child))
701#define sch_msg_snd_set_js_root(child,parent)	\
702		smsg_snd00((child),SMSG_SET_JS_ROOT,(parent))
703#define sch_msg_snd_js_again(parent,leaf)	\
704		smsg_snd00((parent),SMSG_JS_AGAIN,(leaf))
705#define sch_msg_snd_idle_eng(leaf,leaf0)	\
706		smsg_snd00((leaf),SMSG_IDLE_ENG,(leaf0))
707#define sch_msg_snd_wake_eng(leaf,leaf0)	\
708		smsg_snd00((leaf),SMSG_WAKE_ENG,(leaf0))
709#define sch_msg_snd_idle_told(leaf,parent)	\
710		smsg_snd00((leaf),SMSG_IDLE_TOLD,(parent))
711#define sch_msg_snd_lmp(child,parent)	\
712		smsg_snd00((child),SMSG_LMP,(parent))
713#define sch_msg_snd_tell_idle(parent,leaf)	\
714		smsg_snd00((parent),SMSG_TELL_IDLE,(leaf))
715#define sch_msg_snd_stop_idle(parent,leaf)	\
716		smsg_snd00((parent),SMSG_STOP_IDLE,(leaf))
717#define sch_msg_snd_reduce_wk_up(parent,child)	\
718		smsg_snd00((parent),SMSG_REDUCE_WK_UP,(child))
719#define sch_msg_snd_reduce_wk_dn(child, parent)	\
720		smsg_snd00((child),SMSG_REDUCE_WK_DN,(parent))
721#define sch_msg_snd_engine_migrate(parent,leaf) \
722		smsg_snd00((parent),SMSG_ENGINE_MIGRATE,(leaf))
723
724#define sch_msg_snd_cut_ok(leaf,parent,info)		\
725		smsg_snd01((leaf),SMSG_CUT_OK,(parent),(info))
726#define sch_msg_snd_init_lodge(root, leaf, wm)	\
727		smsg_snd01((root),SMSG_INIT_LODGE,(leaf),(wm))
728
729#define sch_msg_snd_js_success(leaf,parent,nxtcls,info)	\
730		smsg_snd02((leaf),SMSG_JS_SUCCESS,(parent),(nxtcls),(info))
731
732#define sch_msg_snd_cut(parent, olf, leaf)		\
733		smsg_snd10((parent),SMSG_CUT,(olf),(leaf))
734#define sch_msg_snd_lodge(parent,child,leaf)		\
735		smsg_snd10((parent),SMSG_LODGE,(child),(leaf))
736#define sch_msg_snd_chop(child,parent,ancestor)	\
737		smsg_snd10((child),SMSG_CHOP,(parent),(ancestor))
738#define sch_msg_snd_lodge_idle(parent,child,leaf)	\
739		smsg_snd10((parent),SMSG_LODGE_IDLE,(child),(leaf))
740#define sch_msg_snd_js_prologue(parent,child,leaf)	\
741		smsg_snd10((parent),SMSG_JS_PROLOGUE,(child),(leaf))
742
743#define sch_msg_snd_js_trust(leaf,parent,parent_alt,nxtcls,info)	\
744		smsg_snd12((leaf),SMSG_JS_TRUST,(parent),(parent_alt),(nxtcls),(info))
745
746#define sch_msg_snd_js_trav_up(parent,child,leaf,coma)	\
747		smsg_snd20((parent),SMSG_JS_TRAV_UP,(child),(leaf),(coma))
748#define sch_msg_snd_js_trav_dn(child,parent,leaf,coma)	\
749		smsg_snd20((child),SMSG_JS_TRAV_DN,(parent),(leaf),(coma))
750#define sch_msg_snd_js_install_fl(lodge,child,leaf,coma)		\
751		smsg_snd20((lodge),SMSG_JS_INSTALL_FL,(child),(leaf),(coma))
752
753#define sch_msg_snd_straighten(parent,child,leaf,parent_alt,alt)	\
754		smsg_snd21((parent),SMSG_STRAIGHTEN,(child),(leaf),(parent_alt),(alt))
755
756#define sch_msg_snd_js_install(child,parent,lodge,leaf,coma)		\
757	smsg_snd30((child), SMSG_JS_INSTALL,  (parent),(lodge),(leaf),(coma))
758
759
760#if defined(MULTI_THREADS)
761int simp_lock(lock)
762char *lock;
763{
764   int ok = 0;
765   if (sch_mutex_lock()) {
766      if (!*lock) {
767	ok = *lock = 1;
768      }
769      sch_mutex_unlock();
770   }
771   return(ok);
772}
773
774void simp_unlock(lock)
775char *lock;
776{
777   while (!sch_mutex_lock()) {}
778   assert(*lock);
779   *lock = 0;
780   sch_mutex_unlock();
781}
782#endif /* MULTI_THREADS */
783
784void sch_port_upcall(p)
785site_id_t p;
786{
787   LOG_EVENT_PUSH(SCH_ASYNC)
788   if (Scheduler(p)->async_hdl) {
789      sch_async_msg_hdls(p, 1);
790   } else {
791      sch_port_naive_upcall(p);
792   }
793   LOG_EVENT_POP;
794}
795
796/* UPCALL functions for the Scheduler Port */
797static void sch_port_naive_upcall(port)
798aport_id_t port;
799{
800   eng_msg_trigger(Scheduler(port)->engine);
801   return;
802}
803
804/* UPCALL functions for the Scheduler Port */
805static void sch_async_msg_hdls(port, async)
806aport_id_t port;
807int async;
808{
809   amsg_ret_t ret;
810   amsg_t msg;
811   smsg00_t *data;
812   amsg_type_t mdt_type;
813   amsg_count_t mdt_count;
814
815   st_id_t *recv;
816   st_id_t *send;
817
818   eng_msg_trigger(Scheduler(port)->engine);
819   while (1) {
820     Disable_Int();
821     ret = amsg_peek(	port,
822			&msg,
823			(amsg_data_t * *)&data,
824			&mdt_type,
825			&mdt_count);
826     if (ret == AMSG_NOMESSAGE) {
827        eng_msg_reset(Scheduler(port)->engine);
828#if !defined(NO_SHORTCUT)
829        assert(async || !Intrasite_Smsg(port));
830#endif  /* NO_SHORTCUT */
831        Enable_Int();
832        return;
833     }
834     Enable_Int();
835     assert(ret==AMSG_OK && mdt_count == 1);
836     recv = &data->recv;
837     if (!Sch_Lock(recv)) {
838	assert(async);
839	return;
840     }
841     send = &data->send;
842
843     IntraSiteCheckOut(port,Site(send));
844
845     switch (data->type) {
846     case SMSG_BACKTRACK:
847       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
848       sch_msg_hdl_backtrack(recv,send);
849       break;
850     case SMSG_LODGED:
851       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
852       sch_msg_hdl_lodged(recv,send);
853       break;
854     case SMSG_WITHERED:
855       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
856       sch_msg_hdl_withered(recv,send);
857       break;
858     case SMSG_DEC_CORPSE:
859       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
860       sch_msg_hdl_dec_corpse(recv,send);
861       break;
862     case SMSG_JS_IN_VAIN:
863       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
864       sch_msg_hdl_js_in_vain(recv,send);
865       break;
866     case SMSG_LOAD_REPORT:
867       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
868       sch_msg_hdl_load_report(recv,send);
869       break;
870     case SMSG_SET_JS_ROOT:
871       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
872       sch_msg_hdl_set_js_root(recv,send);
873       break;
874     case SMSG_JS_AGAIN:
875       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
876       sch_msg_hdl_js_again(recv,send);
877       break;
878     case SMSG_IDLE_ENG:
879       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
880       sch_msg_hdl_idle_eng(recv,send);
881       break;
882     case SMSG_WAKE_ENG:
883       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
884       sch_msg_hdl_wake_eng(recv,send);
885       break;
886     case SMSG_TELL_IDLE:
887       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
888       sch_msg_hdl_tell_idle(recv,send);
889       break;
890     case SMSG_STOP_IDLE:
891       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
892       sch_msg_hdl_stop_idle(recv,send);
893       break;
894     case SMSG_IDLE_TOLD:
895       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
896       sch_msg_hdl_idle_told(recv,send);
897       break;
898     case SMSG_LMP:
899       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
900       sch_msg_hdl_lmp(recv,send);
901       break;
902     case SMSG_REDUCE_WK_UP:
903       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
904       sch_msg_hdl_reduce_wk_up(recv,send);
905       break;
906     case SMSG_REDUCE_WK_DN:
907       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
908       sch_msg_hdl_reduce_wk_dn(recv,send);
909       break;
910     case SMSG_ENGINE_MIGRATE:
911       assert(mdt_type == Scheduler(port)->smsg_type[0][0]);
912       sch_msg_hdl_engine_migrate(recv,send);
913       break;
914
915     case SMSG_CUT_OK:
916       assert(mdt_type == Scheduler(port)->smsg_type[0][1]);
917       sch_msg_hdl_cut_ok(recv,send,((smsg01_t *)data)->i1);
918       break;
919     case SMSG_INIT_LODGE:
920       assert(mdt_type == Scheduler(port)->smsg_type[0][1]);
921       sch_msg_hdl_init_lodge(recv,send, ((smsg01_t *)data)->i1);
922       break;
923
924     case SMSG_JS_SUCCESS:
925       assert(mdt_type == Scheduler(port)->smsg_type[0][2]);
926       sch_msg_hdl_js_success(recv, send,
927		((smsg02_t *)data)->i1, ((smsg02_t *)data)->i2);
928	   break;
929
930     case SMSG_CUT:
931       assert(mdt_type == Scheduler(port)->smsg_type[1][0]);
932       sch_msg_hdl_cut(recv,send,&(((smsg10_t *)data)->t1));
933       break;
934     case SMSG_LODGE:
935       assert(mdt_type == Scheduler(port)->smsg_type[1][0]);
936       sch_msg_hdl_lodge(recv,send,&(((smsg10_t *)data)->t1));
937       break;
938     case SMSG_CHOP:
939       assert(mdt_type == Scheduler(port)->smsg_type[1][0]);
940       sch_msg_hdl_chop(recv,send,&(((smsg10_t *)data)->t1));
941       break;
942     case SMSG_LODGE_IDLE:
943       assert(mdt_type == Scheduler(port)->smsg_type[1][0]);
944       sch_msg_hdl_lodge_idle(recv,send,&(((smsg10_t *)data)->t1));
945       break;
946     case SMSG_JS_PROLOGUE:
947       assert(mdt_type == Scheduler(port)->smsg_type[1][0]);
948       sch_msg_hdl_js_prologue(recv,send, &(((smsg10_t *)data)->t1));
949       break;
950
951     case SMSG_JS_TRUST:
952       assert(mdt_type == Scheduler(port)->smsg_type[1][2]);
953       sch_msg_hdl_js_trust(recv, send, &(((smsg12_t *)data)->t1),
954		((smsg12_t *)data)->i1, ((smsg12_t *)data)->i2);
955	   break;
956
957     case SMSG_JS_TRAV_UP:
958       assert(mdt_type == Scheduler(port)->smsg_type[2][0]);
959       sch_msg_hdl_js_trav_up(recv,send,
960	&(((smsg20_t *)data)->t1), &(((smsg20_t *)data)->t2));
961       break;
962     case SMSG_JS_TRAV_DN:
963       assert(mdt_type == Scheduler(port)->smsg_type[2][0]);
964       sch_msg_hdl_js_trav_dn(recv,send,
965	&(((smsg20_t *)data)->t1), &(((smsg20_t *)data)->t2));
966       break;
967     case SMSG_JS_INSTALL_FL:
968       assert(mdt_type == Scheduler(port)->smsg_type[2][0]);
969       sch_msg_hdl_js_install_fl(recv,send,
970	&(((smsg20_t *)data)->t1), &(((smsg20_t *)data)->t2));
971       break;
972
973     case SMSG_STRAIGHTEN:
974       assert(mdt_type == Scheduler(port)->smsg_type[2][1]);
975       sch_msg_hdl_straighten(recv,send,
976	&(((smsg21_t *)data)->t1), &(((smsg21_t *)data)->t2), ((smsg21_t *)data)->i1);
977       break;
978
979     case SMSG_JS_INSTALL:
980       assert(mdt_type == Scheduler(port)->smsg_type[3][0]);
981       sch_msg_hdl_js_install(recv,send,
982	&(((smsg30_t *)data)->t1), &(((smsg30_t *)data)->t2), &(((smsg30_t *)data)->t3));
983	   break;
984
985       default: error("unknown scheduler message");
986     }
987     /* throw away the handled message */
988     ret = amsg_receive(
989		port,
990		(amsg_t *)0,
991		(amsg_data_t * *)0,
992		&mdt_type,
993		&mdt_count,
994		(amsg_option_t) 0
995		);
996     assert(ret==AMSG_OK);
997  }
998}
999
1000
1001/* Interface functions called by Worker Management */
1002
1003void sch_create_leaf(site, engine, leaf)
1004site_id_t site;
1005eng_handle_t engine;
1006st_handle_t **leaf;
1007{
1008   void smsg_type_init();
1009   void smsg_stat_init();
1010   void sch_create_leaf0();
1011
1012   /* initilize a template for a knot. */
1013   knot_template->suspended = (st_susp_t *)0;
1014   PackSite(knot_template,site);
1015   knot_template->alive_twigs = 0;
1016   knot_template->nxtcls = 0;
1017   knot_template->nxtcls_b = 0;
1018   knot_template->hybrid = 0;
1019   knot_template->jroot = 0;
1020   knot_template->proot = 0;
1021   knot_template->local = 0;
1022   knot_template->tip = 1;
1023   knot_template->lock = 0;
1024   knot_template->trunk.info = 0;
1025
1026   /* register the various message types which will be sent and/or received
1027   ** via the scheduler port.
1028   */
1029   smsg_type_init(site);
1030
1031   /* initialise the scheduler datastructure */
1032   Scheduler(site)->port			= site;
1033   Scheduler(site)->engine			= engine;
1034   Scheduler(site)->load_report_eager		= 0;
1035   Scheduler(site)->async_hdl			= 0;
1036   Scheduler(site)->idling			= 0;
1037   Scheduler(site)->waking			= 0;
1038   Scheduler(site)->lmp				= 0;
1039   Scheduler(site)->root_first			= 1;
1040   Scheduler(site)->left_first			= 1;
1041
1042   Scheduler(site)->max_to_publish		= 5;
1043
1044   Scheduler(site)->edge_buffer.count		= 0;
1045   Scheduler(site)->edge_buffer.head.trunk.next	=
1046   Scheduler(site)->edge_buffer.head.trunk.prev	=
1047		&(Scheduler(site)->edge_buffer.head.trunk);
1048   Simp_Initlock(&(Scheduler(site)->edge_buffer));
1049
1050   Scheduler(site)->susp_buffer.count		= 0;
1051   Scheduler(site)->susp_buffer.next		= (st_susp_t *) 0;
1052   Simp_Initlock(&(Scheduler(site)->susp_buffer));
1053
1054#if !defined(NO_SHORTCUT)
1055   Intrasite_Smsg(site) = 0;
1056#endif  /* NO_SHORTCUT */
1057
1058   /* reset scheduler message traffic statistics */
1059   smsg_stat_init(site);
1060   InitSchOffset(site);
1061   *leaf = &(Scheduler(site)->leaf);
1062   sch_create_leaf0(site, (st_id_t *)*leaf);
1063   return;
1064}
1065
1066void sch_create_leaf0(site, leaf)
1067site_id_t site;
1068st_id_t *leaf;
1069{
1070   Sch_Alloc_Knot(site,leaf);
1071   if (Sch_Lock(leaf)) {
1072      SetNalive(Trunk(leaf), ST_INIT);
1073      return;
1074   } else {
1075     assert(zero());
1076  }
1077}
1078
1079
1080void sch_create_root(site, root_hdl)
1081site_id_t site;
1082st_handle_t *root_hdl;
1083{
1084   st_id_t *root = (st_id_t *)root_hdl;
1085   Sch_Alloc_Knot(site,root);
1086   Knot(root)->tip = 0;
1087   Knot(root)->jroot  = 1;
1088   *SupTree(root) = *(root);
1089   SetAlive(Trunk(root));
1090   SetRich(Trunk(root));
1091   SetEldest(Trunk(root));
1092   return;
1093}
1094
1095void sch_genesis(root_hdl,leaf_hdl,twig_hdl,first)
1096st_handle_t *root_hdl, *leaf_hdl, *twig_hdl;
1097int first;
1098{
1099   st_id_t *root = (st_id_t *)root_hdl;
1100   st_id_t *leaf = (st_id_t *)leaf_hdl;
1101   st_id_t *twig = (st_id_t *)twig_hdl;
1102
1103   Scheduler(Site(leaf))->root = *root_hdl;
1104
1105   if (first) {
1106#if defined(INITIAL_SCHTR)
1107     /* set the scheduler trace */
1108     (void) global_flags(0, SCH_TRACE_FLAG);
1109#endif /* INITIAL_SCHTR */
1110      Add_Alive_Twig_Next(twig,leaf,Knot(root),Trunk(root)->prev);
1111      Twig(twig)->info = Trunk(leaf)->info = Trunk(root)->info;
1112      Knot(leaf)->jroot = Knot(root)->jroot;
1113      Sch_Event_Notify2("S_GENESIS", "null         ", twig, leaf);
1114   } else {
1115      *twig = *root;
1116      Sch_Event_Notify2("NEW_COMER", "null         ", twig, leaf);
1117   }
1118
1119   *SupTree(leaf) = *twig;
1120   return;
1121}
1122
1123void sch_init_lodge(site,wm,leaf)
1124aport_id_t site;
1125int wm;
1126st_handle_t *leaf;
1127{
1128   st_id_t *root = (st_id_t *)&Scheduler(site)->root;
1129   assert(SchRoot(root) && Alive(Trunk(root)));
1130   if (Sch_Lock(root)) {
1131      st_id_t twig;
1132      Add_Lodge_Twig(&twig,(st_id_t *)leaf,Knot(root));
1133      wm_init_lodged(wm, (st_handle_t *)&twig);
1134      Sch_Unlock(root);
1135   } else {
1136      sch_msg_snd_init_lodge(root,(st_id_t *)leaf, wm);
1137   }
1138   return;
1139}
1140
1141
1142/* Interface functions called by Engines */
1143
1144void sch_sync_msg_hdls(leaf_hdl)
1145const st_handle_t *leaf_hdl;
1146{
1147   int ok;
1148   site_id_t site = Site((st_id_t *)leaf_hdl);
1149
1150   Sch_Unlock(SiteLeaf(site));
1151   sch_async_msg_hdls(site, 0);
1152
1153   Disable_Int();
1154   ok = Sch_Lock(SiteLeaf(site));
1155   Enable_Int();
1156   assert(ok);
1157   return;
1158}
1159
1160void sch_backtrack(leaf_hdl)
1161const st_handle_t *leaf_hdl;
1162{
1163  int ok;
1164  st_id_t *leaf = (st_id_t *) leaf_hdl;
1165  st_id_t parent; parent = *SupTree(leaf);
1166  if (Life(Trunk(leaf))==ST_INIT) { /* ## INITIAL connection */
1167     SetNalive(Trunk(leaf),ST_LODGED);
1168     Smsg_ShortCut_End(leaf, &parent,
1169	  sch_msg_hdl_js_trav_up(&parent,leaf,&parent,leaf),
1170	  sch_msg_snd_js_trav_up(&parent,leaf,&parent,leaf)
1171	 );
1172     goto _return;
1173  } else {
1174     assert(Alive(Trunk(leaf)));
1175     SetNalive(Trunk(leaf),ST_BACKTRACK);
1176
1177	/* imagine: the leaf is jsroot, and its parent is a worker_boundry
1178        ** node which has to be taken by a leaf which might be currently
1179	** suspended to this backtracking leaf. This has happened: all of
1180	** workers become suddenly inactive. Thus added the following check.
1181	*/
1182     if (Suspended(leaf)) {
1183	void relocate_suspended();
1184	assert(JsRoot(leaf));
1185        relocate_suspended(leaf);
1186     }
1187     ResetJsRoot(leaf);
1188     if (Scheduler(Site(leaf))->idling) {	/* ## Idling */
1189        /* idling bit remains, as not known yet if idle-tell accepted */
1190	Smsg_ShortCut_End(leaf, &parent,
1191	     sch_msg_hdl_tell_idle(&parent, leaf),
1192	     sch_msg_snd_tell_idle(&parent, leaf)
1193	    );
1194     } else {
1195	Smsg_ShortCut_End(leaf, &parent,
1196	     sch_msg_hdl_backtrack(&parent, leaf),
1197	     sch_msg_snd_backtrack(&parent, leaf)
1198	    );
1199     }
1200_return:
1201     Disable_Int();
1202     ok = Sch_Lock(leaf);
1203     Enable_Int();
1204     assert(ok);
1205     return;
1206  }
1207}
1208
1209void sch_cut(leaf_hdl,parent_hdl)
1210const st_handle_t *leaf_hdl, *parent_hdl;
1211{
1212  st_id_t olf, nlf, parent;
1213  site_id_t site = Site(leaf_hdl);
1214  int ok;
1215  olf    = *(st_id_t *) leaf_hdl;
1216  parent = *(st_id_t *) parent_hdl;
1217
1218  if (Suspended(&olf)) {
1219     void relocate_suspended();
1220     assert(JsRoot(&olf));
1221     relocate_suspended(&olf);
1222  }
1223  ResetJsRoot(&olf);
1224  Sch_Alloc_Knot(site,&nlf);
1225  Reincarnat(&olf,&nlf);
1226  NewSiteLeaf(&nlf);
1227  Smsg_ShortCut_End(&olf, &parent,
1228       sch_msg_hdl_cut(&parent, &olf, &nlf),
1229       sch_msg_snd_cut(&parent, &olf, &nlf)
1230      );
1231  Disable_Int();
1232  ok = Sch_Lock(SiteLeaf(site)); assert(ok);
1233  Enable_Int();
1234  return;
1235}
1236
1237/* these two sch-interface functions differ from others:
1238**     they do return, without checking scheduler message queue
1239*/
1240
1241void sch_load_report(leaf_hdl)
1242const st_handle_t *leaf_hdl;
1243{
1244   st_id_t * leaf = (st_id_t *)leaf_hdl;
1245   if (!Rich(Trunk(leaf))) {
1246      assert(!JsRoot(leaf));
1247      SetRich(Trunk(leaf));
1248      Smsg_ShortCut_Mid(leaf, SupTree(leaf),
1249 	   sch_msg_hdl_load_report(SupTree(leaf),leaf),
1250	   sch_msg_snd_load_report(SupTree(leaf),leaf)
1251	  );
1252      return;
1253   } else if (Suspended(leaf)) {
1254/*
1255      void loadreport_and_publish();
1256      st_id_t olf; olf = *leaf;
1257      assert(JsRoot(leaf));
1258      loadreport_and_publish(&olf);
1259      return;
1260*/
1261      /* as there exists a bug that a suspended leaf has a chopped
1262      ** common ancestor which should not happen, I have to comment
1263      ** out the above code (lll before 3.5.2 release).
1264      */
1265      assert(JsRoot(leaf));
1266      Sch_WakeUp_Suspended(leaf);
1267      return;
1268   }
1269}
1270
1271void loadreport_and_publish(olf)
1272st_id_t *olf;
1273{
1274   site_id_t site = Site(olf);
1275   int remains, published, ok=0;
1276   st_id_t *nlf;
1277   st_susp_t *x = Suspended(olf);
1278   int max = (Scheduler(site)->root_first)?Scheduler(site)->max_to_publish:9999;
1279
1280   /* calculate the number of suspended leaves */
1281   while (x) {
1282      ok++;
1283      x = x->next;
1284   }
1285   if (ok > max) max = ok;
1286   x = Suspended(olf);
1287   Suspended(olf) = (st_susp_t *)0;
1288   if (!(published=eng_publish(LeafEngine(olf), max, &remains))) {
1289      /* nothing published. it can happen when some ad hoc parallel chpts
1290      ** are published or engine is crazy with a false load report
1291      */
1292      nlf = SiteLeaf(site);
1293      Suspended(nlf) = x;
1294      while (!ComnKnot(nlf,olf)) { /* it is safe as no upward messages */
1295	 SetJsRoot(nlf);
1296	 nlf = SupTree(nlf);
1297      }
1298      return;
1299   } else {
1300      st_id_t twig;
1301
1302   /* Published alternatives will wholelly be at the disposal of the current
1303   ** allocation. Some can be booked owing to asynchronous smsg-handling,
1304   ** but the relevant installations will not be handled before this function
1305   ** finishes, since the leaf is locked.
1306   */
1307      assert(!(remains && published<max));
1308      /* lock the published to simplify the handling */
1309      nlf = SiteLeaf(site);
1310      do {
1311	 nlf = SupTree(nlf);
1312	 ok = Sch_Lock(nlf);
1313      } while (!ComnKnot(nlf,olf));
1314      Suspended(olf) = x;
1315      if (!Alive(Trunk(olf))) { /* already chopped */
1316	 void relocate_suspended();
1317	 relocate_suspended(olf);
1318	 nlf = SiteLeaf(site);
1319	 do {
1320	    nlf = SupTree(nlf);
1321	    Sch_Unlock(nlf);
1322	 } while (!ComnKnot(nlf,olf));
1323	 return;
1324      }
1325      nlf = SiteLeaf(site);
1326      while (x) {
1327         while (Exhausted(nlf) && !ComnKnot(nlf,olf)) {
1328	    nlf = SupTree(nlf);
1329	    if (!remains) {
1330               SetPoor(Twig(nlf));
1331               SetPoor(Trunk(SubTree(nlf)));
1332	    }
1333	 }
1334	 if (Exhausted(nlf)) break;
1335         Bk_NextClause0(nlf);
1336         Add_Lodge_Twig(&twig, &(x->leaf), Knot(nlf));
1337         eng_donate_state(LeafEngine(SiteLeaf(site)), (st_handle_t *)&twig,
1338                        (st_handle_t *)&(x->coma), (st_handle_t *)&(x->leaf));
1339         Scheduler(site)->state_donate++;
1340         Suspended(olf) = x->next;
1341         Sch_Gc_Suspended(site,x);
1342	 x = Suspended(olf);
1343      }
1344      if (Suspended(olf)) {
1345	 assert(!remains);
1346	 assert(ComnKnot(nlf,olf));
1347      }
1348      nlf = SiteLeaf(site);
1349      do {
1350         nlf = SupTree(nlf);
1351         Sch_Unlock(nlf);
1352      } while (!ComnKnot(nlf,olf));
1353      return;
1354   }
1355}
1356
1357void sch_load_publish_one(leaf_hdl, alt, parent_hdl, hybrid)
1358const st_handle_t *leaf_hdl;
1359st_handle_t *parent_hdl;
1360int alt, hybrid;
1361{
1362  st_id_t * olf    = (st_id_t *)leaf_hdl;
1363  st_id_t * parent = (st_id_t *)parent_hdl;
1364
1365  st_id_t nlf;
1366
1367  assert(Rich(Trunk(olf)));
1368  /* make sure the engine follows the convention:
1369   * when an engine rejects a job request, it is expected to
1370   * issue a job-report before it actually publishes anything.
1371   * It is to avoid the situation that suspended request flows
1372   * are buried within ancestors. A job-report will wake the
1373   * suspended request flows.
1374   */
1375  assert(!JsRoot(olf)||!Suspended(olf));
1376  Sch_Alloc_Knot(Site(olf), &nlf);
1377  Add_Alive_Twig_Next(parent,&nlf,Knot(olf),Trunk(olf)->prev);
1378  Twig(parent)->info = Trunk(&nlf)->info = Trunk(olf)->info;
1379  if (alt > 0) {
1380     Knot(olf)->nxtcls = Knot(olf)->nxtcls_b = alt;
1381  } else { /* a dummy node */
1382     SetPsRoot(olf);
1383     if (alt==(-1)) /* a reserve the sequential choice points for
1384		    ** the local worker
1385		    */
1386        SetLocal(olf);
1387  }
1388  Hybrid(olf) = hybrid;
1389  Knot(olf)->tip = 0;
1390  *SupTree(&nlf) = *parent;
1391
1392  Sch_Event_Notify3("LF_SPROUT","alt          ",SupTree(parent),parent,&nlf);
1393
1394  if (Sch_Lock(&nlf)) {
1395     Sch_Unlock(olf);
1396     NewSiteLeaf(&nlf);
1397  } else {
1398     assert(zero());
1399  }
1400}
1401
1402/* Scheduler message handlers */
1403/* Covention: the subject node/leaf, often named as 'self', has been locked,
1404	      before the handler is called;
1405	      they should be unlocked before the handler returns.
1406*/
1407
1408
1409/* Up */
1410static void sch_msg_hdl_backtrack(self, leaf)
1411st_id_t *self, *leaf;
1412{
1413  void sch_msg_hdl_backtrack_();
1414
1415  Smsg_Hdl_Notify(SMSG_BACKTRACK,self,leaf);
1416  if (Alive(Trunk(self))) {
1417     sch_msg_hdl_backtrack_(self, leaf);
1418     return;
1419  } else {
1420     assert(Chopped(Trunk(self)));
1421     Sch_Unlock(self);
1422     return;
1423  }
1424}
1425
1426void sch_msg_hdl_backtrack_(self, leaf)
1427st_id_t *self, *leaf;
1428{
1429  int alt = Bk_NextClause(self); alt = Tk_NextClause(self);
1430  UpdateLmp(self);
1431  AliveTwigs(self)--;
1432  SetNalive(Twig(self),ST_LODGED);
1433
1434/* ## schedule an alternative available
1435**    we do not care about special nodes (e.g. proot,sroot) as they
1436**    created as dummy one, thus with no alternative
1437*/
1438  if (alt && (AliveTwigs(self) || !Exhausted(self))) {
1439     Quit_Chain(Twig(self));
1440     Join_Chain_Next(Twig(self),Trunk(self)->prev);
1441     SetAlive(Twig(self));
1442     AliveTwigs(self)++;
1443     SetPoor(Twig(self));
1444     Smsg_ShortCut_End(self, leaf,
1445          sch_msg_hdl_js_success(leaf, self, alt, Twig(self)->info),
1446          sch_msg_snd_js_success(leaf, self, alt, Twig(self)->info)
1447         );
1448     return;
1449  } else if (alt || (!AliveTwigs(self)&&(ComnSite(self,leaf)||!Local(self)))) {
1450     assert(!SchRoot(self));
1451     SetNalive(Trunk(self), ST_DYING);
1452     if (!alt && Hybrid(self)) alt = -1;
1453     Smsg_ShortCut_End(self, SupTree(self),
1454          sch_msg_hdl_straighten(SupTree(self),self,leaf,self,alt),
1455          sch_msg_snd_straighten(SupTree(self),self,leaf,self,alt)
1456         );
1457     return;
1458  } else if (!AliveTwigs(self) && Suspended(self)) {
1459     st_susp_t **x = &Suspended(self);
1460     do { /* only when the local leaf is idling, this loop can finish
1461	     without breaking */
1462	if (ComnSite(self,&((*x)->leaf))) {
1463	   st_susp_t *y = *x;
1464	   *x = y->next;
1465	   SetNalive(Trunk(self), ST_DYING);
1466	   if (Hybrid(self)) alt = -1;
1467	   Smsg_ShortCut_Mid(self, SupTree(self),
1468		sch_msg_hdl_straighten(SupTree(self),self,&(y->leaf),self,alt),
1469		sch_msg_snd_straighten(SupTree(self),self,&(y->leaf),self,alt)
1470	       );
1471	   Sch_Gc_Suspended(Site(self),y);
1472	   break;
1473	} else {
1474	   x = &((*x)->next);
1475	}
1476     } while (*x);
1477  }
1478  /* ## job-search prologue. */
1479  if (ComnSite(self,SupTree(self)) && !PoorSpine(self) && !JsRoot(self) &&
1480      !(Local(self)&&ComnSite(self,leaf))) {
1481     Smsg_ShortCut_End(self,SupTree(self),
1482          sch_msg_hdl_js_prologue(SupTree(self),self,leaf),
1483          sch_msg_snd_js_prologue(SupTree(self),self,leaf)
1484         );
1485  } else {
1486    st_id_t *coma = self;
1487    SetPoorSpine(self);
1488    Sch_JS_Trav_Down(self,coma,leaf);
1489    Sch_JS_Trav_Up(self,coma,leaf);
1490  }
1491}
1492
1493
1494/* Up */
1495static void sch_msg_hdl_straighten(self,child,leaf,parent,alt)
1496st_id_t *self, *child, *leaf, *parent;
1497int alt;
1498{
1499  st_id_t twig;
1500  Smsg_Hdl_Notify(SMSG_STRAIGHTEN,self,child);
1501  if (Alive(Twig(self))) {
1502     AliveTwigs(self)--;
1503     if (!Exhausted(self)||(AliveTwigs(self)||PsRoot(self)||SchRoot(self))) {
1504	if (alt) {
1505	   Add_Alive_Twig_Next(&twig,leaf,Knot(self),Twig(self));
1506	   Twig(&twig)->info = Twig(self)->info;
1507	   if (JsRoot(self) && Monad(self) && !Suspended(self)) {
1508	      SetRich(Twig(&twig));
1509	      Smsg_ShortCut_Mid(&twig,leaf,
1510	           sch_msg_hdl_js_trust(leaf,&twig,parent,alt,Twig(&twig)->info),
1511	           sch_msg_snd_js_trust(leaf,&twig,parent,alt,Twig(&twig)->info)
1512	          );
1513	      Smsg_ShortCut_Mid(&twig,leaf,
1514		   sch_msg_hdl_set_js_root(leaf, &twig),
1515		   sch_msg_snd_set_js_root(leaf, &twig)
1516	          );
1517	   } else {
1518	      SetPoor(Twig(&twig));
1519	      Smsg_ShortCut_Mid(&twig,leaf,
1520	           sch_msg_hdl_js_trust(leaf,&twig,parent,alt,Twig(&twig)->info),
1521	           sch_msg_snd_js_trust(leaf,&twig,parent,alt,Twig(&twig)->info)
1522	          );
1523	   }
1524	} else if (!Exhausted(self)) {
1525	   alt = Bk_NextClause(self);
1526	   alt = Tk_NextClause(self);
1527	   if (!Exhausted(self)||(AliveTwigs(self)||PsRoot(self)||SchRoot(self))) {
1528	      Add_Alive_Twig_Next(&twig,leaf,Knot(self),Twig(self));
1529	      Twig(&twig)->info = Twig(self)->info;
1530	      SetPoor(Twig(self));
1531	      Smsg_ShortCut_Mid(&twig, leaf,
1532                   sch_msg_hdl_js_success(leaf,&twig,alt,Twig(&twig)->info),
1533                   sch_msg_snd_js_success(leaf,&twig,alt,Twig(&twig)->info)
1534                  );
1535	   } else {
1536	      SetNalive(Trunk(self),ST_DYING);
1537	      Smsg_ShortCut_Mid(self, SupTree(self),
1538		   sch_msg_hdl_straighten(SupTree(self),self,leaf,self,alt),
1539		   sch_msg_snd_straighten(SupTree(self),self,leaf,self,alt)
1540		  );
1541	   }
1542	} else if (PsRoot(self) && !AliveTwigs(self)) {
1543	   if (!Local(self) || ComnSite(self,leaf)) {
1544	      SetNalive(Trunk(self),ST_DYING);
1545	      if (Hybrid(self)) alt = -1;
1546	      Smsg_ShortCut_Mid(self, SupTree(self),
1547		   sch_msg_hdl_straighten(SupTree(self),self,leaf,self,alt),
1548		   sch_msg_snd_straighten(SupTree(self),self,leaf,self,alt)
1549		  );
1550	   } else {
1551	      if (Suspended(self)) {
1552		 st_susp_t **x = &Suspended(self);
1553		 do { /* only when the local leaf is idling, this loop can
1554			 finish without breaking */
1555		    if (ComnSite(self,&((*x)->leaf))) {
1556			st_susp_t *y = *x;
1557			*x = y->next;
1558			SetNalive(Trunk(self), ST_DYING);
1559			if (Hybrid(self)) alt = -1;
1560			Smsg_ShortCut_Mid(self, SupTree(self),
1561		sch_msg_hdl_straighten(SupTree(self),self,&(y->leaf),self,alt),
1562		sch_msg_snd_straighten(SupTree(self),self,&(y->leaf),self,alt)
1563			);
1564			Sch_Gc_Suspended(Site(self),y);
1565			break;
1566		    } else {
1567			x = &((*x)->next);
1568		    }
1569		 } while (*x);
1570	      }
1571	      Add_Lodge_Twig(&twig,leaf,Knot(self));
1572	      Smsg_ShortCut_Mid(&twig, leaf,
1573		   sch_msg_hdl_lodged(leaf, &twig),
1574		   sch_msg_snd_lodged(leaf, &twig)
1575		  );
1576	   }
1577	} else if (Local(self)&&ComnSite(self,leaf)) {
1578	   st_susp_t *x;
1579	   Sch_Alloc_Suspended(Site(self), x);
1580	   x->next = Suspended(self);
1581	   x->leaf = *(leaf);
1582	   x->coma = *(self);
1583	   Suspended(self) = x;
1584	} else if (!JsRoot(self) && !PoorSpine(self)
1585				 && ComnSite(self,leaf)
1586				 && ComnSite(self,SubTree(self))
1587				 && ComnSite(self,SupTree(self))) {
1588	   Smsg_ShortCut_Mid(self, SupTree(self),
1589		sch_msg_hdl_js_prologue(SupTree(self),self,leaf),
1590		sch_msg_snd_js_prologue(SupTree(self),self,leaf)
1591		);
1592	} else {
1593	   Add_Lodge_Twig(&twig,leaf,Knot(self));
1594	   Smsg_ShortCut_Mid(&twig, leaf,
1595                sch_msg_hdl_lodged(leaf, &twig),
1596                sch_msg_snd_lodged(leaf, &twig)
1597               );
1598	}
1599	SetNalive(Twig(self),ST_CHOPPED);
1600	Smsg_ShortCut_End(self, SubTree(self),
1601	     sch_msg_hdl_chop(SubTree(self),self,self),
1602	     sch_msg_snd_chop(SubTree(self),self,self)
1603	    );
1604	return;
1605     } else { /* need resume sequential chpts: further up */
1606	SetNalive(Trunk(self),ST_DYING);
1607	SetNalive(Twig(self),ST_DYING);
1608	if (!alt && Hybrid(self)) alt = -1;
1609	Smsg_ShortCut_End(self, SupTree(self),
1610	     sch_msg_hdl_straighten(SupTree(self),self,leaf,parent,alt),
1611	     sch_msg_snd_straighten(SupTree(self),self,leaf,parent,alt)
1612	    );
1613	return;
1614     }
1615  } else {
1616     assert(!Alive(Trunk(self))); /* i.e. whole subtree chopped */
1617     if (ComnSite(self,SupTree(self)) && ComnSite(self,leaf) &&
1618	 !PoorSpine(self) && !PoorSpine(SupTree(self))) {
1619	Smsg_ShortCut_End(self, SupTree(self),
1620	     sch_msg_hdl_js_prologue(SupTree(self),self,leaf),
1621	     sch_msg_snd_js_prologue(SupTree(self),self,leaf)
1622	    );
1623     } else {
1624	Smsg_ShortCut_End(self,SupTree(self),
1625             sch_msg_hdl_lodge(SupTree(self),self,leaf),
1626             sch_msg_snd_lodge(SupTree(self),self,leaf)
1627            );
1628     }
1629  }
1630}
1631
1632/* Up */
1633static void sch_msg_hdl_js_prologue(self, child, leaf)
1634st_id_t *self, *child, *leaf;
1635{
1636  Smsg_Hdl_Notify(SMSG_JS_PROLOGUE, self, child);
1637  if (!Exhausted(self)) { /* it does not care about the twig state */
1638     st_id_t twig;
1639     int alt = Bk_NextClause(self); /* value not interesting */
1640     alt = Tk_NextClause(self);
1641     Add_Alive_Twig_Next(&twig,leaf,Knot(self),Trunk(self)->prev);
1642     CheckLmp(&twig);
1643     SetPoor(Twig(&twig));
1644     Smsg_ShortCut_End(&twig, leaf,
1645	  sch_msg_hdl_js_success(leaf,&twig,alt,Twig(&twig)->info),
1646	  sch_msg_snd_js_success(leaf,&twig,alt,Twig(&twig)->info)
1647	 );
1648     return;
1649  }
1650  if (Alive(Trunk(self)) && (JsRoot(self) || PoorSpine(self) ||
1651             !ComnSite((self),SupTree(self)) || PoorSpine(SupTree(self)) ||
1652             (ComnSite(self,leaf) && Local(self)))) {
1653     Smsg_ShortCut_End(self,leaf,
1654          sch_msg_hdl_js_in_vain(leaf,self),
1655          sch_msg_snd_js_in_vain(leaf,self)
1656         );
1657     return;
1658  } else if (ComnSite((self),SupTree(self))) {
1659     Smsg_ShortCut_End(self, SupTree(self),
1660          sch_msg_hdl_js_prologue(SupTree(self),self,leaf),
1661          sch_msg_snd_js_prologue(SupTree(self),self,leaf)
1662         );
1663     return;
1664  } else {
1665     Smsg_ShortCut_End(self, SupTree(self),
1666          sch_msg_hdl_lodge(SupTree(self),self,leaf),
1667          sch_msg_snd_lodge(SupTree(self),self,leaf)
1668         );
1669     return;
1670  }
1671}
1672
1673/* Down */
1674static void sch_msg_hdl_js_success(leaf,parent,nxtcls,info)
1675st_id_t *leaf, *parent;
1676int nxtcls, info;
1677{
1678  Smsg_Hdl_Notify(SMSG_JS_SUCCESS, leaf,parent);
1679  eng_backtrack(LeafEngine(leaf),(st_handle_t *)parent,(unsigned) nxtcls);
1680
1681  switch (Life(Trunk(leaf))) {
1682    case ST_CUT:
1683      Smsg_ShortCut_Mid(leaf, Corpse(leaf),
1684	   sch_msg_hdl_dec_corpse(Corpse(leaf),leaf),
1685	   sch_msg_snd_dec_corpse(Corpse(leaf),leaf)
1686	  );
1687      break;
1688    case ST_BACKTRACK:
1689    case ST_LODGED:
1690    case ST_CHOPPED:
1691      if (ComnNode(SupTree(leaf),parent))
1692	 break;
1693      Smsg_ShortCut_Mid(leaf, SupTree(leaf),
1694	   sch_msg_hdl_withered(SupTree(leaf),leaf),
1695	   sch_msg_snd_withered(SupTree(leaf),leaf)
1696	  );
1697      break;
1698    default:
1699      error("illegal leaf type");
1700  }
1701  Trunk(leaf)->info = info;
1702  assert(!Suspended(leaf));
1703  *SupTree(leaf) = *parent;
1704  Sch_Unlock(leaf);
1705  return;
1706}
1707
1708/* Down */
1709static void sch_msg_hdl_js_trust(leaf,parent,parent_nxtcls,nxtcls,info)
1710st_id_t *leaf, *parent, *parent_nxtcls;
1711int nxtcls, info;
1712{
1713  Smsg_Hdl_Notify(SMSG_JS_TRUST, leaf,parent);
1714  /* the leaf could in a lodged state when a 'Local' node becomes resumable */
1715  assert(Life(Trunk(leaf))==ST_BACKTRACK || Life(Trunk(leaf))==ST_LODGED);
1716  assert(!Suspended(leaf));
1717  Smsg_ShortCut_Mid(leaf, SupTree(leaf),
1718        sch_msg_hdl_withered(SupTree(leaf),leaf),
1719        sch_msg_snd_withered(SupTree(leaf),leaf)
1720       );
1721  if (!ComnNode(parent_nxtcls,SupTree(leaf))) {
1722     eng_backtrack(LeafEngine(leaf), (st_handle_t *)parent_nxtcls, 0);
1723  }
1724  if (nxtcls>0) {
1725     assert(nxtcls==1);
1726     eng_trust(LeafEngine(leaf),(unsigned) nxtcls); /* keep this order with next line */
1727     eng_undo_publish(LeafEngine(leaf),(st_handle_t *)parent);
1728  } else {
1729     eng_undo_publish(LeafEngine(leaf), (st_handle_t *)parent);
1730     eng_fail(LeafEngine(leaf));
1731  }
1732  *SupTree(leaf) = *parent;
1733  Trunk(leaf)->info = info;
1734  if (!Rich(Trunk(leaf))) ResetJsRoot(leaf);
1735  Sch_Unlock(leaf);
1736  return;
1737}
1738
1739
1740static void sch_msg_hdl_dec_corpse(old,new)
1741st_id_t *old, *new;
1742{
1743  Smsg_Hdl_Notify(SMSG_DEC_CORPSE,old,new);
1744   switch (Life(Trunk(old))) {
1745      case ST_DYING:
1746	SetNalive(Trunk(old), ST_DEAD);
1747	Sch_Unlock(old);
1748	return;
1749      case ST_CHOPPED:
1750	Smsg_ShortCut_End(old, SupTree(old),
1751	     sch_msg_hdl_withered(SupTree(old),old),
1752	     sch_msg_snd_withered(SupTree(old),old)
1753	    );
1754	Sch_Gc_Knot(old);
1755	return;
1756     default: error("illegal leaf type");
1757   }
1758}
1759
1760/* Up */
1761static void sch_msg_hdl_cut(self, olf, leaf)
1762st_id_t *self, *olf, *leaf;
1763{
1764  st_id_t twig;
1765  Smsg_Hdl_Notify(SMSG_CUT, self, olf);
1766  if (Alive(Twig(self))) { /* the cut wins */
1767     AliveTwigs(self)--;
1768     Add_Alive_Twig_Next(&twig,leaf,Knot(self),Twig(self));
1769     Twig(&twig)->info = Twig(self)->info;
1770     if (JsRoot(self) && Monad(self) && !Suspended(self)) {
1771        SetRich(Twig(&twig));
1772        Smsg_ShortCut_Mid(&twig,leaf,
1773             sch_msg_hdl_cut_ok(leaf,&twig,Twig(&twig)->info),
1774             sch_msg_snd_cut_ok(leaf,&twig,Twig(&twig)->info)
1775            );
1776        Smsg_ShortCut_Mid(&twig,leaf,
1777             sch_msg_hdl_set_js_root(leaf, &twig),
1778             sch_msg_snd_set_js_root(leaf, &twig)
1779            );
1780     } else {
1781        SetPoor(Twig(&twig));
1782        Smsg_ShortCut_Mid(&twig,leaf,
1783             sch_msg_hdl_cut_ok(leaf,&twig,Twig(&twig)->info),
1784             sch_msg_snd_cut_ok(leaf,&twig,Twig(&twig)->info)
1785            );
1786     }
1787     SetNalive(Twig(self),ST_CHOPPED);
1788     Smsg_ShortCut_End(self, SubTree(self),
1789	  sch_msg_hdl_chop(SubTree(self), self, self),
1790	  sch_msg_snd_chop(SubTree(self), self, self)
1791	 );
1792     return;
1793  } else if (Exhausted(self)) {
1794     Add_Lodge_Twig(&twig,leaf,Knot(self));
1795     Smsg_ShortCut_End(&twig,leaf,
1796           sch_msg_hdl_lodged(leaf,&twig),
1797           sch_msg_snd_lodged(leaf,&twig)
1798          );
1799     return;
1800  } else {
1801     int alt = Bk_NextClause(self);
1802     alt = Tk_NextClause(self);
1803     Add_Alive_Twig_Next(&twig,leaf,Knot(self), Trunk(self)->prev);
1804     CheckLmp(&twig);
1805     SetPoor(Twig(&twig));
1806     Smsg_ShortCut_End(&twig, leaf,
1807          sch_msg_hdl_js_success(leaf, &twig, alt, Twig(&twig)->info),
1808          sch_msg_snd_js_success(leaf, &twig, alt, Twig(&twig)->info)
1809         );
1810     return;
1811  }
1812}
1813
1814/* Down */
1815static void sch_msg_hdl_cut_ok(leaf, parent, info)
1816st_id_t *leaf, *parent;
1817int info;
1818{
1819   Smsg_Hdl_Notify(SMSG_CUT_OK, leaf, parent);
1820   assert(Life(Trunk(leaf)) == ST_CUT);
1821   Smsg_ShortCut_Mid(leaf,Corpse(leaf),
1822	sch_msg_hdl_dec_corpse(Corpse(leaf),leaf),
1823	sch_msg_snd_dec_corpse(Corpse(leaf),leaf)
1824       );
1825   *SupTree(leaf) = *parent;
1826   Trunk(leaf)->info = info;
1827   eng_cut_ok(LeafEngine(leaf), (st_handle_t *)parent);
1828   assert(!Suspended(leaf));
1829   Sch_Unlock(leaf);
1830   return;
1831}
1832
1833/* Up */
1834static void sch_msg_hdl_init_lodge(root, leaf, wm)
1835st_id_t *root, *leaf;
1836int wm;
1837{
1838  st_id_t twig;
1839  Smsg_Hdl_Notify(SMSG_INIT_LODGE,root,leaf);
1840  assert(SchRoot(root) && Alive(Trunk(root)));
1841  Add_Lodge_Twig(&twig,leaf,Knot(root));
1842  wm_init_lodged(wm, (st_handle_t *)&twig);
1843  Sch_Unlock(root);
1844}
1845
1846/* Up */
1847static void sch_msg_hdl_lodge(self, child, leaf)
1848st_id_t *self, *child, *leaf;
1849{
1850  Smsg_Hdl_Notify(SMSG_LODGE, self, child);
1851  if (AliveTwigs(self)) {
1852     st_id_t twig;
1853     if (Exhausted(self)) {
1854	Add_Lodge_Twig(&twig,leaf,Knot(self));
1855	Smsg_ShortCut_End(&twig, leaf,
1856	     sch_msg_hdl_lodged(leaf, &twig),
1857	     sch_msg_snd_lodged(leaf, &twig)
1858	    );
1859	return;
1860     } else {
1861	int alt = Bk_NextClause(self); /* value not interesting */
1862	alt = Tk_NextClause(self);
1863	Add_Alive_Twig_Next(&twig,leaf,Knot(self),Trunk(self)->prev);
1864	CheckLmp(&twig);
1865	SetPoor(Twig(&twig));
1866	Smsg_ShortCut_End(&twig, leaf,
1867	     sch_msg_hdl_js_success(leaf,&twig,alt,Twig(&twig)->info),
1868	     sch_msg_snd_js_success(leaf,&twig,alt,Twig(&twig)->info)
1869	    );
1870	return;
1871     }
1872  } else if (Alive(Trunk(self))&&Local(self)&&ComnSite(self,leaf)) {
1873     int alt = Hybrid(self) ? (-1):0;
1874     SetNalive(Trunk(self), ST_DYING);
1875     Smsg_ShortCut_End(self,SupTree(self),
1876	  sch_msg_hdl_straighten(SupTree(self),self,leaf,self,alt),
1877	  sch_msg_snd_straighten(SupTree(self),self,leaf,self,alt)
1878	 );
1879     return;
1880  } else {
1881     Smsg_ShortCut_End(self, SupTree(self),
1882	  sch_msg_hdl_lodge(SupTree(self), self, leaf),
1883	  sch_msg_snd_lodge(SupTree(self), self, leaf)
1884	 );
1885     return;
1886  }
1887}
1888
1889/* Down */
1890static void sch_msg_hdl_lodged(leaf, parent)
1891st_id_t *leaf, *parent;
1892{
1893   Smsg_Hdl_Notify(SMSG_LODGED, leaf, parent);
1894   eng_backtrack(LeafEngine(leaf), (st_handle_t *)parent, 0);
1895   switch (Life(Trunk(leaf))) {
1896      case ST_CUT:
1897	Smsg_ShortCut_Mid(leaf, Corpse(leaf),
1898	     sch_msg_hdl_dec_corpse(Corpse(leaf),leaf),
1899	     sch_msg_snd_dec_corpse(Corpse(leaf),leaf)
1900	    );
1901        SetNalive(Trunk(leaf),ST_LODGED);
1902        *SupTree(leaf) = *parent;
1903        Smsg_ShortCut_End(leaf, SupTree(leaf),
1904             sch_msg_hdl_js_prologue(SupTree(leaf),leaf,leaf),
1905             sch_msg_snd_js_prologue(SupTree(leaf),leaf,leaf)
1906            );
1907	return;
1908      case ST_BACKTRACK:
1909	if (ComnNode(SupTree(leaf),parent))
1910	   break;
1911      case ST_CHOPPED:
1912      case ST_LODGED:
1913	Smsg_ShortCut_Mid(leaf, SupTree(leaf),
1914	     sch_msg_hdl_withered(SupTree(leaf),leaf),
1915	     sch_msg_snd_withered(SupTree(leaf),leaf)
1916	    );
1917	break;
1918     default:
1919	error("illegal leaf type");
1920   }
1921   SetNalive(Trunk(leaf),ST_LODGED);
1922   *SupTree(leaf) = *parent;
1923   if (Scheduler(Site(leaf))->idling) {
1924      Scheduler(Site(leaf))->idling = 0;
1925      Smsg_ShortCut_End(leaf,SupTree(leaf),
1926	   sch_msg_hdl_lodge_idle(SupTree(leaf),leaf,leaf),
1927	   sch_msg_snd_lodge_idle(SupTree(leaf),leaf,leaf)
1928	  );
1929   } else {
1930      Smsg_ShortCut_End(leaf,SupTree(leaf),
1931	   sch_msg_hdl_js_trav_up(SupTree(leaf),leaf,SupTree(leaf),leaf),
1932	   sch_msg_snd_js_trav_up(SupTree(leaf),leaf,SupTree(leaf),leaf)
1933          );
1934   }
1935}
1936
1937/* Up */
1938static void sch_msg_hdl_withered(self,child)
1939st_id_t *self, *child;
1940{
1941   Smsg_Hdl_Notify(SMSG_WITHERED, self,child);
1942   assert(Chopped(Twig(self)) || Lodged(Twig(self)));
1943   Quit_Chain(Twig(self));
1944   Sch_Gc_Edge(Site(self),Twig(self));
1945   if (Twigless(self)) {
1946      if (Chopped(Trunk(self))) {
1947         Smsg_ShortCut_End(self, SupTree(self),
1948	      sch_msg_hdl_withered(SupTree(self),self),
1949	      sch_msg_snd_withered(SupTree(self),self)
1950	     );
1951         Sch_Gc_Knot(self);
1952         return;
1953      } else {
1954	 assert(Dying(Trunk(self)));
1955      }
1956   }
1957   Sch_Unlock(self);
1958   return;
1959}
1960
1961
1962/* Down */
1963static void sch_msg_hdl_chop(self,parent,ancestor)
1964st_id_t *self, *parent, *ancestor;
1965{
1966   Smsg_Hdl_Notify(SMSG_CHOP,self,parent);
1967
1968   /* ## NODE ## */
1969   if (IsNode(self)) {
1970      st_edge_t *x = Trunk(self)->next;
1971      st_edge_t *y = (st_edge_t *) 0;
1972      st_id_t twig; twig = *self;
1973
1974      SetNalive(Trunk(self),ST_CHOPPED);
1975      SetExhausted(self);
1976
1977      if (Suspended(self)) {
1978	 void relocate_suspended();
1979	 assert(JsRoot(self) || Local(self));
1980	 relocate_suspended(self);
1981      }
1982      /* kill alive / idle branches */
1983      while (x != Trunk(self)) {
1984	 if (Alive(x) || Dying(x) || Idle(x)) {
1985	    if (Alive(x)) AliveTwigs(self)--;
1986	    SetNalive(x,ST_CHOPPED);
1987	    if (!y && ComnSite(self,&(x->tree)))
1988	       y = x;
1989	    else {
1990	       PackEdge(&twig,x);
1991	       Smsg_ShortCut_Mid(&twig, SubTree(&twig),
1992		    sch_msg_hdl_chop(SubTree(&twig), &twig, ancestor),
1993		    sch_msg_snd_chop(SubTree(&twig), &twig, ancestor)
1994		   );
1995	    }
1996	 }
1997	 x = x->next;
1998      }
1999      assert(!AliveTwigs(self));
2000      if (y) {
2001	 PackEdge(&twig,y);
2002	 Smsg_ShortCut_End(&twig, SubTree(&twig),
2003	      sch_msg_hdl_chop(SubTree(&twig), &twig, ancestor),
2004	      sch_msg_snd_chop(SubTree(&twig), &twig, ancestor)
2005	     );
2006      } else {
2007	 if (Twigless(self)) {
2008	    Smsg_ShortCut_End(self,SupTree(self),
2009		 sch_msg_hdl_withered(SupTree(self),self),
2010		 sch_msg_snd_withered(SupTree(self),self)
2011		);
2012	    Sch_Gc_Knot(&twig);
2013	 } else {
2014	   Sch_Unlock(self);
2015	 }
2016      }
2017      return;
2018   }
2019
2020   /* ## LEAF ## */
2021   switch (Life(Trunk(self))) {
2022     case ST_ALIVE:
2023       /* who will chop the only alive subtree ? */
2024       assert(!Suspended(self));
2025       Scheduler(Site(self))->lmp = 0;
2026       eng_stop(LeafEngine(self));
2027     case ST_BACKTRACK:
2028       if (!Scheduler(Site(self))->idling) {
2029	  SetNalive(Trunk(self),ST_LODGED);
2030	  if (ComnSite(SupTree(self),ancestor)) {
2031	     Smsg_ShortCut_End(self, ancestor,
2032		  sch_msg_hdl_js_prologue(ancestor, self, self),
2033		  sch_msg_snd_js_prologue(ancestor, self, self)
2034		 );
2035	     return;
2036	  } else {
2037	     Smsg_ShortCut_End(self, ancestor,
2038		  sch_msg_hdl_js_again(ancestor,self),
2039		  sch_msg_snd_js_again(ancestor,self)
2040		 );
2041	     return;
2042	  }
2043       }
2044       Scheduler(Site(self))->idling = 0;
2045     case ST_IDLE:
2046	SetNalive(Trunk(self),ST_LODGED);
2047	Smsg_ShortCut_End(self,ancestor,
2048	     sch_msg_hdl_lodge_idle(ancestor,self,self),
2049	     sch_msg_snd_lodge_idle(ancestor,self,self)
2050	    );
2051	return;
2052     case ST_DYING:
2053	SetNalive(Trunk(self),ST_CHOPPED);
2054	Sch_Unlock(self);
2055	return;
2056     case ST_DEAD: {
2057	st_id_t gb;
2058	gb = *self;
2059	Smsg_ShortCut_End(self, SupTree(self),
2060	     sch_msg_hdl_withered(SupTree(self), self),
2061	     sch_msg_snd_withered(SupTree(self), self)
2062	    );
2063	Sch_Gc_Knot(&gb);
2064	return;
2065	}
2066     default:
2067	error("illegal leaf state");
2068   }
2069}
2070
2071void relocate_suspended(self)
2072st_id_t *self;
2073{
2074   st_susp_t *s;
2075   st_id_t *ncoma;
2076   while (s = Suspended(self)) {
2077      ncoma = ComnNode(self, &(s->coma)) ? SupTree(self) : &(s->coma);
2078      Smsg_ShortCut_Mid((self),SupTree(self),
2079           sch_msg_hdl_js_trav_up(SupTree(self), self, ncoma, &(s->leaf)),
2080           sch_msg_snd_js_trav_up(SupTree(self), self, ncoma, &(s->leaf))
2081          );
2082      Suspended(self) = s->next;
2083      Sch_Gc_Suspended(Site(self),s);
2084   }
2085}
2086
2087/* Down */
2088static void sch_msg_hdl_js_in_vain(leaf,jroot)
2089st_id_t *leaf, *jroot;
2090{
2091   Smsg_Hdl_Notify(SMSG_JS_IN_VAIN, leaf,jroot);
2092   switch (Life(Trunk(leaf))) {
2093     case ST_BACKTRACK:
2094      SetNalive(Trunk(leaf),ST_LODGED);
2095     case ST_LODGED:
2096      if (Scheduler(Site(leaf))->idling) {
2097         Scheduler(Site(leaf))->idling = 0;
2098         Smsg_ShortCut_End(leaf,SupTree(leaf),
2099	      sch_msg_hdl_lodge_idle(SupTree(leaf),leaf,leaf),
2100	      sch_msg_snd_lodge_idle(SupTree(leaf),leaf,leaf)
2101	     );
2102         return;
2103      } else {
2104         Smsg_ShortCut_End(leaf, SupTree(leaf),
2105	      sch_msg_hdl_js_again(SupTree(leaf), leaf),
2106	      sch_msg_snd_js_again(SupTree(leaf), leaf)
2107             );
2108         return;
2109      }
2110     default:
2111      error("illegal leaf state");
2112   }
2113}
2114
2115/* Up */
2116static void sch_msg_hdl_js_again(self,leaf)
2117st_id_t *self, *leaf;
2118{
2119   void sch_msg_hdl_js_trav_up_();
2120   Smsg_Hdl_Notify(SMSG_JS_AGAIN, self, leaf);
2121   if (Alive(Trunk(self))) {
2122      sch_msg_hdl_js_trav_up_(self,self,leaf);
2123      return;
2124   } else {
2125      Smsg_ShortCut_End(self, SupTree(self),
2126	   sch_msg_hdl_lodge(SupTree(self), self, leaf),
2127	   sch_msg_snd_lodge(SupTree(self), self, leaf)
2128	  );
2129      return;
2130   }
2131}
2132
2133/* Down */
2134static void sch_msg_hdl_js_trav_dn(self,parent,coma,leaf)
2135st_id_t *self, *parent, *coma, *leaf;
2136{
2137   unsigned root_first = Scheduler(Site(self))->root_first;
2138   Smsg_Hdl_Notify(SMSG_JS_TRAV_DN, self,parent);
2139
2140repeat:
2141   if (Alive(Trunk(self))) {
2142      if (IsNode(self)) {
2143/** NODE **/
2144         if (Knot(self)->nxtcls_b) {
2145            st_id_t lodge;
2146            if (!root_first) {
2147#if defined(NON_DIRECT_CHECK)
2148               Sch_JS_Trav_Down(self,coma,leaf);
2149#else /* NON_DIRECT_CHECK */
2150               st_edge_t *x = Trunk(self)->prev;
2151               while (x != Trunk(self)) {
2152                  if (ComnSite(self,&(x->tree))) {
2153                     assert(Alive(x));
2154                     if (!Alive(x) || !Rich(x) || !Sch_Lock(&(x->tree))) break;
2155                     if (Knot(&(x->tree))->nxtcls_b) {
2156                        Sch_Unlock(self);
2157                        self = &(x->tree);
2158                        x = Trunk(self)->prev;
2159                     } else {
2160                        Sch_Unlock(&(x->tree));
2161                        break;
2162                     }
2163                  } else {
2164                     x = x->prev;
2165                  }
2166               }
2167#endif /* NON_DIRECT_CHECK */
2168            }
2169            Bk_NextClause0(self);
2170            Add_Lodge_Twig(&lodge, leaf, Knot(self));
2171            Sch_JS_Install(self, &lodge, coma, leaf);
2172            assert(zero());
2173            return;
2174         }
2175         if (root_first) {
2176            SetPoorSpine(self);
2177         }
2178         Sch_JS_Trav_Down(self,coma,leaf);
2179      } else {
2180/** LEAF **/
2181         if (Rich(Trunk(self))) {
2182            int max = (root_first) ? Scheduler(Site(self))->max_to_publish
2183				   : 9999;
2184	    int left;
2185	    if (!eng_publish(LeafEngine(self), max, &left)) {
2186	        st_id_t *nlf = SiteLeaf(Site(self));
2187	        if (!JsRoot(nlf)) SetPoor(Trunk(nlf));
2188		Sch_JS_Trav_Up(nlf,coma,leaf);
2189		return;
2190	    } else {
2191               st_id_t nlf;
2192	       /* make sure the engine follows the convention:
2193		* when an engine rejects a job request, it is expected to
2194		* issue a job-report before it actually publishes anything.
2195		* It is to avoid the situation that suspended request flows
2196		* are buried within ancestors. A job-report will wake the
2197		* suspended request flows.
2198		*/
2199	       assert(!JsRoot(self)||!Suspended(self));
2200	       nlf = *SiteLeaf(Site(self));
2201	       if (!left) {
2202		  SetPoor(Trunk(&nlf));
2203		  SetPoor(Twig(SupTree(&nlf)));
2204	       }
2205	       { st_id_t *next = SupTree(&nlf);
2206		 st_id_t *last = self;
2207		 st_id_t *prev;
2208		 do {
2209	           if (Sch_Lock(next)) {
2210		     if (!Exhausted(next)) {
2211			st_id_t twig;
2212			Bk_NextClause0(next);
2213			Add_Lodge_Twig(&twig,leaf,Knot(next));
2214			eng_donate_state(LeafEngine(&nlf),(st_handle_t *)&twig,
2215							  (st_handle_t *)coma,
2216							  (st_handle_t *)leaf);
2217			Scheduler(Site(self))->state_donate++;
2218			Sch_Unlock(&twig);
2219			Sch_Unlock(&nlf);
2220			return;
2221	             } else {
2222		         Sch_Unlock(next);
2223	             }
2224	            }
2225		    prev = next;
2226	            next = SupTree(next);
2227	         } while (!ComnKnot(prev,last));
2228	       }
2229	       if (Sch_Lock(self)) {
2230	          Sch_Unlock(&nlf);
2231	          goto repeat;
2232	       } else
2233	          assert(zero());
2234	    }
2235         }
2236      }
2237   }
2238   Sch_JS_Trav_Up(self,coma,leaf);
2239}
2240
2241void sch_msg_hdl_js_trav_up_(self, coma, leaf)
2242st_id_t *self, *coma, *leaf;
2243{
2244   unsigned root_first = Scheduler(Site(self))->root_first;
2245   if (Alive(Trunk(self))) {
2246      if (!root_first) {
2247         Sch_JS_Trav_Down(self,coma,leaf);
2248      }
2249      if (!Exhausted(self) && ComnNode(self,coma)) {
2250         st_id_t twig;
2251	 int alt = Bk_NextClause(self); /* value not interesting */
2252	 alt = Tk_NextClause(self);
2253         Add_Alive_Twig_Next(&twig,leaf,Knot(self),Trunk(self)->prev);
2254	 CheckLmp(&twig);
2255     	 SetPoor(Twig(&twig));
2256         Smsg_ShortCut_End(&twig, leaf,
2257              sch_msg_hdl_js_success(leaf, &twig, alt, Twig(&twig)->info),
2258              sch_msg_snd_js_success(leaf, &twig, alt, Twig(&twig)->info)
2259             );
2260         return;
2261      }
2262      if (Bk_NextClause(self)) {
2263          st_id_t lodge;
2264          Add_Lodge_Twig(&lodge,leaf,Knot(self));
2265          Sch_JS_Install(self, &lodge, coma, leaf);
2266          assert(zero());
2267          return;
2268      }
2269      if (root_first) {
2270         SetPoorSpine(self);
2271         Sch_JS_Trav_Down(self,coma,leaf);
2272      }
2273      assert(!Rich(Trunk(self)) || JsRoot(self));
2274   }
2275   Sch_JS_Trav_Up(self,coma,leaf);
2276}
2277
2278/* Up */
2279static void sch_msg_hdl_js_trav_up(self, child, coma, leaf)
2280st_id_t *self, *child, *coma, *leaf;
2281{
2282   SetPoor(Twig(self));
2283   Smsg_Hdl_Notify(SMSG_JS_TRAV_UP, self, child);
2284   sch_msg_hdl_js_trav_up_(self, coma, leaf);
2285}
2286
2287static void sch_msg_hdl_js_install(self,parent,lodge,coma,leaf)
2288st_id_t *self, *parent, *lodge, *coma, *leaf;
2289{
2290   Smsg_Hdl_Notify(SMSG_JS_INSTALL, self,parent);
2291   if (IsNode(self)) {
2292      Sch_JS_Install(self, lodge, coma, leaf);
2293      /* returns back only if no alive local subtree found */
2294   } else if (Alive(Trunk(self))||Idle(Trunk(self))) {
2295     /* LEAF */
2296      eng_donate_state(LeafEngine(self),(st_handle_t *)lodge,
2297		(st_handle_t *)coma,(st_handle_t *)leaf);
2298      Scheduler(Site(self))->state_donate++;
2299      Sch_Unlock(self);
2300      return;
2301   }
2302   Smsg_ShortCut_End(self, lodge,
2303	sch_msg_hdl_js_install_fl(lodge, self, coma, leaf),
2304	sch_msg_snd_js_install_fl(lodge, self, coma, leaf)
2305       );
2306   return;
2307}
2308
2309
2310static void sch_msg_hdl_engine_migrate(self, leaf)
2311st_id_t *self, *leaf;
2312{
2313   Smsg_Hdl_Notify(SMSG_ENGINE_MIGRATE, self, leaf);
2314   assert(ComnNode(SubTree(self),leaf) && Lodged(Twig(self)));
2315   if (Exhausted(self)) {
2316      if (ComnSite(self,SupTree(self)) && !PoorSpine(self) && !JsRoot(self)) {
2317	 Smsg_ShortCut_End(self,SupTree(self),
2318	      sch_msg_hdl_js_prologue(SupTree(self),self,leaf),
2319	      sch_msg_snd_js_prologue(SupTree(self),self,leaf)
2320	     );
2321	 return;
2322      } else {
2323         void sch_msg_hdl_js_trav_up_();
2324         st_id_t coma; coma = *self;
2325         sch_msg_hdl_js_trav_up_(self,&coma,leaf);
2326         return;
2327      }
2328   } else {
2329      int alt = Tk_NextClause(self);
2330      Quit_Chain(Twig(self));
2331      Join_Chain_Next(Twig(self),Trunk(self)->prev);
2332      AliveTwigs(self)++;
2333      SetAlive(Twig(self));
2334      SetPoor(Twig(self));
2335      CheckLmp(self);
2336      Smsg_ShortCut_End(self,leaf,
2337	   sch_msg_hdl_js_success(leaf,self,alt,Twig(self)->info),
2338	   sch_msg_snd_js_success(leaf,self,alt,Twig(self)->info)
2339	  );
2340      return;
2341   }
2342}
2343
2344static void sch_msg_hdl_js_install_fl(self, child, coma, leaf)
2345st_id_t *self, *child, *coma, *leaf;
2346{
2347   Smsg_Hdl_Notify(SMSG_JS_INSTALL_FL, self, child);
2348   if (Exhausted(self)) {
2349      st_id_t garbage; garbage = *self;
2350      Quit_Chain(Twig(self));
2351      Sch_JS_Trav_Down(self,coma,leaf);
2352      Sch_JS_Trav_Up(self,coma,leaf);
2353      Sch_Gc_Edge(Site(&garbage),Twig(&garbage));
2354   } else {
2355      st_edge_t *x = Trunk(self)->prev;
2356      while (x != Trunk(self)) {
2357	if (Alive(x) || Idle(x)) {
2358           st_id_t twig; twig = *self;
2359	   PackEdge(&twig,x);
2360	   sch_msg_snd_js_install(SubTree(&twig),&twig,self,coma,leaf);
2361	   Sch_Unlock(self);
2362	   return;
2363	} else {
2364	   x = x->prev;
2365	}
2366      }
2367      assert(zero());
2368   }
2369}
2370
2371static void sch_msg_hdl_load_report(self, child)
2372st_id_t *self, *child;
2373{
2374   Smsg_Hdl_Notify(SMSG_LOAD_REPORT, self, child);
2375   if (!Alive(Twig(self))) {
2376      Sch_Unlock(self);
2377      return;
2378   }
2379   /* the assertion below may not hold for the local leaf: when
2380   ** the child is a local node, and the local leaf, after finishing
2381   ** traversal of the whole subtree, will reset it (trunk) poor, but it
2382   ** will not reset poor the suptree twig as other js_trav leaves as
2383   ** it does not go up, instead, suspends itself at the local node.
2384   */
2385   /*assert(!Rich(Twig(self)));*/
2386   SetRich(Twig(self));
2387   if (JsRoot(self) && Monad(self) && Exhausted(self)) {
2388      assert(Rich(Trunk(self)));
2389      Smsg_ShortCut_Mid(self, SubTree(self),
2390	   sch_msg_hdl_set_js_root(SubTree(self), self),
2391	   sch_msg_snd_set_js_root(SubTree(self), self)
2392	  );
2393   }
2394   if (Suspended(self)) {
2395      st_susp_t *x;
2396      assert(JsRoot(self) || Local(self));
2397      while (x = Suspended(self)) {
2398	 Smsg_ShortCut_Mid((self),SubTree(self),
2399	    sch_msg_hdl_js_trav_dn(SubTree(self), self, &(x->coma), &(x->leaf)),
2400	    sch_msg_snd_js_trav_dn(SubTree(self), self, &(x->coma), &(x->leaf))
2401	     );
2402	 Suspended(self) = x->next;
2403	 Sch_Gc_Suspended(Site(self),x);
2404      }
2405   }
2406   if (!Rich(Trunk(self))) { /* further report up */
2407      assert(!JsRoot(self));
2408      SetRich(Trunk(self));
2409      Smsg_ShortCut_End(self, SupTree(self),
2410	   sch_msg_hdl_load_report(SupTree(self), self),
2411	   sch_msg_snd_load_report(SupTree(self), self)
2412	  );
2413      return;
2414   } else {
2415      Sch_Unlock(self);
2416      return;
2417   }
2418}
2419
2420/* Down */
2421static void sch_msg_hdl_set_js_root(self, parent)
2422st_id_t *self, *parent;
2423{
2424   Smsg_Hdl_Notify(SMSG_SET_JS_ROOT, self, parent);
2425   if (Rich(Trunk(self))) {
2426      SetJsRoot(self);
2427      /* assert(!Suspended(self) || Local(self)); */
2428      if (Monad(self) && Exhausted(self) && !Suspended(self)) {
2429 	 st_id_t twig;
2430 	 st_edge_t *x = Trunk(self)->next;
2431 	 while (x != Trunk(self)) {
2432    	   if (Alive(x)) {
2433              twig = *self;
2434              PackEdge(&twig,x);
2435	      Smsg_ShortCut_End(&twig, SubTree(&twig),
2436		   sch_msg_hdl_set_js_root(SubTree(&twig), &twig),
2437		   sch_msg_snd_set_js_root(SubTree(&twig), &twig)
2438		  );
2439	      return;
2440           }
2441           x = x->next;
2442         }
2443         assert(zero());
2444      }
2445   }
2446   Sch_Unlock(self);
2447   return;
2448}
2449
2450/* Up */
2451static void sch_msg_hdl_stop_idle(self,leaf)
2452st_id_t *self, *leaf;
2453{
2454   Smsg_Hdl_Notify(SMSG_STOP_IDLE, self, leaf);
2455   if (!Alive(Trunk(self))) {
2456      if (Chopped(Trunk(self))) {
2457	 Sch_Unlock(self);
2458	 return;
2459      } else {
2460         assert(Dying(Trunk(self)));
2461         assert(Idle(Twig(self)));
2462         SetNalive(Twig(self),ST_LODGED);
2463         if (ComnSite(self,SupTree(self)) && !PoorSpine(self) &&
2464					     !PoorSpine(SupTree(self))) {
2465	    Smsg_ShortCut_End(self, SupTree(self),
2466	         sch_msg_hdl_js_prologue(SupTree(self),self,leaf),
2467	         sch_msg_snd_js_prologue(SupTree(self),self,leaf)
2468	        );
2469            return;
2470         } else {
2471	    Smsg_ShortCut_End(self, SupTree(self),
2472	         sch_msg_hdl_lodge(SupTree(self),self,leaf),
2473	         sch_msg_snd_lodge(SupTree(self),self,leaf)
2474	        );
2475	    return;
2476         }
2477      }
2478   } else {
2479      int alt = Bk_NextClause(self);
2480      alt = Tk_NextClause(self);
2481      /* the below assert relies on the assumption that an exhausted
2482      ** monad leaf not allowed to become idle.
2483      */
2484      assert(alt || AliveTwigs(self) || Local(self));
2485      assert(Idle(Twig(self)));
2486      SetNalive(Twig(self),ST_LODGED);
2487      if (alt && (AliveTwigs(self)||!Exhausted(self))) {
2488         Quit_Chain(Twig(self));
2489         Join_Chain_Next(Twig(self),Trunk(self)->prev);
2490         AliveTwigs(self)++;
2491         SetAlive(Twig(self));
2492         SetPoor(Twig(self));
2493         Smsg_ShortCut_End(self, leaf,
2494              sch_msg_hdl_js_success(leaf, self, alt, Twig(self)->info),
2495              sch_msg_snd_js_success(leaf, self, alt, Twig(self)->info)
2496             );
2497         return;
2498      } else if (alt || (!AliveTwigs(self)&&ComnSite(self,leaf))) {
2499	 SetNalive(Trunk(self),ST_DYING);
2500	 if (!alt && Hybrid(self)) alt = -1;
2501         Smsg_ShortCut_End(self, SupTree(self),
2502              sch_msg_hdl_straighten(SupTree(self),self,leaf,self,alt),
2503              sch_msg_snd_straighten(SupTree(self),self,leaf,self,alt)
2504             );
2505         return;
2506      } else if (ComnSite(self,SupTree(self)) && !PoorSpine(self) &&
2507                                                 !PoorSpine(SupTree(self))) {
2508         Smsg_ShortCut_End(self, SupTree(self),
2509              sch_msg_hdl_js_prologue(SupTree(self),self,leaf),
2510              sch_msg_snd_js_prologue(SupTree(self),self,leaf)
2511             );
2512         return;
2513      } else {
2514         st_id_t *coma = self;
2515         SetPoorSpine(self);
2516         Sch_JS_Trav_Down(self,coma,leaf);
2517         Sch_JS_Trav_Up(self,coma,leaf);
2518      }
2519   }
2520}
2521
2522/* Up */
2523static void sch_msg_hdl_tell_idle(self,leaf)
2524st_id_t *self, *leaf;
2525{
2526   Smsg_Hdl_Notify(SMSG_TELL_IDLE, self, leaf);
2527   if (Alive(Twig(self))) {
2528      if (Monad(self) && Exhausted(self)) {
2529         /* cant become idle, has to take over sequential chpts */
2530         void sch_msg_hdl_backtrack_();
2531         sch_msg_hdl_backtrack_(self,leaf);
2532         return;
2533      }
2534      UpdateLmp(self);
2535      AliveTwigs(self)--;
2536      SetNalive(Twig(self),ST_IDLE);
2537      Smsg_ShortCut_End(self, leaf,
2538	   sch_msg_hdl_idle_told(leaf, self),
2539	   sch_msg_snd_idle_told(leaf, self)
2540	  );
2541      return;
2542   } else {
2543      Sch_Unlock(self);
2544      return;
2545   }
2546}
2547
2548/* Up */
2549static void sch_msg_hdl_lodge_idle(self,child,leaf)
2550st_id_t *self, *child, *leaf;
2551{
2552   Smsg_Hdl_Notify(SMSG_LODGE_IDLE,self,child);
2553   if (Alive(Trunk(self))) {
2554      st_id_t idle;
2555      Add_Lodge_Twig(&idle,leaf,Knot(self));
2556      SetNalive(Twig(&idle),ST_IDLE);
2557      Smsg_ShortCut_End(&idle, leaf,
2558           sch_msg_hdl_idle_told(leaf, &idle),
2559           sch_msg_snd_idle_told(leaf, &idle)
2560          );
2561      return;
2562   } else {
2563      assert(!SchRoot(self));
2564      Smsg_ShortCut_End(self,SupTree(self),
2565	   sch_msg_hdl_lodge_idle(SupTree(self),self,leaf),
2566	   sch_msg_snd_lodge_idle(SupTree(self),self,leaf)
2567          );
2568      return;
2569   }
2570}
2571
2572/* Down */
2573static void sch_msg_hdl_idle_told(leaf, parent)
2574st_id_t *leaf, *parent;
2575{
2576   Smsg_Hdl_Notify(SMSG_IDLE_TOLD,leaf,parent);
2577   switch (Life(Trunk(leaf))) {
2578     case ST_BACKTRACK:
2579       if (Scheduler(Site(leaf))->idling)
2580	  /* Note: this bit is not reset when telling idle.
2581	  ** Therefore, if it becomes reset in the meantime,
2582          ** it must have consumed a waking request.
2583	  */
2584	  Scheduler(Site(leaf))->idling = 0;
2585       else
2586	  Scheduler(Site(leaf))->waking = 1;
2587       if (ComnNode(SupTree(leaf),parent))
2588          break;
2589     case ST_LODGED:
2590       Smsg_ShortCut_Mid(leaf, SupTree(leaf),
2591	    sch_msg_hdl_withered(SupTree(leaf), leaf),
2592	    sch_msg_snd_withered(SupTree(leaf), leaf)
2593	   );
2594       break;
2595
2596     default:
2597	error("illegal leaf type");
2598   }
2599   *SupTree(leaf) = *parent;
2600   SetNalive(Twig(leaf),ST_IDLE);
2601   if (Scheduler(Site(leaf))->waking) {
2602      Scheduler(Site(leaf))->waking = 0;
2603      /* emulate a backtrack */
2604      SetNalive(Trunk(leaf),ST_BACKTRACK);
2605      Smsg_ShortCut_End(leaf, SupTree(leaf),
2606           sch_msg_hdl_stop_idle(SupTree(leaf),leaf),
2607           sch_msg_snd_stop_idle(SupTree(leaf),leaf)
2608          );
2609      return;
2610   } else {
2611      eng_backtrack(LeafEngine(leaf), (st_handle_t *)parent, 0);
2612      Sch_Unlock(leaf);
2613      return;
2614   }
2615}
2616
2617
2618static void sch_msg_hdl_idle_eng(leaf, leaf0)
2619st_id_t *leaf, *leaf0;
2620{
2621   Smsg_Hdl_Notify(SMSG_IDLE_ENG, leaf, leaf0);
2622   if (Knot(SiteLeaf(Site(leaf)))!=Knot(leaf)) {
2623      sch_msg_snd_idle_eng(SiteLeaf(Site(leaf)),leaf);
2624      Sch_Unlock(leaf);
2625      return;
2626   }
2627   if (Scheduler(Site(leaf))->waking) {
2628      Scheduler(Site(leaf))->waking = 0;
2629      Sch_Unlock(leaf);
2630      return;
2631   }
2632   Scheduler(Site(leaf))->idling = 1;
2633   if (Alive(Trunk(leaf))) {
2634      if (JsRoot(leaf)) {
2635         Sch_WakeUp_Suspended(leaf);
2636         Sch_Unlock(leaf);
2637         return;
2638      } else {
2639         int left;
2640         if (!eng_publish(LeafEngine(leaf),99999, &left) || !left) {
2641	    SetPoor(Trunk(SiteLeaf(Site(leaf))));
2642	    SetPoor(Twig(SupTree(SiteLeaf(Site(leaf)))));
2643         }
2644      }
2645   }
2646   if (Life(Trunk(leaf)) != ST_CUT) {
2647      Smsg_ShortCut_End(leaf, SupTree(leaf),
2648	   sch_msg_hdl_reduce_wk_up(SupTree(leaf), leaf),
2649	   sch_msg_snd_reduce_wk_up(SupTree(leaf), leaf)
2650	  );
2651      return;
2652   } else {
2653      st_id_t *olf = Corpse(leaf);
2654      Smsg_ShortCut_Mid(olf, SupTree(olf),
2655           sch_msg_hdl_reduce_wk_up(SupTree(olf), olf),
2656           sch_msg_snd_reduce_wk_up(SupTree(olf), olf)
2657          );
2658      Sch_Unlock(leaf);
2659      return;
2660   }
2661}
2662
2663static void sch_msg_hdl_reduce_wk_up(self,child)
2664st_id_t *self, *child;
2665{
2666   Smsg_Hdl_Notify(SMSG_REDUCE_WK_UP,self,child);
2667   if (Alive(Trunk(self)) && JsRoot(self)) {
2668      if (Suspended(self)) {
2669	 Sch_WakeUp_Suspended(self);
2670	 Sch_Unlock(self);
2671	 return;
2672      }
2673      if (!Alive(Twig(self)) && Monad(self) && Exhausted(self)) {
2674	 st_edge_t *x = Trunk(self)->next;
2675         while (x != Trunk(self)) {
2676	    if (Alive(x)) {
2677	       if (!Rich(x)) break;
2678	       else {
2679	          st_id_t twig;
2680	          twig = *self;
2681	          PackEdge(&twig,x);
2682	          Smsg_ShortCut_End(&twig, SubTree(&twig),
2683		       sch_msg_hdl_reduce_wk_dn(SubTree(&twig),&twig),
2684		       sch_msg_snd_reduce_wk_dn(SubTree(&twig),&twig)
2685	              );
2686	          return;
2687	       }
2688	    }
2689	    x = x->next;
2690         }
2691      }
2692      Sch_Unlock(self);
2693      return;
2694   } else {
2695     assert(!Suspended(self));
2696     Smsg_ShortCut_End(self,SupTree(self),
2697           sch_msg_hdl_reduce_wk_up(SupTree(self),self),
2698           sch_msg_snd_reduce_wk_up(SupTree(self),self)
2699          );
2700     return;
2701   }
2702}
2703
2704static void sch_msg_hdl_reduce_wk_dn(self, parent)
2705st_id_t *self, *parent;
2706{
2707   Smsg_Hdl_Notify(SMSG_REDUCE_WK_DN, self, parent);
2708   if (!Alive(Trunk(self))) {
2709      Smsg_ShortCut_End(self,SupTree(self),
2710           sch_msg_hdl_reduce_wk_up(SupTree(self),self),
2711           sch_msg_snd_reduce_wk_up(SupTree(self),self)
2712          );
2713      return;
2714   }
2715   if (JsRoot(self)) {
2716      if (Suspended(self)) {
2717         Sch_WakeUp_Suspended(self);
2718         Sch_Unlock(self);
2719         return;
2720      }
2721      if (Monad(self) && Exhausted(self)) {
2722	 st_edge_t *x = Trunk(self)->next;
2723	 while (x != Trunk(self)) {
2724	    if (Alive(x)) {
2725	       if (!Rich(x)) break;
2726               else {
2727                  st_id_t twig;
2728                  twig = *self;
2729                  PackEdge(&twig,x);
2730                  Smsg_ShortCut_End(&twig, SubTree(&twig),
2731                       sch_msg_hdl_reduce_wk_dn(SubTree(&twig),&twig),
2732                       sch_msg_snd_reduce_wk_dn(SubTree(&twig),&twig)
2733                      );
2734                  return;
2735               }
2736            }
2737            x = x->next;
2738         }
2739      }
2740   }
2741   Sch_Unlock(self);
2742   return;
2743}
2744
2745
2746
2747static void sch_msg_hdl_wake_eng(leaf, leaf0)
2748st_id_t *leaf, *leaf0;
2749{
2750   Smsg_Hdl_Notify(SMSG_WAKE_ENG, leaf, leaf0);
2751   if (Knot(SiteLeaf(Site(leaf)))!=Knot(leaf)) {
2752      sch_msg_snd_wake_eng(SiteLeaf(Site(leaf)),leaf);
2753      Sch_Unlock(leaf);
2754      return;
2755   }
2756   if (Idle(Trunk(leaf))) {
2757      /* emulate a backtrack */
2758      SetNalive(Trunk(leaf),ST_BACKTRACK);
2759      Smsg_ShortCut_End(leaf, SupTree(leaf),
2760           sch_msg_hdl_stop_idle(SupTree(leaf),leaf),
2761	   sch_msg_snd_stop_idle(SupTree(leaf),leaf)
2762          );
2763      return;
2764   }
2765   if (Scheduler(Site(leaf))->idling) {
2766      Scheduler(Site(leaf))->idling = 0;
2767      Sch_Unlock(leaf);
2768      return;
2769   }
2770   if (Scheduler(Site(leaf))->waking) {
2771#if defined(SDEBUG)
2772#else /* SDEBUG */
2773   (void) fprintf(stderr, "Warning: waking requests overlapped !");
2774#endif /* SDEBUG */
2775      Sch_Unlock(leaf);
2776      return;
2777   } else if (Lodged(Trunk(leaf))) {
2778       Scheduler(Site(leaf))->waking = 1;
2779       Sch_Unlock(leaf);
2780       return;
2781   } else
2782       (void) fprintf(stderr, "Warning: waking a non-idle engine");
2783}
2784
2785/* Down */
2786static void sch_msg_hdl_lmp(self, parent)
2787st_id_t *self, *parent;
2788{
2789   Smsg_Hdl_Notify(SMSG_LMP, self, parent);
2790   if (Alive(Trunk(self))) {
2791      SetEldest(Trunk(self));
2792      if (IsLeaf(self)) {
2793	 if (Scheduler(Site(self))->lmp) {
2794	    Scheduler(Site(self))->lmp = 0;
2795	    eng_lmp(LeafEngine(self));
2796	 }
2797      } else if (AliveTwigs(self)) {
2798	 /* when equal 0, this the case of engine idling */
2799	 st_id_t twig;
2800         st_edge_t *x = Trunk(self)->next;
2801         while (x != Trunk(self)) {
2802           if (Alive(x)) {
2803              twig = *self;
2804              PackEdge(&twig,x);
2805	      SetEldest(x);
2806              Smsg_ShortCut_End(&twig, SubTree(&twig),
2807                   sch_msg_hdl_lmp(SubTree(&twig), &twig),
2808                   sch_msg_snd_lmp(SubTree(&twig), &twig)
2809                  );
2810              return;
2811           }
2812           x = x->next;
2813         }
2814         assert(zero());
2815      }
2816   }
2817   Sch_Unlock(self);
2818   return;
2819}
2820
2821
2822void sch_idle_eng(site)
2823site_id_t site;
2824{
2825   /*
2826   ** 1. to fit with a general tracing utility, the leaf doubled;
2827   ** 2. the short-up optimization is skipped here.
2828   */
2829   sch_msg_snd_idle_eng(SiteLeaf(site), SiteLeaf(site));
2830   return;
2831}
2832
2833void sch_wake_eng(site)
2834site_id_t site;
2835{
2836   /*
2837   ** 1. to fit with a general tracing utility, the leaf doubled;
2838   ** 2. the short-up optimization is skipped here.
2839   */
2840   sch_msg_snd_wake_eng(SiteLeaf(site), SiteLeaf(site));
2841   return;
2842}
2843
2844void sch_reduce_worker(site)
2845aport_id_t site;
2846{
2847   st_id_t *leaf = SiteLeaf(site);
2848   assert(Alive(Trunk(leaf)));
2849   if (JsRoot(leaf)) {
2850      Sch_WakeUp_Suspended(leaf);
2851      return;
2852   }
2853   Smsg_ShortCut_Mid(leaf,SupTree(leaf),
2854        sch_msg_hdl_reduce_wk_up(SupTree(leaf),leaf),
2855        sch_msg_snd_reduce_wk_up(SupTree(leaf),leaf)
2856       );
2857   return;
2858}
2859
2860void sch_engine_migrate(leaf_hdl,where_hdl)
2861const st_handle_t *leaf_hdl, *where_hdl;
2862{
2863   st_id_t *leaf  = (st_id_t *)leaf_hdl;
2864   st_id_t *where = (st_id_t *)where_hdl;
2865   assert(!Alive(Trunk(leaf))&&!ComnNode(SupTree(leaf),where));
2866   Smsg_ShortCut_Mid(leaf,SupTree(leaf),
2867	sch_msg_hdl_withered(SupTree(leaf),leaf),
2868	sch_msg_snd_withered(SupTree(leaf),leaf)
2869       );
2870   *SupTree(leaf) = *where;
2871   Smsg_ShortCut_Mid(leaf,where,
2872	sch_msg_hdl_engine_migrate(where,leaf),
2873	sch_msg_snd_engine_migrate(where,leaf)
2874       );
2875   return;
2876}
2877
2878
2879/*ARGSUSED*/
2880void eng_lmp(engine)
2881const eng_handle_t engine;
2882{
2883}
2884
2885#if defined(PROLOG_LMP)
2886int sch_lmp(leaf)
2887const st_handle_t *leaf;
2888{
2889   if (Eldest(Trunk((st_id_t *) leaf)))
2890      return(1);
2891   Scheduler(Site(leaf))->lmp = 1;
2892   return(0);
2893}
2894#endif /* PROLOG_LMP */
2895
2896
2897
2898void smsg_stat_init(site)
2899site_id_t site;
2900{
2901   int i;
2902
2903   Scheduler(site)->state_donate     = 0;
2904   Scheduler(site)->smsg_count_hdl   = 0;
2905   Scheduler(site)->smsg_count_snd   = 0;
2906   Scheduler(site)->smsg_count_intra = 0;
2907   Scheduler(site)->smsg_count_intra_shortcut = 0;
2908   for (i = SMSG_MAXNUM; i>=0; i--)
2909      Scheduler(site)->smsg_subcount[i] = 0;
2910
2911   smsg_name[SMSG_INIT_LODGE]     = "INIT_LODGE   ";
2912   smsg_name[SMSG_BACKTRACK]      = "BACKTRACK    ";
2913   smsg_name[SMSG_STRAIGHTEN]     = "STRAIGHTEN   ";
2914   smsg_name[SMSG_CUT]            = "CUT          ";
2915   smsg_name[SMSG_CUT_OK]         = "CUT_OK       ";
2916   smsg_name[SMSG_CHOP]           = "CHOP         ";
2917   smsg_name[SMSG_WITHERED]       = "WITHERED     ";
2918   smsg_name[SMSG_LODGE]          = "LODGE        ";
2919   smsg_name[SMSG_LODGED]         = "LODGED       ";
2920   smsg_name[SMSG_DEC_CORPSE]     = "DEC_CORPSE   ";
2921   smsg_name[SMSG_JS_PROLOGUE]    = "JS_PROLOGUE  ";
2922   smsg_name[SMSG_JS_TRAV_UP]     = "JS_TRAV_UP   ";
2923   smsg_name[SMSG_JS_TRAV_DN]     = "JS_TRAV_DN   ";
2924   smsg_name[SMSG_JS_INSTALL]     = "JS_INSTALL   ";
2925   smsg_name[SMSG_JS_INSTALL_FL]  = "JS_INSTALL_FL";
2926   smsg_name[SMSG_JS_SUCCESS]     = "JS_SUCCESS   ";
2927   smsg_name[SMSG_JS_TRUST]       = "JS_TRUST     ";
2928   smsg_name[SMSG_JS_IN_VAIN]     = "JS_IN_VAIN   ";
2929   smsg_name[SMSG_JS_AGAIN]       = "JS_AGAIN     ";
2930   smsg_name[SMSG_LOAD_REPORT]    = "LOAD_REPORT  ";
2931   smsg_name[SMSG_SET_JS_ROOT]    = "SET_JS_ROOT  ";
2932   smsg_name[SMSG_IDLE_ENG]	  = "IDLE_ENG     ";
2933   smsg_name[SMSG_WAKE_ENG]	  = "WAKE_ENG     ";
2934   smsg_name[SMSG_TELL_IDLE]	  = "TELL_IDLE    ";
2935   smsg_name[SMSG_IDLE_TOLD]	  = "IDLE_TOLD    ";
2936   smsg_name[SMSG_LODGE_IDLE]	  = "LODGE_IDLE   ";
2937   smsg_name[SMSG_STOP_IDLE]	  = "STOP_IDLE    ";
2938   smsg_name[SMSG_LMP]	          = "LMP          ";
2939   smsg_name[SMSG_REDUCE_WK_UP]	  = "REDUCE_WK_UP ";
2940   smsg_name[SMSG_REDUCE_WK_DN]	  = "REDUCE_WK_DN ";
2941   smsg_name[SMSG_ENGINE_MIGRATE] = "ENGINE_MIGRATE";
2942   smsg_name[SMSG_MAXNUM]         = "MAXNUM       ";
2943
2944   return;
2945}
2946
2947int zero() {
2948   int i;
2949   i = 0;
2950   return(i);
2951}
2952
2953void sch_break() {}
2954
2955scheduler_t *site_scheduler(site)
2956aport_id_t site;
2957{
2958  return(Scheduler(site));
2959}
2960
2961int get_smsg_max()
2962{
2963  return(SMSG_MAXNUM);
2964}
2965
2966
2967/*
2968sch_empty_queue0()
2969{
2970   static amsg_t msg;
2971   static smsg00_t *data;
2972   static amsg_type_t mdt_type;
2973   static amsg_count_t mdt_count;
2974   return amsg_peek( scheduler->port,
2975                        &msg,
2976                        (amsg_data_t * *)&data,
2977                        &mdt_type,
2978                        &mdt_count
2979                        );
2980}
2981
2982sch_empty_queue()
2983{
2984   amsg_ret_t ret;
2985   int event;
2986
2987   Disable_Int();
2988   ret = sch_empty_queue0();
2989   event = sch_msg_event();
2990   Enable_Int();
2991   assert(ret != AMSG_OK || event);
2992   return(ret != AMSG_OK || event);
2993}
2994*/
2995