Skip to content

Commit 0579f91

Browse files
trastgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b8ffedc commit 0579f91

File tree

3 files changed

+63
-33
lines changed

3 files changed

+63
-33
lines changed

builtin/grep.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include "grep.h"
1818
#include "quote.h"
1919
#include "dir.h"
20-
#include "thread-utils.h"
2120

2221
static char const * const grep_usage[] = {
2322
"git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]",
@@ -256,6 +255,7 @@ static void start_threads(struct grep_opt *opt)
256255

257256
pthread_mutex_init(&grep_mutex, NULL);
258257
pthread_mutex_init(&read_sha1_mutex, NULL);
258+
pthread_mutex_init(&grep_attr_mutex, NULL);
259259
pthread_cond_init(&cond_add, NULL);
260260
pthread_cond_init(&cond_write, NULL);
261261
pthread_cond_init(&cond_result, NULL);
@@ -303,6 +303,7 @@ static int wait_all(void)
303303

304304
pthread_mutex_destroy(&grep_mutex);
305305
pthread_mutex_destroy(&read_sha1_mutex);
306+
pthread_mutex_destroy(&grep_attr_mutex);
306307
pthread_cond_destroy(&cond_add);
307308
pthread_cond_destroy(&cond_write);
308309
pthread_cond_destroy(&cond_result);
@@ -1002,17 +1003,21 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10021003
opt.regflags |= REG_ICASE;
10031004

10041005
#ifndef NO_PTHREADS
1005-
if (online_cpus() == 1 || !grep_threads_ok(&opt))
1006+
if (online_cpus() == 1)
10061007
use_threads = 0;
1008+
#else
1009+
use_threads = 0;
1010+
#endif
1011+
1012+
opt.use_threads = use_threads;
10071013

1014+
#ifndef NO_PTHREADS
10081015
if (use_threads) {
10091016
if (opt.pre_context || opt.post_context || opt.file_break ||
10101017
opt.funcbody)
10111018
skip_first_line = 1;
10121019
start_threads(&opt);
10131020
}
1014-
#else
1015-
use_threads = 0;
10161021
#endif
10171022

10181023
compile_grep_patterns(&opt);

grep.c

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -806,10 +806,46 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
806806
opt->output(opt, "\n", 1);
807807
}
808808

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)
810833
{
811834
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) {
813849
char buf[1];
814850
return xecfg->find_func(bol, eol - bol, buf, 1,
815851
xecfg->find_func_priv) >= 0;
@@ -835,7 +871,7 @@ static void show_funcname_line(struct grep_opt *opt, const char *name,
835871
if (lno <= opt->last_shown)
836872
break;
837873

838-
if (match_funcname(opt, bol, eol)) {
874+
if (match_funcname(opt, name, bol, eol)) {
839875
show_line(opt, bol, eol, name, lno, '=');
840876
break;
841877
}
@@ -848,7 +884,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
848884
unsigned cur = lno, from = 1, funcname_lno = 0;
849885
int funcname_needed = !!opt->funcname;
850886

851-
if (opt->funcbody && !match_funcname(opt, bol, end))
887+
if (opt->funcbody && !match_funcname(opt, name, bol, end))
852888
funcname_needed = 2;
853889

854890
if (opt->pre_context < lno)
@@ -864,7 +900,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
864900
while (bol > buf && bol[-1] != '\n')
865901
bol--;
866902
cur--;
867-
if (funcname_needed && match_funcname(opt, bol, eol)) {
903+
if (funcname_needed && match_funcname(opt, name, bol, eol)) {
868904
funcname_lno = cur;
869905
funcname_needed = 0;
870906
}
@@ -942,19 +978,6 @@ static int look_ahead(struct grep_opt *opt,
942978
return 0;
943979
}
944980

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-
958981
static void std_output(struct grep_opt *opt, const void *buf, size_t size)
959982
{
960983
fwrite(buf, size, 1, stdout);
@@ -1008,16 +1031,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
10081031
}
10091032

10101033
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+
10211036
try_lookahead = should_lookahead(opt);
10221037

10231038
while (left) {
@@ -1093,7 +1108,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
10931108
show_function = 1;
10941109
goto next_line;
10951110
}
1096-
if (show_function && match_funcname(opt, bol, eol))
1111+
if (show_function && match_funcname(opt, name, bol, eol))
10971112
show_function = 0;
10981113
if (show_function ||
10991114
(last_hit && lno <= last_hit + opt->post_context)) {

grep.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ typedef int pcre;
88
typedef int pcre_extra;
99
#endif
1010
#include "kwset.h"
11+
#include "thread-utils.h"
1112

1213
enum grep_pat_token {
1314
GREP_PATTERN,
@@ -115,6 +116,7 @@ struct grep_opt {
115116
int show_hunk_mark;
116117
int file_break;
117118
int heading;
119+
int use_threads;
118120
void *priv;
119121

120122
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
131133
extern struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
132134
extern int grep_threads_ok(const struct grep_opt *opt);
133135

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+
134144
#endif

0 commit comments

Comments
 (0)