Merging in latest from upstream (HDFFV/hdf5:refs/heads/develop)

* commit '73d7f7e7d37b869ce9c39cc8e648ef50d563fc93':
  Updated the threadsafety test to use error macros instead of asserts.
This commit is contained in:
Allen Byrne 2018-05-21 09:11:39 -05:00
commit 73efe72e0d
5 changed files with 250 additions and 269 deletions

View File

@ -27,14 +27,8 @@
* Each test module should include ttsafe.h and define a unique set of
* names for test files they create.
*
* BUGS/LIMITATIONS
*
* EXPORTED ROUTINES/VARIABLES:
*
*/
#include "h5test.h"
/* ANY new test needs to have a prototype in ttsafe.h */
#include "ttsafe.h"
@ -120,7 +114,7 @@ int main(int argc, char *argv[])
#else /* H5_HAVE_THREADSAFE */
printf("Most thread-safety tests skipped because THREADSAFE not enabled\n");
HDprintf("Most thread-safety tests skipped because THREADSAFE not enabled\n");
#endif /* H5_HAVE_THREADSAFE */

View File

@ -26,31 +26,15 @@
* dataset), there is a small chance that consecutive reads occur
* before a write to that shared variable.
*
* HDF5 APIs exercised in thread:
* H5Acreate2, H5Awrite, H5Aclose.
*
* Created: Oct 5 1999
* Programmer: Chee Wai LEE
*
* Modification History
* --------------------
*
* 15 May 2000, Chee Wai LEE
* Incorporated into library tests.
*
* 19 May 2000, Bill Wendling
* Changed so that it creates its own HDF5 file and removes it at cleanup
* time.
*
********************************************************************/
#include "ttsafe.h"
#ifdef H5_HAVE_THREADSAFE
#include <stdio.h>
#include <stdlib.h>
#define FILENAME "ttsafe_acreate.h5"
#define DATASETNAME "IntData"
#define NUM_THREADS 16
@ -64,20 +48,24 @@ typedef struct acreate_data_struct {
int current_index;
} ttsafe_name_data_t;
void tts_acreate(void)
void
tts_acreate(void)
{
/* Thread declarations */
H5TS_thread_t threads[NUM_THREADS];
/* HDF5 data declarations */
hid_t file, dataset;
hid_t dataspace, datatype;
hid_t attribute;
hid_t file = H5I_INVALID_HID;
hid_t dataset = H5I_INVALID_HID;
hid_t dataspace = H5I_INVALID_HID;
hid_t datatype = H5I_INVALID_HID;
hid_t attribute = H5I_INVALID_HID;
hsize_t dimsf[1]; /* dataset dimensions */
/* data declarations */
int data; /* data to write */
int buffer, ret, i;
int buffer, i;
herr_t status;
ttsafe_name_data_t *attrib_data;
@ -86,25 +74,27 @@ void tts_acreate(void)
* creation plist and default file access plist
*/
file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
assert(file>=0);
CHECK(file, H5I_INVALID_HID, "H5Fcreate");
/* create a simple dataspace for the dataset */
dimsf[0] = 1;
dataspace = H5Screate_simple(1, dimsf, NULL);
assert(dataspace>=0);
CHECK(dataspace, H5I_INVALID_HID, "H5Screate_simple");
/* define datatype for the data using native little endian integers */
datatype = H5Tcopy(H5T_NATIVE_INT);
H5Tset_order(datatype, H5T_ORDER_LE);
CHECK(datatype, H5I_INVALID_HID, "H5Tcopy");
status = H5Tset_order(datatype, H5T_ORDER_LE);
CHECK(status, FAIL, "H5Tset_order");
/* create a new dataset within the file */
dataset = H5Dcreate2(file, DATASETNAME, datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
assert(dataset >= 0);
CHECK(dataset, H5I_INVALID_HID, "H5Dcreate2");
/* initialize data for dataset and write value to dataset */
data = NUM_THREADS;
ret = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &data);
assert(ret >= 0);
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &data);
CHECK(status, FAIL, "H5Dwrite");
/*
* Simultaneously create a large number of attributes to be associated
@ -117,45 +107,46 @@ void tts_acreate(void)
attrib_data->dataspace = dataspace;
attrib_data->current_index = i;
threads[i] = H5TS_create_thread(tts_acreate_thread, NULL, attrib_data);
} /* end for */
}
for(i = 0; i < NUM_THREADS; i++) {
for(i = 0; i < NUM_THREADS; i++)
H5TS_wait_for_thread(threads[i]);
} /* end for */
/* verify the correctness of the test */
for(i = 0; i < NUM_THREADS; i++) {
attribute = H5Aopen(dataset, gen_name(i), H5P_DEFAULT);
CHECK(attribute, H5I_INVALID_HID, "H5Aopen");
if(attribute < 0)
TestErrPrintf("unable to open appropriate attribute. Test failed!\n");
else {
ret = H5Aread(attribute, H5T_NATIVE_INT, &buffer);
status = H5Aread(attribute, H5T_NATIVE_INT, &buffer);
CHECK(status, FAIL, "H5Aread");
VERIFY(buffer, i, "data values don't match");
if(ret < 0 || buffer != i)
TestErrPrintf("wrong data values. Test failed!\n");
H5Aclose(attribute);
} /* end else */
} /* end for */
status = H5Aclose(attribute);
CHECK(status, FAIL, "H5Aclose");
}
}
/* close remaining resources */
ret = H5Sclose(dataspace);
assert(ret >= 0);
ret = H5Tclose(datatype);
assert(ret >= 0);
ret = H5Dclose(dataset);
assert(ret >= 0);
ret = H5Fclose(file);
assert(ret >= 0);
}
status = H5Sclose(dataspace);
CHECK(status, FAIL, "H5Sclose");
status = H5Tclose(datatype);
CHECK(status, FAIL, "H5Sclose");
status = H5Dclose(dataset);
CHECK(status, FAIL, "H5Dclose");
status = H5Fclose(file);
CHECK(status, FAIL, "H5Fclose");
} /* end tts_acreate() */
void *tts_acreate_thread(void *client_data)
void *
tts_acreate_thread(void *client_data)
{
hid_t attribute;
hid_t attribute = H5I_INVALID_HID;
char *attribute_name;
int *attribute_data; /* data for attributes */
herr_t status;
ttsafe_name_data_t *attrib_data;
@ -166,18 +157,23 @@ void *tts_acreate_thread(void *client_data)
attribute = H5Acreate2(attrib_data->dataset, attribute_name,
attrib_data->datatype, attrib_data->dataspace,
H5P_DEFAULT, H5P_DEFAULT);
CHECK(attribute, H5I_INVALID_HID, "H5Acreate2");
/* Write data to the attribute */
attribute_data = (int *)HDmalloc(sizeof(int));
*attribute_data = attrib_data->current_index;
H5Awrite(attribute, H5T_NATIVE_INT, attribute_data);
H5Aclose(attribute);
status = H5Awrite(attribute, H5T_NATIVE_INT, attribute_data);
CHECK(status, FAIL, "H5Awrite");
status = H5Aclose(attribute);
CHECK(status, FAIL, "H5Aclose");
return NULL;
}
} /* end tts_acreate_thread() */
void cleanup_acreate(void)
void
cleanup_acreate(void)
{
HDunlink(FILENAME);
}
#endif /*H5_HAVE_THREADSAFE*/

