diff options
author | Thomas White <taw@physics.org> | 2013-09-20 14:25:54 +0200 |
---|---|---|
committer | Thomas White <taw@physics.org> | 2013-09-20 14:25:54 +0200 |
commit | 0c8386b95dfa444660cdab2df03e3a6f0e175450 (patch) | |
tree | 605b6ed4d888c21c9e2dde705edbc444891a69c7 /src | |
parent | 72b949c4ec28e76dea966d88eae549fad6548143 (diff) |
partial_sim: Fix racy locking
Diffstat (limited to 'src')
-rw-r--r-- | src/partial_sim.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/src/partial_sim.c b/src/partial_sim.c index 74b1d734..bbdc1550 100644 --- a/src/partial_sim.c +++ b/src/partial_sim.c @@ -116,15 +116,21 @@ static void calculate_partials(Crystal *cr, if ( rfull == NULL ) { if ( random_intensities ) { - /* The full reflection is immutable (in this - * program) once created, but creating it must - * be an atomic operation. So do the whole - * thing under lock. */ pthread_rwlock_wrlock(full_lock); - rfull = add_refl(full, h, k, l); - If = fabs(gaussian_noise(0.0, full_stddev)); - set_intensity(rfull, If); - set_redundancy(rfull, 1); + + /* In the gap between the unlock and the wrlock, + * the reflection might have been created by + * another thread. So, we must check again */ + rfull = find_refl(full, h, k, l); + if ( rfull == NULL ) { + rfull = add_refl(full, h, k, l); + If = fabs(gaussian_noise(0.0, + full_stddev)); + set_intensity(rfull, If); + set_redundancy(rfull, 1); + } else { + If = get_intensity(rfull); + } pthread_rwlock_unlock(full_lock); } else { |