aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hrs-scaling.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/src/hrs-scaling.c b/src/hrs-scaling.c
index a4c9626e..200a90ab 100644
--- a/src/hrs-scaling.c
+++ b/src/hrs-scaling.c
@@ -189,7 +189,7 @@ static double iterate_scale(Crystal **crystals, int n, RefList *reference,
struct merge_queue_args
{
RefList *full;
- pthread_mutex_t full_lock;
+ pthread_rwlock_t full_lock;
Crystal **crystals;
int n_started;
PartialityModel pmodel;
@@ -200,7 +200,7 @@ struct merge_worker_args
{
Crystal *crystal;
RefList *full;
- pthread_mutex_t *full_lock;
+ pthread_rwlock_t *full_lock;
PartialityModel pmodel;
};
@@ -245,22 +245,45 @@ static void run_merge_job(void *vwargs, int cookie)
if ( !get_scalable(refl) ) continue;
get_indices(refl, &h, &k, &l);
- /* FIXME (somehow): Huge contention on this lock */
- pthread_mutex_lock(wargs->full_lock);
+ pthread_rwlock_rdlock(wargs->full_lock);
f = find_refl(full, h, k, l);
if ( f == NULL ) {
- f = add_refl(full, h, k, l);
- lock_reflection(f);
- pthread_mutex_unlock(wargs->full_lock);
- num = 0.0;
- den = 0.0;
- red = 0;
+
+ /* Swap read lock for write lock */
+ pthread_rwlock_unlock(wargs->full_lock);
+ pthread_rwlock_wrlock(wargs->full_lock);
+
+ /* In the gap between the unlock and the wrlock, the
+ * reflection might have been created by another thread.
+ * So, we must check again */
+ f = find_refl(full, h, k, l);
+ if ( f == NULL ) {
+ f = add_refl(full, h, k, l);
+ lock_reflection(f);
+ pthread_rwlock_unlock(wargs->full_lock);
+ num = 0.0;
+ den = 0.0;
+ red = 0;
+
+ } else {
+
+ /* Someone else created it */
+ lock_reflection(f);
+ pthread_rwlock_unlock(wargs->full_lock);
+ num = get_temp1(f);
+ den = get_temp2(f);
+ red = get_redundancy(f);
+
+ }
+
} else {
+
lock_reflection(f);
- pthread_mutex_unlock(wargs->full_lock);
+ pthread_rwlock_unlock(wargs->full_lock);
num = get_temp1(f);
den = get_temp2(f);
red = get_redundancy(f);
+
}
/* If you change this, be sure to also change
@@ -317,12 +340,12 @@ static RefList *lsq_intensities(Crystal **crystals, int n, int n_threads,
qargs.n_started = 0;
qargs.crystals = crystals;
qargs.pmodel = pmodel;
- pthread_mutex_init(&qargs.full_lock, NULL);
+ pthread_rwlock_init(&qargs.full_lock, NULL);
run_threads(n_threads, run_merge_job, create_merge_job,
finalise_merge_job, &qargs, n, 0, 0, 0);
- pthread_mutex_destroy(&qargs.full_lock);
+ pthread_rwlock_destroy(&qargs.full_lock);
for ( refl = first_refl(full, &iter);
refl != NULL;