View File

@ -27,20 +27,9 @@
* Temporary files generated:
* ttsafe_cancel.h5
*
* HDF5 APIs exercised in thread:
* H5Screate_simple, H5Tcopy, H5Tset_order, H5Dcreate2, H5Dclose,
* H5Dwrite, H5Dread, H5Diterate, H5Tclose, H5Sclose.
*
* Created: May 15 2000
* Programmer: Chee Wai LEE
*
* Modification History
* --------------------
*
* 19 May 2000, Bill Wendling
* Changed so that it creates its own HDF5 file and removes it at cleanup
* time.
*
********************************************************************/
#include "ttsafe.h"
@ -66,7 +55,8 @@ pthread_t childthread;
pthread_mutex_t mutex;
pthread_cond_t cond;
void tts_cancel(void)
void
tts_cancel(void)
{
pthread_attr_t attribute;
hid_t dataset;
@ -116,31 +106,34 @@ void tts_cancel(void)
/* Destroy the thread attribute */
ret=pthread_attr_destroy(&attribute);
assert(ret==0);
}
} /* end tts_cancel() */
void *tts_cancel_thread(void H5_ATTR_UNUSED *arg)
void *
tts_cancel_thread(void H5_ATTR_UNUSED *arg)
{
hid_t dataspace = H5I_INVALID_HID;
hid_t datatype = H5I_INVALID_HID;
hid_t dataset = H5I_INVALID_HID;
int datavalue;
int buffer;
hid_t dataspace, datatype, dataset;
hsize_t dimsf[1]; /* dataset dimensions */
cancel_cleanup_t *cleanup_structure;
int ret;
herr_t status;
/* define dataspace for dataset */
dimsf[0] = 1;
dataspace = H5Screate_simple(1, dimsf, NULL);
assert(dataspace >= 0);
CHECK(dataspace, H5I_INVALID_HID, "H5Screate_simple");
/* define datatype for the data using native little endian integers */
datatype = H5Tcopy(H5T_NATIVE_INT);
assert(datatype >= 0);
ret = H5Tset_order(datatype, H5T_ORDER_LE);
assert(ret >= 0);
CHECK(datatype, H5I_INVALID_HID, "H5Tcopy");
status = H5Tset_order(datatype, H5T_ORDER_LE);
CHECK(status, FAIL, "H5Tset_order");
/* create a new dataset within the file */
dataset = H5Dcreate2(cancel_file, DATASETNAME, datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
assert(dataset >= 0);
CHECK(dataset, H5I_INVALID_HID, "H5Dcreate2");
/* If thread is cancelled, make cleanup call */
cleanup_structure = (cancel_cleanup_t*)HDmalloc(sizeof(cancel_cleanup_t));
@ -151,25 +144,26 @@ void *tts_cancel_thread(void H5_ATTR_UNUSED *arg)
datavalue = 1;
ret=H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
assert(ret>=0);
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
CHECK(status, FAIL, "H5Dwrite");
ret=H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &buffer);
assert(ret>=0);
ret=H5Diterate(&buffer, H5T_NATIVE_INT, dataspace, tts_cancel_callback, &dataset);
assert(ret>=0);
status = H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &buffer);
CHECK(status, FAIL, "H5Dread");
status = H5Diterate(&buffer, H5T_NATIVE_INT, dataspace, tts_cancel_callback, &dataset);
CHECK(status, FAIL, "H5Diterate");
HDsleep(3);
datavalue = 100;
ret=H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
assert(ret>=0);
ret=H5Dclose(dataset);
assert(ret>=0);
ret=H5Tclose(datatype);
assert(ret>=0);
ret=H5Sclose(dataspace);
assert(ret>=0);
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
CHECK(status, FAIL, "H5Dwrite");
status = H5Dclose(dataset);
CHECK(status, FAIL, "H5Dclose");
status = H5Tclose(datatype);
CHECK(status, FAIL, "H5Tclose");
status = H5Sclose(dataspace);
CHECK(status, FAIL, "H5Sclose");
/*
* Required by pthreads. The argument 0 pops the stack but does not
@ -178,73 +172,78 @@ void *tts_cancel_thread(void H5_ATTR_UNUSED *arg)
pthread_cleanup_pop(0);
return NULL;
}
} /* end tts_cancel_thread() */
herr_t tts_cancel_callback(void *elem, hid_t H5_ATTR_UNUSED type_id, unsigned H5_ATTR_UNUSED ndim,
herr_t
tts_cancel_callback(void *elem, hid_t H5_ATTR_UNUSED type_id, unsigned H5_ATTR_UNUSED ndim,
const hsize_t H5_ATTR_UNUSED *point, void *operator_data)
{
int value = *(int *)elem;
hid_t dataset = *(hid_t *)operator_data;
int ret;
int value = *(int *)elem;
herr_t status;
tts_cancel_barrier();
HDsleep(3);
if (value != 1) {
TestErrPrintf("Error! Element value should be 1 and not %d\n", value);
return -1;
return FAIL;
}
value += 10;
ret=H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
assert(ret>=0);
return 0;
}
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
CHECK(status, FAIL, "H5Dwrite");
return SUCCEED;
} /* end tts_cancel_callback() */
/*
* Need to perform the dataset, datatype and dataspace close that was never
* performed because of thread cancellation
*/
void cancellation_cleanup(void *arg)
void
cancellation_cleanup(void *arg)
{
cancel_cleanup_t *cleanup_structure = (cancel_cleanup_t *)arg;
int ret;
herr_t status;
ret=H5Dclose(cleanup_structure->dataset);
assert(ret>=0);
ret=H5Tclose(cleanup_structure->datatype);
assert(ret>=0);
ret=H5Sclose(cleanup_structure->dataspace);
assert(ret>=0);
status = H5Dclose(cleanup_structure->dataset);
CHECK(status, FAIL, "H5Dclose");
status = H5Tclose(cleanup_structure->datatype);
CHECK(status, FAIL, "H5Tclose");
status = H5Sclose(cleanup_structure->dataspace);
CHECK(status, FAIL, "H5Sclose");
/* retained for debugging */
/* print_func("cancellation noted, cleaning up ... \n"); */
}
} /* end cancellation_cleanup() */
/*
* Artificial (and specific to this test) barrier to keep track of whether
* both the main and child threads have reached a point in the program.
*/
void tts_cancel_barrier(void)
void
tts_cancel_barrier(void)
{
static int count = 2;
int ret;
int status;
ret=pthread_mutex_lock(&mutex);
assert(ret==0);
status = pthread_mutex_lock(&mutex);
VERIFY(status, 0, "pthread_mutex_lock");
if (count != 1) {
count--;
ret=pthread_cond_wait(&cond, &mutex);
assert(ret==0);
} else {
ret=pthread_cond_signal(&cond);
assert(ret==0);
status = pthread_cond_wait(&cond, &mutex);
VERIFY(status, 0, "pthread_cond_wait");
}
else {
status = pthread_cond_signal(&cond);
VERIFY(status, 0, "pthread_cond_signal");
}
ret=pthread_mutex_unlock(&mutex);
assert(ret==0);
}
status = pthread_mutex_unlock(&mutex);
VERIFY(status, 0, "pthread_mutex_unlock");
} /* end tts_cancel_barrier() */
void cleanup_cancel(void)
{
@ -253,3 +252,4 @@ void cleanup_cancel(void)
#endif /*H5_HAVE_WIN_THREADS*/
#endif /*H5_HAVE_THREADSAFE*/

View File

@ -23,20 +23,9 @@
* Temporary files generated:
* ttsafe_dcreate.h5
*
* HDF5 APIs exercised in thread:
* H5Screate_simple, H5Tcopy, H5Tset_order, H5Dcreate2, H5Dwrite, H5Dclose,
* H5Tclose, H5Sclose.
*
* Created: Apr 28 2000
* Programmer: Chee Wai LEE
*
* Modification History
* --------------------
*
* 19 May 2000, Bill Wendling
* Changed so that it creates its own HDF5 file and removes it at cleanup
* time.
*
********************************************************************/
#include "ttsafe.h"
@ -83,16 +72,18 @@ thread_info thread_out[NUM_THREAD];
* Thread safe test - multiple dataset creation
**********************************************************************
*/
void tts_dcreate(void)
void
tts_dcreate(void)
{
/* thread definitions */
H5TS_thread_t threads[NUM_THREAD];
/* HDF5 data definitions */
hid_t file, dataset;
hid_t file = H5I_INVALID_HID;
hid_t dataset = H5I_INVALID_HID;
int datavalue, i;
H5TS_attr_t attribute;
int ret;
herr_t status;
/* set pthread attribute to perform global scheduling */
H5TS_attr_init(&attribute);
@ -107,7 +98,7 @@ void tts_dcreate(void)
* creation plist and default file access plist
*/
file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
assert(file >= 0);
CHECK(file, H5I_INVALID_HID, "H5Fcreate");
/* simultaneously create a large number of datasets within the file */
for(i = 0; i < NUM_THREAD; i++) {
@ -115,11 +106,10 @@ void tts_dcreate(void)
thread_out[i].file = file;
thread_out[i].dsetname = dsetname[i];
threads[i] = H5TS_create_thread(tts_dcreate_creator, NULL, &thread_out[i]);
} /* end for */
}
for(i = 0;i < NUM_THREAD; i++) {
for(i = 0;i < NUM_THREAD; i++)
H5TS_wait_for_thread(threads[i]);
} /* end for */
/* compare data to see if it is written correctly */
@ -129,36 +119,38 @@ void tts_dcreate(void)
H5Fclose(file);
return;
} else {
ret = H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
assert(ret >= 0);
status = H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
CHECK(status, FAIL, "H5Dread");
if(datavalue != i) {
TestErrPrintf("Wrong value read %d for dataset name %s - test failed\n",
datavalue, dsetname[i]);
ret = H5Dclose(dataset);
assert(ret >= 0);
ret = H5Fclose(file);
assert(ret >= 0);
status = H5Dclose(dataset);
CHECK(status, FAIL, "H5Dclose");
status = H5Fclose(file);
CHECK(status, FAIL, "H5Fclose");
return;
}
ret = H5Dclose(dataset);
assert(ret >= 0);
status= H5Dclose(dataset);
CHECK(status, FAIL, "H5Dclose");
}
}
/* close remaining resources */
ret = H5Fclose(file);
assert(ret >= 0);
status = H5Fclose(file);
CHECK(status, FAIL, "H5Fclose");
/* Destroy the thread attribute */
H5TS_attr_destroy(&attribute);
}
} /* end tts_dcreate() */
void *tts_dcreate_creator(void *_thread_data)
void *
tts_dcreate_creator(void *_thread_data)
{
hid_t dataspace, dataset;
herr_t ret;
hid_t dataspace = H5I_INVALID_HID;
hid_t dataset = H5I_INVALID_HID;
herr_t status;
hsize_t dimsf[1]; /* dataset dimensions */
struct thread_info thread_data;
@ -167,28 +159,29 @@ void *tts_dcreate_creator(void *_thread_data)
/* define dataspace for dataset */
dimsf[0] = 1;
dataspace = H5Screate_simple(1, dimsf, NULL);
assert(dataspace >= 0);
CHECK(dataspace, H5I_INVALID_HID, "H5Screate_simple");
/* create a new dataset within the file */
dataset = H5Dcreate2(thread_data.file, thread_data.dsetname,
H5T_NATIVE_INT, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
assert(dataset >= 0);
CHECK(dataset, H5I_INVALID_HID, "H5Dcreate2");
/* initialize data for dataset and write value to dataset */
ret = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
H5P_DEFAULT, &thread_data.id);
assert(ret >= 0);
CHECK(status, FAIL, "H5Dwrite");
/* close dataset and dataspace resources */
ret = H5Dclose(dataset);
assert(ret >= 0);
ret = H5Sclose(dataspace);
assert(ret >= 0);
status = H5Dclose(dataset);
CHECK(status, FAIL, "H5Dclose");
status = H5Sclose(dataspace);
CHECK(status, FAIL, "H5Sclose");
return NULL;
}
} /* end tts_dcreate_creator() */
void cleanup_dcreate(void)
void
cleanup_dcreate(void)
{
HDunlink(FILENAME);
}

