about summary refs log tree commit diff stats
path: root/src/libtools/threads.c
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-06-19 11:15:20 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-06-19 11:15:20 +0200
commit1791c0937aedfabc496e12a41bfcf43cfb154ee7 (patch)
treef170f7e2481c72467096c957099a6d5e5fc3c0eb /src/libtools/threads.c
parentc2dd6a0c6a2aee17e9f9f07f8a2a24e2efbbac39 (diff)
downloadbox64-1791c0937aedfabc496e12a41bfcf43cfb154ee7.tar.gz
box64-1791c0937aedfabc496e12a41bfcf43cfb154ee7.zip
Improved mutex handling
Diffstat (limited to 'src/libtools/threads.c')
-rwxr-xr-xsrc/libtools/threads.c142
1 files changed, 93 insertions, 49 deletions
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index cedab70b..7b243d58 100755
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -733,18 +733,89 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m) {
 	return m;
 }
 #else
-//#define TRACK_MUTEX
-// mutex alignment
-#ifdef TRACK_MUTEX
-KHASH_MAP_INIT_INT(mutex, pthread_mutex_t*)
+#define MUTEXES_SIZE	64
+typedef struct mutexes_block_s {
+	pthread_mutex_t mutexes[MUTEXES_SIZE];
+	uint8_t	taken[MUTEXES_SIZE];
+	struct mutexes_block_s* next;
+	int n_free, pad;
+} mutexes_block_t;
+
+static mutexes_block_t *mutexes = NULL;
+static pthread_mutex_t mutex_mutexes = PTHREAD_MUTEX_INITIALIZER;
+
+static mutexes_block_t* NewMutexesBlock()
+{
+	mutexes_block_t* ret = (mutexes_block_t*)calloc(1, sizeof(mutexes_block_t));
+	ret->n_free = MUTEXES_SIZE;
+	return ret;
+}
+
+static int NewMutex() {
+	pthread_mutex_lock(&mutex_mutexes);
+	if(!mutexes) {
+		mutexes = NewMutexesBlock();
+	}
+	int j = 0;
+	mutexes_block_t* m = mutexes;
+	while(!m->n_free) {
+		if(!m->next) {
+			m->next = NewMutexesBlock();
+		}
+		++j;
+		m = m->next;
+	}
+	--m->n_free;
+	for (int i=0; i<MUTEXES_SIZE; ++i)
+		if(!m->taken[i]) {
+			m->taken[i] = 1;
+			pthread_mutex_unlock(&mutex_mutexes);
+			return j*MUTEXES_SIZE + i;
+		}
+	pthread_mutex_unlock(&mutex_mutexes);
+	printf_log(LOG_NONE, "Error: NewMutex unreachable part reached\n");
+	return (int)-1;	// error!!!!
+}
+
+void FreeMutex(int k)
+{
+	if(!mutexes)
+		return;	//???
+	pthread_mutex_lock(&mutex_mutexes);
+	mutexes_block_t* m = mutexes;
+	for(int i=0; i<k/MUTEXES_SIZE; ++i)
+		m = m->next;
+	m->taken[k%MUTEXES_SIZE] = 0;
+	++m->n_free;
+	pthread_mutex_unlock(&mutex_mutexes);
+}
+
+void FreeAllMutexes(mutexes_block_t* m)
+{
+	if(!m)
+		return;
+	FreeAllMutexes(m->next);
+	// should destroy all mutexes also?
+	free(m);
+}
+
+pthread_mutex_t* GetMutex(int k)
+{
+	if(!mutexes)
+		return NULL;	//???
+	mutexes_block_t* m = mutexes;
+	for(int i=0; i<k/MUTEXES_SIZE; ++i)
+		m = m->next;
+	return &m->mutexes[k%MUTEXES_SIZE];
+}
 
