mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-11 16:01:00 +08:00
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:
commit
73efe72e0d
@ -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 */
|
||||
|
||||
|
@ -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*/
|
||||
|
||||
|
@ -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*/
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user