View File

@ -25,21 +25,9 @@
*
* ttsafe_error.h5
*
* HDF5 APIs exercised in thread:
*
* H5Screate_simple, H5Tcopy, H5Tset_order, H5Dcreate2, H5Dclose,
* H5Tclose, H5Sclose.
*
* Created: Apr 28 2000
* Programmer: Chee Wai LEE
*
* Modification History
* --------------------
*
* 19 May 2000, Bill Wendling
* Modified so that it creates a unique HDF5 file and removes it on
* cleanup.
*
********************************************************************/
#include "ttsafe.h"
@ -49,181 +37,191 @@
#define FILENAME "ttsafe_error.h5"
/* Having a common dataset name is an error */
#define DATASETNAME "commonname"
#define EXPECTED_ERROR_DEPTH 8
#define WRITE_NUMBER 37
static herr_t error_callback(hid_t , void *);
static herr_t walk_error_callback(unsigned, const H5E_error2_t *, void *);
static void *tts_error_thread(void *);
/* Global variables */
hid_t error_file;
#define DATASETNAME "commonname"
#define EXPECTED_ERROR_DEPTH 7
#define WRITE_NUMBER 37
/* Typedefs */
typedef struct err_num_struct {
hid_t maj_num;
hid_t min_num;
} err_num_t;
err_num_t expected[8];
/* Global variables */
hid_t error_file_g = H5I_INVALID_HID;
int error_flag_g = 0;
int error_count_g = 0;
err_num_t expected_g[EXPECTED_ERROR_DEPTH];
H5TS_mutex_simple_t error_mutex_g;
int error_flag = 0;
int error_count = 0;
H5TS_mutex_simple_t error_mutex;
/* Prototypes */
static herr_t error_callback(hid_t , void *);
static herr_t walk_error_callback(unsigned, const H5E_error2_t *, void *);
static void *tts_error_thread(void *);
void tts_error(void)
void
tts_error(void)
{
H5TS_thread_t threads[NUM_THREAD];
H5TS_attr_t attribute;
hid_t dataset;
int value, i;
int ret;
hid_t dataset = H5I_INVALID_HID;
H5TS_thread_t threads[NUM_THREAD];
H5TS_attr_t attribute;
int value, i;
herr_t status;
/* Must initialize these at runtime */
expected[0].maj_num = H5E_DATASET;
expected[0].min_num = H5E_CANTINIT;
expected_g[0].maj_num = H5E_DATASET;
expected_g[0].min_num = H5E_CANTINIT;
expected[1].maj_num = H5E_DATASET;
expected[1].min_num = H5E_CANTINIT;
expected_g[1].maj_num = H5E_DATASET;
expected_g[1].min_num = H5E_CANTINIT;
expected[2].maj_num = H5E_LINK;
expected[2].min_num = H5E_CANTINIT;
expected_g[2].maj_num = H5E_LINK;
expected_g[2].min_num = H5E_CANTINIT;
expected[3].maj_num = H5E_LINK;
expected[3].min_num = H5E_CANTINSERT;
expected_g[3].maj_num = H5E_LINK;
expected_g[3].min_num = H5E_CANTINSERT;
expected[4].maj_num = H5E_SYM;
expected[4].min_num = H5E_NOTFOUND;
expected_g[4].maj_num = H5E_SYM;
expected_g[4].min_num = H5E_NOTFOUND;
expected[5].maj_num = H5E_SYM;
expected[5].min_num = H5E_CALLBACK;
expected_g[5].maj_num = H5E_SYM;
expected_g[5].min_num = H5E_CALLBACK;
expected[6].maj_num = H5E_LINK;
expected[6].min_num = H5E_EXISTS;
expected_g[6].maj_num = H5E_LINK;
expected_g[6].min_num = H5E_EXISTS;
/* set up mutex for global count of errors */
H5TS_mutex_init(&error_mutex);
H5TS_mutex_init(&error_mutex_g);
/* make thread scheduling global */
H5TS_attr_init(&attribute);
/* set thread scope to system */
#ifdef H5_HAVE_SYSTEM_SCOPE_THREADS
/* set thread scope to system */
H5TS_attr_setscope(&attribute, H5TS_SCOPE_SYSTEM);
#endif /* H5_HAVE_SYSTEM_SCOPE_THREADS */
/*
* Create a hdf5 file using H5F_ACC_TRUNC access, default file
/* Create a hdf5 file using H5F_ACC_TRUNC access, default file
* creation plist and default file access plist
*/
error_file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
assert(error_file>=0);
error_file_g = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
CHECK(error_file_g, H5I_INVALID_HID, "H5Fcreate");
for (i = 0; i < NUM_THREAD; i++){
for (i = 0; i < NUM_THREAD; i++)
threads[i] = H5TS_create_thread(tts_error_thread, &attribute, NULL);
}
for (i = 0; i < NUM_THREAD; i++){
for (i = 0; i < NUM_THREAD; i++)
H5TS_wait_for_thread(threads[i]);
if (error_flag_g) {
TestErrPrintf("At least one thread reported a value that was different from the exected value\n");
HDprintf("(Update this test if the error stack changed!)\n");
}
if (error_flag)
TestErrPrintf("Threads reporting different error values!\n");
if (error_count_g != NUM_THREAD - 1)
TestErrPrintf("Error: %d threads failed instead of %d\n", error_count_g, NUM_THREAD-1);
if (error_count != NUM_THREAD - 1)
TestErrPrintf("Error: %d threads failed instead of %d\n", error_count, NUM_THREAD-1);
dataset = H5Dopen2(error_file_g, DATASETNAME, H5P_DEFAULT);
CHECK(dataset, H5I_INVALID_HID, "H5Dopen2");
dataset = H5Dopen2(error_file, DATASETNAME, H5P_DEFAULT);
assert(dataset >= 0);
ret=H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
assert(ret>=0);
status = H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
CHECK(status, FAIL, "H5Dread");
if (value != WRITE_NUMBER)
TestErrPrintf("Error: Successful thread wrote value %d instead of %d\n", value, WRITE_NUMBER);
ret=H5Dclose(dataset);
assert(ret>=0);
ret=H5Fclose(error_file);
assert(ret>=0);
status = H5Dclose(dataset);
CHECK(status, FAIL, "H5Dclose");
status = H5Fclose(error_file_g);
CHECK(status, FAIL, "H5Fclose");
H5TS_attr_destroy(&attribute);
}
} /* end tts_error() */
static
void *tts_error_thread(void H5_ATTR_UNUSED *arg)
static void *
tts_error_thread(void H5_ATTR_UNUSED *arg)
{
hid_t dataspace, datatype, dataset;
hid_t dataspace = H5I_INVALID_HID;
hid_t datatype = H5I_INVALID_HID;
hid_t dataset = H5I_INVALID_HID;
hsize_t dimsf[1]; /* dataset dimensions */
H5E_auto2_t old_error_cb;
void *old_error_client_data;
int value;
int ret;
herr_t status;
/* preserve previous error stack handler */
H5Eget_auto2(H5E_DEFAULT, &old_error_cb, &old_error_client_data);
status = H5Eget_auto2(H5E_DEFAULT, &old_error_cb, &old_error_client_data);
CHECK(status, FAIL, "H5Eget_auto2");
/* set each thread's error stack handler */
H5Eset_auto2(H5E_DEFAULT, error_callback, NULL);
status = H5Eset_auto2(H5E_DEFAULT, error_callback, NULL);
CHECK(status, FAIL, "H5Eset_auto2");
/* define dataspace for dataset */
dimsf[0] = 1;
dataspace = H5Screate_simple(1, dimsf, NULL);
assert(dataspace >= 0);
CHECK(dataspace, H5I_INVALID_HID, "H5Screate_simple");
/* define datatype for the data using native little endian integers */
datatype = H5Tcopy(H5T_NATIVE_INT);
assert(datatype >= 0);
H5Tset_order(datatype, H5T_ORDER_LE);
CHECK(datatype, H5I_INVALID_HID, "H5Tcopy");
status = H5Tset_order(datatype, H5T_ORDER_LE);
CHECK(status, FAIL, "H5Tset_order");
/* create a new dataset within the file */
dataset = H5Dcreate2(error_file, DATASETNAME, datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if(dataset >= 0) { /* not an error */
dataset = H5Dcreate2(error_file_g, DATASETNAME, datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
/* Most of these will fail, so don't check the error here */
if (dataset >= 0) {
value = WRITE_NUMBER;
H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
H5Dclose(dataset);
} /* end if */
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
CHECK(status, FAIL, "H5Dwrite");
status = H5Dclose(dataset);
CHECK(status, FAIL, "H5Dclose");
}
ret = H5Tclose(datatype);
assert(ret >= 0);
ret = H5Sclose(dataspace);
assert(ret >= 0);
status = H5Tclose(datatype);
CHECK(status, FAIL, "H5Tclose");
status = H5Sclose(dataspace);
CHECK(status, FAIL, "H5Sclose");
/* turn our error stack handler off */
H5Eset_auto2(H5E_DEFAULT, old_error_cb, old_error_client_data);
status = H5Eset_auto2(H5E_DEFAULT, old_error_cb, old_error_client_data);
CHECK(status, FAIL, "H5Eset_auto2");
return NULL;
}
} /* end tts_error_thread() */
static
herr_t error_callback(hid_t H5_ATTR_UNUSED estack_id, void *client_data)
static herr_t
error_callback(hid_t H5_ATTR_UNUSED estack_id, void *client_data)
{
H5TS_mutex_lock_simple(&error_mutex);
error_count++;
H5TS_mutex_unlock_simple(&error_mutex);
H5TS_mutex_lock_simple(&error_mutex_g);
error_count_g++;
H5TS_mutex_unlock_simple(&error_mutex_g);
return H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, walk_error_callback, client_data);
}
static
herr_t walk_error_callback(unsigned n, const H5E_error2_t *err_desc, void H5_ATTR_UNUSED *client_data)
static herr_t
walk_error_callback(unsigned n, const H5E_error2_t *err_desc, void H5_ATTR_UNUSED *client_data)
{
hid_t maj_num, min_num;
hid_t maj_num = H5I_INVALID_HID;
hid_t min_num = H5I_INVALID_HID;
if (err_desc) {
maj_num = err_desc->maj_num;
min_num = err_desc->min_num;
if (n < EXPECTED_ERROR_DEPTH && maj_num == expected[n].maj_num &&
min_num == expected[n].min_num)
if (n <= EXPECTED_ERROR_DEPTH && maj_num == expected_g[n].maj_num && min_num == expected_g[n].min_num)
return SUCCEED;
}
error_flag = -1;
error_flag_g = -1;
return SUCCEED;
}
void cleanup_error(void)
void
cleanup_error(void)
{
HDunlink(FILENAME);
}