trace2: refactor setting process starting time
Create trace2_initialize_clock() and call from main() to capture process start time in isolation and before other sub-systems are ready. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									1703751f21
								
							
						
					
					
						commit
						a089724958
					
				|  | @ -160,17 +160,23 @@ purposes. | |||
|  | ||||
| These are concerned with the lifetime of the overall git process. | ||||
|  | ||||
| `void trace2_initialize_clock()`:: | ||||
|  | ||||
| 	Initialize the Trace2 start clock and nothing else.  This should | ||||
| 	be called at the very top of main() to capture the process start | ||||
| 	time and reduce startup order dependencies. | ||||
|  | ||||
| `void trace2_initialize()`:: | ||||
|  | ||||
| 	Determines if any Trace2 Targets should be enabled and | ||||
| 	initializes the Trace2 facility.  This includes starting the | ||||
| 	elapsed time clocks and thread local storage (TLS). | ||||
| 	initializes the Trace2 facility.  This includes setting up the | ||||
| 	Trace2 thread local storage (TLS). | ||||
| + | ||||
| This function emits a "version" message containing the version of git | ||||
| and the Trace2 protocol. | ||||
| + | ||||
| This function should be called from `main()` as early as possible in | ||||
| the life of the process. | ||||
| the life of the process after essential process initialization. | ||||
|  | ||||
| `int trace2_is_enabled()`:: | ||||
|  | ||||
|  |  | |||
|  | @ -27,6 +27,8 @@ int main(int argc, const char **argv) | |||
| { | ||||
| 	int result; | ||||
|  | ||||
| 	trace2_initialize_clock(); | ||||
|  | ||||
| 	/* | ||||
| 	 * Always open file descriptors 0/1/2 to avoid clobbering files | ||||
| 	 * in die().  It also avoids messing up when the pipes are dup'ed | ||||
|  |  | |||
|  | @ -2569,6 +2569,8 @@ void mingw_startup(void) | |||
| 	wchar_t **wenv, **wargv; | ||||
| 	_startupinfo si; | ||||
|  | ||||
| 	trace2_initialize_clock(); | ||||
|  | ||||
| 	maybe_redirect_std_handles(); | ||||
|  | ||||
| 	/* get wide char arguments and environment */ | ||||
|  |  | |||
							
								
								
									
										7
									
								
								trace2.c
								
								
								
								
							
							
						
						
									
										7
									
								
								trace2.c
								
								
								
								
							|  | @ -142,6 +142,11 @@ static void tr2main_signal_handler(int signo) | |||
| 	raise(signo); | ||||
| } | ||||
|  | ||||
| void trace2_initialize_clock(void) | ||||
| { | ||||
| 	tr2tls_start_process_clock(); | ||||
| } | ||||
|  | ||||
| void trace2_initialize_fl(const char *file, int line) | ||||
| { | ||||
| 	struct tr2_tgt *tgt_j; | ||||
|  | @ -428,7 +433,7 @@ void trace2_thread_start_fl(const char *file, int line, const char *thread_name) | |||
| 	us_now = getnanotime() / 1000; | ||||
| 	us_elapsed_absolute = tr2tls_absolute_elapsed(us_now); | ||||
|  | ||||
| 	tr2tls_create_self(thread_name); | ||||
| 	tr2tls_create_self(thread_name, us_now); | ||||
|  | ||||
| 	for_each_wanted_builtin (j, tgt_j) | ||||
| 		if (tgt_j->pfn_thread_start_fl) | ||||
|  |  | |||
							
								
								
									
										17
									
								
								trace2.h
								
								
								
								
							
							
						
						
									
										17
									
								
								trace2.h
								
								
								
								
							|  | @ -19,6 +19,23 @@ struct json_writer; | |||
|  * [] trace2_printf*    -- legacy trace[1] messages. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Initialize the TRACE2 clock and do nothing else, in particular | ||||
|  * no mallocs, no system inspection, and no environment inspection. | ||||
|  * | ||||
|  * This should be called at the very top of main() to capture the | ||||
|  * process start time.  This is intended to reduce chicken-n-egg | ||||
|  * bootstrap pressure. | ||||
|  * | ||||
|  * It is safe to call this more than once.  This allows capturing | ||||
|  * absolute startup costs on Windows which uses a little trickery | ||||
|  * to do setup work before common-main.c:main() is called. | ||||
|  * | ||||
|  * The main trace2_initialize_fl() may be called a little later | ||||
|  * after more infrastructure is established. | ||||
|  */ | ||||
| void trace2_initialize_clock(void); | ||||
|  | ||||
| /* | ||||
|  * Initialize TRACE2 tracing facility if any of the builtin TRACE2 | ||||
|  * targets are enabled in the environment.  Emits a 'version' event. | ||||
|  |  | |||
|  | @ -10,16 +10,30 @@ | |||
| #define TR2_REGION_NESTING_INITIAL_SIZE (100) | ||||
|  | ||||
| static struct tr2tls_thread_ctx *tr2tls_thread_main; | ||||
| static uint64_t tr2tls_us_start_main; | ||||
| static uint64_t tr2tls_us_start_process; | ||||
|  | ||||
| static pthread_mutex_t tr2tls_mutex; | ||||
| static pthread_key_t tr2tls_key; | ||||
|  | ||||
| static int tr2_next_thread_id; /* modify under lock */ | ||||
|  | ||||
| struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name) | ||||
| void tr2tls_start_process_clock(void) | ||||
| { | ||||
| 	if (tr2tls_us_start_process) | ||||
| 		return; | ||||
|  | ||||
| 	/* | ||||
| 	 * Keep the absolute start time of the process (i.e. the main | ||||
| 	 * process) in a fixed variable since other threads need to | ||||
| 	 * access it.  This allows them to do that without a lock on | ||||
| 	 * main thread's array data (because of reallocs). | ||||
| 	 */ | ||||
| 	tr2tls_us_start_process = getnanotime() / 1000; | ||||
| } | ||||
|  | ||||
| struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name, | ||||
| 					     uint64_t us_thread_start) | ||||
| { | ||||
| 	uint64_t us_now = getnanotime() / 1000; | ||||
| 	struct tr2tls_thread_ctx *ctx = xcalloc(1, sizeof(*ctx)); | ||||
|  | ||||
| 	/* | ||||
|  | @ -29,7 +43,7 @@ struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name) | |||
| 	 */ | ||||
| 	ctx->alloc = TR2_REGION_NESTING_INITIAL_SIZE; | ||||
| 	ctx->array_us_start = (uint64_t *)xcalloc(ctx->alloc, sizeof(uint64_t)); | ||||
| 	ctx->array_us_start[ctx->nr_open_regions++] = us_now; | ||||
| 	ctx->array_us_start[ctx->nr_open_regions++] = us_thread_start; | ||||
|  | ||||
| 	ctx->thread_id = tr2tls_locked_increment(&tr2_next_thread_id); | ||||
|  | ||||
|  | @ -55,7 +69,7 @@ struct tr2tls_thread_ctx *tr2tls_get_self(void) | |||
| 	 * here and silently continue. | ||||
| 	 */ | ||||
| 	if (!ctx) | ||||
| 		ctx = tr2tls_create_self("unknown"); | ||||
| 		ctx = tr2tls_create_self("unknown", getnanotime() / 1000); | ||||
|  | ||||
| 	return ctx; | ||||
| } | ||||
|  | @ -124,22 +138,18 @@ uint64_t tr2tls_absolute_elapsed(uint64_t us) | |||
| 	if (!tr2tls_thread_main) | ||||
| 		return 0; | ||||
|  | ||||
| 	return us - tr2tls_us_start_main; | ||||
| 	return us - tr2tls_us_start_process; | ||||
| } | ||||
|  | ||||
| void tr2tls_init(void) | ||||
| { | ||||
| 	tr2tls_start_process_clock(); | ||||
|  | ||||
| 	pthread_key_create(&tr2tls_key, NULL); | ||||
| 	init_recursive_mutex(&tr2tls_mutex); | ||||
|  | ||||
| 	tr2tls_thread_main = tr2tls_create_self("main"); | ||||
| 	/* | ||||
| 	 * Keep a copy of the absolute start time of the main thread | ||||
| 	 * in a fixed variable since other threads need to access it. | ||||
| 	 * This also eliminates the need to lock accesses to the main | ||||
| 	 * thread's array (because of reallocs). | ||||
| 	 */ | ||||
| 	tr2tls_us_start_main = tr2tls_thread_main->array_us_start[0]; | ||||
| 	tr2tls_thread_main = | ||||
| 		tr2tls_create_self("main", tr2tls_us_start_process); | ||||
| } | ||||
|  | ||||
| void tr2tls_release(void) | ||||
|  |  | |||
|  | @ -31,7 +31,8 @@ struct tr2tls_thread_ctx { | |||
|  * In this and all following functions the term "self" refers to the | ||||
|  * current thread. | ||||
|  */ | ||||
| struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name); | ||||
| struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_name, | ||||
| 					     uint64_t us_thread_start); | ||||
|  | ||||
| /* | ||||
|  * Get our TLS data. | ||||
|  | @ -94,4 +95,9 @@ void tr2tls_release(void); | |||
|  */ | ||||
| int tr2tls_locked_increment(int *p); | ||||
|  | ||||
| /* | ||||
|  * Capture the process start time and do nothing else. | ||||
|  */ | ||||
| void tr2tls_start_process_clock(void); | ||||
|  | ||||
| #endif /* TR2_TLS_H */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Jeff Hostetler
						Jeff Hostetler