summaryrefslogtreecommitdiff
path: root/replace-object.c
diff options
context:
space:
mode:
authorMatheus Tavares <matheus.bernardino@usp.br>2020-01-16 02:39:52 (GMT)
committerJunio C Hamano <gitster@pobox.com>2020-01-17 21:52:14 (GMT)
commitb1fc9da1c84a94ef03eb07df361f3ec43006b39f (patch)
tree690e752f40991e17caf26cf68598010877ab644b /replace-object.c
parentd5b0bac52841857b5ba197ca931ecf729fdbc63e (diff)
downloadgit-b1fc9da1c84a94ef03eb07df361f3ec43006b39f.zip
git-b1fc9da1c84a94ef03eb07df361f3ec43006b39f.tar.gz
git-b1fc9da1c84a94ef03eb07df361f3ec43006b39f.tar.bz2
replace-object: make replace operations thread-safe
replace-object functions are very close to being thread-safe: the only current racy section is the lazy initialization at prepare_replace_object(). The following patches will protect some object reading operations to be called threaded, but before that, replace functions must be protected. To do so, add a mutex to struct raw_object_store and acquire it before lazy initializing the replace_map. This won't cause any noticeable performance drop as the mutex will no longer be used after the replace_map is initialized. Later, when the replace functions are called in parallel, thread debuggers might point our use of the added replace_map_initialized flag as a data race. However, as this boolean variable is initialized as false and it's only updated once, there's no real harm. It's perfectly fine if the value is updated right after a thread read it in replace-map.h:lookup_replace_object() (there'll only be a performance penalty for the affected threads at that moment). We could cease the debugger warning protecting the variable reading at the said function. However, this would negatively affect performance for all threads calling it, at any time, so it's not really worthy since the warning doesn't represent a real problem. Instead, to make sure we don't get false positives (at ThreadSanitizer, at least) an entry for the respective function is added to .tsan-suppressions. Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'replace-object.c')
-rw-r--r--replace-object.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/replace-object.c b/replace-object.c
index e295e87..7bd9aba 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -34,14 +34,23 @@ static int register_replace_ref(struct repository *r,
void prepare_replace_object(struct repository *r)
{
- if (r->objects->replace_map)
+ if (r->objects->replace_map_initialized)
return;
+ pthread_mutex_lock(&r->objects->replace_mutex);
+ if (r->objects->replace_map_initialized) {
+ pthread_mutex_unlock(&r->objects->replace_mutex);
+ return;
+ }
+
r->objects->replace_map =
xmalloc(sizeof(*r->objects->replace_map));
oidmap_init(r->objects->replace_map, 0);
for_each_replace_ref(r, register_replace_ref, NULL);
+ r->objects->replace_map_initialized = 1;
+
+ pthread_mutex_unlock(&r->objects->replace_mutex);
}
/* We allow "recursive" replacement. Only within reason, though */