1 #include "BSprivate.h"
2 
3 /* ******************************************************************* */
4 /* Routines for building, manipulating, and using the compiled message */
5 /* passing routines.                                                   */
6 /* ******************************************************************* */
7 
8 /*+ BMcomp_init - Initialize a compiled message structure.
9 
10 	Input Parameters:
11 .   base_type - The base number for message types in this structure.
12                  See BMmsg.h for more information on base_type.
13 
14 	Returns:
15     pointer to the compiled message structure
16  +*/
BMcomp_init(int base_type)17 BMcomp_msg *BMcomp_init(int base_type)
18 {
19 	BMcomp_msg *ph_ptr;
20 
21 	MY_MALLOCN(ph_ptr,(BMcomp_msg *),sizeof(BMcomp_msg),1);
22 	ph_ptr->num_phases = 0;
23 	ph_ptr->num_msgs = 0;
24 	ph_ptr->base_type = base_type;
25 	ph_ptr->phase_list = NULL;
26 	return(ph_ptr);
27 }
28 
29 /*+ BMfree_comp_msg - Free a compiled message structure.
30 
31 	Input Parameters:
32 .   comp_msg - Pointer to compiled message structure to free
33 
34 	Returns: void
35  +*/
BMfree_comp_msg(BMcomp_msg * comp_msg)36 void BMfree_comp_msg(BMcomp_msg *comp_msg)
37 {
38 	BMphase *phase_ptr;
39 	BMmsg *msg_ptr;
40 
41 	while (comp_msg->phase_list != NULL) {
42 		/* free a phase */
43 		phase_ptr = comp_msg->phase_list;
44 		comp_msg->phase_list = comp_msg->phase_list->next;
45 		while (phase_ptr->msg_list != NULL) {
46 			/* free a msg */
47 			msg_ptr = phase_ptr->msg_list;
48 			phase_ptr->msg_list = phase_ptr->msg_list->next;
49 			BMfree_user_data(msg_ptr); CHKERR(0);
50 			BMfree_setup_data(msg_ptr); CHKERR(0);
51 			if (msg_ptr->msg != NULL) {
52 				MY_FREE(msg_ptr->msg);
53 			}
54 			MY_FREE(msg_ptr);
55 		}
56 		MY_FREE(phase_ptr);
57 	}
58 	MY_FREE(comp_msg);
59 }
60 
61 /*+ BMget_phase - Get a pointer to a particular message phase.
62 
63 	Input Parameters:
64 .   comp_msg - The compiled message structure
65 .   phase_num - the phase number point to find
66 
67 	Returns:
68     pointer to the phase list or NULL if not found
69  +*/
BMget_phase(BMcomp_msg * comp_msg,int phase_num)70 BMphase *BMget_phase(BMcomp_msg *comp_msg, int phase_num)
71 {
72 	BMphase *phase_ptr;
73 
74 	phase_ptr = comp_msg->phase_list;
75 	while (phase_ptr != NULL) {
76 		if (phase_ptr->phase == phase_num) {
77 			return(phase_ptr);
78 		}
79 		phase_ptr = phase_ptr->next;
80 	}
81 	return(phase_ptr);
82 }
83 
84 /*+ BMadd_msg - Insert a message into the structure.
85 
86 	Input Parameters:
87 .   comp_msg - The compiled message structure
88 .   phase_num - a pointer to the message
89 .   procinfo - information about the processor number, etc.
90 
91 	Returns:
92     void
93  +*/
BMadd_msg(BMcomp_msg * comp_msg,BMmsg * msg_ptr,BSprocinfo * procinfo)94 void BMadd_msg(BMcomp_msg *comp_msg, BMmsg *msg_ptr, BSprocinfo *procinfo)
95 {
96 	BMphase *phase_ptr, *prev;
97 	int	found;
98 	BMmsg *cur_msg;
99 
100 	/* do we need to generate a msg number? */
101 	if (msg_ptr->msg_type < 0) {
102 		if (comp_msg->num_msgs >= MAX_NUM_MSGS) {
103 			MY_SETERRC(MSG_ERROR,"Too many messages in comp_msg\n");
104 		}
105 		msg_ptr->msg_type = comp_msg->base_type + comp_msg->num_msgs +
106 			procinfo->my_id*MAX_NUM_MSGS;
107 	}
108 	comp_msg->num_msgs++;
109 
110 	/* find the phase, if possible */
111 	phase_ptr = comp_msg->phase_list;
112 	prev = phase_ptr;
113 	found = FALSE;
114 	while (phase_ptr != NULL) {
115 		if (phase_ptr->phase == msg_ptr->phase) {
116 			/* put the msg at the end of the list */
117 			cur_msg = phase_ptr->end_msg_list;
118 			phase_ptr->end_msg_list = msg_ptr;
119 			cur_msg->next = msg_ptr;
120 			msg_ptr->next = NULL;
121 			found = TRUE;
122 			break;
123 		}
124 		if (phase_ptr->phase > msg_ptr->phase) break;
125 		prev = phase_ptr;
126 		phase_ptr = phase_ptr->next;
127 	}
128 	/* did not find phase, must create it */
129 	if (!found) {
130 		comp_msg->num_phases++;
131 		if (phase_ptr == comp_msg->phase_list) {
132 			MY_MALLOC(comp_msg->phase_list,(BMphase *),sizeof(BMphase),1);
133 			comp_msg->phase_list->phase = msg_ptr->phase;
134 			comp_msg->phase_list->msg_list = msg_ptr;
135 			comp_msg->phase_list->end_msg_list = msg_ptr;
136 			comp_msg->phase_list->cur_msg = NULL;
137 			comp_msg->phase_list->cur_list_ptr = NULL;
138 			comp_msg->phase_list->cur_recv_msg = NULL;
139 			comp_msg->phase_list->async_list = NULL;
140 			msg_ptr->next = NULL;
141 			comp_msg->phase_list->next = prev;
142 		} else {
143 			MY_MALLOC(phase_ptr,(BMphase *),sizeof(BMphase),1);
144 			phase_ptr->phase = msg_ptr->phase;
145 			phase_ptr->msg_list = msg_ptr;
146 			phase_ptr->end_msg_list = msg_ptr;
147 			phase_ptr->next = prev->next;
148 			phase_ptr->cur_msg = NULL;
149 			phase_ptr->cur_list_ptr = NULL;
150 			phase_ptr->async_list = NULL;
151 			phase_ptr->cur_recv_msg = NULL;
152 			prev->next = phase_ptr;
153 			msg_ptr->next = NULL;
154 		}
155 	}
156 }
157 
158 /*+ BMcreate_msg - Create a message
159 
160 	Input Parameters:
161 .   phase - the message phase number
162 .   msg_type - the message type
163 .   msg_data_type - the data type of the message (see tools)
164 .   proc - the processor to send to/from
165 
166 	Returns:
167     pointer to the new message data structure
168  +*/
BMcreate_msg(int phase,int msg_type,MPI_Datatype msg_data_type,int proc)169 BMmsg *BMcreate_msg(int phase, int msg_type, MPI_Datatype msg_data_type,
170 					int proc)
171 {
172 	BMmsg *msg;
173 
174 	MY_MALLOCN(msg,(BMmsg *),sizeof(BMmsg),1);
175 	msg->phase = phase;
176 	msg->msg_type = msg_type;
177 	msg->msg_data_type = msg_data_type;
178 	msg->status = COMPLETED;
179 	msg->proc = proc;
180 	msg->msg = NULL;
181 	BMinit_user(&(msg->user_data)); CHKERRN(0);
182 	BMinit_user(&(msg->setup_data)); CHKERRN(0);
183 	return(msg);
184 }
185 
186 /*+ BMget_msg_size - Return the size of a message (in number of elements)
187 
188 	Input Parameters:
189 .   msg - pointer to a message
190 
191 	Returns:
192     the message size in number of elements
193  +*/
BMget_msg_size(BMmsg * msg)194 int BMget_msg_size(BMmsg *msg)
195 {
196 	return(msg->size);
197 }
198 
199 /*+ BMset_msg_size - Set the size of a message (in number of elements)
200 
201 	Input Parameters:
202 .   msg - pointer to a message
203 .   size - the message size (in number of elements)
204 
205 	Returns:
206     void
207  +*/
BMset_msg_size(BMmsg * msg,int size)208 void BMset_msg_size(BMmsg *msg, int size)
209 {
210 	msg->size = size;
211 }
212 
213 /*+ BMinit_user - Initialize the user data structure
214 
215 	Input Parameters:
216 .   user_data - pointer to the user_data structure
217 
218 	Returns:
219     void
220  +*/
BMinit_user(BMuser_data * user_data)221 void BMinit_user(BMuser_data *user_data)
222 {
223 	user_data->data = NULL;
224 	user_data->length = 0;
225 	user_data->free_data = NULL;
226 }
227 
228 /*+ BMfree_user - Free the user data structure
229 
230 	Input Parameters:
231 .   user_data - pointer to the user_data structure
232 
233 	Returns:
234     void
235  +*/
BMfree_user(BMuser_data * user_data)236 void BMfree_user(BMuser_data *user_data)
237 {
238 	if (user_data->free_data != NULL) {
239 		(*user_data->free_data)(user_data->data); CHKERR(0);
240 	}
241 	user_data->data = NULL;
242 	user_data->length = 0;
243 	user_data->free_data = NULL;
244 }
245 
246 /*+ BMfree_user_data - Free the user's data (from the message structure)
247 
248 	Input Parameters:
249 .   msg - pointer to the message
250 
251 	Returns:
252     void
253  +*/
BMfree_user_data(BMmsg * msg)254 void BMfree_user_data(BMmsg *msg)
255 {
256 	BMfree_user(&(msg->user_data)); CHKERR(0);
257 }
258 
259 /*+ BMfree_setup_data - Free the user's setup data (from the message structure)
260 
261 	Input Parameters:
262 .   msg - pointer to the message
263 
264 	Returns:
265     void
266  +*/
BMfree_setup_data(BMmsg * msg)267 void BMfree_setup_data(BMmsg *msg)
268 {
269 	BMfree_user(&(msg->setup_data)); CHKERR(0);
270 }
271 
272 /*+ BMset_user - Set the user data structure
273 
274 	Input Parameters:
275 .   user_data - pointer to the user data structure
276 .   data - pointer to the user's data
277 .   length - the length of the user data
278 .   fcn - the function to free the user data
279 
280 	Returns:
281     void
282  +*/
BMset_user(BMuser_data * user_data,int * data,int length,void (* fcn)(int *))283 void BMset_user(BMuser_data *user_data, int *data, int length, void (*fcn)(int *))
284 {
285 	user_data->data = data;
286 	user_data->length = length;
287 	user_data->free_data = fcn;
288 }
289 
290 /*+ BMset_user_data - Set the user data structure (in a message)
291 
292 	Input Parameters:
293 .   msg - pointer to the message
294 .   data - pointer to the user's data
295 .   length - the length of the user data
296 .   fcn - the function to free the user data
297 
298 	Returns:
299     void
300  +*/
BMset_user_data(BMmsg * msg,int * data,int length,void (* fcn)(int *))301 void BMset_user_data(BMmsg *msg, int *data, int length, void (*fcn)(int *))
302 {
303 	BMset_user(&(msg->user_data),data,length,fcn); CHKERR(0);
304 }
305 
306 /*+ BMset_setup_data - Set the user's setup data structure (in a message)
307 
308 	Input Parameters:
309 .   msg - pointer to the message
310 .   data - pointer to the user's data
311 .   length - the length of the user data
312 .   fcn - the function to free the user data
313 
314 	Returns:
315     void
316  +*/
BMset_setup_data(BMmsg * msg,int * data,int length,void (* fcn)(int *))317 void BMset_setup_data(BMmsg *msg, int *data, int length, void (*fcn)(int *))
318 {
319 	BMset_user(&(msg->setup_data),data,length,fcn); CHKERR(0);
320 }
321 
322 /*+ BMget_user - Return the user's data and it's length
323 
324 	Input Parameters:
325 .   msg - pointer to a message
326 
327 	Output Parameters:
328 .   length - pointer to the length of the message
329 
330 	Returns:
331     pointer to the user data
332  +*/
BMget_user(BMmsg * msg,int * length)333 int *BMget_user(BMmsg *msg, int *length)
334 {
335 	(*length) = msg->user_data.length;
336 	return(msg->user_data.data);
337 }
338 
339 /*+ BMget_setup - Return the user's setup data and it's length
340 
341 	Input Parameters:
342 .   msg - pointer to a message
343 
344 	Output Parameters:
345 .   length - pointer to the length of the message
346 
347 	Returns:
348     pointer to the user data
349  +*/
BMget_setup(BMmsg * msg,int * length)350 int *BMget_setup(BMmsg *msg, int *length)
351 {
352 	(*length) = msg->setup_data.length;
353 	return(msg->setup_data.data);
354 }
355 
356 /*+ BMset_msg_ptr - Give the message structure a pointer to the space
357                     allocated for the message data.
358 
359 	Input Parameters:
360 .   msg - pointer to a message
361 .   msg_ptr - pointer to the space for the message
362 
363 	Returns:
364     void
365  +*/
BMset_msg_ptr(BMmsg * msg,void * msg_ptr)366 void BMset_msg_ptr(BMmsg *msg, void *msg_ptr)
367 {
368 	msg->msg = msg_ptr;
369 }
370 
371 /*+ BMget_msg_ptr - Get the pointer to the message data.
372 
373 	Input Parameters:
374 .   msg - pointer to a message
375 
376 	Returns:
377     pointer to the message data
378  +*/
BMget_msg_ptr(BMmsg * msg)379 void *BMget_msg_ptr(BMmsg *msg)
380 {
381 	return(msg->msg);
382 }
383 
384 /*+ BMnext_msg - Get the next message in this phase
385 
386 	Input Parameters:
387 .   phase_ptr - pointer to the phase
388 .   msg_ptr - pointer to a message
389 
390 	Returns:
391     pointer to the next message (NULL if none)
392  +*/
BMnext_msg(BMphase * phase_ptr,BMmsg * msg_ptr)393 BMmsg *BMnext_msg(BMphase *phase_ptr, BMmsg *msg_ptr)
394 {
395 
396 	if (phase_ptr == NULL) return(NULL);
397 	if (msg_ptr == NULL) {
398 		msg_ptr = phase_ptr->msg_list;
399 	} else {
400 		msg_ptr = msg_ptr->next;
401 	}
402 	return(msg_ptr);
403 }
404 
405 /*+ BMalloc_msg - Pre-allocate messages for the compiled message structure
406 
407 	Input Parameters:
408 .   comp_msg - pointer to the compiled message structure
409 
410  +*/
BMalloc_msg(BMcomp_msg * comp_msg)411 void BMalloc_msg(BMcomp_msg *comp_msg)
412 {
413 	BMphase *phase_ptr;
414 	BMmsg *msg_ptr;
415 	int	type_size;
416 
417 	for (phase_ptr=comp_msg->phase_list;phase_ptr != NULL;
418 		phase_ptr=phase_ptr->next) {
419 		for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
420 			if (msg_ptr->msg == NULL) {
421 				MPI_Type_size(msg_ptr->msg_data_type,(MPI_Aint *)&type_size);
422 				MY_MALLOC(msg_ptr->msg,(char *),
423 					type_size*msg_ptr->size,1);
424 			}
425 		}
426 	}
427 }
428 
429 /*+ BMfix_send - Decide what must be sent when
430 
431 	Input Parameters:
432 .   msg_type - message type for the use of BMfix_send
433 .   comp_msg_type - base type for the compiled message structure
434 .   comp_msg_data_type - message data type for the compiled message structure
435 .                        (see tools)
436 .   comp_msg - pointer to the compiled message structure
437 .   phase_ptr - pointer to the phase to work on
438 .   free_fcn - pointer to function to free user data
439 .   procinfo - the usual processor information
440 
441 	Returns:
442     the number of messages to be sent
443  +*/
BMfix_send(int msg_type,int comp_msg_type,MPI_Datatype comp_msg_data_type,BMcomp_msg * comp_msg,BMphase * phase_ptr,void (* free_fcn)(int *),BSprocinfo * procinfo)444 int BMfix_send(int msg_type, int comp_msg_type, MPI_Datatype comp_msg_data_type,
445 	BMcomp_msg *comp_msg, BMphase *phase_ptr, void (*free_fcn)(int *),
446 	BSprocinfo *procinfo)
447 {
448 	BMmsg	*msg_ptr;
449 	int	size, from, msg_len;
450 	int	i, source_len, *t_msg;
451 	int	*addr, *source;
452 	BSmsg_list *msg_list;
453 	int	num_to_recv, num_recved;
454 	int	*tot_num_msg, *tot_num_msg2, *iwork, *tot_len;
455 	int	**msg, **cur_msg_ptr;
456 	int	cur_size;
457 	int	*int_msg;
458 	int	consumed;
459 	int	np;
460 	MPI_Status	mpi_status;
461 	void *in_msg;
462 
463 	msg_list = NULL;
464 
465 	/* sync up to avoid problems */
466 	GSYNC(procinfo->procset);
467 	np = procinfo->nprocs;
468 	MY_MALLOCN(tot_num_msg,(int *),sizeof(int)*np,0);
469 	MY_MALLOCN(tot_num_msg2,(int *),sizeof(int)*np,0);
470 	MY_MALLOCN(tot_len,(int *),sizeof(int)*np,1);
471 	MY_MALLOCN(msg,(int **),sizeof(int *)*np,3);
472 	MY_MALLOCN(cur_msg_ptr,(int **),sizeof(int *)*np,3);
473 	MY_MALLOCN(iwork,(int *),sizeof(int)*np,2);
474 	for (i=0;i<np;i++) {
475 		tot_num_msg[i] = 0;
476 		tot_num_msg2[i] = 0;
477 		tot_len[i] = 0;
478 		msg[i] = NULL;
479 	}
480 	if (phase_ptr != NULL) {
481 		for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
482 			source = BMget_setup(msg_ptr,&source_len); CHKERRN(0);
483 			msg_len = source_len + 3;
484 			tot_num_msg[msg_ptr->proc]++;
485 			tot_num_msg2[msg_ptr->proc]++;
486 			tot_len[msg_ptr->proc] += msg_len;
487 		}
488 	}
489 	GISUM(tot_num_msg2,np,iwork,procinfo->procset);
490 	num_to_recv = tot_num_msg2[procinfo->my_id];
491 	MY_FREE(iwork);
492 	MY_FREE(tot_num_msg2);
493 
494 	/* tell the people who you want stuff from, that you want it */
495 	if (phase_ptr != NULL) {
496 		for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
497 			source = BMget_setup(msg_ptr,&source_len); CHKERRN(0);
498 			msg_len = source_len + 3;
499 			if (msg[msg_ptr->proc] == NULL) {
500 				MY_MALLOCN(t_msg,(int *),tot_len[msg_ptr->proc]*sizeof(int),5);
501 				msg[msg_ptr->proc] = t_msg;
502 				cur_msg_ptr[msg_ptr->proc] = t_msg;
503 			} else {
504 				t_msg = cur_msg_ptr[msg_ptr->proc];
505 			}
506 			cur_msg_ptr[msg_ptr->proc] += msg_len;
507 			t_msg[0] = msg_ptr->phase;
508 			t_msg[1] = msg_ptr->msg_type;
509 			t_msg[2] = msg_len;
510 			for (i=0;i<source_len;i++) {
511 				t_msg[3+i] = source[i];
512 			}
513 			tot_num_msg[msg_ptr->proc]--;
514 			if (tot_num_msg[msg_ptr->proc] == 0) {
515 				MY_SEND_SYNC(msg_list,msg_type,msg[msg_ptr->proc],
516 					tot_len[msg_ptr->proc],(msg_ptr->proc),MPI_INT,procinfo);
517 				MY_FREE(msg[msg_ptr->proc]);
518 			}
519 		}
520 	}
521 	MY_FREE(tot_num_msg);
522 	MY_FREE(tot_len);
523 	MY_FREE(msg);
524 	MY_FREE(cur_msg_ptr);
525 
526 	/* now wait for msgs from people */
527 	num_recved = 0;
528 	while (num_recved < num_to_recv) {
529 		/* receive a message */
530 		RECVSYNCUNSZN(msg_type,in_msg,size,MPI_INT,procinfo,mpi_status);
531 		CHKERRN(0);
532 		from = mpi_status.MPI_SOURCE;
533 		CHECK_SEND_LIST(msg_list);
534 		int_msg = (int *)in_msg;
535 		consumed = 0;
536 		while (consumed < size) {
537 			cur_size = int_msg[2];
538 			/* if no message number, then create one */
539 			if (int_msg[1] < 0) {
540 				int_msg[1] = num_recved + comp_msg_type;
541 			}
542 			msg_ptr = BMcreate_msg(int_msg[0],int_msg[1],comp_msg_data_type,
543 				from); CHKERRN(0);
544 			BMadd_msg(comp_msg,msg_ptr,procinfo); CHKERRN(0);
545 			/* copy user data from message */
546 			MY_MALLOCN(addr,(int *),(cur_size-3)*sizeof(int),6);
547 			for (i=0;i<cur_size-3;i++) {
548 				addr[i] = int_msg[i+3];
549 			}
550 			BMset_user_data(msg_ptr,addr,cur_size-3,free_fcn);
551 			CHKERRN(0);
552 			consumed += cur_size;
553 			int_msg += cur_size;
554 			num_recved++;
555 		}
556 		MSGFREERECV(in_msg);CHKERRN(0);
557 	}
558 	FINISH_SEND_LIST(msg_list);
559 
560 	/* return the number of messages that were created */
561 	return(num_recved);
562 }
563 
564 /*+ BMinit_comp_msg - Post receives for all messages in this structure
565 
566 	Input Parameters:
567 .   comp_msg - pointer to the message structure
568 .   procinfo - the usual processor information
569 
570 	Returns:
571     void
572  +*/
BMinit_comp_msg(BMcomp_msg * comp_msg,BSprocinfo * procinfo)573 void BMinit_comp_msg(BMcomp_msg *comp_msg, BSprocinfo *procinfo)
574 {
575 	BMphase *phase_ptr;
576 	BMmsg *msg_ptr;
577 
578 	for (phase_ptr=comp_msg->phase_list;phase_ptr!=NULL;
579 		phase_ptr=phase_ptr->next) {
580 		for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
581 			msg_ptr->status = NOT_COMPLETED;
582 			if (msg_ptr->msg != NULL) {
583 				RECVASYNCNOMEMFORCE(msg_ptr->msg_type,msg_ptr->msg,
584 					msg_ptr->size,msg_ptr->msg_data_type,
585 					msg_ptr->recv_id,procinfo); CHKERR(0);
586 			}
587 		}
588 	}
589 	GSYNC(procinfo->procset);
590 }
591 
592 /*+ BMfinish_comp_msg - Clean up after using message structure
593 
594 	Input Parameters:
595 .   comp_msg - pointer to the message structure
596 .   procinfo - the usual processor information
597 
598 	Returns:
599     void
600  +*/
BMfinish_comp_msg(BMcomp_msg * comp_msg,BSprocinfo * procinfo)601 void BMfinish_comp_msg(BMcomp_msg *comp_msg, BSprocinfo *procinfo)
602 {
603 	BMphase *phase_ptr;
604 	BMmsg *msg_ptr;
605 
606 	for (phase_ptr=comp_msg->phase_list;phase_ptr!=NULL;
607 		phase_ptr=phase_ptr->next) {
608 		for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
609 			if ((msg_ptr->msg != NULL) && (msg_ptr->status != COMPLETED)) {
610 				SENDWAITNOMEM(msg_ptr->msg_type,msg_ptr->msg,msg_ptr->size,
611 					msg_ptr->proc,msg_ptr->msg_data_type,msg_ptr->send_id);
612 				CHKERR(0);
613 				msg_ptr->status = COMPLETED;
614 			}
615 		}
616 	}
617 }
618 
619 /*+ BMsendf_msg - Send a message as a "forced" message
620 
621 	Input Parameters:
622 .   msg - pointer to a message
623 .   procinfo - information about the processor number, etc.
624 
625 	Returns:
626     void
627  +*/
BMsendf_msg(BMmsg * msg,BSprocinfo * procinfo)628 void BMsendf_msg(BMmsg *msg, BSprocinfo *procinfo)
629 {
630 	SENDASYNCNOMEMFORCE(msg->msg_type,msg->msg,msg->size,msg->proc,
631 		msg->msg_data_type,msg->send_id,procinfo);
632 	msg->status = NOT_COMPLETED;
633 	CHKERR(0);
634 }
635 
636 /*+ BMcheck_on_async_block(phase_ptr)
637     Input Parameters:
638 .   phase_ptr -- pointer to the current phase
639 
640 	Returns:
641     void
642  +*/
BMcheck_on_async_block(BMphase * phase_ptr)643 void BMcheck_on_async_block(BMphase *phase_ptr)
644 {
645 	if (phase_ptr != NULL) {
646 		MCHECK_SEND_LIST(phase_ptr->async_list);
647 	}
648 }
649 
650 /*+ BMfinish_on_async_block(phase_ptr)
651     Input Parameters:
652 .   phase_ptr -- pointer to the current phase
653 
654 	Returns:
655     void
656  +*/
BMfinish_on_async_block(BMphase * phase_ptr)657 void BMfinish_on_async_block(BMphase *phase_ptr)
658 {
659 	if (phase_ptr != NULL) {
660 		MFINISH_SEND_LIST(phase_ptr->async_list);
661 	}
662 }
663 
664 #define TRUE_MSG_LEN(msg_len) \
665 (((int)((msg_len+sizeof(int))/sizeof(FLOAT)))*sizeof(FLOAT))
666 /*+ BMsend_block_msg - Send a message and try to group with others
667 
668 	Input Parameters:
669 .   phase_ptr -- pointer to the current phase
670 .   msg - pointer to a message
671 .   procinfo - information about the processor number, etc.
672 
673 	Returns:
674     void
675  +*/
BMsend_block_msg(BMphase * phase_ptr,BMmsg * msg,BSprocinfo * procinfo)676 void BMsend_block_msg(BMphase *phase_ptr, BMmsg *msg, BSprocinfo *procinfo)
677 {
678 	int	*int_msg;
679 	char	*char_msg, *ochar_msg;
680 	BSmsg_list	*msg_list_node;
681 	int	i;
682 	int	*tint1;
683 
684 	/* this really shouldn't happen */
685 	if (phase_ptr == NULL) return;
686 
687 	/* this means we should send off the pending message, if it exists */
688 	if (msg == NULL) {
689 		if (phase_ptr->cur_msg != NULL) {
690 			msg_list_node = phase_ptr->cur_msg;
691 			phase_ptr->cur_msg = NULL;
692 			msg_list_node->next = phase_ptr->async_list;
693 			phase_ptr->async_list = msg_list_node;
694 			SENDASYNCNOMEM(msg_list_node->msg_type,msg_list_node->msg_buf,
695 				msg_list_node->msg_len,msg_list_node->msg_to,
696 				msg_list_node->msg_data_type,msg_list_node->msg_id,procinfo);
697 			CHKERR(0);
698 		}
699 		return;
700 	}
701 
702 	/* check to see if any of the messages have been sent */
703 	MCHECK_SEND_LIST(phase_ptr->async_list);
704 
705 	if (phase_ptr->cur_msg != NULL) {
706 		msg_list_node = phase_ptr->cur_msg;
707 		/* check to see if the destination of the message in cur_msg is the */
708 		/* same as the message to be sent, if not, then clear cur_msg */
709 		/* same thing if there isn't enough room for the message */
710 		if ((msg->proc != msg_list_node->msg_to) ||
711 			(msg->size+sizeof(FLOAT)+TRUE_MSG_LEN(msg_list_node->msg_len) >
712 			PREFER_MAX_MSG_SIZE)) {
713 			msg_list_node = phase_ptr->cur_msg;
714 			phase_ptr->cur_msg = NULL;
715 			msg_list_node->next = phase_ptr->async_list;
716 			phase_ptr->async_list = msg_list_node;
717 			SENDASYNCNOMEM(msg_list_node->msg_type,msg_list_node->msg_buf,
718 				msg_list_node->msg_len,msg_list_node->msg_to,
719 				msg_list_node->msg_data_type,msg_list_node->msg_id,procinfo);
720 			CHKERR(0);
721 			/* fall through... */
722 		} else {
723 			/* we have enough room put it here and return */
724 			/* find my place in the message */
725 			char_msg = &(msg_list_node->msg_buf[msg_list_node->msg_len]);
726 			msg_list_node->msg_len += (TRUE_MSG_LEN(msg->size) + sizeof(FLOAT));
727 			tint1 = (int *) msg_list_node->msg_buf;
728 			(*tint1)++;
729 			int_msg = (int *) char_msg;
730 			int_msg[0] = msg->size;
731 			char_msg += sizeof(FLOAT);
732 			ochar_msg = (char *)msg->msg;
733 			for (i=0;i<msg->size;i++) {
734 				char_msg[i] = ochar_msg[i];
735 			}
736 			return;
737 		}
738 	}
739 
740 	/* the type of the block message is the type of the 1st message */
741 	/* extra data in each message */
742 	/* 1 int -- the number of messages in the block */
743 	/* 1 int per sub message -- the type of a single message */
744 	/* 1 int per sub message -- the length of a single message */
745 	if (phase_ptr->cur_msg == NULL) {
746 		if (TRUE_MSG_LEN(msg->size)+sizeof(FLOAT)*2 <= PREFER_MAX_MSG_SIZE) {
747 			MY_MALLOC(msg_list_node,(BSmsg_list *),sizeof(BSmsg_list),1);
748 			phase_ptr->cur_msg = msg_list_node;
749 			msg_list_node->msg_type = msg->msg_type;
750 			msg_list_node->msg_len = TRUE_MSG_LEN(msg->size)+2*sizeof(FLOAT);
751 			msg_list_node->msg_to = msg->proc;
752 			msg_list_node->msg_data_type = msg->msg_data_type;
753 			MY_MALLOC(msg_list_node->msg_buf,(char *),PREFER_MAX_MSG_SIZE,1);
754 			char_msg = (char *) msg_list_node->msg_buf;
755 			int_msg = (int *) char_msg;
756 			int_msg[0] = 1;
757 			char_msg += sizeof(FLOAT);
758 			int_msg = (int *) char_msg;
759 			int_msg[0] = msg->size;
760 			char_msg += sizeof(FLOAT);
761 			ochar_msg = (char *)msg->msg;
762 			for (i=0;i<msg->size;i++) {
763 				char_msg[i] = ochar_msg[i];
764 			}
765 		} else {
766 			MY_MALLOC(msg_list_node,(BSmsg_list *),sizeof(BSmsg_list),1);
767 			msg_list_node->next = phase_ptr->async_list;
768 			phase_ptr->async_list = msg_list_node;
769 			msg_list_node->msg_type = msg->msg_type;
770 			msg_list_node->msg_len = TRUE_MSG_LEN(msg->size) + sizeof(FLOAT)*2;
771 			msg_list_node->msg_to = msg->proc;
772 			msg_list_node->msg_data_type = msg->msg_data_type;
773 			MY_MALLOC(msg_list_node->msg_buf,(char *),msg_list_node->msg_len,1);
774 			char_msg = (char *) msg_list_node->msg_buf;
775 			int_msg = (int *) char_msg;
776 			int_msg[0] = 1;
777 			char_msg += sizeof(FLOAT);
778 			int_msg = (int *) char_msg;
779 			int_msg[0] = msg->size;
780 			char_msg += sizeof(FLOAT);
781 			ochar_msg = (char *)msg->msg;
782 			for (i=0;i<msg->size;i++) {
783 				char_msg[i] = ochar_msg[i];
784 			}
785 			SENDASYNCNOMEM(msg_list_node->msg_type,msg_list_node->msg_buf,
786 				msg_list_node->msg_len,msg_list_node->msg_to,
787 				msg_list_node->msg_data_type,msg_list_node->msg_id,procinfo);
788 			CHKERR(0);
789 		}
790 	}
791 }
792 
793 /*+ BMrecv_block_msg - Receive any unreceived blocked message in this phase
794 
795 	Input Parameters:
796 .   phase_ptr - pointer to the phase
797 .   procinfo - information about the processor number, etc.
798 
799 	Returns:
800     pointer to the message (NULL if no more messages)
801  +*/
BMrecv_block_msg(BMphase * phase_ptr,BSprocinfo * procinfo)802 BMmsg *BMrecv_block_msg(BMphase *phase_ptr, BSprocinfo  *procinfo)
803 {
804 	BMmsg *msg_ptr, *tmsg_ptr;
805 	int	i;
806 	int	*int_msg;
807 	char	*char_msg;
808 	int	num_msg;
809 	MPI_Status	mpi_status;
810 
811 	if (phase_ptr == NULL) return(NULL);
812 	if (phase_ptr->cur_list_ptr == NULL) {
813 		phase_ptr->cur_list_ptr = phase_ptr->msg_list;
814 	} else {
815 		phase_ptr->cur_list_ptr = phase_ptr->cur_list_ptr->next;
816 	}
817 	msg_ptr = phase_ptr->cur_list_ptr;
818 	if (msg_ptr == NULL) {
819 		return(NULL);
820 	} else {
821 		if (msg_ptr->status == NOT_COMPLETED) {
822 			/* this means we *really* have to receive it */
823 			/* first, free up the current received message */
824 			BMfree_block_msg(phase_ptr);
825 			RECVSYNCUNSZN(msg_ptr->msg_type,phase_ptr->cur_recv_msg,
826 				msg_ptr->size,msg_ptr->msg_data_type,procinfo,mpi_status);
827 			CHKERRN(0);
828 			/* now break up the message */
829 			char_msg = (char *)phase_ptr->cur_recv_msg;
830 			int_msg = (int *) char_msg;
831 			tmsg_ptr = msg_ptr;
832 			num_msg = int_msg[0];
833 			char_msg += sizeof(FLOAT);
834 			for (i=0;i<num_msg;i++) {
835 				int_msg = (int *) char_msg;
836 				tmsg_ptr->size = int_msg[0];
837 				char_msg += sizeof(FLOAT);
838 				tmsg_ptr->msg = char_msg;
839 				tmsg_ptr->status = COMPLETED;
840 				tmsg_ptr = tmsg_ptr->next;
841 				char_msg += TRUE_MSG_LEN(int_msg[0]);
842 			}
843 			return(msg_ptr);
844 		} else {
845 			/* we just have to return with it */
846 			return(msg_ptr);
847 		}
848 	}
849 }
850 
851 
852 /*+ BMrecv_msg - Receive any unreceived message in this phase
853 
854 	Input Parameters:
855 .   phase_ptr - pointer to the phase
856 
857 	Returns:
858     pointer to the message (NULL if no more messages)
859  +*/
BMrecv_msg(BMphase * phase_ptr)860 BMmsg *BMrecv_msg(BMphase *phase_ptr)
861 {
862 	BMmsg *msg_ptr;
863 	int	waiting;
864 	int	finished;
865 	MPI_Status	mpi_status;
866 
867 	if (phase_ptr == NULL) return(NULL);
868 	waiting = TRUE;
869 	while (waiting) {
870 		waiting = FALSE;
871 		for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
872 			if (msg_ptr->status == NOT_COMPLETED) {
873 				if (msg_ptr->msg != NULL) {
874 					MPI_Test(&(msg_ptr->recv_id),&finished,&mpi_status);
875 					if (finished) {
876 						msg_ptr->alloced = FALSE;
877 						msg_ptr->status = COMPLETED;
878 						return(msg_ptr);
879 					} else {
880 						waiting = TRUE;
881 					}
882 				} else {
883 					printf("Major error in BMrecv_msg\n");
884 				}
885 			}
886 		}
887 	}
888 	return(NULL);
889 }
890 
891 /*+ BMfree_block_msg - Free the current blocked message, if any
892 
893 	Input Parameters:
894 .   phase_ptr - pointer to the current phase
895 
896 	Returns:
897     void
898  +*/
BMfree_block_msg(BMphase * phase_ptr)899 void BMfree_block_msg(BMphase *phase_ptr)
900 {
901 	if (phase_ptr != NULL) {
902 		if (phase_ptr->cur_recv_msg != NULL) {
903 			MSGFREERECV(phase_ptr->cur_recv_msg); CHKERR(0);
904 			phase_ptr->cur_recv_msg = NULL;
905 		}
906 	}
907 }
908 
909 /*+ BMfree_msg - Free a received message
910 
911 	Input Parameters:
912 .   msg_ptr - pointer to a message
913 
914 	Returns:
915     void
916  +*/
BMfree_msg(BMmsg * msg_ptr)917 void BMfree_msg(BMmsg *msg_ptr)
918 {
919 	if (msg_ptr->alloced) {
920 		if (msg_ptr->msg != NULL) {
921 			MSGFREERECV(msg_ptr->msg); CHKERR(0);
922 		}
923 		msg_ptr->msg = NULL;
924 		msg_ptr->alloced = FALSE;
925 	}
926 }
927