diff options
Diffstat (limited to '')
| -rw-r--r-- | libar2simplified_init_context.c | 72 |
1 files changed, 50 insertions, 22 deletions
diff --git a/libar2simplified_init_context.c b/libar2simplified_init_context.c index 9dcbfb0..814e182 100644 --- a/libar2simplified_init_context.c +++ b/libar2simplified_init_context.c @@ -2,6 +2,7 @@ #include "common.h" #include <pthread.h> #include <semaphore.h> +#include <stdatomic.h> struct user_data; @@ -11,7 +12,7 @@ struct thread_data { struct user_data *master; pthread_t thread; sem_t semaphore; - int error; + _Atomic int error; void (*function)(void *data); void *function_input; }; @@ -50,14 +51,15 @@ alignedalloc(size_t num, size_t size, size_t extra, size_t alignment) static void * allocate(size_t num, size_t size, size_t alignment, struct libar2_context *ctx) { - size_t pad = (alignment - ((2 * sizeof(size_t)) & (alignment - 1))) & (alignment - 1); - char *ptr = alignedalloc(num, size, pad + 2 * sizeof(size_t), alignment); + size_t extra = 2 * sizeof(size_t); + size_t pad = -extra & (alignment - 1); + char *ptr = alignedalloc(num, size, pad + extra, alignment); if (ptr) { - ptr = &ptr[pad]; - *(size_t *)ptr = pad; - ptr = &ptr[sizeof(size_t)]; - *(size_t *)ptr = num * size; - ptr = &ptr[sizeof(size_t)]; + ptr += pad; + memcpy(ptr, &pad, sizeof(size_t)); + ptr += sizeof(size_t); + memcpy(ptr, &(size_t){num * size}, sizeof(size_t)); + ptr += sizeof(size_t); } (void) ctx; return ptr; @@ -68,10 +70,13 @@ static void deallocate(void *ptr, struct libar2_context *ctx) { char *p = ptr; + size_t size, pad; p -= sizeof(size_t); - libar2_erase(ptr, *(size_t *)p); + memcpy(&size, p, sizeof(size_t)); p -= sizeof(size_t); - p -= *(size_t *)p; + memcpy(&pad, p, sizeof(size_t)); + p -= pad; + libar2_erase(p, size + pad + 2u * sizeof(size_t)); free(p); (void) ctx; } @@ -81,31 +86,44 @@ static void * thread_loop(void *data_) { struct thread_data *data = data_; + void (*function)(void *data); + void *function_input; int err; for (;;) { if (sem_wait(&data->semaphore)) { if (errno == EINTR) continue; - data->error = errno; + atomic_store(&data->error, errno); return NULL; } - if (!data->function) { - data->error = ENOTRECOVERABLE; + err = pthread_mutex_lock(&data->master->mutex); + if (err) { + atomic_store(&data->error, err); + return NULL; + } + function = data->function; + function_input = data->function_input; + if (!function) { + atomic_store(&data->error, ENOTRECOVERABLE); + pthread_mutex_unlock(&data->master->mutex); return NULL; } - data->function(data->function_input); + pthread_mutex_unlock(&data->master->mutex); + + function(function_input); err = pthread_mutex_lock(&data->master->mutex); if (err) { - data->error = err; + atomic_store(&data->error, err); return NULL; } data->master->resting[data->index / 64] |= (uint_least64_t)1 << (data->index % 64); + pthread_mutex_unlock(&data->master->mutex); if (sem_post(&data->master->semaphore)) { - data->error = errno; + atomic_store(&data->error, errno); return NULL; } } @@ -124,15 +142,17 @@ run_thread(size_t index, void (*function)(void *arg), void *arg, struct libar2_c return -1; } data->resting[index / 64] ^= (uint_least64_t)1 << (index % 64); - pthread_mutex_unlock(&data->mutex); - if (data->threads[index].error) { - errno = data->threads[index].error; + err = atomic_load(&data->threads[index].error); + if (err) { + pthread_mutex_unlock(&data->mutex); + errno = err; return -1; } data->threads[index].function = function; data->threads[index].function_input = arg; + pthread_mutex_unlock(&data->mutex); if (sem_post(&data->threads[index].semaphore)) return -1; @@ -145,15 +165,16 @@ destroy_thread_pool(struct libar2_context *ctx) { struct user_data *data = ctx->user_data; size_t i; - int ret = 0; + int err, ret = 0; for (i = data->nthreads; i--;) if (run_thread(i, pthread_exit, NULL, ctx)) return -1; for (i = data->nthreads; i--;) { pthread_join(data->threads[i].thread, NULL); sem_destroy(&data->threads[i].semaphore); - if (data->threads[i].error) - ret = data->threads[i].error; + err = atomic_load(&data->threads[i].error); + if (err) + ret = err; } sem_destroy(&data->semaphore); pthread_mutex_destroy(&data->mutex); @@ -244,6 +265,7 @@ init_thread_pool(size_t desired, size_t *createdp, struct libar2_context *ctx) for (i = 0; i < data->nthreads; i++) { memset(&data->threads[i], 0, sizeof(data->threads[i])); + atomic_init(&data->threads[i].error, 0); data->threads[i].master = data; data->threads[i].index = i; data->resting[i / 64] |= (uint_least64_t)1 << (i % 64); @@ -290,6 +312,11 @@ await_threads(size_t *indices, size_t n, size_t require, struct libar2_context * memset(data->joined, 0, (data->nthreads + 63) / 64 * sizeof(*data->joined)); + err = pthread_mutex_lock(&data->mutex); + if (err) { + errno = err; + return 0; + } for (i = 0; i < data->nthreads; i += 64) { for (;;) { one = data->resting[i / 64]; @@ -302,6 +329,7 @@ await_threads(size_t *indices, size_t n, size_t require, struct libar2_context * indices[ret - 1] = i + lb(one); } } + pthread_mutex_unlock(&data->mutex); for (;;) { if (ret < require) { |
