From 75d3985319f2eb40008e9fe6454880ecc620a0de Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 6 Sep 2007 02:13:08 -0400 Subject: straighten the list of objects to deltify Not all objects are subject to deltification, so avoid carrying those along, and provide the real count to progress display. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 77 +++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index e64e3a03a0..b1c64bec3e 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1313,12 +1313,6 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, if (trg_entry->type != src_entry->type) return -1; - /* We do not compute delta to *create* objects we are not - * going to pack. - */ - if (trg_entry->preferred_base) - return -1; - /* * We do not bother to try a delta that we discarded * on an earlier try, but only when reusing delta data. @@ -1443,43 +1437,24 @@ static void free_unpacked(struct unpacked *n) n->depth = 0; } -static void find_deltas(struct object_entry **list, int window, int depth) +static void find_deltas(struct object_entry **list, unsigned list_size, + unsigned nr_deltas, int window, int depth) { - uint32_t i = nr_objects, idx = 0, count = 0, processed = 0; + uint32_t i = list_size, idx = 0, count = 0, processed = 0; unsigned int array_size = window * sizeof(struct unpacked); struct unpacked *array; int max_depth; - if (!nr_objects) - return; array = xmalloc(array_size); memset(array, 0, array_size); if (progress) - start_progress(&progress_state, "Deltifying %u objects...", "", nr_result); + start_progress(&progress_state, "Deltifying %u objects...", "", nr_deltas); do { struct object_entry *entry = list[--i]; struct unpacked *n = array + idx; int j, best_base = -1; - if (!entry->preferred_base) - processed++; - - if (progress) - display_progress(&progress_state, processed); - - if (entry->delta) - /* This happens if we decided to reuse existing - * delta from a pack. "!no_reuse_delta &&" is implied. - */ - continue; - - if (entry->size < 50) - continue; - - if (entry->no_try_delta) - continue; - free_unpacked(n); n->entry = entry; @@ -1491,6 +1466,15 @@ static void find_deltas(struct object_entry **list, int window, int depth) count--; } + /* We do not compute delta to *create* objects we are not + * going to pack. + */ + if (entry->preferred_base) + goto next; + + if (progress) + display_progress(&progress_state, ++processed); + /* * If the current object is at pack edge, take the depth the * objects that depend on the current object into account @@ -1565,18 +1549,41 @@ static void find_deltas(struct object_entry **list, int window, int depth) static void prepare_pack(int window, int depth) { struct object_entry **delta_list; - uint32_t i; + uint32_t i, n, nr_deltas; get_object_details(); - if (!window || !depth) + if (!nr_objects || !window || !depth) return; delta_list = xmalloc(nr_objects * sizeof(*delta_list)); - for (i = 0; i < nr_objects; i++) - delta_list[i] = objects + i; - qsort(delta_list, nr_objects, sizeof(*delta_list), type_size_sort); - find_deltas(delta_list, window+1, depth); + nr_deltas = n = 0; + + for (i = 0; i < nr_objects; i++) { + struct object_entry *entry = objects + i; + + if (entry->delta) + /* This happens if we decided to reuse existing + * delta from a pack. "!no_reuse_delta &&" is implied. + */ + continue; + + if (entry->size < 50) + continue; + + if (entry->no_try_delta) + continue; + + if (!entry->preferred_base) + nr_deltas++; + + delta_list[n++] = entry; + } + + if (nr_deltas) { + qsort(delta_list, n, sizeof(*delta_list), type_size_sort); + find_deltas(delta_list, n, nr_deltas, window+1, depth); + } free(delta_list); } -- cgit v1.2.3 From ef0316fcd996c1679fef37ae2a53bef403c77356 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 6 Sep 2007 02:13:09 -0400 Subject: localize window memory usage accounting This is to help threadification of delta searching. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index b1c64bec3e..b8495bf924 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -78,7 +78,6 @@ static unsigned long delta_cache_size = 0; static unsigned long max_delta_cache_size = 0; static unsigned long cache_max_small_delta_size = 1000; -static unsigned long window_memory_usage = 0; static unsigned long window_memory_limit = 0; /* @@ -1300,7 +1299,7 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size, * one. */ static int try_delta(struct unpacked *trg, struct unpacked *src, - unsigned max_depth) + unsigned max_depth, unsigned long *mem_usage) { struct object_entry *trg_entry = trg->entry; struct object_entry *src_entry = src->entry; @@ -1356,7 +1355,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, if (sz != trg_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(trg_entry->idx.sha1), sz, trg_size); - window_memory_usage += sz; + *mem_usage += sz; } if (!src->data) { src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz); @@ -1366,7 +1365,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, if (sz != src_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(src_entry->idx.sha1), sz, src_size); - window_memory_usage += sz; + *mem_usage += sz; } if (!src->index) { src->index = create_delta_index(src->data, src_size); @@ -1376,7 +1375,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, warning("suboptimal pack - out of memory"); return 0; } - window_memory_usage += sizeof_delta_index(src->index); + *mem_usage += sizeof_delta_index(src->index); } delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size); @@ -1423,18 +1422,19 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n) return m; } -static void free_unpacked(struct unpacked *n) +static unsigned long free_unpacked(struct unpacked *n) { - window_memory_usage -= sizeof_delta_index(n->index); + unsigned long freed_mem = sizeof_delta_index(n->index); free_delta_index(n->index); n->index = NULL; if (n->data) { + freed_mem += n->entry->size; free(n->data); n->data = NULL; - window_memory_usage -= n->entry->size; } n->entry = NULL; n->depth = 0; + return freed_mem; } static void find_deltas(struct object_entry **list, unsigned list_size, @@ -1443,7 +1443,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size, uint32_t i = list_size, idx = 0, count = 0, processed = 0; unsigned int array_size = window * sizeof(struct unpacked); struct unpacked *array; - int max_depth; + unsigned long mem_usage = 0; array = xmalloc(array_size); memset(array, 0, array_size); @@ -1453,16 +1453,16 @@ static void find_deltas(struct object_entry **list, unsigned list_size, do { struct object_entry *entry = list[--i]; struct unpacked *n = array + idx; - int j, best_base = -1; + int j, max_depth, best_base = -1; - free_unpacked(n); + mem_usage -= free_unpacked(n); n->entry = entry; while (window_memory_limit && - window_memory_usage > window_memory_limit && + mem_usage > window_memory_limit && count > 1) { uint32_t tail = (idx + window - count) % window; - free_unpacked(array + tail); + mem_usage -= free_unpacked(array + tail); count--; } @@ -1497,7 +1497,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size, m = array + other_idx; if (!m->entry) break; - ret = try_delta(n, m, max_depth); + ret = try_delta(n, m, max_depth, &mem_usage); if (ret < 0) break; else if (ret > 0) -- cgit v1.2.3 From e334977dfad575cd8ac1a9e5f8e73fe4d018cec0 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 6 Sep 2007 02:13:10 -0400 Subject: rearrange delta search progress reporting This is to help threadification of the delta search code, with a bonus consistency check. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index b8495bf924..9d565925e7 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1438,17 +1438,15 @@ static unsigned long free_unpacked(struct unpacked *n) } static void find_deltas(struct object_entry **list, unsigned list_size, - unsigned nr_deltas, int window, int depth) + int window, int depth, unsigned *processed) { - uint32_t i = list_size, idx = 0, count = 0, processed = 0; + uint32_t i = list_size, idx = 0, count = 0; unsigned int array_size = window * sizeof(struct unpacked); struct unpacked *array; unsigned long mem_usage = 0; array = xmalloc(array_size); memset(array, 0, array_size); - if (progress) - start_progress(&progress_state, "Deltifying %u objects...", "", nr_deltas); do { struct object_entry *entry = list[--i]; @@ -1472,8 +1470,9 @@ static void find_deltas(struct object_entry **list, unsigned list_size, if (entry->preferred_base) goto next; + (*processed)++; if (progress) - display_progress(&progress_state, ++processed); + display_progress(&progress_state, *processed); /* * If the current object is at pack edge, take the depth the @@ -1536,9 +1535,6 @@ static void find_deltas(struct object_entry **list, unsigned list_size, idx = 0; } while (i > 0); - if (progress) - stop_progress(&progress_state); - for (i = 0; i < window; ++i) { free_delta_index(array[i].index); free(array[i].data); @@ -1581,8 +1577,17 @@ static void prepare_pack(int window, int depth) } if (nr_deltas) { + unsigned nr_done = 0; + if (progress) + start_progress(&progress_state, + "Deltifying %u objects...", "", + nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); - find_deltas(delta_list, n, nr_deltas, window+1, depth); + find_deltas(delta_list, n, window+1, depth, &nr_done); + if (progress) + stop_progress(&progress_state); + if (nr_done != nr_deltas) + die("inconsistency with delta count"); } free(delta_list); } -- cgit v1.2.3 From 8ecce684a38f7cea084abe9eef80bda04d7c77be Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 6 Sep 2007 02:13:11 -0400 Subject: basic threaded delta search this is still rough, hence it is disabled by default. You need to compile with "make THREADED_DELTA_SEARCH=1 ..." at the moment. Threading is done on different portions of the object list to be deltified. This is currently done by spliting the list into n parts and then a thread is spawned for each of them. A better method would consist of spliting the list into more smaller parts and have the n threads pick the next part available. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- Makefile | 8 +++++ builtin-pack-objects.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 51af531c9a..a92fb31695 100644 --- a/Makefile +++ b/Makefile @@ -122,6 +122,9 @@ all:: # If not set it defaults to the bare 'wish'. If it is set to the empty # string then NO_TCLTK will be forced (this is used by configure script). # +# Define THREADED_DELTA_SEARCH if you have pthreads and wish to exploit +# parallel delta searching when packing objects. +# GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN @@ -662,6 +665,11 @@ ifdef NO_HSTRERROR COMPAT_OBJS += compat/hstrerror.o endif +ifdef THREADED_DELTA_SEARCH + BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH + EXTLIBS += -lpthread +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK=NoThanks endif diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 9d565925e7..1bcee23ca1 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -15,6 +15,10 @@ #include "list-objects.h" #include "progress.h" +#ifdef THREADED_DELTA_SEARCH +#include +#endif + static const char pack_usage[] = "\ git-pack-objects [{ -q | --progress | --all-progress }] \n\ [--max-pack-size=N] [--local] [--incremental] \n\ @@ -1290,6 +1294,25 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size, return 0; } +#ifdef THREADED_DELTA_SEARCH + +static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER; +#define read_lock() pthread_mutex_lock(&read_mutex) +#define read_unlock() pthread_mutex_unlock(&read_mutex) + +static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER; +#define progress_lock() pthread_mutex_lock(&progress_mutex) +#define progress_unlock() pthread_mutex_unlock(&progress_mutex) + +#else + +#define read_lock() 0 +#define read_unlock() 0 +#define progress_lock() 0 +#define progress_unlock() 0 + +#endif + /* * We search for deltas _backwards_ in a list sorted by type and * by size, so that we see progressively smaller and smaller files. @@ -1348,7 +1371,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, /* Load data if not already done */ if (!trg->data) { + read_lock(); trg->data = read_sha1_file(trg_entry->idx.sha1, &type, &sz); + read_unlock(); if (!trg->data) die("object %s cannot be read", sha1_to_hex(trg_entry->idx.sha1)); @@ -1358,7 +1383,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, *mem_usage += sz; } if (!src->data) { + read_lock(); src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz); + read_unlock(); if (!src->data) die("object %s cannot be read", sha1_to_hex(src_entry->idx.sha1)); @@ -1470,9 +1497,11 @@ static void find_deltas(struct object_entry **list, unsigned list_size, if (entry->preferred_base) goto next; + progress_lock(); (*processed)++; if (progress) display_progress(&progress_state, *processed); + progress_unlock(); /* * If the current object is at pack edge, take the depth the @@ -1542,6 +1571,58 @@ static void find_deltas(struct object_entry **list, unsigned list_size, free(array); } +#ifdef THREADED_DELTA_SEARCH + +struct thread_params { + pthread_t thread; + struct object_entry **list; + unsigned list_size; + int window; + int depth; + unsigned *processed; +}; + +static void *threaded_find_deltas(void *arg) +{ + struct thread_params *p = arg; + if (p->list_size) + find_deltas(p->list, p->list_size, + p->window, p->depth, p->processed); + return NULL; +} + +#define NR_THREADS 8 + +static void ll_find_deltas(struct object_entry **list, unsigned list_size, + int window, int depth, unsigned *processed) +{ + struct thread_params p[NR_THREADS]; + int i, ret; + + for (i = 0; i < NR_THREADS; i++) { + unsigned sublist_size = list_size / (NR_THREADS - i); + p[i].list = list; + p[i].list_size = sublist_size; + p[i].window = window; + p[i].depth = depth; + p[i].processed = processed; + ret = pthread_create(&p[i].thread, NULL, + threaded_find_deltas, &p[i]); + if (ret) + die("unable to create thread: %s", strerror(ret)); + list += sublist_size; + list_size -= sublist_size; + } + + for (i = 0; i < NR_THREADS; i++) { + pthread_join(p[i].thread, NULL); + } +} + +#else +#define ll_find_deltas find_deltas +#endif + static void prepare_pack(int window, int depth) { struct object_entry **delta_list; @@ -1583,7 +1664,7 @@ static void prepare_pack(int window, int depth) "Deltifying %u objects...", "", nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); - find_deltas(delta_list, n, window+1, depth, &nr_done); + ll_find_deltas(delta_list, n, window+1, depth, &nr_done); if (progress) stop_progress(&progress_state); if (nr_done != nr_deltas) -- cgit v1.2.3 From c2a33679a726aeb75529540c2b295f21023ddbc7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 10 Sep 2007 00:06:09 -0400 Subject: threaded delta search: refine work allocation With this, each thread get repeatedly assigned the next available chunk of objects to process until the whole list is done. The idea is to have reasonably small chunks so that all CPUs remain busy with a minimum number of threads for as long as there is data to process. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 59 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 1bcee23ca1..60141196df 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1582,27 +1582,42 @@ struct thread_params { unsigned *processed; }; +static pthread_mutex_t data_request = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t data_ready = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t data_provider = PTHREAD_MUTEX_INITIALIZER; +static struct thread_params *data_requester; + static void *threaded_find_deltas(void *arg) { - struct thread_params *p = arg; - if (p->list_size) - find_deltas(p->list, p->list_size, - p->window, p->depth, p->processed); - return NULL; + struct thread_params *me = arg; + + for (;;) { + pthread_mutex_lock(&data_request); + data_requester = me; + pthread_mutex_unlock(&data_provider); + pthread_mutex_lock(&data_ready); + + if (!me->list_size) + return NULL; + + find_deltas(me->list, me->list_size, + me->window, me->depth, me->processed); + } } -#define NR_THREADS 8 +#define NR_THREADS 4 static void ll_find_deltas(struct object_entry **list, unsigned list_size, int window, int depth, unsigned *processed) { struct thread_params p[NR_THREADS]; int i, ret; + unsigned chunk_size; + + pthread_mutex_lock(&data_provider); + pthread_mutex_lock(&data_ready); for (i = 0; i < NR_THREADS; i++) { - unsigned sublist_size = list_size / (NR_THREADS - i); - p[i].list = list; - p[i].list_size = sublist_size; p[i].window = window; p[i].depth = depth; p[i].processed = processed; @@ -1610,13 +1625,29 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size, threaded_find_deltas, &p[i]); if (ret) die("unable to create thread: %s", strerror(ret)); - list += sublist_size; - list_size -= sublist_size; } - for (i = 0; i < NR_THREADS; i++) { - pthread_join(p[i].thread, NULL); - } + /* this should be auto-tuned somehow */ + chunk_size = window * 1000; + + do { + unsigned sublist_size = chunk_size; + if (sublist_size > list_size) + sublist_size = list_size; + + pthread_mutex_lock(&data_provider); + data_requester->list = list; + data_requester->list_size = sublist_size; + pthread_mutex_unlock(&data_ready); + + list += sublist_size; + list_size -= sublist_size; + if (!sublist_size) { + pthread_join(data_requester->thread, NULL); + i--; + } + pthread_mutex_unlock(&data_request); + } while (i); } #else -- cgit v1.2.3 From 59921b4b3f24b19e2593085ee27d5e1f2448c6bb Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 10 Sep 2007 00:06:10 -0400 Subject: threaded delta search: better chunck split point Try to keep object with the same name hash together. Suggested by Martin Koegler. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 60141196df..b13558ee7e 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1635,6 +1635,11 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size, if (sublist_size > list_size) sublist_size = list_size; + /* try to split chunks on "path" boundaries */ + while (sublist_size < list_size && list[sublist_size]->hash && + list[sublist_size]->hash == list[sublist_size-1]->hash) + sublist_size++; + pthread_mutex_lock(&data_provider); data_requester->list = list; data_requester->list_size = sublist_size; -- cgit v1.2.3 From 367f4a4343d467ac76641362b102bc86da5cb584 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 10 Sep 2007 00:06:11 -0400 Subject: threaded delta search: specify number of threads at run time This adds a --threads= parameter to 'git pack-objects' with documentation. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- Documentation/git-pack-objects.txt | 8 ++++++++ builtin-pack-objects.c | 26 +++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 6f17cff24a..f9b97956e3 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -173,6 +173,14 @@ base-name:: length, this option typically shrinks the resulting packfile by 3-5 per-cent. +--threads=:: + Specifies the number of threads to spawn when searching for best + delta matches. This requires that pack-objects be compiled with + pthreads otherwise this option is ignored with a warning. + This is meant to reduce packing time on multiprocessor machines. + The required amount of memory for the delta search window is + however multiplied by the number of threads. + --index-version=[,]:: This is intended to be used by the test suite only. It allows to force the version for the generated pack index, and to force diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index b13558ee7e..42698d2948 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -24,7 +24,7 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\ [--max-pack-size=N] [--local] [--incremental] \n\ [--window=N] [--window-memory=N] [--depth=N] \n\ [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\ - [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\ + [--threads=N] [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\ [--stdout | base-name] [ 1) + warning("no threads support, ignoring %s", k); +#endif + return 0; + } return git_default_config(k, v); } -- cgit v1.2.3 From 3c70183918d97eda06ae847cd7432fd23257caea Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 10 Sep 2007 11:10:11 -0400 Subject: threaded delta search: proper locking for cache accounting Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index e091bcbda9..b126fc8e72 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1301,6 +1301,10 @@ static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER; #define read_lock() pthread_mutex_lock(&read_mutex) #define read_unlock() pthread_mutex_unlock(&read_mutex) +static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER; +#define cache_lock() pthread_mutex_lock(&cache_mutex) +#define cache_unlock() pthread_mutex_unlock(&cache_mutex) + static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER; #define progress_lock() pthread_mutex_lock(&progress_mutex) #define progress_unlock() pthread_mutex_unlock(&progress_mutex) @@ -1309,6 +1313,8 @@ static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER; #define read_lock() 0 #define read_unlock() 0 +#define cache_lock() 0 +#define cache_unlock() 0 #define progress_lock() 0 #define progress_unlock() 0 @@ -1423,17 +1429,27 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, trg_entry->delta_size = delta_size; trg->depth = src->depth + 1; + /* + * Handle memory allocation outside of the cache + * accounting lock. Compiler will optimize the strangeness + * away when THREADED_DELTA_SEARCH is not defined. + */ + if (trg_entry->delta_data) + free(trg_entry->delta_data); + cache_lock(); if (trg_entry->delta_data) { delta_cache_size -= trg_entry->delta_size; - free(trg_entry->delta_data); trg_entry->delta_data = NULL; } - if (delta_cacheable(src_size, trg_size, delta_size)) { - trg_entry->delta_data = xrealloc(delta_buf, delta_size); delta_cache_size += trg_entry->delta_size; - } else + cache_unlock(); + trg_entry->delta_data = xrealloc(delta_buf, delta_size); + } else { + cache_unlock(); free(delta_buf); + } + return 1; } -- cgit v1.2.3 From e1ef867328bd7d2cd67499ac30479821bdf96662 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 14 Sep 2007 22:30:20 -0700 Subject: builtin-pack-objects.c: avoid bogus gcc warnings These empty statement marcos can solicit bogus "statement with no effect" warnings; squelch them. Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index b126fc8e72..a15906bdb2 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1311,12 +1311,12 @@ static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER; #else -#define read_lock() 0 -#define read_unlock() 0 -#define cache_lock() 0 -#define cache_unlock() 0 -#define progress_lock() 0 -#define progress_unlock() 0 +#define read_lock() (void)0 +#define read_unlock() (void)0 +#define cache_lock() (void)0 +#define cache_unlock() (void)0 +#define progress_lock() (void)0 +#define progress_unlock() (void)0 #endif -- cgit v1.2.3