1/* BEGIN LICENSE BLOCK
2 * Version: CMPL 1.1
3 *
4 * The contents of this file are subject to the Cisco-style Mozilla Public
5 * License Version 1.1 (the "License"); you may not use this file except
6 * in compliance with the License.  You may obtain a copy of the License
7 * at www.eclipse-clp.org/license.
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11 * the License for the specific language governing rights and limitations
12 * under the License.
13 *
14 * The Original Code is  The ECLiPSe Constraint Logic Programming System.
15 * The Initial Developer of the Original Code is  Cisco Systems, Inc.
16 * Portions created by the Initial Developer are
17 * Copyright (C) 1994-2006 Cisco Systems, Inc.  All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * END LICENSE BLOCK */
22
23/**********************************************************************
24**      System: Parallel ECLiPSe Scheduler
25**        File: sch_util.c
26**      Author: Liang-Liang Li
27** Description: Utilities for Prolog manipulations of the scheduler data
28**		structures.
29***********************************************************************/
30
31#include <stdio.h>
32
33#include "config.h"
34#include "sepia.h"
35#include <pds.h>
36#include "types.h"
37#include "embed.h"
38#include "error.h"
39#include "mem.h"
40#include "dict.h"
41
42/* The scheduler tree definitions and macros */
43#define ST_HANDLE_DS_DEFINED 1
44
45#include "sch_types.h"
46#include "sch_macros.h"
47
48extern char * smsg_name[];
49extern void sch_wake_eng();
50extern void sch_idle_eng();
51
52/*
53** mapping keys to their scheduler setting instructions.
54*/
55
56#define SCHSET_ROOT2BOTTOM	0x00010000	/* root_first */
57#define SCHSET_BOTTOM2ROOT	0x00020000	/* bottom_first */
58#define SCHSET_LEFT2RIGHT	0x00040000	/* left_first */
59#define SCHSET_RIGHT2LEFT	0x00080000	/* right_first */
60#define SCHSET_MAX2PUBLISH	0x00100000	/* max_to_publish */
61#define SCHSET_RESETCOUNTS	0x00200000	/* msg_counts */
62#define SCHSET_IDLING		0x00400000	/* idle_eng */
63#define SCHSET_WAKING		0x00800000	/* wake_eng */
64#define SCHSET_ASYNC_HDL	0x01000000	/* async_hdl */
65#define SCHSET_SYNC_HDL		0x02000000	/* sync_hdl */
66#define SCHSET_LOAD_REPORT_E	0x10000000	/* load_report_eager */
67#define SCHSET_LOAD_REPORT_L	0x20000000	/* load_report_lazy */
68#define SCHSET_MAXVALUE		0x000fffff	/* max_value */
69/*
70** int p_sch_set(Int: wid, List: instructions)
71** int p_sch_get(Int: wid, Var/List: info)
72*/
73
74int p_sch_set(v_wid, t_wid, v_inst, t_inst)
75value  v_wid;
76type   t_wid;
77value v_inst;
78type  t_inst;
79{
80   char *key;
81   int instruction = 0;
82   pword  *cur_mc, *tmp, *cur_tail;
83   pword first;
84
85   Check_Integer(t_wid);
86
87   first.tag = t_inst;
88   first.val = v_inst;
89   cur_mc = &first;
90
91   while (IsList(cur_mc->tag)) {
92      cur_tail = cur_mc->val.ptr + 1;
93      cur_mc = cur_mc->val.ptr;
94      Dereference_(cur_mc);
95      if (IsList(cur_mc->tag)) {
96         tmp = cur_mc->val.ptr;
97	 Dereference_(tmp);
98	 Get_Name(tmp->val,tmp->tag,key);
99	 if (strcmp(key,"max_to_publish") == 0) {
100	    tmp = cur_mc->val.ptr+1;
101	    Dereference_(tmp);
102	    if (IsList(tmp->tag)) {
103	       tmp = tmp->val.ptr;
104	       Dereference_(tmp);
105	       if (IsInteger(tmp->tag)) {
106	          instruction |= SCHSET_MAX2PUBLISH;
107	          instruction |= SCHSET_MAXVALUE & tmp->val.nint;
108	       }
109	    }
110	 }
111      } else {
112	 Get_Name(cur_mc->val, cur_mc->tag, key);
113         if (strcmp(key,"root_first") == 0)
114	    instruction |= SCHSET_ROOT2BOTTOM;
115	 else if (strcmp(key,"bottom_first") == 0)
116	    instruction |= SCHSET_BOTTOM2ROOT;
117	 else if (strcmp(key,"left_first") == 0)
118	    instruction |= SCHSET_LEFT2RIGHT;
119	 else if (strcmp(key,"right_first") == 0)
120	    instruction |= SCHSET_RIGHT2LEFT;
121	 else if (strcmp(key,"reset_msg_counts") == 0)
122	    instruction |= SCHSET_RESETCOUNTS;
123	 else if (strcmp(key,"idle_eng") == 0)
124	    instruction |= SCHSET_IDLING;
125	 else if (strcmp(key,"wake_eng") == 0)
126	    instruction |= SCHSET_WAKING;
127	 else if (strcmp(key,"async_hdl") == 0)
128	    instruction |= SCHSET_ASYNC_HDL;
129	 else if (strcmp(key,"sync_hdl") == 0)
130	    instruction |= SCHSET_SYNC_HDL;
131	 else if (strcmp(key,"load_report_eager") == 0)
132	    instruction |= SCHSET_LOAD_REPORT_E;
133	 else if (strcmp(key,"load_report_lazy") == 0)
134	    instruction |= SCHSET_LOAD_REPORT_L;
135      }
136      cur_mc = cur_tail;
137   }
138   Check_Nil(cur_mc->tag);
139
140   if (instruction) {
141      void wm_set_worker_info();
142      wm_set_worker_info((int) v_wid.nint, 1, sizeof(int), (void_ptr) &instruction);
143   }
144   Succeed_;
145}
146
147int p_sch_get(v_wid, t_wid, v_info, t_info)
148value  v_wid;
149type   t_wid;
150value v_info;
151type  t_info;
152{
153   /*
154   ** The info output is [States, Statistics].
155   **
156   ** Transform the scheduler info into a plain prolog list INFO:
157   **   struct scheduler {
158   **	    aport_id_t port;			## States ##
159   **	    struct st_handle_ds leaf;
160   **	    eng_handle_t engine;
161   **	    struct susp_buffer_ds susp_buffer;
162   **	    struct edge_buffer_ds edge_buffer;
163   **	    int max_to_publish;
164   **	    unsigned root_first:1;
165   **	    unsigned left_first:1;
166   **	    unsigned idling    :1;
167   **	    unsigned waking    :1;
168   **	    unsigned sync_hdl  :1;
169   **	    unsigned async_hdl  :1;
170   **	    unsigned lmp       :1;
171   **	    unsigned load_report_eager:1;
172   **	    int state_donate;			## Statistics ##
173   **	    int smsg_count_hdl;
174   **	    int smsg_count_snd;
175   **	    int smsg_count_intra;
176   **	    int smsg_count_intra_shortcut;
177   **	    int smsg_subcount[40+1];
178   **	};
179   */
180   scheduler_t scheduler_data[1];
181   pword  *cur_mc, *prev_mc, *cur_tail, *cur_head, *statistics;
182   int i, bufsize = sizeof(scheduler_t);
183   extern void wm_get_worker_info();
184   Check_Integer(t_wid);
185   wm_get_worker_info((int) v_wid.nint, 1, bufsize, (void_ptr) scheduler_data);
186
187   prev_mc = NULL;
188   /* smsg_subcount */
189   /* [[n1,v1],[n2,v2] ...] */
190   for (i = get_smsg_max()-1; i>0; i--) {
191   cur_mc = TG;
192   Push_List_Frame()
193   cur_head = TG;
194   Push_List_Frame()
195   Make_List(cur_mc,cur_head);
196   Make_String(cur_head,smsg_name[i])
197   cur_tail = cur_head + 1;
198   cur_head = TG;
199   Push_List_Frame()
200   Make_List(cur_tail,cur_head);
201   Make_Integer(cur_head,scheduler_data->smsg_subcount[i])
202   cur_tail = cur_head + 1;
203   Make_Nil(cur_tail)
204   cur_tail = cur_mc + 1;
205   if (prev_mc == NULL)
206      Make_Nil(cur_tail)
207   else {
208      Make_List(cur_tail, prev_mc);
209   }
210   prev_mc = cur_mc;
211   }
212   /* [smsg_count_intra_shortcut, v] */
213   cur_mc = TG;
214   Push_List_Frame()
215   cur_head = TG;
216   Push_List_Frame()
217   Make_List(cur_mc,cur_head);
218   Make_String(cur_head,"smsg_count_intra_shortcut")
219   cur_tail = cur_head + 1;
220   cur_head = TG;
221   Push_List_Frame()
222   Make_List(cur_tail,cur_head);
223   Make_Integer(cur_head,scheduler_data->smsg_count_intra_shortcut)
224   cur_tail = cur_head + 1;
225   Make_Nil(cur_tail)
226   cur_tail = cur_mc + 1;
227   Make_List(cur_tail, prev_mc);
228   prev_mc = cur_mc;
229
230   /* [smsg_count_intra, v] */
231   cur_mc = TG;
232   Push_List_Frame()
233   cur_head = TG;
234   Push_List_Frame()
235   Make_List(cur_mc,cur_head);
236   Make_String(cur_head,"smsg_count_intra")
237   cur_tail = cur_head + 1;
238   cur_head = TG;
239   Push_List_Frame()
240   Make_List(cur_tail,cur_head);
241   Make_Integer(cur_head,scheduler_data->smsg_count_intra)
242   cur_tail = cur_head + 1;
243   Make_Nil(cur_tail)
244   cur_tail = cur_mc + 1;
245   Make_List(cur_tail, prev_mc);
246   prev_mc = cur_mc;
247
248   /* [smsg_count_snd,v] */
249   cur_mc = TG;
250   Push_List_Frame()
251   cur_head = TG;
252   Push_List_Frame()
253   Make_List(cur_mc,cur_head);
254   Make_String(cur_head,"smsg_count_snd")
255   cur_tail = cur_head + 1;
256   cur_head = TG;
257   Push_List_Frame()
258   Make_List(cur_tail,cur_head);
259   Make_Integer(cur_head,scheduler_data->smsg_count_snd)
260   cur_tail = cur_head + 1;
261   Make_Nil(cur_tail)
262   cur_tail = cur_mc + 1;
263   Make_List(cur_tail, prev_mc);
264   prev_mc = cur_mc;
265
266   /* [smsg_count_hdl, v] */
267   cur_mc = TG;
268   Push_List_Frame()
269   cur_head = TG;
270   Push_List_Frame()
271   Make_List(cur_mc,cur_head);
272   Make_String(cur_head,"smsg_count_hdl")
273   cur_tail = cur_head + 1;
274   cur_head = TG;
275   Push_List_Frame()
276   Make_List(cur_tail,cur_head);
277   Make_Integer(cur_head,scheduler_data->smsg_count_hdl)
278   cur_tail = cur_head + 1;
279   Make_Nil(cur_tail)
280   cur_tail = cur_mc + 1;
281   Make_List(cur_tail, prev_mc);
282   prev_mc = cur_mc;
283
284   /* [state_donate, v] */
285   cur_mc = TG;
286   Push_List_Frame()
287   cur_head = TG;
288   Push_List_Frame()
289   Make_List(cur_mc,cur_head);
290   Make_String(cur_head,"state_donate")
291   cur_tail = cur_head + 1;
292   cur_head = TG;
293   Push_List_Frame()
294   Make_List(cur_tail,cur_head);
295   Make_Integer(cur_head,scheduler_data->state_donate)
296   cur_tail = cur_head + 1;
297   Make_Nil(cur_tail)
298   cur_tail = cur_mc + 1;
299   Make_List(cur_tail, prev_mc);
300   statistics = cur_mc;
301
302   /* [lmp, v] */
303   cur_mc = TG;
304   Push_List_Frame()
305   cur_head = TG;
306   Push_List_Frame()
307   Make_List(cur_mc,cur_head);
308   Make_String(cur_head,"lmp")
309   cur_tail = cur_head + 1;
310   cur_head = TG;
311   Push_List_Frame()
312   Make_List(cur_tail,cur_head);
313   Make_Integer(cur_head,scheduler_data->lmp)
314   cur_tail = cur_head + 1;
315   Make_Nil(cur_tail)
316   cur_tail = cur_mc + 1;
317   Make_Nil(cur_tail);
318   prev_mc = cur_mc;
319
320   /* [async_hdl, v] */
321   cur_mc = TG;
322   Push_List_Frame()
323   cur_head = TG;
324   Push_List_Frame()
325   Make_List(cur_mc,cur_head);
326   Make_String(cur_head,"async_hdl")
327   cur_tail = cur_head + 1;
328   cur_head = TG;
329   Push_List_Frame()
330   Make_List(cur_tail,cur_head);
331   Make_Integer(cur_head,scheduler_data->async_hdl)
332   cur_tail = cur_head + 1;
333   Make_Nil(cur_tail)
334   cur_tail = cur_mc + 1;
335   Make_List(cur_tail, prev_mc);
336   prev_mc = cur_mc;
337
338   /* [load_report_eager, v] */
339   cur_mc = TG;
340   Push_List_Frame()
341   cur_head = TG;
342   Push_List_Frame()
343   Make_List(cur_mc,cur_head);
344   Make_String(cur_head,"load_report_eager")
345   cur_tail = cur_head + 1;
346   cur_head = TG;
347   Push_List_Frame()
348   Make_List(cur_tail,cur_head);
349   Make_Integer(cur_head,scheduler_data->load_report_eager)
350   cur_tail = cur_head + 1;
351   Make_Nil(cur_tail)
352   cur_tail = cur_mc + 1;
353   Make_List(cur_tail, prev_mc);
354   prev_mc = cur_mc;
355
356   /* [waking, v] */
357   cur_mc = TG;
358   Push_List_Frame()
359   cur_head = TG;
360   Push_List_Frame()
361   Make_List(cur_mc,cur_head);
362   Make_String(cur_head,"waking")
363   cur_tail = cur_head + 1;
364   cur_head = TG;
365   Push_List_Frame()
366   Make_List(cur_tail,cur_head);
367   Make_Integer(cur_head,scheduler_data->waking)
368   cur_tail = cur_head + 1;
369   Make_Nil(cur_tail)
370   cur_tail = cur_mc + 1;
371   Make_List(cur_tail, prev_mc);
372   prev_mc = cur_mc;
373
374   /* [idling, v] */
375   cur_mc = TG;
376   Push_List_Frame()
377   cur_head = TG;
378   Push_List_Frame()
379   Make_List(cur_mc,cur_head);
380   Make_String(cur_head,"idling")
381   cur_tail = cur_head + 1;
382   cur_head = TG;
383   Push_List_Frame()
384   Make_List(cur_tail,cur_head);
385   Make_Integer(cur_head,scheduler_data->idling)
386   cur_tail = cur_head + 1;
387   Make_Nil(cur_tail)
388   cur_tail = cur_mc + 1;
389   Make_List(cur_tail, prev_mc);
390   prev_mc = cur_mc;
391
392   /* [left_first, v] */
393   cur_mc = TG;
394   Push_List_Frame()
395   cur_head = TG;
396   Push_List_Frame()
397   Make_List(cur_mc,cur_head);
398   Make_String(cur_head,"left_first")
399   cur_tail = cur_head + 1;
400   cur_head = TG;
401   Push_List_Frame()
402   Make_List(cur_tail,cur_head);
403   Make_Integer(cur_head,scheduler_data->left_first)
404   cur_tail = cur_head + 1;
405   Make_Nil(cur_tail)
406   cur_tail = cur_mc + 1;
407   Make_List(cur_tail, prev_mc);
408   prev_mc = cur_mc;
409
410   /* [root_first, v] */
411   cur_mc = TG;
412   Push_List_Frame()
413   cur_head = TG;
414   Push_List_Frame()
415   Make_List(cur_mc,cur_head);
416   Make_String(cur_head,"root_first")
417   cur_tail = cur_head + 1;
418   cur_head = TG;
419   Push_List_Frame()
420   Make_List(cur_tail,cur_head);
421   Make_Integer(cur_head,scheduler_data->root_first)
422   cur_tail = cur_head + 1;
423   Make_Nil(cur_tail)
424   cur_tail = cur_mc + 1;
425   Make_List(cur_tail, prev_mc);
426   prev_mc = cur_mc;
427
428   /* [max_to_publish, v] */
429   cur_mc = TG;
430   Push_List_Frame()
431   cur_head = TG;
432   Push_List_Frame()
433   Make_List(cur_mc,cur_head);
434   Make_String(cur_head,"max_to_publish")
435   cur_tail = cur_head + 1;
436   cur_head = TG;
437   Push_List_Frame()
438   Make_List(cur_tail,cur_head);
439   Make_Integer(cur_head,scheduler_data->max_to_publish)
440   cur_tail = cur_head + 1;
441   Make_Nil(cur_tail)
442   cur_tail = cur_mc + 1;
443   Make_List(cur_tail, prev_mc);
444   prev_mc = cur_mc;
445
446   /* [edge_buffer, v] */
447   cur_mc = TG;
448   Push_List_Frame()
449   cur_head = TG;
450   Push_List_Frame()
451   Make_List(cur_mc,cur_head);
452   Make_String(cur_head,"edge_buffer")
453   cur_tail = cur_head + 1;
454   cur_head = TG;
455   Push_List_Frame()
456   Make_List(cur_tail,cur_head);
457   Make_Integer(cur_head,scheduler_data->edge_buffer.count)
458   cur_tail = cur_head + 1;
459   Make_Nil(cur_tail)
460   cur_tail = cur_mc + 1;
461   Make_List(cur_tail, prev_mc);
462   prev_mc = cur_mc;
463
464   /* [susp_buffer, v] */
465   cur_mc = TG;
466   Push_List_Frame()
467   cur_head = TG;
468   Push_List_Frame()
469   Make_List(cur_mc,cur_head);
470   Make_String(cur_head,"susp_buffer")
471   cur_tail = cur_head + 1;
472   cur_head = TG;
473   Push_List_Frame()
474   Make_List(cur_tail,cur_head);
475   Make_Integer(cur_head,scheduler_data->susp_buffer.count)
476   cur_tail = cur_head + 1;
477   Make_Nil(cur_tail)
478   cur_tail = cur_mc + 1;
479   Make_List(cur_tail, prev_mc);
480   prev_mc = cur_mc;
481
482   /* [engine, v] */
483   cur_mc = TG;
484   Push_List_Frame()
485   cur_head = TG;
486   Push_List_Frame()
487   Make_List(cur_mc,cur_head);
488   Make_String(cur_head,"engine")
489   cur_tail = cur_head + 1;
490   cur_head = TG;
491   Push_List_Frame()
492   Make_List(cur_tail,cur_head);
493   Make_Integer(cur_head,scheduler_data->engine)
494   cur_tail = cur_head + 1;
495   Make_Nil(cur_tail)
496   cur_tail = cur_mc + 1;
497   Make_List(cur_tail, prev_mc);
498   prev_mc = cur_mc;
499
500   /* [leaf, v] */
501   cur_mc = TG;
502   Push_List_Frame()
503   cur_head = TG;
504   Push_List_Frame()
505   Make_List(cur_mc,cur_head);
506   Make_String(cur_head,"leaf")
507   cur_tail = cur_head + 1;
508   cur_head = TG;
509   Push_List_Frame()
510   Make_List(cur_tail,cur_head);
511   Make_Integer(cur_head, scheduler_data->leaf.site)
512   cur_tail = cur_head + 1;
513   cur_head = TG;
514   Push_List_Frame()
515   Make_List(cur_tail,cur_head);
516   Make_Integer(cur_head, scheduler_data->leaf.edge)
517   cur_tail = cur_head + 1;
518   cur_head = TG;
519   Push_List_Frame()
520   Make_List(cur_tail,cur_head);
521   Make_Integer(cur_head, scheduler_data->leaf.knot)
522   cur_tail = cur_head + 1;
523   Make_Nil(cur_tail)
524   cur_tail = cur_mc + 1;
525   Make_List(cur_tail, prev_mc);
526   prev_mc = cur_mc;
527
528   /* [port, v] */
529   cur_mc = TG;
530   Push_List_Frame()
531   cur_head = TG;
532   Push_List_Frame()
533   Make_List(cur_mc,cur_head);
534   Make_String(cur_head,"port")
535   cur_tail = cur_head + 1;
536   cur_head = TG;
537   Push_List_Frame()
538   Make_List(cur_tail,cur_head);
539   Make_Integer(cur_head,scheduler_data->port)
540   cur_tail = cur_head + 1;
541   Make_Nil(cur_tail)
542   cur_tail = cur_mc + 1;
543   Make_List(cur_tail, prev_mc);
544   prev_mc = cur_mc;
545
546   /* pack states and statistics together */
547   cur_mc = TG;
548   Push_List_Frame()
549   Make_List(cur_mc, prev_mc);
550   cur_head = TG;
551   Push_List_Frame()
552   cur_tail = cur_mc + 1;
553   Make_List(cur_tail,cur_head);
554   Make_List(cur_head, statistics);
555   cur_tail = cur_head+1;
556   Make_Nil(cur_tail)
557
558   Return_Unify_List(v_info, t_info, cur_mc)
559}
560
561
562void sch_get_info(site,infosize,infoval)
563aport_id_t site;
564int * infosize;
565void_ptr * infoval;
566{
567   scheduler_t * site_scheduler();
568   *infoval = (void_ptr) site_scheduler(site);
569   *infosize = sizeof(scheduler_t);
570   return;
571}
572
573void sch_set_info(site,infoval)
574aport_id_t site;
575void_ptr infoval;
576{
577  scheduler_t * site_scheduler();
578  scheduler_t *s = (scheduler_t *) site_scheduler(site);
579  int i, instruction = * (int *) infoval;
580
581  if (instruction&SCHSET_ROOT2BOTTOM)
582     s->root_first = 1;
583  if (instruction&SCHSET_BOTTOM2ROOT)
584     s->root_first = 0;
585  if (instruction&SCHSET_LEFT2RIGHT)
586     s->left_first = 1;
587  if (instruction&SCHSET_RIGHT2LEFT)
588     s->left_first = 0;
589  if (instruction&SCHSET_MAX2PUBLISH)
590     s->max_to_publish = instruction&SCHSET_MAXVALUE;
591  if (instruction&SCHSET_RESETCOUNTS) {
592     s->state_donate = 0;
593     s->smsg_count_hdl = 0;
594     s->smsg_count_snd = 0;
595     s->smsg_count_intra = 0;
596     s->smsg_count_intra_shortcut = 0;
597     for (i = get_smsg_max()-1; i>0; i--)
598        s->smsg_subcount[i] = 0;
599  }
600  if (instruction&SCHSET_ASYNC_HDL)
601     s->async_hdl = 1;
602  if (instruction&SCHSET_SYNC_HDL)
603     s->async_hdl = 0;
604  if (instruction&SCHSET_IDLING)
605     sch_idle_eng(site);
606  if (instruction&SCHSET_WAKING)
607     sch_wake_eng(site);
608  if (instruction&SCHSET_LOAD_REPORT_E)
609     s->load_report_eager = 1;
610  if (instruction&SCHSET_LOAD_REPORT_L)
611     s->load_report_eager = 0;
612  return;
613}
614
615/* int p_schtrace_on() */
616
617int p_sch_trace_on()
618{
619   (void) global_flags(0,SCH_TRACE_FLAG);
620   Sch_Trace_Begin();
621   Succeed_;
622}
623