| 
					
				 | 
			
			
				@@ -1153,6 +1153,15 @@ mg_current_thread_id(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static uint64_t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+mg_get_current_time_ns() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct timespec tsnow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	clock_gettime(CLOCK_REALTIME, &tsnow); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #if defined(__GNUC__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* Show no warning in case system functions are not used. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #pragma GCC diagnostic pop 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1174,15 +1183,13 @@ static void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	va_list args; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	struct timespec tsnow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	uint64_t nsnow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	static uint64_t nslast; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/* Get some operating system independent thread id */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	unsigned long thread_id = mg_current_thread_id(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	clock_gettime(CLOCK_REALTIME, &tsnow); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	nsnow = (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	msmow = mg_get_current_time(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	flockfile(stdout); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	printf("*** %lu.%09lu %12" INT64_FMT " %lu %s:%u: ", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3580,7 +3587,6 @@ pthread_cond_timedwait(pthread_cond_t *cv, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	struct mg_workerTLS **ptls, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	int ok; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	struct timespec tsnow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	int64_t nsnow, nswaitabs, nswaitrel; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	DWORD mswaitrel; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3594,8 +3600,7 @@ pthread_cond_timedwait(pthread_cond_t *cv, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	LeaveCriticalSection(&cv->threadIdSec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (abstime) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		clock_gettime(CLOCK_REALTIME, &tsnow); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		nsnow = (((int64_t)tsnow.tv_sec) * 1000000000) + tsnow.tv_nsec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		nsnow = mg_get_current_time_ns(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		nswaitabs = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		    (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		nswaitrel = nswaitabs - nsnow; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -4601,18 +4606,12 @@ get_random(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	static uint64_t lfsr = 0; /* Linear feedback shift register */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	static uint64_t lcg = 0;  /* Linear congruential generator */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	struct timespec now; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	memset(&now, 0, sizeof(now)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	clock_gettime(CLOCK_MONOTONIC, &now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (lfsr == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		/* lfsr will be only 0 if has not been initialized, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		 * so this code is called only once. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		lfsr = (((uint64_t)now.tv_sec) << 21) ^ ((uint64_t)now.tv_nsec) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		       ^ ((uint64_t)(ptrdiff_t)&now) ^ (((uint64_t)time(NULL)) << 33); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		lcg = (((uint64_t)now.tv_sec) << 25) + (uint64_t)now.tv_nsec 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		      + (uint64_t)(ptrdiff_t)&now; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		lfsr = mg_get_current_time_ns(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		lcg = mg_get_current_time_ns(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		/* Get the next step of both random number generators. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		lfsr = (lfsr >> 1) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -4680,7 +4679,7 @@ push(struct mg_context *ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      int len, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      double timeout) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	struct timespec start, now; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint64_t start, now, timeout_ns; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	int n, err; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #ifdef _WIN32 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -4690,9 +4689,10 @@ push(struct mg_context *ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (timeout > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		memset(&start, 0, sizeof(start)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		memset(&now, 0, sizeof(now)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		clock_gettime(CLOCK_MONOTONIC, &start); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		start = mg_get_current_time_ns(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		timeout_ns = (uint64_t)(timeout * 1.0E9); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		timeout_ns = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (ctx == NULL) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -4777,11 +4777,11 @@ push(struct mg_context *ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		/* Only in case n=0 (timeout), repeat calling the write function */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (timeout > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			clock_gettime(CLOCK_MONOTONIC, &now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (timeout >= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			now = mg_get_current_time_ns(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} while ((timeout <= 0) || ((start - now) <= timeout_ns)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	              used */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -4996,16 +4996,18 @@ pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	int n, nread = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	double timeout = -1.0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	double dt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	struct timespec start_time, now; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint64_t start_time, now, timeout_ns; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (conn->ctx->config[REQUEST_TIMEOUT]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		clock_gettime(CLOCK_MONOTONIC, &start_time); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (timeout >= 0.0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		start_time = mg_get_current_time_ns(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		timeout_ns = (uint64_t)(timeout * 1.0E9); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		/* The variable is not used, but if it is left uninitialized, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		 * we get a spurious warning. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		memset(&start_time, 0, sizeof(start_time)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		start_time = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	while (len > 0 && conn->ctx->stop_flag == 0) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -5017,11 +5019,9 @@ pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} else if (n == -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			/* timeout */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if (timeout > 0.0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				clock_gettime(CLOCK_MONOTONIC, &now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				dt = (double)(now.tv_sec - start_time.tv_sec) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				     + 1.0E-9 * (double)(now.tv_nsec - start_time.tv_nsec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if (dt < timeout) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (timeout >= 0.0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				now = mg_get_current_time_ns(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if ((now - start_time) <= timeout_ns) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 |