diff --git a/src/MINT/MINT_load_data.c b/src/MINT/MINT_load_data.c index 5080be5306728a3919cd094e45689701d52dba72..f4d64272cf2919a048f5686f47c0092ad59dac87 100644 --- a/src/MINT/MINT_load_data.c +++ b/src/MINT/MINT_load_data.c @@ -22,13 +22,18 @@ void MINT_load_data(struct stardata_t * stardata) /* * Initialize MINT data */ - Pthread_lock(BINARY_C_MUTEX_MINT_LOAD); if(stardata->store->MINT_loaded == FALSE) { - MINT_load_grid(stardata); - stardata->store->MINT_loaded = TRUE; + if(Pthread_lock(BINARY_C_MUTEX_MINT_LOAD) == 0) + { + if(stardata->store->MINT_loaded == FALSE) + { + MINT_load_grid(stardata); + stardata->store->MINT_loaded = TRUE; + } + Pthread_unlock(BINARY_C_MUTEX_MINT_LOAD); + } } - Pthread_unlock(BINARY_C_MUTEX_MINT_LOAD); } } #endif // MINT diff --git a/src/binary_c_code_options.h b/src/binary_c_code_options.h index b7872869294d3ad213643d1ad2b135c9d1e274ea..25e73fea474023f5a80b1f86214e97b618d313b0 100644 --- a/src/binary_c_code_options.h +++ b/src/binary_c_code_options.h @@ -1208,8 +1208,69 @@ void Print_trace(void); * only. */ #ifdef __HAVE_LIBPTHREAD__ -#define Pthread_lock(X) pthread_mutex_lock(&stardata->store->pthread_mutexes[(X)]) -#define Pthread_unlock(X) pthread_mutex_unlock(&stardata->store->pthread_mutexes[(X)]) + +/* + * Pthread calls: use Pthread_lock and Pthread_unlock + * if you have stardata available + */ +#define Pthread_lock(X) Pthread_lock_primitive(stardata->store,(X)) +#define Pthread_unlock(X) Pthread_unlock_primitive(stardata->store,(X)) + +/* + * Otherwise use the primitives if you only have the store + */ +#define Pthread_lock_primitive(STORE,X) \ + __extension__ \ + ({ \ + const int status = \ + pthread_mutex_lock(&(STORE)->pthread_mutexes[(X)].mutex); \ + if(status!=0) \ + { \ + fprintf(stderr, \ + "\n warning: could not lock mutex %zu, error %d %s\n", \ + (size_t)(X), \ + status, \ + Mutex_error_string(status)); \ + } \ + else \ + { \ + (STORE)->pthread_mutexes[(X)].locked = TRUE; \ + } \ + status; \ + }) + +/* + * The unlock primitive does nothing if the locked Boolean + * is FALSE. This prevents us calling pthread_mutex_unlock + * on an already unlocked mutex. + */ +#define Pthread_unlock_primitive(STORE,X) \ + __extension__ \ + ({ \ + int status; \ + if((STORE)->pthread_mutexes[(X)].locked == TRUE) \ + { \ + status = \ + pthread_mutex_unlock(&(STORE)->pthread_mutexes[(X)].mutex); \ + if(status!=0) \ + { \ + fprintf(stderr, \ + "\n warning: could not unlock mutex %zu, error %d %s\n", \ + (size_t)(X), \ + status, \ + Mutex_error_string(status)); \ + } \ + else \ + { \ + (STORE)->pthread_mutexes[(X)].locked = FALSE; \ + } \ + } \ + else \ + { \ + status = 0; \ + } \ + status; \ + }) #else /* do nothing if we have no pthread */ #define Pthread_lock(X) diff --git a/src/binary_c_mutexes.def b/src/binary_c_mutexes.def index 79e16726d9fba2507a9e338c86eee6de37b4643a..0114ba17b5f10a98e57922bd77b65003204f1360 100644 --- a/src/binary_c_mutexes.def +++ b/src/binary_c_mutexes.def @@ -7,7 +7,7 @@ */ #define BINARY_C_MUTEXES_LIST \ - X(STORE_LOCK) \ + X(BUILD_STORE_LOCK) \ X(MINT_LOAD) \ X(DERIVATIVE_MAP) \ diff --git a/src/binary_c_structures.h b/src/binary_c_structures.h index ba220d4cca27ef65b3b9674476848f9f90f186cd..5420c8318d7c3374e731a078935bf301f10049b3 100644 --- a/src/binary_c_structures.h +++ b/src/binary_c_structures.h @@ -216,6 +216,11 @@ struct nuclear_network_range_t { }; #endif // NUCSYN +struct binary_c_mutex_t { + Boolean locked; + pthread_mutex_t mutex; +}; + /* * store_t is for data that cannot be altered by threads * @@ -235,7 +240,7 @@ struct store_t { //pthread_mutex_t MINT_load_lock; BINARY_C_MUTEX_MINT_LOAD_LOCK #endif // MINT //pthread_mutex_t derivative_map_lock; BINARY_C_MUTEX_DERIVATIVE_MAP_LOCK - pthread_mutex_t pthread_mutexes[BINARY_C_MUTEX_NUMBER]; + struct binary_c_mutex_t pthread_mutexes[BINARY_C_MUTEX_NUMBER]; #endif //__HAVE_LIBPTHREAD__ #ifdef NUCSYN Nuclear_mass * mnuc; /* Nuclear masses */ diff --git a/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c b/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c index 665083ae6d9b142f00af857481fc28381da88d03..f7f6c5afdb4073aadf7a49b8a0e62796d9678a59 100644 --- a/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c +++ b/src/binary_star_functions/apply_stellar_mass_and_angular_momentum_derivatives.c @@ -128,30 +128,33 @@ Boolean apply_stellar_mass_and_angular_momentum_derivatives(struct stardata_t * static Reject_index reject_map[NUMBER_OF_CORES]; /* first time setup */ - if(core_map[0] == DUMMY_DERIVATIVE && - Pthread_lock(BINARY_C_MUTEX_DERIVATIVE_MAP) == 0 && - core_map[0] == DUMMY_DERIVATIVE) + if(core_map[0] == DUMMY_DERIVATIVE) { + if(Pthread_lock(BINARY_C_MUTEX_DERIVATIVE_MAP) == 0) + { + if(core_map[0] == DUMMY_DERIVATIVE) + { #undef X #include "binary_c_stellar_cores.h" -#define X(TYPE, \ - LONG_LABEL, \ - SHORT_LABEL, \ - DERIV) \ - if(TYPE != CORE_NONE && TYPE != NUMBER_OF_CORES) \ - { \ - core_map[TYPE] = \ - DERIVATIVE_STELLAR_ ## DERIV ## _CORE_MASS; \ - reject_map[TYPE] = \ - REJECT_STELLAR_ ## DERIV ## _CORE; \ - } +#define X(TYPE, \ + LONG_LABEL, \ + SHORT_LABEL, \ + DERIV) \ + if(TYPE != CORE_NONE && TYPE != NUMBER_OF_CORES) \ + { \ + core_map[TYPE] = \ + DERIVATIVE_STELLAR_ ## DERIV ## _CORE_MASS; \ + reject_map[TYPE] = \ + REJECT_STELLAR_ ## DERIV ## _CORE; \ + } - BINARY_C_STELLAR_CORE_LIST; + BINARY_C_STELLAR_CORE_LIST; #undef X + } + Pthread_unlock(BINARY_C_MUTEX_DERIVATIVE_MAP); + } } - Pthread_unlock(BINARY_C_MUTEX_DERIVATIVE_MAP); - if(core_map[0] == DUMMY_DERIVATIVE) { diff --git a/src/memory/build_store_contents.c b/src/memory/build_store_contents.c index 18822719983d5dd8ffbffdac7e6a2bd3fc8fa24c..71b95c8ac04122a129669510b013e98e76ebd1ff 100644 --- a/src/memory/build_store_contents.c +++ b/src/memory/build_store_contents.c @@ -28,8 +28,9 @@ void build_store_contents(struct store_t * RESTRICT const store) */ for(size_t i=0; i<BINARY_C_MUTEX_NUMBER; i++) { + store->pthread_mutexes[i].locked = FALSE; const int init_status = - pthread_mutex_init(&store->pthread_mutexes[i], + pthread_mutex_init(&store->pthread_mutexes[i].mutex, NULL); if(init_status != 0) { @@ -42,18 +43,11 @@ void build_store_contents(struct store_t * RESTRICT const store) } } - { - const int lock_status = - pthread_mutex_lock(&store->pthread_mutexes[BINARY_C_MUTEX_STORE_LOCK]); - if(lock_status != 0) - { - fprintf(stderr, - "\n failed to lock mutex BINARY_C_MUTEX_STORE_LOCK == %d, error %d %s.\n", - BINARY_C_MUTEX_STORE_LOCK, - lock_status, - Mutex_error_string(lock_status)); - } - } + + /* + * Lock the store creation mutex + */ + Pthread_lock_primitive(store,BINARY_C_MUTEX_BUILD_STORE_LOCK); #endif//__HAVE_LIBPTHREAD__ @@ -136,18 +130,9 @@ void build_store_contents(struct store_t * RESTRICT const store) store->built = TRUE; store->debug_stopping = 0; } -#ifdef __HAVE_LIBPTHREAD__ - { - const int unlock_status = - pthread_mutex_unlock(&store->pthread_mutexes[BINARY_C_MUTEX_STORE_LOCK]); - if(unlock_status != 0) - { - fprintf(stderr, - "\n failed to unlock mutex BINARY_C_MUTEX_STORE_LOCK == %d, error %d %s.\n", - BINARY_C_MUTEX_STORE_LOCK, - unlock_status, - Mutex_error_string(unlock_status)); - } - } -#endif//__HAVE_PTHREAD__ + + /* + * Lock the store creation mutex + */ + Pthread_unlock_primitive(store,BINARY_C_MUTEX_BUILD_STORE_LOCK); } diff --git a/src/memory/free_store_contents.c b/src/memory/free_store_contents.c index c0349192fa1793e85638e7b6c707050dd3441906..1677f16c21628746341dfb2be56b924c144e908c 100644 --- a/src/memory/free_store_contents.c +++ b/src/memory/free_store_contents.c @@ -87,28 +87,19 @@ void free_store_contents(struct store_t * RESTRICT const store) #ifdef __HAVE_LIBPTHREAD__ -#define Mutex_error_string(X) \ - (X) == EINVAL ? "EINVAL" : \ - (X) == EBUSY ? "EBUSY" : \ - (X) == EAGAIN ? "EAGAIN" : \ - (X) == EPERM ? "EPERM" : \ - (X) == EDEADLK ? "EDEADLK" : \ - "unknown" - /* * Make mutexes for later locking */ for(size_t i=0; i<BINARY_C_MUTEX_NUMBER; i++) { - const int unlock_status = pthread_mutex_unlock(&store->pthread_mutexes[i]); - if(unlock_status != 0) - { - fprintf(stderr,"\n mutex %zu unlock failed with error %d %s\n", - i, - unlock_status, - Mutex_error_string(unlock_status)); - } - const int destroy_status = pthread_mutex_destroy(&store->pthread_mutexes[i]); + /* + * First, we try to get the lock ourselves. We have + * to do this otherwise the mutex is unlocked when + * it is already unlocked. This causes errors. + */ + Pthread_unlock_primitive(store,i); + const int destroy_status = + pthread_mutex_destroy(&store->pthread_mutexes[i].mutex); if(destroy_status != 0) { fprintf(stderr,