aboutsummaryrefslogtreecommitdiff
path: root/src/std/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/std/thread.c')
-rw-r--r--src/std/thread.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/src/std/thread.c b/src/std/thread.c
index 64a7f1b..ba67463 100644
--- a/src/std/thread.c
+++ b/src/std/thread.c
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <assert.h>
#include <errno.h>
+#include <string.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/syscall.h>
@@ -48,12 +49,21 @@ int amal_thread_deinit(amal_thread *self) {
if(self->cancellable) {
r1 = pthread_cancel(self->thread_id);
+ /* thread deinit on a thread that has not been started shouldn't be an error */
+ if(r1 == ESRCH)
+ r1 = 0;
+ if(r1 != 0)
+ amal_log_error("amal_thread_deinit: failed to cancel thread, error: %s", strerror(r1));
self->cancellable = bool_false;
}
+
if(self->destroyable) {
r2 = pthread_attr_destroy(&self->thread_attr);
+ if(r2 != 0)
+ amal_log_error("amal_thread_deinit: failed to destroy thread attributes, error: %s", strerror(r2));
self->destroyable = bool_false;
}
+
return r1 != 0 ? r1 : r2;
}
@@ -73,20 +83,35 @@ int amal_thread_detach(amal_thread *self) {
int amal_thread_join(amal_thread *self, void **result) {
int result_err;
int thread_type;
- if((result_err = pthread_attr_getdetachstate(&self->thread_attr, &thread_type)) != 0)
+
+ if((result_err = pthread_attr_getdetachstate(&self->thread_attr, &thread_type)) != 0) {
+ amal_log_error("amal_thread_join: failed to get detach state, error: %d", result_err);
return result_err;
- if(thread_type != PTHREAD_CREATE_JOINABLE)
+ }
+
+ if(thread_type != PTHREAD_CREATE_JOINABLE) {
+ amal_log_error("amal_thread_join: thread not joinable type");
return AMAL_THREAD_NOT_JOINABLE;
- if((result_err = pthread_join(self->thread_id, result)) != 0)
+ }
+
+ if((result_err = pthread_join(self->thread_id, result)) != 0) {
+ /* Joining a thread that is not joinable shouldn't be an error */
+ if(result_err == ESRCH)
+ goto cleanup;
+ amal_log_error("amal_thread_join: failed to join thread %llu, error: %s", self->thread_id, strerror(result_err));
return result_err == EINVAL ? AMAL_THREAD_NOT_JOINABLE : result_err;
+ }
+
+ cleanup:
self->cancellable = bool_false;
return 0;
}
void amal_mutex_init(amal_mutex *self) {
pthread_mutex_init(&self->mutex, NULL);
- /* TODO: pthread_mutex_destroy in amal_mutex_deinit */
self->lock_identifier = NULL;
+ self->locked = bool_false;
+ self->owner_thread = 0;
}
void amal_mutex_deinit(amal_mutex *self) {
@@ -105,6 +130,8 @@ int amal_mutex_lock(amal_mutex *self, const char *lock_identifier) {
int result;
result = pthread_mutex_lock(&self->mutex);
self->lock_identifier = lock_identifier;
+ self->owner_thread = pthread_self();
+ self->locked = bool_true;
#ifdef AMAL_MUTEX_DEBUG
if(result == 0 && self->lock_identifier) {
amal_log_debug("amal_mutex_lock: mutex locked by thread %lu (%s), identification: %s",
@@ -122,6 +149,10 @@ int amal_mutex_unlock(amal_mutex *self) {
const char *identifier;
identifier = self->lock_identifier;
#endif
+ if(!self->locked || pthread_equal(self->owner_thread, pthread_self()) == 0)
+ return 0;
+ self->locked = bool_false;
+ self->owner_thread = 0;
result = pthread_mutex_unlock(&self->mutex);
#ifdef AMAL_MUTEX_DEBUG
if(result == 0 && identifier) {