|
11 | 11 | * Copyright (c) 2004-2006 The Regents of the University of California. |
12 | 12 | * All rights reserved. |
13 | 13 | * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. |
14 | | - * Copyright (c) 2013 Los Alamos National Security, LLC. All rights |
| 14 | + * Copyright (c) 2013-2016 Los Alamos National Security, LLC. All rights |
15 | 15 | * reserved. |
16 | 16 | * Copyright (c) 2015 Research Organization for Information Science |
17 | 17 | * and Technology (RIST). All rights reserved. |
@@ -481,39 +481,63 @@ int ompi_datatype_get_pack_description( ompi_datatype_t* datatype, |
481 | 481 | { |
482 | 482 | ompi_datatype_args_t* args = (ompi_datatype_args_t*)datatype->args; |
483 | 483 | int next_index = OMPI_DATATYPE_MAX_PREDEFINED; |
| 484 | + void *packed_description = datatype->packed_description; |
484 | 485 | void* recursive_buffer; |
485 | 486 |
|
486 | | - if( NULL == datatype->packed_description ) { |
487 | | - if( ompi_datatype_is_predefined(datatype) ) { |
488 | | - datatype->packed_description = malloc(2 * sizeof(int)); |
489 | | - } else if( NULL == args ) { |
490 | | - return OMPI_ERROR; |
| 487 | + if (NULL == packed_description) { |
| 488 | + if (opal_atomic_cmpset (&datatype->packed_description, NULL, (void *) 1)) { |
| 489 | + if( ompi_datatype_is_predefined(datatype) ) { |
| 490 | + packed_description = malloc(2 * sizeof(int)); |
| 491 | + } else if( NULL == args ) { |
| 492 | + return OMPI_ERROR; |
| 493 | + } else { |
| 494 | + packed_description = malloc(args->total_pack_size); |
| 495 | + } |
| 496 | + recursive_buffer = packed_description; |
| 497 | + __ompi_datatype_pack_description( datatype, &recursive_buffer, &next_index ); |
| 498 | + |
| 499 | + if (!ompi_datatype_is_predefined(datatype)) { |
| 500 | + args->total_pack_size = (uintptr_t)((char*)recursive_buffer - (char *) packed_description); |
| 501 | + } |
| 502 | + |
| 503 | + opal_atomic_wmb (); |
| 504 | + datatype->packed_description = packed_description; |
491 | 505 | } else { |
492 | | - datatype->packed_description = malloc(args->total_pack_size); |
| 506 | + /* another thread beat us to it */ |
| 507 | + packed_description = datatype->packed_description; |
493 | 508 | } |
494 | | - recursive_buffer = datatype->packed_description; |
495 | | - __ompi_datatype_pack_description( datatype, &recursive_buffer, &next_index ); |
496 | | - if( !ompi_datatype_is_predefined(datatype) ) { |
497 | | - args->total_pack_size = (uintptr_t)((char*)recursive_buffer - (char*)datatype->packed_description); |
| 509 | + } |
| 510 | + |
| 511 | + if ((void *) 1 == packed_description) { |
| 512 | + struct timespec interval = {.tv_sec = 0, .tv_nsec = 1000}; |
| 513 | + |
| 514 | + /* wait until the packed description is updated */ |
| 515 | + while ((void *) 1 == datatype->packed_description) { |
| 516 | + nanosleep (&interval, NULL); |
498 | 517 | } |
| 518 | + |
| 519 | + packed_description = datatype->packed_description; |
499 | 520 | } |
500 | 521 |
|
501 | | - *packed_buffer = (const void*)datatype->packed_description; |
| 522 | + *packed_buffer = (const void *) packed_description; |
502 | 523 | return OMPI_SUCCESS; |
503 | 524 | } |
504 | 525 |
|
505 | 526 | size_t ompi_datatype_pack_description_length( ompi_datatype_t* datatype ) |
506 | 527 | { |
| 528 | + void *packed_description = datatype->packed_description; |
| 529 | + |
507 | 530 | if( ompi_datatype_is_predefined(datatype) ) { |
508 | 531 | return 2 * sizeof(int); |
509 | 532 | } |
510 | | - if( NULL == datatype->packed_description ) { |
| 533 | + if( NULL == packed_description || (void *) 1 == packed_description) { |
511 | 534 | const void* buf; |
512 | 535 | int rc; |
513 | 536 |
|
514 | 537 | rc = ompi_datatype_get_pack_description(datatype, &buf); |
515 | | - if( OMPI_SUCCESS != rc ) |
| 538 | + if( OMPI_SUCCESS != rc ) { |
516 | 539 | return 0; |
| 540 | + } |
517 | 541 | } |
518 | 542 | assert( NULL != (ompi_datatype_args_t*)datatype->args ); |
519 | 543 | assert( NULL != (ompi_datatype_args_t*)datatype->packed_description ); |
|
0 commit comments