|
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