grep: enable threading with -p and -W using lazy attribute lookup
Lazily load the userdiff attributes in match_funcname(). Use a separate mutex around this loading to protect the (not thread-safe) attributes machinery. This lets us re-enable threading with -p and -W while reducing the overhead caused by looking up attributes. Signed-off-by: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Thomas Rast committed
Dec 12, 2011 at 22:16 UTC
0579f91dd74a0902e52d1e6e839cc31b99f12cfc
3 files changed
+63
-33
builtin/grep.c
+9
-4
@@ -17,7 +17,6 @@
17
#include "grep.h"
18
#include "quote.h"
19
#include "dir.h"
20
-#include "thread-utils.h"
20
21
static char const * const grep_usage[] = {
22
"git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]",
@@ -256,6 +255,7 @@ static void start_threads(struct grep_opt *opt)
255
256
pthread_mutex_init(&grep_mutex, NULL);
257
pthread_mutex_init(&read_sha1_mutex, NULL);
258
+ pthread_mutex_init(&grep_attr_mutex, NULL);
259
pthread_cond_init(&cond_add, NULL);
260
pthread_cond_init(&cond_write, NULL);
261
pthread_cond_init(&cond_result, NULL);
@@ -303,6 +303,7 @@ static int wait_all(void)
303
304
pthread_mutex_destroy(&grep_mutex);
305
pthread_mutex_destroy(&read_sha1_mutex);
306
+ pthread_mutex_destroy(&grep_attr_mutex);
307
pthread_cond_destroy(&cond_add);
308
pthread_cond_destroy(&cond_write);
309
pthread_cond_destroy(&cond_result);
@@ -1002,17 +1003,21 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1003
opt.regflags |= REG_ICASE;
1004
1005
#ifndef NO_PTHREADS
1005
- if (online_cpus() == 1 || !grep_threads_ok(&opt))
1006
+ if (online_cpus() == 1)
1007
use_threads = 0;
1008
+#else
1009
+ use_threads = 0;
1010
+#endif
1011
+
1012
+ opt.use_threads = use_threads;
1013
1014
+#ifndef NO_PTHREADS
1015
if (use_threads) {
1016
if (opt.pre_context || opt.post_context || opt.file_break ||
1017
opt.funcbody)
1018
skip_first_line = 1;
1019
start_threads(&opt);
1020
}
1014
-#else
1015
- use_threads = 0;
1021
#endif
1022
1023
compile_grep_patterns(&opt);
grep.c
+44
-29
@@ -806,10 +806,46 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
806
opt->output(opt, "\n", 1);
807
}
808
809
-static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
809
+#ifndef NO_PTHREADS
810
+/*
811
+ * This lock protects access to the gitattributes machinery, which is
812
+ * not thread-safe.
813
+ */
814
+pthread_mutex_t grep_attr_mutex;
815
+
816
+static inline void grep_attr_lock(struct grep_opt *opt)
817
+{
818
+ if (opt->use_threads)
819
+ pthread_mutex_lock(&grep_attr_mutex);
820
+}
821
+
822
+static inline void grep_attr_unlock(struct grep_opt *opt)
823
+{
824
+ if (opt->use_threads)
825
+ pthread_mutex_unlock(&grep_attr_mutex);
826
+}
827
+#else
828
+#define grep_attr_lock(opt)
829
+#define grep_attr_unlock(opt)
830
+#endif
831
+
832
+static int match_funcname(struct grep_opt *opt, const char *name, char *bol, char *eol)
833
{
834
xdemitconf_t *xecfg = opt->priv;
812
- if (xecfg && xecfg->find_func) {
835
+ if (xecfg && !xecfg->find_func) {
836
+ struct userdiff_driver *drv;
837
+ grep_attr_lock(opt);
838
+ drv = userdiff_find_by_path(name);
839
+ grep_attr_unlock(opt);
840
+ if (drv && drv->funcname.pattern) {
841
+ const struct userdiff_funcname *pe = &drv->funcname;
842
+ xdiff_set_find_func(xecfg, pe->pattern, pe->cflags);
843
+ } else {
844
+ xecfg = opt->priv = NULL;
845
+ }
846
+ }
847
+
848
+ if (xecfg) {
849
char buf[1];
850
return xecfg->find_func(bol, eol - bol, buf, 1,
851
xecfg->find_func_priv) >= 0;
@@ -835,7 +871,7 @@ static void show_funcname_line(struct grep_opt *opt, const char *name,
871
if (lno <= opt->last_shown)
872
break;
873
838
- if (match_funcname(opt, bol, eol)) {
874
+ if (match_funcname(opt, name, bol, eol)) {
875
show_line(opt, bol, eol, name, lno, '=');
876
break;
877
}
@@ -848,7 +884,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
884
unsigned cur = lno, from = 1, funcname_lno = 0;
885
int funcname_needed = !!opt->funcname;
886
851
- if (opt->funcbody && !match_funcname(opt, bol, end))
887
+ if (opt->funcbody && !match_funcname(opt, name, bol, end))
888
funcname_needed = 2;
889
890
if (opt->pre_context < lno)
@@ -864,7 +900,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
900
while (bol > buf && bol[-1] != '\n')
901
bol--;
902
cur--;
867
- if (funcname_needed && match_funcname(opt, bol, eol)) {
903
+ if (funcname_needed && match_funcname(opt, name, bol, eol)) {
904
funcname_lno = cur;
905
funcname_needed = 0;
906
}
@@ -942,19 +978,6 @@ static int look_ahead(struct grep_opt *opt,
978
return 0;
979
}
980
945
-int grep_threads_ok(const struct grep_opt *opt)
946
-{
947
- /* If this condition is true, then we may use the attribute
948
- * machinery in grep_buffer_1. The attribute code is not
949
- * thread safe, so we disable the use of threads.
950
- */
951
- if ((opt->funcname || opt->funcbody)
952
- && !opt->unmatch_name_only && !opt->status_only && !opt->name_only)
953
- return 0;
954
-
955
- return 1;
956
-}
957
-
981
static void std_output(struct grep_opt *opt, const void *buf, size_t size)
982
{
983
fwrite(buf, size, 1, stdout);
@@ -1008,16 +1031,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
1031
}
1032
1033
memset(&xecfg, 0, sizeof(xecfg));
1011
- if ((opt->funcname || opt->funcbody)
1012
- && !opt->unmatch_name_only && !opt->status_only &&
1013
- !opt->name_only && !binary_match_only && !collect_hits) {
1014
- struct userdiff_driver *drv = userdiff_find_by_path(name);
1015
- if (drv && drv->funcname.pattern) {
1016
- const struct userdiff_funcname *pe = &drv->funcname;
1017
- xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
1018
- opt->priv = &xecfg;
1019
- }
1020
- }
1034
+ opt->priv = &xecfg;
1035
+
1036
try_lookahead = should_lookahead(opt);
1037
1038
while (left) {
@@ -1093,7 +1108,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
1108
show_function = 1;
1109
goto next_line;
1110
}
1096
- if (show_function && match_funcname(opt, bol, eol))
1111
+ if (show_function && match_funcname(opt, name, bol, eol))
1112
show_function = 0;
1113
if (show_function ||
1114
(last_hit && lno <= last_hit + opt->post_context)) {
grep.h
+10
@@ -8,6 +8,7 @@ typedef int pcre;
8
typedef int pcre_extra;
9
#endif
10
#include "kwset.h"
11
+#include "thread-utils.h"
12
13
enum grep_pat_token {
14
GREP_PATTERN,
@@ -115,6 +116,7 @@ struct grep_opt {
116
int show_hunk_mark;
117
int file_break;
118
int heading;
119
+ int use_threads;
120
void *priv;
121
122
void (*output)(struct grep_opt *opt, const void *data, size_t size);
@@ -131,4 +133,12 @@ extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsign
133
extern struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
134
extern int grep_threads_ok(const struct grep_opt *opt);
135
136
+#ifndef NO_PTHREADS
137
+/*
138
+ * Mutex used around access to the attributes machinery if
139
+ * opt->use_threads. Must be initialized/destroyed by callers!
140
+ */
141
+extern pthread_mutex_t grep_attr_mutex;
142
+#endif
143
+
144
#endif