68
68
#include <stdio.h>
69
69
#include <inttypes.h>
70
70
#include <string.h>
71
+ #include <pthread.h>
71
72
72
73
static void traceme (const HDSLoc * loc , const char * expected , int explev ,
73
74
int * status );
@@ -81,6 +82,8 @@ static void testThreadSafety( const char *path, int *status );
81
82
static void * test1ThreadSafety ( void * data );
82
83
static void * test2ThreadSafety ( void * data );
83
84
static void * test3ThreadSafety ( void * data );
85
+ void showloc ( HDSLoc * loc , const char * title , int ind );
86
+ void showhan ( Handle * h , int ind );
84
87
85
88
typedef struct threadData {
86
89
HDSLoc * loc ;
@@ -90,6 +93,9 @@ typedef struct threadData {
90
93
int status ;
91
94
} threadData ;
92
95
96
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;
97
+
98
+
93
99
int main (void ) {
94
100
95
101
/* Local Variables: */
@@ -1161,7 +1167,9 @@ static void testThreadSafety( const char *path, int *status ) {
1161
1167
}
1162
1168
1163
1169
/* Attempt to access the two top-level objects in two separate threads.
1164
- Each thread attempt to lock the object read/write, but only one can win.
1170
+ Each thread attempt to lock the object read/write, but only one can
1171
+ win (assuming that the second thread starts up before the first thread
1172
+ has finished and unlocked the object).
1165
1173
The other should report an error. */
1166
1174
if ( * status == SAI__OK ) {
1167
1175
threaddata1 .id = 1 ;
@@ -1197,9 +1205,6 @@ static void testThreadSafety( const char *path, int *status ) {
1197
1205
threaddata1 .failed + threaddata2 .failed );
1198
1206
}
1199
1207
1200
- /* Unlock them now that the test has completed. */
1201
- datUnlock ( loc1 , 1 , status );
1202
- datUnlock ( loc1b , 1 , status );
1203
1208
}
1204
1209
1205
1210
/* Attempt to access the two top-level objects in two separate threads.
@@ -1236,10 +1241,6 @@ static void testThreadSafety( const char *path, int *status ) {
1236
1241
"- expected 0 to fail." , status ,
1237
1242
threaddata1 .failed + threaddata2 .failed );
1238
1243
}
1239
-
1240
- /* Unlock them now that the test has completed. */
1241
- datUnlock ( loc1 , 1 , status );
1242
- datUnlock ( loc1b , 1 , status );
1243
1244
}
1244
1245
1245
1246
/* Lock both top level locators for read-only use by the current thread. The
@@ -1410,23 +1411,42 @@ void *test2ThreadSafety( void *data ) {
1410
1411
HDSLoc * loc2 = NULL ;
1411
1412
int status = SAI__OK ;
1412
1413
int expect = tdata -> rdonly ? 3 : 1 ;
1414
+ int i , ii ;
1413
1415
1414
1416
datLock ( loc1 , 1 , tdata -> rdonly , & status );
1415
1417
if ( status == DAT__THREAD ) {
1416
1418
emsAnnul ( & status );
1417
1419
tdata -> failed = 1 ;
1418
- } else {
1420
+ } else if ( status == SAI__OK ){
1421
+
1419
1422
tdata -> failed = 0 ;
1420
1423
datFind ( loc1 , "Records" , & loc2 , & status );
1421
1424
1422
1425
/* Check the component locator is locked by the current thread. */
1423
- if ( datLocked ( loc2 , 1 , & status ) != expect && status == SAI__OK ) {
1426
+ ii = datLocked ( loc2 , 1 , & status );
1427
+ if ( ii != expect && status == SAI__OK ) {
1424
1428
status = DAT__FATAL ;
1425
1429
emsRepf ("" , "testThreadSafety error B1: loc2 is not locked by "
1426
- "current thread. " , & status );
1430
+ "current thread (%d %d). " , & status , ii , expect );
1427
1431
1428
1432
}
1429
1433
datAnnul ( & loc2 , & status );
1434
+
1435
+ /* Do something time consuming to make it likely that this thread
1436
+ will not have finished (and so unlocked the object), before the other
1437
+ thread starts. */
1438
+ for ( i = 0 ; i < 1000000 ; i ++ ) {
1439
+ ii = datLocked ( loc1 , 1 , & status );
1440
+ if ( ii != expect && status == SAI__OK ) {
1441
+ status = SAI__ERROR ;
1442
+ emsRepf ( " " , "test2ThreadSafety: Unexpected lock status %d - "
1443
+ "expected %d" , & status , ii , expect );
1444
+ break ;
1445
+ }
1446
+ }
1447
+
1448
+ datUnlock ( loc1 , 1 , & status );
1449
+
1430
1450
}
1431
1451
1432
1452
tdata -> status = status ;
@@ -1481,3 +1501,36 @@ void *test3ThreadSafety( void *data ) {
1481
1501
1482
1502
1483
1503
1504
+ /* Display information about the locs on a locator. */
1505
+ void showloc ( HDSLoc * loc , const char * title , int indent ) {
1506
+ int i ;
1507
+ pthread_mutex_lock (& mutex );
1508
+ printf ("\n" );
1509
+ for ( i = 0 ; i < indent ; i ++ ) printf (" " );
1510
+ printf ( "%s\n" , title );
1511
+ for ( i = 0 ; i < indent ; i ++ ) printf (" " );
1512
+ for ( i = 0 ; i < strlen (title ); i ++ ) printf ("-" );
1513
+ printf ("\n" );
1514
+ showhan ( loc -> handle , indent );
1515
+ pthread_mutex_unlock (& mutex );
1516
+ }
1517
+
1518
+ void showhan ( Handle * h , int indent ) {
1519
+ if ( !h ) return ;
1520
+
1521
+ int i ;
1522
+ for ( i = 0 ; i < indent ; i ++ ) printf (" " );
1523
+ printf ("'%s' " , h -> name ? h -> name : " " );
1524
+ if ( h -> nwrite_lock ) printf ("w:%zu " , h -> write_locker );
1525
+ for ( i = 0 ; i < h -> nread_lock ; i ++ ) {
1526
+ printf ("r:%zu " , h -> read_lockers [ i ] );
1527
+ }
1528
+ printf ("\n" );
1529
+
1530
+ for ( i = 0 ; i < h -> nchild ; i ++ ) {
1531
+ showhan ( h -> children [i ], indent + 3 );
1532
+ }
1533
+ }
1534
+
1535
+
1536
+
0 commit comments