24
24
#include "submodule.h"
25
25
#include "submodule-config.h"
26
26
#include "object-store.h"
27
+ #include "packfile.h"
27
28
28
29
static char const * const grep_usage [] = {
29
30
N_ ("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]" ),
@@ -32,7 +33,6 @@ static char const * const grep_usage[] = {
32
33
33
34
static int recurse_submodules ;
34
35
35
- #define GREP_NUM_THREADS_DEFAULT 8
36
36
static int num_threads ;
37
37
38
38
static pthread_t * threads ;
@@ -91,18 +91,18 @@ static pthread_cond_t cond_result;
91
91
92
92
static int skip_first_line ;
93
93
94
- static void add_work (struct grep_opt * opt , const struct grep_source * gs )
94
+ static void add_work (struct grep_opt * opt , struct grep_source * gs )
95
95
{
96
+ if (opt -> binary != GREP_BINARY_TEXT )
97
+ grep_source_load_driver (gs , opt -> repo -> index );
98
+
96
99
grep_lock ();
97
100
98
101
while ((todo_end + 1 ) % ARRAY_SIZE (todo ) == todo_done ) {
99
102
pthread_cond_wait (& cond_write , & grep_mutex );
100
103
}
101
104
102
105
todo [todo_end ].source = * gs ;
103
- if (opt -> binary != GREP_BINARY_TEXT )
104
- grep_source_load_driver (& todo [todo_end ].source ,
105
- opt -> repo -> index );
106
106
todo [todo_end ].done = 0 ;
107
107
strbuf_reset (& todo [todo_end ].out );
108
108
todo_end = (todo_end + 1 ) % ARRAY_SIZE (todo );
@@ -200,12 +200,12 @@ static void start_threads(struct grep_opt *opt)
200
200
int i ;
201
201
202
202
pthread_mutex_init (& grep_mutex , NULL );
203
- pthread_mutex_init (& grep_read_mutex , NULL );
204
203
pthread_mutex_init (& grep_attr_mutex , NULL );
205
204
pthread_cond_init (& cond_add , NULL );
206
205
pthread_cond_init (& cond_write , NULL );
207
206
pthread_cond_init (& cond_result , NULL );
208
207
grep_use_locks = 1 ;
208
+ enable_obj_read_lock ();
209
209
210
210
for (i = 0 ; i < ARRAY_SIZE (todo ); i ++ ) {
211
211
strbuf_init (& todo [i ].out , 0 );
@@ -257,12 +257,12 @@ static int wait_all(void)
257
257
free (threads );
258
258
259
259
pthread_mutex_destroy (& grep_mutex );
260
- pthread_mutex_destroy (& grep_read_mutex );
261
260
pthread_mutex_destroy (& grep_attr_mutex );
262
261
pthread_cond_destroy (& cond_add );
263
262
pthread_cond_destroy (& cond_write );
264
263
pthread_cond_destroy (& cond_result );
265
264
grep_use_locks = 0 ;
265
+ disable_obj_read_lock ();
266
266
267
267
return hit ;
268
268
}
@@ -295,16 +295,6 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
295
295
return st ;
296
296
}
297
297
298
- static void * lock_and_read_oid_file (const struct object_id * oid , enum object_type * type , unsigned long * size )
299
- {
300
- void * data ;
301
-
302
- grep_read_lock ();
303
- data = read_object_file (oid , type , size );
304
- grep_read_unlock ();
305
- return data ;
306
- }
307
-
308
298
static int grep_oid (struct grep_opt * opt , const struct object_id * oid ,
309
299
const char * filename , int tree_name_len ,
310
300
const char * path )
@@ -407,30 +397,28 @@ static int grep_submodule(struct grep_opt *opt,
407
397
{
408
398
struct repository subrepo ;
409
399
struct repository * superproject = opt -> repo ;
410
- const struct submodule * sub = submodule_from_path (superproject ,
411
- & null_oid , path );
400
+ const struct submodule * sub ;
412
401
struct grep_opt subopt ;
413
402
int hit ;
414
403
415
- /*
416
- * NEEDSWORK: submodules functions need to be protected because they
417
- * access the object store via config_from_gitmodules(): the latter
418
- * uses get_oid() which, for now, relies on the global the_repository
419
- * object.
420
- */
421
- grep_read_lock ();
404
+ sub = submodule_from_path (superproject , & null_oid , path );
422
405
423
- if (!is_submodule_active (superproject , path )) {
424
- grep_read_unlock ();
406
+ if (!is_submodule_active (superproject , path ))
425
407
return 0 ;
426
- }
427
408
428
- if (repo_submodule_init (& subrepo , superproject , sub )) {
429
- grep_read_unlock ();
409
+ if (repo_submodule_init (& subrepo , superproject , sub ))
430
410
return 0 ;
431
- }
432
411
433
- repo_read_gitmodules (& subrepo );
412
+ /*
413
+ * NEEDSWORK: repo_read_gitmodules() might call
414
+ * add_to_alternates_memory() via config_from_gitmodules(). This
415
+ * operation causes a race condition with concurrent object readings
416
+ * performed by the worker threads. That's why we need obj_read_lock()
417
+ * here. It should be removed once it's no longer necessary to add the
418
+ * subrepo's odbs to the in-memory alternates list.
419
+ */
420
+ obj_read_lock ();
421
+ repo_read_gitmodules (& subrepo , 0 );
434
422
435
423
/*
436
424
* NEEDSWORK: This adds the submodule's object directory to the list of
@@ -443,7 +431,7 @@ static int grep_submodule(struct grep_opt *opt,
443
431
* object.
444
432
*/
445
433
add_to_alternates_memory (subrepo .objects -> odb -> path );
446
- grep_read_unlock ();
434
+ obj_read_unlock ();
447
435
448
436
memcpy (& subopt , opt , sizeof (subopt ));
449
437
subopt .repo = & subrepo ;
@@ -455,14 +443,12 @@ static int grep_submodule(struct grep_opt *opt,
455
443
unsigned long size ;
456
444
struct strbuf base = STRBUF_INIT ;
457
445
446
+ obj_read_lock ();
458
447
object = parse_object_or_die (oid , oid_to_hex (oid ));
459
-
460
- grep_read_lock ();
448
+ obj_read_unlock ();
461
449
data = read_object_with_reference (& subrepo ,
462
450
& object -> oid , tree_type ,
463
451
& size , NULL );
464
- grep_read_unlock ();
465
-
466
452
if (!data )
467
453
die (_ ("unable to read tree (%s)" ), oid_to_hex (& object -> oid ));
468
454
@@ -587,7 +573,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
587
573
void * data ;
588
574
unsigned long size ;
589
575
590
- data = lock_and_read_oid_file (& entry .oid , & type , & size );
576
+ data = read_object_file (& entry .oid , & type , & size );
591
577
if (!data )
592
578
die (_ ("unable to read tree (%s)" ),
593
579
oid_to_hex (& entry .oid ));
@@ -625,12 +611,9 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
625
611
struct strbuf base ;
626
612
int hit , len ;
627
613
628
- grep_read_lock ();
629
614
data = read_object_with_reference (opt -> repo ,
630
615
& obj -> oid , tree_type ,
631
616
& size , NULL );
632
- grep_read_unlock ();
633
-
634
617
if (!data )
635
618
die (_ ("unable to read tree (%s)" ), oid_to_hex (& obj -> oid ));
636
619
@@ -659,13 +642,18 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
659
642
660
643
for (i = 0 ; i < nr ; i ++ ) {
661
644
struct object * real_obj ;
645
+
646
+ obj_read_lock ();
662
647
real_obj = deref_tag (opt -> repo , list -> objects [i ].item ,
663
648
NULL , 0 );
649
+ obj_read_unlock ();
664
650
665
651
/* load the gitmodules file for this rev */
666
652
if (recurse_submodules ) {
667
653
submodule_free (opt -> repo );
654
+ obj_read_lock ();
668
655
gitmodules_config_oid (& real_obj -> oid );
656
+ obj_read_unlock ();
669
657
}
670
658
if (grep_object (opt , pathspec , real_obj , list -> objects [i ].name ,
671
659
list -> objects [i ].path )) {
@@ -1065,7 +1053,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1065
1053
pathspec .recursive = 1 ;
1066
1054
pathspec .recurse_submodules = !!recurse_submodules ;
1067
1055
1068
- if (list .nr || cached || show_in_pager ) {
1056
+ if (recurse_submodules && untracked )
1057
+ die (_ ("--untracked not supported with --recurse-submodules" ));
1058
+
1059
+ if (show_in_pager ) {
1069
1060
if (num_threads > 1 )
1070
1061
warning (_ ("invalid option combination, ignoring --threads" ));
1071
1062
num_threads = 1 ;
@@ -1075,7 +1066,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1075
1066
} else if (num_threads < 0 )
1076
1067
die (_ ("invalid number of threads specified (%d)" ), num_threads );
1077
1068
else if (num_threads == 0 )
1078
- num_threads = HAVE_THREADS ? GREP_NUM_THREADS_DEFAULT : 1 ;
1069
+ num_threads = HAVE_THREADS ? online_cpus () : 1 ;
1079
1070
1080
1071
if (num_threads > 1 ) {
1081
1072
if (!HAVE_THREADS )
@@ -1084,6 +1075,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1084
1075
&& (opt .pre_context || opt .post_context ||
1085
1076
opt .file_break || opt .funcbody ))
1086
1077
skip_first_line = 1 ;
1078
+
1079
+ /*
1080
+ * Pre-read gitmodules (if not read already) and force eager
1081
+ * initialization of packed_git to prevent racy lazy
1082
+ * reading/initialization once worker threads are started.
1083
+ */
1084
+ if (recurse_submodules )
1085
+ repo_read_gitmodules (the_repository , 1 );
1086
+ if (startup_info -> have_repository )
1087
+ (void )get_packed_git (the_repository );
1088
+
1087
1089
start_threads (& opt );
1088
1090
} else {
1089
1091
/*
@@ -1118,9 +1120,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1118
1120
}
1119
1121
}
1120
1122
1121
- if (recurse_submodules && untracked )
1122
- die (_ ("--untracked not supported with --recurse-submodules" ));
1123
-
1124
1123
if (!show_in_pager && !opt .status_only )
1125
1124
setup_pager ();
1126
1125
0 commit comments