Code

Merge branch 'tr/grep-threading'
authorJunio C Hamano <gitster@pobox.com>
Thu, 22 Dec 2011 19:27:28 +0000 (11:27 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 22 Dec 2011 19:27:28 +0000 (11:27 -0800)
* 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

builtin/grep.c
grep.c
grep.h
t/t7810-grep.sh

index 988ea1d3324d6e32fcfd3b97da0fad5ae41b592c..9ce064ac1131e9a93383f568bb6f567791740b77 100644 (file)
@@ -17,7 +17,6 @@
 #include "grep.h"
 #include "quote.h"
 #include "dir.h"
-#include "thread-utils.h"
 
 static char const * const grep_usage[] = {
        "git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]",
@@ -256,6 +255,7 @@ static void start_threads(struct grep_opt *opt)
 
        pthread_mutex_init(&grep_mutex, NULL);
        pthread_mutex_init(&read_sha1_mutex, NULL);
+       pthread_mutex_init(&grep_attr_mutex, NULL);
        pthread_cond_init(&cond_add, NULL);
        pthread_cond_init(&cond_write, NULL);
        pthread_cond_init(&cond_result, NULL);
@@ -303,6 +303,7 @@ static int wait_all(void)
 
        pthread_mutex_destroy(&grep_mutex);
        pthread_mutex_destroy(&read_sha1_mutex);
+       pthread_mutex_destroy(&grep_attr_mutex);
        pthread_cond_destroy(&cond_add);
        pthread_cond_destroy(&cond_write);
        pthread_cond_destroy(&cond_result);
@@ -1001,20 +1002,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        if (!opt.fixed && opt.ignore_case)
                opt.regflags |= REG_ICASE;
 
-#ifndef NO_PTHREADS
-       if (online_cpus() == 1 || !grep_threads_ok(&opt))
-               use_threads = 0;
-
-       if (use_threads) {
-               if (opt.pre_context || opt.post_context || opt.file_break ||
-                   opt.funcbody)
-                       skip_first_line = 1;
-               start_threads(&opt);
-       }
-#else
-       use_threads = 0;
-#endif
-
        compile_grep_patterns(&opt);
 
        /* Check revs and then paths */
@@ -1036,6 +1023,24 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                break;
        }
 
+#ifndef NO_PTHREADS
+       if (list.nr || cached || online_cpus() == 1)
+               use_threads = 0;
+#else
+       use_threads = 0;
+#endif
+
+       opt.use_threads = use_threads;
+
+#ifndef NO_PTHREADS
+       if (use_threads) {
+               if (opt.pre_context || opt.post_context || opt.file_break ||
+                   opt.funcbody)
+                       skip_first_line = 1;
+               start_threads(&opt);
+       }
+#endif
+
        /* The rest are paths */
        if (!seen_dashdash) {
                int j;
diff --git a/grep.c b/grep.c
index b29d09c7f6a5a7f9621fb5287eb07e72ece7f484..486230b511952dcf975199c82a5265d1906999cd 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -806,10 +806,46 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
        opt->output(opt, "\n", 1);
 }
 
-static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
+#ifndef NO_PTHREADS
+/*
+ * This lock protects access to the gitattributes machinery, which is
+ * not thread-safe.
+ */
+pthread_mutex_t grep_attr_mutex;
+
+static inline void grep_attr_lock(struct grep_opt *opt)
+{
+       if (opt->use_threads)
+               pthread_mutex_lock(&grep_attr_mutex);
+}
+
+static inline void grep_attr_unlock(struct grep_opt *opt)
+{
+       if (opt->use_threads)
+               pthread_mutex_unlock(&grep_attr_mutex);
+}
+#else
+#define grep_attr_lock(opt)
+#define grep_attr_unlock(opt)
+#endif
+
+static int match_funcname(struct grep_opt *opt, const char *name, char *bol, char *eol)
 {
        xdemitconf_t *xecfg = opt->priv;
-       if (xecfg && xecfg->find_func) {
+       if (xecfg && !xecfg->find_func) {
+               struct userdiff_driver *drv;
+               grep_attr_lock(opt);
+               drv = userdiff_find_by_path(name);
+               grep_attr_unlock(opt);
+               if (drv && drv->funcname.pattern) {
+                       const struct userdiff_funcname *pe = &drv->funcname;
+                       xdiff_set_find_func(xecfg, pe->pattern, pe->cflags);
+               } else {
+                       xecfg = opt->priv = NULL;
+               }
+       }
+
+       if (xecfg) {
                char buf[1];
                return xecfg->find_func(bol, eol - bol, buf, 1,
                                        xecfg->find_func_priv) >= 0;
@@ -835,7 +871,7 @@ static void show_funcname_line(struct grep_opt *opt, const char *name,
                if (lno <= opt->last_shown)
                        break;
 
-               if (match_funcname(opt, bol, eol)) {
+               if (match_funcname(opt, name, bol, eol)) {
                        show_line(opt, bol, eol, name, lno, '=');
                        break;
                }
@@ -848,7 +884,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
        unsigned cur = lno, from = 1, funcname_lno = 0;
        int funcname_needed = !!opt->funcname;
 
-       if (opt->funcbody && !match_funcname(opt, bol, end))
+       if (opt->funcbody && !match_funcname(opt, name, bol, end))
                funcname_needed = 2;
 
        if (opt->pre_context < lno)
@@ -864,7 +900,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
                while (bol > buf && bol[-1] != '\n')
                        bol--;
                cur--;
-               if (funcname_needed && match_funcname(opt, bol, eol)) {
+               if (funcname_needed && match_funcname(opt, name, bol, eol)) {
                        funcname_lno = cur;
                        funcname_needed = 0;
                }
@@ -942,19 +978,6 @@ static int look_ahead(struct grep_opt *opt,
        return 0;
 }
 
-int grep_threads_ok(const struct grep_opt *opt)
-{
-       /* If this condition is true, then we may use the attribute
-        * machinery in grep_buffer_1. The attribute code is not
-        * thread safe, so we disable the use of threads.
-        */
-       if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
-           !opt->name_only)
-               return 0;
-
-       return 1;
-}
-
 static void std_output(struct grep_opt *opt, const void *buf, size_t size)
 {
        fwrite(buf, size, 1, stdout);
@@ -1008,15 +1031,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
        }
 
        memset(&xecfg, 0, sizeof(xecfg));
-       if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
-           !opt->name_only && !binary_match_only && !collect_hits) {
-               struct userdiff_driver *drv = userdiff_find_by_path(name);
-               if (drv && drv->funcname.pattern) {
-                       const struct userdiff_funcname *pe = &drv->funcname;
-                       xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
-                       opt->priv = &xecfg;
-               }
-       }
+       opt->priv = &xecfg;
+
        try_lookahead = should_lookahead(opt);
 
        while (left) {
@@ -1092,7 +1108,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
                                show_function = 1;
                        goto next_line;
                }
-               if (show_function && match_funcname(opt, bol, eol))
+               if (show_function && match_funcname(opt, name, bol, eol))
                        show_function = 0;
                if (show_function ||
                    (last_hit && lno <= last_hit + opt->post_context)) {
diff --git a/grep.h b/grep.h
index a65280026d5dee8ab059bead79f05d6a1111147a..fb205f354231c0e50026c6e7fbfae5e288620611 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -8,6 +8,7 @@ typedef int pcre;
 typedef int pcre_extra;
 #endif
 #include "kwset.h"
+#include "thread-utils.h"
 
 enum grep_pat_token {
        GREP_PATTERN,
@@ -115,6 +116,7 @@ struct grep_opt {
        int show_hunk_mark;
        int file_break;
        int heading;
+       int use_threads;
        void *priv;
 
        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
 extern struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
 extern int grep_threads_ok(const struct grep_opt *opt);
 
+#ifndef NO_PTHREADS
+/*
+ * Mutex used around access to the attributes machinery if
+ * opt->use_threads.  Must be initialized/destroyed by callers!
+ */
+extern pthread_mutex_t grep_attr_mutex;
+#endif
+
 #endif
index 81263b78516cbe2949ad7e426a5e44af188cccdd..7ba5b16f99443c0dc5aaff8fbb4ce4ad8874a27c 100755 (executable)
@@ -523,6 +523,20 @@ test_expect_success 'grep -W' '
        test_cmp expected actual
 '
 
+cat >expected <<EOF
+hello.c=       printf("Hello world.\n");
+hello.c:       return 0;
+hello.c-       /* char ?? */
+EOF
+
+test_expect_success 'grep -W with userdiff' '
+       test_when_finished "rm -f .gitattributes" &&
+       git config diff.custom.xfuncname "(printf.*|})$" &&
+       echo "hello.c diff=custom" >.gitattributes &&
+       git grep -W return >actual &&
+       test_cmp expected actual
+'
+
 test_expect_success 'grep from a subdirectory to search wider area (1)' '
        mkdir -p s &&
        (