-static kh_mutex_t* unaligned_mutex = NULL;
-#endif
 // x86_64 pthread_mutex_t is 40 bytes (ARM64 one is 48)
 typedef struct aligned_mutex_s {
-	uint64_t	dummy;
-	pthread_mutex_t *m;
 	struct aligned_mutex_s *self;
+	uint64_t	dummy;
+	int kind;	// kind position on x86_64
+	int k;
+	pthread_mutex_t* m;
 	uint64_t sign;
 } aligned_mutex_t;
 #define SIGNMTX *(uint64_t*)"BOX64MTX"
@@ -756,27 +827,26 @@ pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
 	aligned_mutex_t* am = (aligned_mutex_t*)m;
 	if(init && (am->sign==SIGNMTX && am->self==am))
 		return am->m;
-	#ifdef TRACK_MUTEX
-	khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
-	if(k!=kh_end(unaligned_mutex))
-		return kh_value(unaligned_mutex, k);
-	int r;
-	k = kh_put(mutex, unaligned_mutex, (uintptr_t)m, &r);
-	pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
-	#else
-	pthread_mutex_t* ret = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
-	#endif
+	int k = NewMutex();
+	// check again, it might be created now becayse NewMutex is under mutex
+	if(init && (am->sign==SIGNMTX && am->self==am)) {
+		FreeMutex(k);
+		return am->m;
+	}
+	pthread_mutex_t* ret = GetMutex(k);
+
 	if(init) {
 		if(am->sign == SIGNMTX) {
 			int kind = ((int*)am->m)[3+__PTHREAD_MUTEX_HAVE_PREV];	// extract kind from original mutex
 			((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind;		// inject in new one (i.e. "init" it)
 		} else {
-			int kind = ((int*)m)[4];	// extract kind from original mutex
+			int kind = am->kind;	// extract kind from original mutex
 			((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind;		// inject in new one (i.e. "init" it)
 		}
 	}
 	am->self = am;
 	am->sign = SIGNMTX;
+	am->k = k;
 	am->m = ret;
 	return ret;
 }
@@ -788,28 +858,13 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
 EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
 {
 	aligned_mutex_t* am = (aligned_mutex_t*)m;
-	#ifdef TRACK_MUTEX
-	if(am->sign==SIGNMTX) {
-		am->sign = 0;
-		am->m = NULL;
-	}
-	khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
-	if(k!=kh_end(unaligned_mutex)) {
-		pthread_mutex_t *n = kh_value(unaligned_mutex, k);
-		kh_del(mutex, unaligned_mutex, k);
-		int ret = pthread_mutex_destroy(n);
-		free(n);
-		return ret;
-	}
-	return pthread_mutex_destroy(m);
-	#else
 	if(am->sign!=SIGNMTX) {
 		return 1;	//???
 	}
 	int ret = pthread_mutex_destroy(am->m);
-	free(am->m);
+	FreeMutex(am->k);
+	am->sign = 0;
 	return ret;
-	#endif
 }
 typedef union my_mutexattr_s {
 	int					x86;
@@ -1069,11 +1124,6 @@ void init_pthread_helper()
 {
 	InitCancelThread();
 	pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
-#ifndef NOALIGN
-	#ifdef TRACK_MUTEX
-	unaligned_mutex = kh_init(mutex);
-	#endif
-#endif
 }
 
 void fini_pthread_helper(box64context_t* context)
@@ -1081,14 +1131,8 @@ void fini_pthread_helper(box64context_t* context)
 	FreeCancelThread(context);
 	CleanStackSize(context);
 #ifndef NOALIGN
-	#ifdef TRACK_MUTEX
-	pthread_mutex_t *m;
-	kh_foreach_value(unaligned_mutex, m, 
-		pthread_mutex_destroy(m);
-		free(m);
-	);
-	kh_destroy(mutex, unaligned_mutex);
-	#endif
+	FreeAllMutexes(mutexes);
+	mutexes = NULL;
 #endif
 	emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
 	if(ejb) {