Just trying to make this whole manual make more sense.
[charm.git] / doc / converse / cmi.tex
1 \chapter{Machine Interface and Scheduler}
2
3 This chapter describes two of Converse's modules: the CMI, and the
4 CSD.  Together, they serve to transmit messages and schedule the
5 delivery of messages.
6
7 \section{Defining Handler Numbers}
8
9 When a message arrives at a processor, it triggers the execution of a
10 {\em handler function}, not unlike a UNIX signal handler.  The handler
11 function receives, as an argument, a pointer to a copy of the message.
12 The message itself specifies which handler function is to be
13 called when the message arrives.  Messages are contiguous sequences of
14 bytes.  The message has two parts: the header, and the data.  The data
15 may contain anything you like.  The header contains a {\em handler
16 number}, which specifies which handler function is to be executed when
17 the message arrives.  Before you can send a message, you have to
18 define the handler numbers.
19
20 Converse maintains a table mapping handler numbers to function
21 pointers.  Each processor has its own copy of the mapping.  There is a
22 caution associated with this approach: it is the user's responsibility
23 to ensure that all processors have identical mappings.  This is easy
24 to do, nonetheless, the user must be aware that this is (usually)
25 required.
26
27 The following functions are provided to define the handler numbers:
28
29 \function{typedef void (*CmiHandler)(void *)}
30 \index{CmiHandler}
31 \desc{Functions that handle Converse messages must be of this type.}
32
33 \function{int CmiRegisterHandler(CmiHandler h)}
34 \index{CmiRegisterHandler}
35 \desc{This represents the standard technique for associating numbers
36 with functions.  To use this technique, the Converse user registers
37 each of his functions, one by one, using CmiRegisterHandler.  One must
38 register exactly the same functions in exactly the same order on all
39 processors.  The system assigns monotonically increasing numbers to
40 the functions, the same numbers on all processors.  This insures
41 global consistency.  CmiRegisterHandler returns the number which was
42 chosen for the function being registered.}
43
44 \function {int CmiRegisterHandlerGlobal(CmiHandler h)}
45 \index{CmiRegisterHandlerLocal}
46 \desc{This represents a second registration technique.   The Converse
47 user registers his functions on processor zero, using
48 CmiRegisterHandlerGlobal.  The Converse user is then responsible for
49 broadcasting those handler numbers to other processors, and installing
50 them using CmiNumberHandler below.  The user should take care not to
51 invoke those handlers until they are fully installed.}
52
53 \function {int CmiRegisterHandlerLocal(CmiHandler h)}
54 \index{CmiRegisterHandlerLocal}
55 \desc{This function is used when one wishes to register functions
56 in a manner that is not consistent across processors.  This function
57 chooses a locally-meaningful number for the function, and records it
58 locally.  No attempt is made to ensure consistency across processors.}
59
60 \function {void CmiNumberHandler(int n, CmiHandler h)}
61 \index{CmiNumberHandler}
62 \desc{Forces the system to associate the specified handler number {\em n}
63 with the specified handler function {\em h}.  If the function number
64 {\em n} was previously mapped to some other function, that old mapping
65 is forgotten.  The mapping that this function creates is local to the
66 current processor.  CmiNumberHandler can be useful in combination with
67 CmiRegisterGlobalHandler.  It can also be used to implement
68 user-defined numbering schemes: such schemes should keep in mind that
69 the size of the table that holds the mapping is proportional to the
70 largest handler number --- do not use big numbers!}
71
72 Note: of the three registration methods, the CmiRegisterHandler method
73 is by far the simplest, and is strongly encouraged.  The others are
74 primarily to ease the porting of systems that already use similar
75 registration techniques.  One may use all three registration methods
76 in a program.  The system guarantees that no numbering conflicts will
77 occur as a result of this combination.
78
79 \section{Building Messages}
80
81 To send a message, one first creates a buffer to hold the message.
82 The buffer must be large enough to hold the header and the data.
83 The buffer can be in any kind of memory: it could be a local variable,
84 it could be a global, it could be allocated with {\tt malloc}, and
85 finally, it could be allocated with {\tt CmiAlloc}.  The Converse user
86 fills the buffer with the message data.  One puts a handler number
87 in the message, thereby specifying which handler function the message
88 should trigger when it arrives.  Finally, one uses a message-transmission
89 function to send the message.
90
91 The following functions are provided to help build message buffers:
92
93 \function{void *CmiAlloc(int size)}
94 \index{CmiAlloc}
95 \desc{Allocates memory of size \param{size} in heap and returns pointer to 
96 the usable space.  There are some message-sending functions that
97 accept only message buffers that were allocated with CmiAlloc.  Thus,
98 this is the preferred way to allocate message buffers.}
99
100 \function{void CmiFree(void *ptr)}
101 \index{CmiFree}
102 \desc{This function frees the memory pointed to by \param{ptr}. \param{ptr}
103 should be a pointer that was previously returned by \param{CmiAlloc}.}
104
105 \function {\#define CmiMsgHeaderSizeBytes}
106 \index{CmiMsgHeaderSizeBytes}
107 \desc{This constant contains the size of the message header.  When one
108 allocates a message buffer, one must set aside enough space for the header
109 and the data.  This macro helps you to do so.}
110
111 \function {void CmiSetHandler(int *MessageBuffer, int HandlerId)}
112 \index{CmiSetHandler}
113 \desc{This macro sets the handler number of a message to \param{HandlerId}.}
114
115 \function {int CmiGetHandler(int *MessageBuffer)}
116 \index{CmiGetHandler}
117 \desc{This call returns the handler of a message in the form of a
118 handler number.}
119  
120 \function {CmiHandler CmiGetHandlerFunction(int *MessageBuffer)}
121 \index{CmiGetHandlerFunction}
122 \desc{This call returns the handler of a message in the form of a
123 function pointer.}
124
125 \function{void CmiGrabBuffer(void **pbuf)}
126 \index{CmiGrabBuffer}
127 \desc{A handler function receives a pointer to a message buffer
128 as an argument.  Normally, it is supposed to copy the data out of the
129 message buffer, and then return, at which time Converse automatically
130 frees the message buffer.  However, a handler function may use
131 CmiGrabBuffer to claim ownership of the message buffer (and therefore
132 prevent Converse from freeing it).  Assuming, for example, that the
133 handler function called its argument {\tt msg}, it would call {\tt
134 CmiGrabBuffer(\&msg)}.  Afterward, {\tt msg} contains a pointer to the
135 message, or a copy of it.  From that point forward, it is the user's
136 responsibility to free the message using \param{CmiFree.}}
137
138 \section{Sending Messages}
139
140 The following functions allow you to send messages:
141
142 \function{void CmiSyncSend(unsigned int destPE, unsigned int size, void *msg)}
143 \index{CmiSyncSend}
144
145 \desc{Sends \param{msg} of size \param{size} bytes to processor
146 \param{destPE}.  The call does not return until the data has been
147 copied from the user-provided message buffer into system buffers.
148 Therefore, once this call returns, you are free to reuse the
149 message buffer immediately.}
150
151 \function{void CmiSyncSendAndFree(unsigned int destPE, unsigned int size, void *msg)}
152 \index{CmiSyncSendAndFree}
153 \desc{Sends \param{msg} of size \param{size} bytes to processor
154 \param{destPE} and then {\tt CmiFree}s the message buffer \param{msg}.
155 Caution: the message buffer {\em must} have been allocated using {\tt
156 CmiAlloc}.}
157
158 \function{CmiCommHandle CmiAsyncSend(unsigned int destPE, unsigned int size, void *msg)}
159 \index{CmiAsyncSend}
160 \desc{Sends a message of size \param{size} bytes to processor
161 \param{destPE}.  This function returns before the data has even been
162 copied out of the user's message buffer.  Therefore, the Converse
163 user must leave the message buffer alone for a time after calling
164 this function.  This function returns a communication handle which
165 can be tested to determine whether or not the buffer can be reused
166 yet.}
167
168 \function{int CmiAsyncMsgSent(CmiCommHandle handle)}
169 \index{CmiAsyncMsgSent}
170 \desc{Returns true if the communication specified by the given
171 CmiCommHandle has proceeded to the point where the message buffer can
172 be reused.}
173
174 \function{void CmiReleaseCommHandle(CmiCommHandle handle)}
175 \index{CmiReleaseCommHandle}
176 \desc{Releases the communication handle \param{handle} and
177 associated resources. It does not free the message buffer.}
178
179 \function{void CmiSyncVectorSend(int destPE, int len, int sizes[], char *msgComps[])}
180 \desc{Synchronous send of data to processor
181 \param{destPE}.  The data consists of \param{len} pieces residing in
182 different areas of memory, which are logically concatenated.  The
183 \param{msgComps} array contains pointers to the pieces; the size of
184 \param{msgComps[i]} is taken from \param{sizes[i]}. 
185 \param{sizes}, \param{msgComps} and the message components specified in
186 \param{msgComps} could be reused after the function call returns.
187 }
188
189 \function{void CmiSyncVectorSendAndFree(int destPE, int len, int sizes[], char *msgComps[])}
190 \desc{Synchronous send of data to processor
191 \param{destPE}.  The data consists of \param{len} pieces residing in
192 different areas of memory, which are logically concatenated.  The
193 \param{msgComps} array contains pointers to the pieces; the size of
194 \param{msgComps[i]} is taken from \param{sizes[i]}. 
195 The message components specified in \param{msgComps} are {\tt
196 CmiFree}d by this function therefore, they should be dynamically
197 allocated using \param{CmiAlloc()}.  However, the \param{sizes} and
198 \param{msgComps} array themselves are not freed.}
199
200 \function{CmiCommHandle CmiAsyncVectorSend(int destPE, int len, int sizes[], char *msgComps[])}
201 \desc{Initiates an asynchronous send of data to processor
202 \param{destPE}.  The data consists of \param{len} pieces residing in
203 different areas of memory, which are logically concatenated.  The
204 \param{msgComps} array contains pointers to the pieces; the size of
205 \param{msgComps[i]} is taken from \param{sizes[i]}. 
206 This function returns a communication handle which could be used to enquire
207 about the status of communication using \param{CmiAsyncMsgSent()}.
208 Individual pieces of data as well as the arrays \param{sizes} and
209 \param{msgComps} should not be overwritten or freed before the
210 communication is complete.}
211
212 \section{Broadcasting Messages}
213
214 \function{void CmiSyncBroadcast(unsigned int size, void *msg)}
215 \index{CmiSyncBroadcast}
216 \desc{Sends \param{msg} of length \param{size} bytes to all processors
217 excluding the processor on which the caller resides. }
218
219 \function{void CmiSyncBroadcastAndFree(unsigned int size, void *msg)}
220 \index{CmiSyncBroadcastAndFree}
221 \desc{Sends \param{msg} of length \param{size} bytes to all processors
222 excluding the processor on which the caller resides.  Uses {\tt
223 CmiFree} to deallocate the message buffer for \param{msg} when the
224 broadcast completes. Therefore \param{msg} must point to a buffer
225 allocated with {\tt CmiAlloc}.}
226
227 \function{void CmiSyncBroadcastAll(unsigned int size, void *msg)}
228 \index{CmiSyncBroadcastAll}
229 \desc{Sends \param{msg} of length \param{size} bytes to all processors
230 including the processor on which the caller resides. This function
231 does not free the message buffer for \param{msg}.}
232
233 \function{void CmiSyncBroadcastAllAndFree(unsigned int size, void *msg)}
234 \index{CmiSyncBroadcastAllAndFree}
235 \desc{Sends \param{msg} of length \param{size} bytes to all processors
236 including the processor on which the caller resides. This function
237 frees the message buffer for \param{msg} before returning, so
238 \param{msg} must point to a dynamically allocated buffer.}
239
240 \function{CmiCommHandle CmiAsyncBroadcast(unsigned int size, void *msg)}
241 \index{CmiAsyncBroadcast}
242 \desc{Initiates asynchronous broadcast of message \param{msg} of
243 length \param{size} bytes to all processors excluding the processor on
244 which the caller resides. It returns a communication handle which
245 could be used to check the status of this send using
246 \param{CmiAsyncMsgSent()}. \param{msg} should not be overwritten or
247 freed before the communication is complete.}
248
249 \function{CmiCommHandle CmiAsyncBroadcastAll(unsigned int size, void *msg)}
250 \index{CmiAsyncBroadcastAll}
251 \desc{Initiates asynchronous broadcast of message \param{msg} of
252 length \param{size} bytes to all processors including the processor on
253 which the caller resides. It returns a communication handle which
254 could be used to check the status of this send using
255 \param{CmiAsyncMsgSent()}. \param{msg} should not be overwritten or
256 freed before the communication is complete.}
257
258 \section{Scheduling Messages}
259
260 The scheduler queue is a powerful priority queue.  The following
261 functions can be used to place messages into the scheduler queue.
262 These messages are treated very much like newly-arrived messages: when
263 they reach the front of the queue, they trigger handler functions,
264 just like messages transmitted with Cmi functions.  Note that unlike
265 the Cmi send functions, these cannot move messages across processors.
266
267 \function{void CsdEnqueueGeneral(void *Message, int strategy, int priobits, int *prioptr)}
268 \index{CsdEnqueueGeneral}
269 \desc{This call enqueues a message to the scheduler's queue, to be processed in 
270 accordance with the queueing \param{strategy}. \param{priobits} and
271 \param{prioptr} specify information about priority associated with the message
272 if prioritized queueing strategies are used. \param{strategy} can take values 
273 defined in {\tt converse.h} depending upon the queueing strategy (FIFO or LIFO)
274 and the nature of priority information used (none, integer or bit-vector).
275 These predefined constants are: 
276 {\tt CQS\_QUEUEING\_FIFO}, {\tt CQS\_QUEUEING\_LIFO},
277 {\tt CQS\_QUEUEING\_IFIFO}, {\tt CQS\_QUEUEING\_ILIFO},
278 {\tt CQS\_QUEUEING\_BFIFO}, and\\  {\tt CQS\_QUEUEING\_BLIFO}.
279 This call is usually made from
280 a message handler when the message is not to be processed immediately,
281 but may be processed later (e.g. depending on the message's priority).
282 Also, it is used to enqueue local ready entities, such as threads.
283 \note{It is necessary to grab the ownership of the message buffer before queuing
284 because on returning from the handler, the system can reuse the buffer.}}
285
286 \function {void CsdEnqueue(void *Message)}
287 \index{CsdEnqueue}
288 \desc{This macro is a shorthand for 
289 {\tt CsdEnqueueGeneral(Message, CQS\_QUEUEING\_FIFO,0, NULL)} 
290 provided here for backward compatibility.}
291
292 \function{void CsdEnqueueFifo(void *Message)}
293 \index{CsdEnqueueFifo}
294 \desc{This macro is a shorthand for 
295 {\tt CsdEnqueueGeneral(Message, CQS\_QUEUEING\_FIFO,0, NULL)} 
296 provided here for backward compatibility.}
297
298
299 \function{void CsdEnqueueLifo(void *Message)}
300 \index{CsdEnqueueLifo}
301 \desc{This macro is a shorthand for
302 {\tt CsdEnqueueGeneral(Message, CQS\_QUEUEING\_LIFO,0, NULL)} 
303 provided here for backward compatibility.}
304
305 \function{int CsdEmpty()}
306 \index{CsdEmpty}
307 \desc{This function returns non-zero integer when the scheduler's queue
308 is empty, zero otherwise.}
309
310 \section{Polling for Messages}
311
312 As we stated earlier, Converse messages trigger handler functions when
313 they arrive.  In fact, for this to work, the processor must
314 occasionally poll for messages.  When the user starts Converse, he can
315 put it into one of several modes.  In the normal mode, the message
316 polling happens automatically.  However {\em user-calls-scheduler}
317 mode is designed to let the user poll manually.  To do this, the user
318 must use one of two polling functions: CmiDeliverMsgs, or
319 CsdScheduler.  CsdScheduler is more general, it will notice any
320 Converse event.  CmiDeliverMsgs is a lower-level function that ignores
321 all events except for recently-arrived messages.  (In particular, it
322 ignores messages in the scheduler queue).  You can save a tiny amount
323 of overhead by using the lower-level function.  We recommend the use
324 of CsdScheduler for all applications except those that are using only
325 the lowest level of Converse, the Cmi.  A third polling function,
326 CmiDeliverSpecificMsg, is used when you know the exact event you want
327 to wait for: it does not allow any other event to occur.
328
329 \function {void CsdScheduler(int NumberOfMessages)}
330 \index{CsdScheduler}
331 \desc{This call invokes the Converse scheduler, which repeatedly
332 delivers messages to their handlers (i.e. invokes the handler for each
333 message it selects).  Each message header encodes a pointer to its
334 handler as described in the next chapter. 
335 In each iteration, the scheduler first looks for any
336 message that  has arrived from another processor, and delivers it.
337 If there isn't any, it selects a message from the locally enqueued
338 messages (see below), and delivers it.
339 The {\tt NumberOfMessages}
340 parameter specifies how many messages should be processed (i.e. delivered
341 to their handlers). If set to -1, the scheduler continues delivering
342 messages until CsdExitScheduler() is called from a message handler.
343 if {\tt NumberOfMessages} is 0, the scheduler continues delivering messages
344 until it exhausts its supply of messages (i.e. becomes idle) or some 
345 handler calls CsdExitScheduler().}
346
347 \function{int CmiDeliverMsgs(int MaxMsgs)}
348 \index{CmiDeliverMsgs}
349 \desc{Retrieves messages from the network message queue and invokes 
350 corresponding handler functions for arrived messages. This function 
351 returns after either the network message queue becomes empty or after
352 \param{MaxMsgs} messages have been retrieved and their handlers called. 
353 It returns the difference between total messages delivered and \param{MaxMsgs}.
354 The handler is given a pointer to the message as  its parameter.
355 Normally, the delivered message is owned by CMI,  and so the handler
356 should not free it, or store it for later use.  
357 If the handler wishes to  use the message later (for example, by
358 enqueueing the message with the scheduler), it must call
359 \param{CmiGrabBuffer()} to
360 acquire the  ownership of the message buffer.}
361
362 \function{void CmiDeliverSpecificMsg(int HandlerId)}
363 \index{CmiDeliverSpecificMsg}
364 \desc{Retrieves messages from the network queue and delivers the first message
365 with its handler field equal to \param{HandlerId}. This functions queues
366 the remaining messages retrieved from the network. It returns after the 
367 invoked handler function returns.}
368
369 \function {void CsdExitScheduler(void)}
370 \index{CsdExitScheduler}
371 \desc{This call causes the scheduler
372 to stop processing messages when control has returned back to it.
373 The scheduler then returns to its calling routine.}
374
375 \internal{
376 \section{Global Pointer}
377
378 \function{int CmiGptrCreate(GlobalPtr *gptr, void *lptr, unsigned int size)}
379 \desc{This function creates a global pointer by initializing contents of
380 \param{*gptr} to point to memory on the local processor pointed to by
381 \param{lptr} of \param{size} bytes. \param{*gptr} could then be sent to other 
382 processors, and could be used by \param{CmiGet()} and \param{CmiPut()}
383 to read and write this memory by remote processors. This functions returns
384 a positive integer on success.}
385
386 \function{void *CmiGptrDref(GlobalPtr *gptr)}
387 \desc{This function returns the address of local memory associated
388 with global pointer \param{gptr}.}
389
390 \function{int CmiSyncGet(GlobalPtr *gptr, void *lptr, unsigned int size)}
391 \desc{Copies \param{size} bytes from 
392 memory pointed to by global pointer \param{gptr}
393 to local memory pointed to by \param{lptr}. 
394 This is a synchronous operation and the calling processor blocks until
395 the data is transferred to local memory. This function returns
396 a positive integer on success.}
397
398 \function{CommHandle CmiGet(GlobalPtr *gptr, void *lptr, unsigned int size)}
399 \desc{Initiates copying of \param{size} bytes from 
400 memory pointed to by global pointer \param{gptr}
401 to local memory pointed to by \param{lptr}. 
402 This function returns a  communication handle which could be used
403 to  enquire about the status of this operation.}
404
405 \function{CommHandle CmiPut(GlobalPtr *gptr, void *lptr, unsigned int size)}
406 \desc{Initiates copying of \param{size} bytes from a processor's local
407 memory pointed to by \param{lptr} to the memory pointed to by global
408 pointer \param{gptr}.  This function returns a  communication handle
409 which could be used to  enquire about the status of this operation.}
410 }
411
412 \section{The Timer}
413
414 \function{double CmiTimer(void)}
415 \index{CmiTimer}
416 \desc{Returns current value of the timer in seconds. This is
417 typically the time spent since the \param{ConverseInit()} call.
418 The precision of this timer is the best available on the particular machine,
419 and usually has at least microsecond accuracy.}
420
421 \section{Processor Ids}
422
423 \function{int CmiNumPe(void)}
424 \index{CmiNumPe}
425 \desc{Returns total number of processors in the machine on which the 
426 parallel program is being run.}
427
428 \function{int CmiMyPe(void)}
429 \index{CmiMyPe}
430 \desc{Returns the logical processor identifier of processor on which the 
431 caller resides. A processor Id is between \param{0} and \param{CmiNumPe()-1}.}
432
433 Also see the calls in Section~\ref{utility}.  % put a ref here..??
434
435 \section{Input/Output}
436
437 \function{void CmiPrintf(char *format, arg1, arg2, ...)}
438 \index{CmiPrintf}
439 \desc{This function does an atomic \param{printf()} on \param{stdout}. 
440 On machine with host, this is implemented on top of the messaging 
441 layer using asynchronous sends.}
442
443 \function{int CmiScanf(char *format, void *arg1, void *arg2, ...)}
444 \index{CmiScanf}
445 \desc{This function performs an atomic \param{scanf} from \param{stdin}.
446 The processor, on which the caller resides, blocks for input. On machines with
447 host, this is implemented on top of the messaging layer using asynchronous
448 send and blocking receive.}
449
450 \function{void CmiError(char *format, arg1, arg2, ...)}
451 \index{CmiError}
452 \desc{This function does an atomic \param{printf()} on \param{stderr}. 
453 On machines with host, this is implemented on top of the messaging 
454 layer using asynchronous sends.}
455
456 \internal{
457 \section{Processor Groups}
458
459 \function{void CmiPgrpCreate(Pgrp *group)}
460 \desc{Creates a processor-group with calling processsor as the root processor.}
461
462 \function{void CmiPgrpDestroy(Pgrp *group)}
463 \desc{Frees resources associated with a processor group \param{group}.}
464
465 \function{void CmiAddChildren(Pgrp *group, int penum, int size, int procs[])}
466 \desc{Adds \param{size} processors from array \param{procs[]} to the
467 processor-group \param{group} as children of processor penum. This function
468 could be called only by the root processor of processor-group \param{group}.}
469
470 \function{CommHandle CmiAsyncMulticast(Pgrp *group, unsigned int size, void *msg)}
471 \desc{Initiates asynchronous broadcast of message \param{msg} of
472 length \param{size} bytes to all processors belonging to \param{group}
473 excluding the processor on which the caller resides. It returns a
474 communication handle which could be used to check the status of this
475 send using \param{CmiAsyncMsgSent()}. \param{msg} should not be
476 overwritten or freed before the communication is complete. \note{Caller
477 need not belong to \param{group}.}} 
478
479 \function{int CmiPgrpRoot(Pgrp *group)}
480 \desc{Returns the processor id of root of processor-group \param{group}. }
481
482 \function{int CmiNumChildren(Pgrp *group, int penum)}
483 \desc{Returns  number of children of processor \param{penum} 
484 in the processor-group \param{group}.}
485
486 \function{int CmiParent(Pgrp *group, int penum)}
487 \desc{Returns  processor id of parent of processor \param{penum} 
488 in the processor-group \param{group}.}
489
490 \function{void CmiChildren(Pgrp *group, int node, int *children)}
491 \desc{Fills in array \param{children} with processor ids of all the
492 children processor \param{node} in processor-group \param{group}. This
493 array should at least be of size \param{CmiNumChildren()}.}
494 }
495
496 \section{Spanning Tree Calls}
497
498 Converse defines a spanning tree organization of the processor procNums along
499 with routines for accessing elements of that tree.  The spanning tree
500 routines come in handy when writing programs with collective communication
501 because message communication patterns can be made to proceed along the
502 spanning tree arcs to avoid bottlenecks at a single procNum.
503
504 \function{int CmiSpanTreeRoot()}
505 \index{CmiSpanTreeRoot}
506 \desc{Returns the processor number of the root of the spanning tree.}
507
508 \function{int CmiSpanTreeParent(int procNum)}
509 \index{CmiSpanTreeParent}
510 \desc{This function returns the processor number of the parent of
511 \param{procNum} in the spanning tree.}
512
513 \function{int CmiNumSpanTreeChildren(int procNum)}
514 \index{CmiNumSpanTreeChildren}
515 \desc{Returns the number of children of \param{procNum} in the spanning tree.}
516
517 \function{void CmiSpanTreeChildren(int procNum, int *children)}
518 \index{CmiSpanTreeChildren}
519 \desc{This function fills the array \param{children} with processor
520 numbers of children of \param{procNum} in the spanning tree.}
521