1
1

pmix2x/class: correctly handle concurrent class initialization

(back-ported from upstream commit pmix/master@ceedbd67fd)

Signed-off-by: Gilles Gouaillardet <gilles@rist.or.jp>
Этот коммит содержится в:
Gilles Gouaillardet 2016-12-15 09:05:16 +09:00
родитель 15b6eaf2d4
Коммит a019095b84
2 изменённых файлов: 32 добавлений и 4 удалений

Просмотреть файл

@ -10,6 +10,8 @@
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2014-2016 Intel, Inc. All rights reserved.
* Copyright (c) 2016 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -28,6 +30,7 @@
#include <stdio.h>
#include <pthread.h>
#include "src/class/pmix_object.h"
@ -48,9 +51,12 @@ pmix_class_t pmix_object_t_class = {
sizeof(pmix_object_t) /* size of the pmix object */
};
int pmix_class_init_epoch = 1;
/*
* Local variables
*/
static pthread_mutex_t class_mutex = PTHREAD_MUTEX_INITIALIZER;
static void** classes = NULL;
static int num_classes = 0;
static int max_classes = 0;
@ -81,7 +87,17 @@ void pmix_class_initialize(pmix_class_t *cls)
/* Check to see if anyone initialized
this class before we got a chance to */
if (1 == cls->cls_initialized) {
if (pmix_class_init_epoch == cls->cls_initialized) {
return;
}
pthread_mutex_lock(&class_mutex);
/* If another thread initializing this same class came in at
roughly the same time, it may have gotten the lock and
initialized. So check again. */
if (pmix_class_init_epoch == cls->cls_initialized) {
pthread_mutex_unlock(&class_mutex);
return;
}
@ -141,10 +157,12 @@ void pmix_class_initialize(pmix_class_t *cls)
}
*cls_destruct_array = NULL; /* end marker for the destructors */
cls->cls_initialized = 1;
cls->cls_initialized = pmix_class_init_epoch;
save_class(cls);
/* All done */
pthread_mutex_unlock(&class_mutex);
}
@ -155,6 +173,12 @@ int pmix_class_finalize(void)
{
int i;
if (INT_MAX == pmix_class_init_epoch) {
pmix_class_init_epoch = 1;
} else {
pmix_class_init_epoch++;
}
if (NULL != classes) {
for (i = 0; i < num_classes; ++i) {
if (NULL != classes[i]) {

Просмотреть файл

@ -12,6 +12,8 @@
* All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2013-2016 Intel, Inc. All rights reserved.
* Copyright (c) 2016 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -163,6 +165,8 @@ struct pmix_class_t {
size_t cls_sizeof; /**< size of an object instance */
};
extern int pmix_class_init_epoch;
/**
* For static initializations of OBJects.
*
@ -347,7 +351,7 @@ do { \
#define PMIX_CONSTRUCT_INTERNAL(object, type) \
do { \
PMIX_SET_MAGIC_ID((object), PMIX_OBJ_MAGIC_ID); \
if (0 == (type)->cls_initialized) { \
if (pmix_class_init_epoch != (type)->cls_initialized) { \
pmix_class_initialize((type)); \
} \
((pmix_object_t *) (object))->obj_class = (type); \
@ -467,7 +471,7 @@ static inline pmix_object_t *pmix_obj_new(pmix_class_t * cls)
assert(cls->cls_sizeof >= sizeof(pmix_object_t));
object = (pmix_object_t *) malloc(cls->cls_sizeof);
if (0 == cls->cls_initialized) {
if (pmix_class_init_epoch != cls->cls_initialized) {
pmix_class_initialize(cls);
}
if (NULL != object) {