Skip to content

Commit f71f261

Browse files
author
David Berry
committed
Make hds-v5 thread safe
1) Guard global or static data using mutexes 2) Add object locking via new functions datLock, datUnlock and datLocked. For HDS-V5 to be thread safe, HDF5 must be configured with --enable-threadsafe.
1 parent dfdaf9c commit f71f261

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1196
-228
lines changed

Makefile.am

+8
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ datType.c \
106106
datUnmap.c \
107107
datValid.c \
108108
datVec.c \
109+
datLock.c \
110+
datLocked.c \
111+
datUnlock.c \
109112
hdsCopy.c \
110113
hdsErase.c \
111114
hdsEwild.c \
@@ -143,8 +146,10 @@ dat1CvtChar.c \
143146
dat1CvtLogical.c \
144147
dat1DumpLoc.c \
145148
dat1EncodeSubscript.c \
149+
dat1EraseHandle.c \
146150
dat1ExportDims.c \
147151
dat1FixNameCell.c \
152+
dat1FreeHandle.c \
148153
dat1FreeLoc.c \
149154
dat1GetAttr.c \
150155
dat1GetAttrBool.c \
@@ -157,6 +162,9 @@ dat1Getenv.c \
157162
dat1GetFullName.c \
158163
dat1GetParentID.c \
159164
dat1GetStructureDims.c \
165+
dat1Handle.c \
166+
dat1HandleLock.c \
167+
dat1HandleMsg.c \
160168
dat1H5EtoEMS.c \
161169
dat1ImportDims.c \
162170
dat1ImportFloc.c \

dat1.h

