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