Skip to content

Commit ced7469

Browse files
committed
Merge branch 'tr/grep-threading'
* tr/grep-threading: grep: disable threading in non-worktree case grep: enable threading with -p and -W using lazy attribute lookup grep: load funcname patterns for -W
2 parents adb8676 + 53b8d93 commit ced7469

File tree

4 files changed

+88
-43
lines changed

4 files changed

+88
-43
lines changed

builtin/grep.c

Lines changed: 20 additions & 15 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);
@@ -1001,20 +1002,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10011002
if (!opt.fixed && opt.ignore_case)
10021003
opt.regflags |= REG_ICASE;
10031004

1004-
#ifndef NO_PTHREADS
1005-
if (online_cpus() == 1 || !grep_threads_ok(&opt))
1006-
use_threads = 0;
1007-
1008-
if (use_threads) {
1009-
if (opt.pre_context || opt.post_context || opt.file_break ||
1010-
opt.funcbody)
1011-
skip_first_line = 1;
1012-
start_threads(&opt);
1013-
}
1014-
#else
1015-
use_threads = 0;
1016-
#endif
1017-
10181005
compile_grep_patterns(&opt);
10191006

10201007
/* Check revs and then paths */
@@ -1036,6 +1023,24 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
10361023
break;
10371024
}
10381025

1026+
#ifndef NO_PTHREADS
1027+
if (list.nr || cached || online_cpus() == 1)
1028+
use_threads = 0;
1029+
#else
1030+
use_threads = 0;
1031+
#endif
1032+
1033+
opt.use_threads = use_threads;
1034+
1035+
#ifndef NO_PTHREADS
1036+
if (use_threads) {
1037+
if (opt.pre_context || opt.post_context || opt.file_break ||
1038+
opt.funcbody)
1039+
skip_first_line = 1;
1040+
start_threads(&opt);
1041+
}
1042+
#endif
1043+
10391044
/* The rest are paths */
10401045
if (!seen_dashdash) {
10411046
int j;

grep.c

Lines changed: 44 additions & 28 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->unmatch_name_only && !opt->status_only &&
952-
!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,15 +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->unmatch_name_only && !opt->status_only &&
1012-
!opt->name_only && !binary_match_only && !collect_hits) {
1013-
struct userdiff_driver *drv = userdiff_find_by_path(name);
1014-
if (drv && drv->funcname.pattern) {
1015-
const struct userdiff_funcname *pe = &drv->funcname;
1016-
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
1017-
opt->priv = &xecfg;
1018-
}
1019-
}
1034+
opt->priv = &xecfg;
1035+
10201036
try_lookahead = should_lookahead(opt);
10211037

10221038
while (left) {
@@ -1092,7 +1108,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
10921108
show_function = 1;
10931109
goto next_line;
10941110
}
1095-
if (show_function && match_funcname(opt, bol, eol))
1111+
if (show_function && match_funcname(opt, name, bol, eol))
10961112
show_function = 0;
10971113
if (show_function ||
10981114
(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

t/t7810-grep.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,20 @@ test_expect_success 'grep -W' '
523523
test_cmp expected actual
524524
'
525525

526+
cat >expected <<EOF
527+
hello.c= printf("Hello world.\n");
528+
hello.c: return 0;
529+
hello.c- /* char ?? */
530+
EOF
531+
532+
test_expect_success 'grep -W with userdiff' '
533+
test_when_finished "rm -f .gitattributes" &&
534+
git config diff.custom.xfuncname "(printf.*|})$" &&
535+
echo "hello.c diff=custom" >.gitattributes &&
536+
git grep -W return >actual &&
537+
test_cmp expected actual
538+
'
539+
526540
test_expect_success 'grep from a subdirectory to search wider area (1)' '
527541
mkdir -p s &&
528542
(

0 commit comments

Comments
 (0)