/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /******************************************************************** * * Testing thread safety in dataset creation in the HDF5 library * ------------------------------------------------------------- * * Set of tests to run multiple threads so that each creates a different * dataset. This is likely to cause race-conditions if run in a non * threadsafe environment. * * Temporary files generated: * ttsafe_dcreate.h5 * * HDF5 APIs exercised in thread: * H5Screate_simple, H5Tcopy, H5Tset_order, H5Dcreate, 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" #ifdef H5_HAVE_THREADSAFE #define FILENAME "ttsafe_dcreate.h5" #define DATASETNAME_LENGTH 10 #define NUM_THREAD 16 void *tts_dcreate_creator(void *); typedef struct thread_info { int id; hid_t file; const char *dsetname; } thread_info; /* * Set individual dataset names (rather than generated the names * automatically) */ const char *dsetname[NUM_THREAD]={ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen" }; thread_info thread_out[NUM_THREAD]; /* ********************************************************************** * Thread safe test - multiple dataset creation ********************************************************************** */ void tts_dcreate(void) { /* Pthread definitions */ pthread_t threads[NUM_THREAD]; /* HDF5 data definitions */ hid_t file, dataset; int datavalue, i; pthread_attr_t attribute; int ret; /* set pthread attribute to perform global scheduling */ ret=pthread_attr_init(&attribute); assert(ret==0); #ifdef H5_HAVE_SYSTEM_SCOPE_THREADS ret=pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); assert(ret==0); #endif /* H5_HAVE_SYSTEM_SCOPE_THREADS */ /* * Create a hdf5 file using H5F_ACC_TRUNC access, default file * creation plist and default file access plist */ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); assert(file>=0); /* simultaneously create a large number of datasets within the file */ for (i = 0; i < NUM_THREAD; i++) { thread_out[i].id = i; thread_out[i].file = file; thread_out[i].dsetname = dsetname[i]; ret=pthread_create(&threads[i], NULL, tts_dcreate_creator, &thread_out[i]); assert(ret==0); } for (i = 0;i < NUM_THREAD; i++) { ret=pthread_join(threads[i], NULL); assert(ret==0); } /* end for */ /* compare data to see if it is written correctly */ for (i = 0; i < NUM_THREAD; i++) { if ((dataset = H5Dopen(file,dsetname[i])) < 0) { TestErrPrintf("Dataset name not found - test failed\n"); H5Fclose(file); return; } else { ret=H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue); assert(ret>=0); if (datavalue != i) { TestErrPrintf("Wrong value read %d for dataset name %s - test failed\n", datavalue, dsetname[i]); H5Dclose(dataset); H5Fclose(file); return; } ret=H5Dclose(dataset); assert(ret>=0); } } /* close remaining resources */ ret=H5Fclose(file); assert(ret>=0); /* Destroy the thread attribute */ ret=pthread_attr_destroy(&attribute); assert(ret==0); } void *tts_dcreate_creator(void *_thread_data) { hid_t dataspace, dataset; herr_t ret; hsize_t dimsf[1]; /* dataset dimensions */ struct thread_info thread_data; memcpy(&thread_data,_thread_data,sizeof(struct thread_info)); /* define dataspace for dataset */ dimsf[0] = 1; dataspace = H5Screate_simple(1,dimsf,NULL); assert(dataspace>=0); /* create a new dataset within the file */ dataset = H5Dcreate(thread_data.file, thread_data.dsetname, H5T_NATIVE_INT, dataspace, H5P_DEFAULT); assert(dataset>=0); /* initialize data for dataset and write value to dataset */ ret=H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &thread_data.id); assert(ret>=0); /* close dataset and dataspace resources */ ret=H5Dclose(dataset); assert(ret>=0); ret=H5Sclose(dataspace); assert(ret>=0); return NULL; } void cleanup_dcreate(void) { HDunlink(FILENAME); } #endif /*H5_HAVE_THREADSAFE*/