aboutsummaryrefslogtreecommitdiff
path: root/src/partial_sim.c
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2013-09-20 14:25:54 +0200
committerThomas White <taw@physics.org>2013-09-20 14:25:54 +0200
commit0c8386b95dfa444660cdab2df03e3a6f0e175450 (patch)
tree605b6ed4d888c21c9e2dde705edbc444891a69c7 /src/partial_sim.c
parent72b949c4ec28e76dea966d88eae549fad6548143 (diff)
partial_sim: Fix racy locking
Diffstat (limited to 'src/partial_sim.c')
-rw-r--r--src/partial_sim.c22
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 {