+32-1
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,31 @@ typedef enum {
138138
#define HDS__ATTR_ROOT_NAME "HDS_ROOT_NAME"
139139
#define HDS__ATTR_ROOT_PRIMITIVE "HDS_ROOT_IS_PRIMITIVE"
140140

141+
/* This structure contains information about an HDF5 object (group or
142+
dataset) that is common to all the locators that refer to the object. */
143+
typedef struct Handle {
144+
char locked; /* Non-zero if the HDF object is currently locked for
145+
access by a single thread. Zero if the object is
146+
unlocked. */
147+
pthread_t locker; /* Id for the thread that has locked the object (if
148+
any) */
149+
struct Handle *parent; /* Pointer to Handle describing the parent object */
150+
struct Handle **children; /* Pointer to array holding pointers to Handles
151+
for any known child objects */
152+
int nchild; /* The length of the "children" array */
153+
char *name; /* Name (cleaned) of the HDF object within its parent */
154+
pthread_mutex_t mutex2; /* Guards access to the values in the handle */
155+
156+
} Handle;
157+
158+
/* Define functions to lock and unlock a Handle's mutex. */
159+
#define DAT_LOCK_MUTEX2(han) pthread_mutex_lock( &((han)->mutex2) )
160+
#define DAT_UNLOCK_MUTEX2(han) pthread_mutex_unlock( &((han)->mutex2) )
161+
162+
141163
/* Private definition of the HDS locator struct */
142164
typedef struct LOC {
165+
Handle *handle; /* Structure holding fixed info for the HDF object */
143166
int hds_version; /* Implementation version number. Always 5 at the moment. */
144167
void *pntr; /* Pointer to memory mapped data array [datMap only] */
145168
void *regpntr; /* Pointer that was registered with CNF */
@@ -345,6 +368,9 @@ hds1CountFiles();
345368
int
346369
hds1CountLocators( size_t ncomp, char **comps, hdsbool_t skip_scratch_root, int * status );
347370

371+
Handle *
372+
hds1FindHandle( hid_t file_id, int *status );
373+
348374
void
349375
dat1SetAttrString( hid_t obj_id, const char * attrname,
350376
const char * value, int * status );
@@ -403,7 +429,12 @@ dat1GetStructureDims( const HDSLoc * locator, int maxdims, hdsdim dims[], int *s
403429
hdsbool_t
404430
dat1NeedsRootName( hid_t objid, hdsbool_t wantprim, char * rootname, size_t rootnamelen, int * status );
405431

406-
int dat1ValidateLocator( const HDSLoc *loc, int *status );
432+
Handle *dat1Handle( const HDSLoc *parent_loc, const char *name, int * status );
433+
Handle *dat1EraseHandle( Handle *parent, const char *name, int * status );
434+
Handle *dat1FreeHandle( Handle *handle );
435+
int dat1ValidateLocator( int checklock, const HDSLoc *loc, int *status );
436+
int dat1HandleLock( Handle *handle, int oper, int recurs, int *status );
437+
void dat1HandleMsg( const char *token, const Handle *handle );
407438

408439
/* DAT1_H_INCLUDED */
409440
#endif

dat1DumpLoc.c

+30-7
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,14 @@
7373
#include "sae_par.h"
7474

7575
static void dump_dataspace_info( hid_t dataspace_id, const char * label, int *status);
76+
static void dump_handle( const HDSLoc *loc, int *status );
7677

7778
void dat1DumpLoc( const HDSLoc* locator, int * status ) {
7879
char * name_str = NULL;
7980
char * file_str = NULL;
8081
ssize_t ll;
8182
hid_t objid = 0;
8283
hid_t dspace_id = 0;
83-
hdsdim lower[DAT__MXDIM];
84-
hdsdim upper[DAT__MXDIM];
85-
hdsbool_t issubset;
86-
int actdim;
87-
hssize_t nelem;
88-
int i;
8984

9085
if (*status != SAI__OK) return;
9186

@@ -107,7 +102,7 @@ void dat1DumpLoc( const HDSLoc* locator, int * status ) {
107102
(locator->uses_true_mmap ? "file" : "memory"));
108103
printf("- Is sliced: %d; Primary: %s; Group name: '%s'\n", locator->isslice,
109104
(locator->isprimary ? "yes" : "no"), locator->grpname);
110-
printf("- Is a discontiguous slice: %d\n", (locator->isdiscont ? "yes" : "no") );
105+
printf("- Is a discontiguous slice: %s\n", (locator->isdiscont ? "yes" : "no") );
111106

112107
if (locator->dataspace_id > 0) {
113108
dump_dataspace_info( locator->dataspace_id, "Locator associated", status);
@@ -116,6 +111,8 @@ void dat1DumpLoc( const HDSLoc* locator, int * status ) {
116111
H5Sclose( dspace_id );
117112
}
118113

114+
dump_handle( locator, status );
115+
119116
if (file_str) MEM_FREE(file_str);
120117
if (name_str) MEM_FREE(name_str);
121118
return;
@@ -189,3 +186,29 @@ static void dump_dataspace_info( hid_t dataspace_id, const char * label, int *st
189186
if (blockbuf) MEM_FREE(blockbuf);
190187
return;
191188
}
189+
190+
static void dump_handle( const HDSLoc *loc, int *status ){
191+
Handle *handle;
192+
const char *name;
193+
194+
if( *status != SAI__OK || !loc ) return;
195+
196+
printf("Handle: ");
197+
198+
handle = loc->handle;
199+
while( handle ) {
200+
name = handle->name ? handle->name : "<>";
201+
printf("%s(%p)", name, handle );
202+
handle = handle->parent;
203+
if( handle ) printf("." );
204+
}
205+
206+
printf("\n" );
207+
208+
}
209+
210+
211+
212+
213+
214+

dat1GetBounds.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,7 @@ dat1GetBounds( const HDSLoc * locator, hdsdim lower[DAT__MXDIM],
133133

134134
/* If we are using datSlice then there should be one (and only one) hyperslab
135135
for the dataspace and we need to handle that. Should be same dimensionality
136-
as above. Negative number indicates there were no hyperslabs. We need to
137-
check that there is a hyperslab first because H5Sget_select_hyper_nblocks
138-
will report an error if there is no hyperslab selection. */
136+
as above. Negative number indicates there were no hyperslabs. */
139137
if( H5Sget_select_type( locator->dataspace_id ) == H5S_SEL_HYPERSLABS ) {
140138
nblocks = H5Sget_select_hyper_nblocks( locator->dataspace_id );
141139
} else {

dat1InitHDF5.c

+13-3
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,26 @@
7777
*/
7878

7979
#include "hdf5.h"
80+
#include <pthread.h>
81+
82+
static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
8083

8184
void dat1InitHDF5(void) {
8285
static int DONE = 0;
8386

84-
if (DONE) return;
87+
/* Serialise entry to this function by locking a mutex. */
88+
pthread_mutex_lock( &mutex1 );
89+
90+
/* Return immediately if HDF5 has already been initialised for use with HDS. */
91+
if(! DONE ) {
8592

8693
/* Disable automatic printing of HDF5 errors */
87-
H5Eset_auto( H5P_DEFAULT, NULL, NULL );
94+
H5Eset_auto( H5P_DEFAULT, NULL, NULL );
8895

96+
DONE = 1;
97+
}
8998

90-
DONE = 1;
99+
/* Unlock the mutex so that any waiting threads can call this function. */
100+
pthread_mutex_unlock( &mutex1 );
91101

92102
}

dat1New.c

+1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ dat1New( const HDSLoc *locator,
239239
if (*status == SAI__OK) {
240240
HDSLoc *thisloc = dat1AllocLoc( status );
241241
if (*status == SAI__OK) {
242+
thisloc->handle = dat1Handle( locator, cleanname, status );
242243
thisloc->dataset_id = dataset_id;
243244
thisloc->group_id = group_id;
244245
thisloc->dataspace_id = dataspace_id;

dat1TypeInfo.c

+9
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
*-
7777
*/
7878

79+
#include <pthread.h>
80+
7981
#include "hdf5.h"
8082

8183
#include "ems.h"
@@ -86,12 +88,17 @@
8688

8789
#include "prm_par.h"
8890

91+
/* A mutex used to serialis entry to this function so that multiple
92+
threads do not try to acces the static data simultaneously. */
93+
static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
94+
8995
HdsTypeInfo *
9096
dat1TypeInfo( void ) {
9197

9298
static int FILLED = 0;
9399
static HdsTypeInfo typeinfo;
94100

101+
pthread_mutex_lock( &mutex1 );
95102
if (!FILLED) {
96103
size_t i;
97104
unsigned char * ptr;
@@ -118,5 +125,7 @@ dat1TypeInfo( void ) {
118125

119126
FILLED = 1;
120127
}
128+
pthread_mutex_unlock( &mutex1 );
129+
121130
return &typeinfo;
122131
}

dat1ValidateLocator.c

+32-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
* Library routine
1414
1515
* Invocation:
16-
* dat1ValidateLocator( const HDSLoc *loc, int * status );
16+
* dat1ValidateLocator( int checklock, const HDSLoc *loc, int * status );
1717
1818
* Arguments:
19+
* checklock = int (Given)
20+
* If non-zero, an error is reported if the supplied locator is not
21+
* locked by the current thread (see datLock). This check is not
22+
* performed if "checklock" is zero.
1923
* loc = HDSLoc * (Given)
2024
* Locator to validate.
2125
* status = int* (Given and Returned)
@@ -61,18 +65,20 @@
6165
*-
6266
*/
6367

68+
#include <pthread.h>
6469
#include "sae_par.h"
6570
#include "ems.h"
6671
#include "hds.h"
6772
#include "dat1.h"
6873
#include "dat_err.h"
6974

70-
int dat1ValidateLocator( const HDSLoc *loc, int * status ) {
75+
int dat1ValidateLocator( int checklock, const HDSLoc *loc, int * status ) {
7176

7277
/* Local Variables; */
7378
int valid;
7479

75-
/* If the locator is not valid, report an error. */
80+
/* If the locator has been annulled (e.g. due to the container file being
81+
closed when the last primary locator was annulled), report an error. */
7682
datValid( loc, &valid, status );
7783
if( !valid && *status == SAI__OK ) {
7884
*status = DAT__LOCIN;
@@ -81,6 +87,29 @@ int dat1ValidateLocator( const HDSLoc *loc, int * status ) {
8187
status );
8288
}
8389

90+
/* Report an error if there is no handle in the locator. */
91+
if( loc && !loc->handle && *status == SAI__OK ) {
92+
*status = DAT__FATAL;
93+
datMsg( "O", loc );
94+
emsRep( " ", "The supplied HDS locator for '^O' has no handle (programming error).",
95+
status );
96+
}
97+
98+
/* If required, check that the object is locked by the current thread.
99+
Do not check any child objects as these wil be checked if and when
100+
accessed. */
101+
if( checklock && *status == SAI__OK ) {
102+
if( dat1HandleLock( loc->handle, 1, 0, status ) != 1 &&
103+
*status == SAI__OK ) {
104+
*status = DAT__THREAD;
105+
datMsg( "O", loc );
106+
emsRep( " ", "The supplied HDS locator for '^O' cannot be used.",
107+
status );
108+
emsRep( " ", "It has not been locked for use by the current thread "
109+
"(programming error).", status );
110+
}
111+
}
112+
84113
return *status;
85114

86115
}

datAlter.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ datAlter( HDSLoc *locator, int ndim, const hdsdim dims[], int *status) {
126126
if (*status != SAI__OK) return *status;
127127

128128
/* Validate input locator. */
129-
dat1ValidateLocator( locator, status );
129+
dat1ValidateLocator( 1, locator, status );
130130

131131
if (locator->vectorized) {
132132
*status = DAT__OBJIN;

datBasic.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ datBasic(const HDSLoc *locator, const char *mode_c, unsigned char **pntr,
105105
if (*status == SAI__OK) return *status;
106106

107107
/* Validate input locator. */
108-
dat1ValidateLocator( locator, status );
108+
dat1ValidateLocator( 1, locator, status );
109109

110110
*status = SAI__ERROR;
111111
emsRep("datBasic", "datBasic is not available in HDF5 interface",

datCcopy.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ datCcopy(const HDSLoc *locator1, const HDSLoc *locator2, const char *name,
105105
if (*status != SAI__OK) return *status;
106106

107107
/* Validate input locators. */
108-
dat1ValidateLocator( locator1, status );
109-
dat1ValidateLocator( locator2, status );
108+
dat1ValidateLocator( 1, locator1, status );
109+
dat1ValidateLocator( 1, locator2, status );
110110

111111
if (dat1IsStructure(locator1, status)) {
112112

datCell.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ datCell(const HDSLoc *locator1, int ndim, const hdsdim subs[],
112112
if (*status != SAI__OK) return *status;
113113

114114
/* Validate input locator. */
115-
dat1ValidateLocator( locator1, status );
115+
dat1ValidateLocator( 1, locator1, status );
116116

117117
datName(locator1, namestr, status );
118118

@@ -203,6 +203,9 @@ datCell(const HDSLoc *locator1, int ndim, const hdsdim subs[],
203203
thisloc = dat1AllocLoc( status );
204204

205205
if (*status == SAI__OK) {
206+
/* Handle for cell's data object */
207+
thisloc->handle = dat1Handle( locator1, cellname, status );
208+
206209
thisloc->group_id = group_id;
207210
/* Secondary locator by definition */
208211
thisloc->file_id = locator1->file_id;

datClen.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ datClen( const HDSLoc * locator, size_t * clen, int * status ) {
116116
if (*status != SAI__OK) return *status;
117117

118118
/* Validate input locator. */
119-
dat1ValidateLocator( locator, status );
119+
dat1ValidateLocator( 1, locator, status );
120120

121121
if (locator->dataset_id <= 0) {
122122
*status = DAT__OBJIN;

datClone.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ datClone(const HDSLoc *locator1, HDSLoc **locator2, int *status) {
106106
if (*status != SAI__OK) return *status;
107107

108108
/* Validate input locator. */
109-
dat1ValidateLocator( locator1, status );
109+
dat1ValidateLocator( 1, locator1, status );
110110

111111
clonedloc = dat1AllocLoc( status );
112112
if (*status != SAI__OK) goto CLEANUP;
@@ -146,6 +146,7 @@ datClone(const HDSLoc *locator1, HDSLoc **locator2, int *status) {
146146
clonedloc->isslice = locator1->isslice;
147147
clonedloc->iscell = locator1->iscell;
148148
clonedloc->isdiscont = locator1->isdiscont;
149+
clonedloc->handle = locator1->handle;
149150

150151
CLEANUP:
151152
if (*status != SAI__OK) {

datCoerc.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ int datCoerc( const HDSLoc *locator1, int ndim, HDSLoc **locator2, int *status)
106106
if (*status != SAI__OK) return *status;
107107

108108
/* Validate input locator. */
109-
dat1ValidateLocator( locator1, status );
109+
dat1ValidateLocator( 1, locator1, status );
110110

111111
*status = DAT__FATAL;
112112
emsRep("datCoerc", "datCoerc: Not yet implemented for HDF5",

datConv.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ datConv(const HDSLoc *locator, const char *type_str, hdsbool_t *conv,
102102
if (*status != SAI__OK) return *status;
103103

104104
/* Validate input locator. */
105-
dat1ValidateLocator( locator, status );
105+
dat1ValidateLocator( 1, locator, status );
106106

107107
*status = DAT__FATAL;
108108
emsRep("datConv", "datConv: Obsolete routine. Do not use",

0 commit comments

Comments
 (0)