[LTP] [PATCH v2 1/2] Enhance Thread Safety in Record Counting

Vishal Chourasia vishalc@linux.ibm.com
Tue Aug 15 11:30:47 CEST 2023


This patch addresses a thread safety concern in record counting. Originally,
the design leveraged a global `records_read` variable to aggregate counts from
different threads. This method was devoid of locks, leading to potential race
conditions. To remedy this:

- Introduced a thread-local variable, `records_thread`, for each thread to
  store its record count.
- Upon thread joining, the accumulated total from each `records_thread` is safely
  captured, ensuring accurate and race-free counting.

The overall change enhances thread safety, especially in multi-threaded
environments, and ensures the correct count is fetched without race conditions.

Signed-off-by: Vishal Chourasia <vishalc@linux.ibm.com>
Reviewed-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Reviewed-by: Shrikanth Hegde <sshegde@linux.vnet.ibm.com>
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Suggested-by: Cyril Hrubis <chrubis@suse.cz>
---
 utils/benchmark/ebizzy-0.3/ebizzy.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/utils/benchmark/ebizzy-0.3/ebizzy.c b/utils/benchmark/ebizzy-0.3/ebizzy.c
index 54b047130..ae0981fbd 100644
--- a/utils/benchmark/ebizzy-0.3/ebizzy.c
+++ b/utils/benchmark/ebizzy-0.3/ebizzy.c
@@ -50,6 +50,7 @@
 #include <time.h>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <stdint.h>
 
 #include "ebizzy.h"
 
@@ -83,7 +84,6 @@ static char **hole_mem;
 static unsigned int page_size;
 static time_t start_time;
 static volatile int threads_go;
-static unsigned int records_read;
 
 static void usage(void)
 {
@@ -366,13 +366,13 @@ static inline unsigned int rand_num(unsigned int max, unsigned int *state)
  *
  */
 
-static unsigned int search_mem(void)
+static uintptr_t search_mem(void)
 {
 	record_t key, *found;
 	record_t *src, *copy;
 	unsigned int chunk;
 	size_t copy_size = chunk_size;
-	unsigned int i;
+	uintptr_t i;
 	unsigned int state = 0;
 
 	for (i = 0; threads_go == 1; i++) {
@@ -423,6 +423,8 @@ static unsigned int search_mem(void)
 
 static void *thread_run(void *arg __attribute__((unused)))
 {
+	uintptr_t records_thread;
+
 	if (verbose > 1)
 		printf("Thread started\n");
 
@@ -430,13 +432,13 @@ static void *thread_run(void *arg __attribute__((unused)))
 
 	while (threads_go == 0) ;
 
-	records_read += search_mem();
+	records_thread = search_mem();
 
 	if (verbose > 1)
 		printf("Thread finished, %f seconds\n",
 		       difftime(time(NULL), start_time));
 
-	return NULL;
+	return (void *)records_thread;
 }
 
 static struct timeval difftimeval(struct timeval *end, struct timeval *start)
@@ -454,6 +456,7 @@ static void start_threads(void)
 	unsigned int i;
 	struct rusage start_ru, end_ru;
 	struct timeval usr_time, sys_time;
+	uintptr_t records_read = 0;
 	int err;
 
 	if (verbose)
@@ -484,18 +487,20 @@ static void start_threads(void)
 	 */
 
 	for (i = 0; i < threads; i++) {
-		err = pthread_join(thread_array[i], NULL);
+		uintptr_t record_thread;
+		err = pthread_join(thread_array[i], (void *)&record_thread);
 		if (err) {
 			fprintf(stderr, "Error joining thread %d\n", i);
 			exit(1);
 		}
+		records_read += record_thread;
 	}
 
 	if (verbose)
 		printf("Threads finished\n");
 
-	printf("%u records/s\n",
-	       (unsigned int)(((double)records_read) / elapsed));
+	printf("%tu records/s\n",
+	       (uintptr_t)(((double)records_read) / elapsed));
 
 	usr_time = difftimeval(&end_ru.ru_utime, &start_ru.ru_utime);
 	sys_time = difftimeval(&end_ru.ru_stime, &start_ru.ru_stime);
-- 
2.39.3



More information about the ltp mailing list