From 0707b1f4460fc23c94cd577ef7951b04fc35e6bf Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sat, 13 Feb 2016 15:35:23 +0100 Subject: [PATCH] Error check all the thread operations No error is expected, and this enforces that expectation. --- cmdline/elem.c | 8 +-- cmdline/io.c | 100 ++++++++++++----------------- cmdline/mingw.c | 33 +++------- cmdline/snapraid.c | 2 +- cmdline/state.c | 28 ++------- cmdline/support.c | 153 ++++++++++++++++++++++++++++++++++++++------- cmdline/support.h | 19 ++++-- cmdline/unix.c | 14 +---- 8 files changed, 206 insertions(+), 151 deletions(-) diff --git a/cmdline/elem.c b/cmdline/elem.c index 47523c95..bd255a4d 100644 --- a/cmdline/elem.c +++ b/cmdline/elem.c @@ -737,7 +737,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev /* ensure that the dir terminate with "/" if it isn't empty */ pathslash(disk->dir, sizeof(disk->dir)); - pthread_mutex_init(&disk->fs_mutex, 0); + thread_mutex_init(&disk->fs_mutex, 0); disk->smartctl[0] = 0; disk->device = dev; @@ -782,19 +782,19 @@ void disk_free(struct snapraid_disk* disk) tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free); tommy_hashdyn_done(&disk->dirset); - pthread_mutex_destroy(&disk->fs_mutex); + thread_mutex_destroy(&disk->fs_mutex); free(disk); } static inline void fs_lock(struct snapraid_disk* disk) { - pthread_mutex_lock(&disk->fs_mutex); + thread_mutex_lock(&disk->fs_mutex); } static inline void fs_unlock(struct snapraid_disk* disk) { - pthread_mutex_unlock(&disk->fs_mutex); + thread_mutex_unlock(&disk->fs_mutex); } struct chunk_disk_empty { diff --git a/cmdline/io.c b/cmdline/io.c index 02485e8c..fab198e7 100644 --- a/cmdline/io.c +++ b/cmdline/io.c @@ -37,11 +37,11 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state, unsigned i; size_t allocated; - pthread_mutex_init(&io->mutex, 0); - pthread_cond_init(&io->read_done, 0); - pthread_cond_init(&io->read_sched, 0); - pthread_cond_init(&io->write_done, 0); - pthread_cond_init(&io->write_sched, 0); + thread_mutex_init(&io->mutex, 0); + thread_cond_init(&io->read_done, 0); + thread_cond_init(&io->read_sched, 0); + thread_cond_init(&io->write_done, 0); + thread_cond_init(&io->write_sched, 0); io->state = state; if (io_cache == 0) { @@ -140,11 +140,11 @@ void io_done(struct snapraid_io* io) free(io->writer_map); free(io->writer_list); - pthread_mutex_destroy(&io->mutex); - pthread_cond_destroy(&io->read_done); - pthread_cond_destroy(&io->read_sched); - pthread_cond_destroy(&io->write_done); - pthread_cond_destroy(&io->write_sched); + thread_mutex_destroy(&io->mutex); + thread_cond_destroy(&io->read_done); + thread_cond_destroy(&io->read_sched); + thread_cond_destroy(&io->write_done); + thread_cond_destroy(&io->write_sched); } /** @@ -258,7 +258,7 @@ static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) struct snapraid_io* io = worker->io; /* the synchronization is protected by the io mutex */ - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); while (1) { unsigned next_index; @@ -266,7 +266,7 @@ static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) /* check if the worker has to exit */ /* even if there is work to do */ if (io->done) { - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); return 0; } @@ -290,9 +290,9 @@ static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) /* if the just completed task is at this index */ if (done_index == waiting_index) { /* notify the IO that a new read is complete */ - pthread_cond_signal_and_unlock(&io->read_done, &io->mutex); + thread_cond_signal_and_unlock(&io->read_done, &io->mutex); } else { - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); } /* return the new task */ @@ -300,7 +300,7 @@ static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) } /* otherwise wait for a read_sched event */ - pthread_cond_wait(&io->read_sched, &io->mutex); + thread_cond_wait(&io->read_sched, &io->mutex); } } @@ -315,7 +315,7 @@ static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int int error_index; /* the synchronization is protected by the io mutex */ - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); /* counts the number of errors in the global state */ error_index = state - IO_WRITER_ERROR_BASE; @@ -345,9 +345,9 @@ static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int /* if the just completed task is at this index */ if (done_index == waiting_index) { /* notify the IO that a new write is complete */ - pthread_cond_signal_and_unlock(&io->write_done, &io->mutex); + thread_cond_signal_and_unlock(&io->write_done, &io->mutex); } else { - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); } /* return the new task */ @@ -357,12 +357,12 @@ static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int /* check if the worker has to exit */ /* but only if there is no work to do */ if (io->done) { - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); return 0; } /* otherwise wait for a write_sched event */ - pthread_cond_wait(&io->write_sched, &io->mutex); + thread_cond_wait(&io->write_sched, &io->mutex); } } @@ -388,7 +388,7 @@ block_off_t io_read_next(struct snapraid_io* io, void*** buffer) io->reader_list[i] = i; /* the synchronization is protected by the io mutex */ - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); /* schedule the next read */ io_reader_sched(io, io->reader_index, blockcur_schedule); @@ -403,7 +403,7 @@ block_off_t io_read_next(struct snapraid_io* io, void*** buffer) *buffer = io->buffer_map[io->reader_index]; /* signal all the workers that there is a new pending task */ - pthread_cond_broadcast_and_unlock(&io->read_sched, &io->mutex); + thread_cond_broadcast_and_unlock(&io->read_sched, &io->mutex); return blockcur_caller; } @@ -420,7 +420,7 @@ void io_write_next(struct snapraid_io* io, block_off_t blockcur, int skip, int* io->writer_list[i] = i; /* the synchronization is protected by the io mutex */ - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); /* report errors */ for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) { @@ -443,7 +443,7 @@ void io_write_next(struct snapraid_io* io, block_off_t blockcur, int skip, int* io->writer_index = (io->writer_index + 1) % io->io_max; /* signal all the workers that there is a new pending task */ - pthread_cond_broadcast_and_unlock(&io->write_sched, &io->mutex); + thread_cond_broadcast_and_unlock(&io->write_sched, &io->mutex); } void io_refresh(struct snapraid_io* io) @@ -451,7 +451,7 @@ void io_refresh(struct snapraid_io* io) unsigned i; /* the synchronization is protected by the io mutex */ - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); /* for all readers, count the number of read blocks */ for (i = 0; i < io->reader_max; ++i) { @@ -489,7 +489,7 @@ void io_refresh(struct snapraid_io* io) io->state->parity[worker->parity_handle->level].cached = cached; } - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); } static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) @@ -503,7 +503,7 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base, *waiting_mac = 0; /* the synchronization is protected by the io mutex */ - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); while (1) { unsigned char* let; @@ -541,7 +541,7 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base, task = &worker->task_map[io->reader_index]; - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); /* mark the worker as processed */ /* setting the previous one to point at the next one */ @@ -563,7 +563,7 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base, } /* if no worker is ready, wait for an event */ - pthread_cond_wait(&io->read_done, &io->mutex); + thread_cond_wait(&io->read_done, &io->mutex); /* count the cycles */ ++waiting_cycle; @@ -591,7 +591,7 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos, unsigned* waiting_ma *waiting_mac = 0; /* the synchronization is protected by the io mutex */ - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); while (1) { unsigned char* let; @@ -627,7 +627,7 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos, unsigned* waiting_ma /* if the worker has finished this index */ if (busy_index != worker->index) { - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); /* mark the worker as processed */ /* setting the previous one to point at the next one */ @@ -648,7 +648,7 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos, unsigned* waiting_ma } /* if no worker is ready, wait for an event */ - pthread_cond_wait(&io->write_done, &io->mutex); + thread_cond_wait(&io->write_done, &io->mutex); /* count the cycles */ ++waiting_cycle; @@ -768,12 +768,7 @@ void io_start(struct snapraid_io* io, worker->index = 0; - if (pthread_create(&worker->thread, 0, io_reader_thread, worker) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to create reader thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_create(&worker->thread, 0, io_reader_thread, worker); } /* start the writer threads */ @@ -782,12 +777,7 @@ void io_start(struct snapraid_io* io, worker->index = io->io_max - 1; - if (pthread_create(&worker->thread, 0, io_writer_thread, worker) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to create writer thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_create(&worker->thread, 0, io_writer_thread, worker); } } @@ -795,16 +785,16 @@ void io_stop(struct snapraid_io* io) { unsigned i; - pthread_mutex_lock(&io->mutex); + thread_mutex_lock(&io->mutex); /* mark that we are stopping */ io->done = 1; /* signal all the threads to recognize the new state */ - pthread_cond_broadcast(&io->read_sched); - pthread_cond_broadcast(&io->write_sched); + thread_cond_broadcast(&io->read_sched); + thread_cond_broadcast(&io->write_sched); - pthread_mutex_unlock(&io->mutex); + thread_mutex_unlock(&io->mutex); /* wait for all readers to terminate */ for (i = 0; i < io->reader_max; ++i) { @@ -812,12 +802,7 @@ void io_stop(struct snapraid_io* io) void* retval; /* wait for thread termination */ - if (pthread_join(worker->thread, &retval) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to join reader thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_join(worker->thread, &retval); } /* wait for all writers to terminate */ @@ -826,12 +811,7 @@ void io_stop(struct snapraid_io* io) void* retval; /* wait for thread termination */ - if (pthread_join(worker->thread, &retval) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to join writer thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_join(worker->thread, &retval); } } diff --git a/cmdline/mingw.c b/cmdline/mingw.c index 12a03976..f8130270 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -2326,12 +2326,7 @@ static int device_thread(tommy_list* list, void* (*func)(void* arg)) for (i = tommy_list_head(list); i != 0; i = i->next) { devinfo_t* devinfo = i->data; - if (pthread_create(&devinfo->thread, 0, func, devinfo) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to create thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_create(&devinfo->thread, 0, func, devinfo); } /* joins all threads */ @@ -2339,12 +2334,7 @@ static int device_thread(tommy_list* list, void* (*func)(void* arg)) devinfo_t* devinfo = i->data; void* retval; - if (pthread_join(devinfo->thread, &retval) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to join thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_join(devinfo->thread, &retval); if (retval != 0) ++fail; @@ -2435,10 +2425,8 @@ int windows_mutex_init(windows_mutex_t* mutex, void* attr) (void)attr; cs = malloc(sizeof(CRITICAL_SECTION)); - if (!cs) { - printf("FATAL! Failed allocation for mutex\n"); - os_abort(); - } + if (!cs) + return -1; InitializeCriticalSection(cs); @@ -2483,10 +2471,8 @@ int windows_cond_init(windows_cond_t* cond, void* attr) (void)attr; cv = malloc(sizeof(CONDITION_VARIABLE)); - if (!cv) { - printf("FATAL! Failed allocation for condition variable\n"); - os_abort(); - } + if (!cv) + return -1; InitializeConditionVariable(cv); @@ -2528,11 +2514,8 @@ int windows_cond_wait(windows_cond_t* cond, windows_mutex_t* mutex) CONDITION_VARIABLE* cv = *cond; CRITICAL_SECTION* cs = *mutex; - if (!SleepConditionVariableCS(cv, cs, INFINITE)) { - DWORD error = GetLastError(); - printf("FATAL! SleepConditionVariableCS failed with error %u\n", (unsigned)error); - os_abort(); - } + if (!SleepConditionVariableCS(cv, cs, INFINITE)) + return -1; return 0; } diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index f773164b..295477a5 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -814,7 +814,7 @@ int main(int argc, char* argv[]) opt.force_stats = 1; break; case OPT_TEST_COND_SIGNAL_OUTSIDE : - pthread_cond_signal_outside = 1; + thread_cond_signal_outside = 1; break; default : /* LCOV_EXCL_START */ diff --git a/cmdline/state.c b/cmdline/state.c index ace696d2..3f4cd5f1 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -3172,12 +3172,7 @@ static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) context->info_has_rehash = info_has_rehash; context->f = f; - if (pthread_create(&context->thread, 0, state_write_thread, context) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to create thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_create(&context->thread, 0, state_write_thread, context); i = i->next; } @@ -3196,12 +3191,7 @@ static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) struct state_write_thread_context* context = content->context; void* retval; - if (pthread_join(context->thread, &retval) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to join thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_join(context->thread, &retval); if (retval) { /* LCOV_EXCL_START */ @@ -3600,12 +3590,7 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc) context->f = f; #if HAVE_MT_VERIFY - if (pthread_create(&context->thread, 0, state_verify_thread, context) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to create thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_create(&context->thread, 0, state_verify_thread, context); #else context->retval = state_verify_thread(context); #endif @@ -3622,12 +3607,7 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc) void* retval; #if HAVE_MT_VERIFY - if (pthread_join(context->thread, &retval) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to join thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_join(context->thread, &retval); #else retval = context->retval; #endif diff --git a/cmdline/support.c b/cmdline/support.c index dd75356a..d1558387 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -33,28 +33,28 @@ static pthread_mutex_t memory_lock; void lock_msg(void) { #if HAVE_PTHREAD - pthread_mutex_lock(&msg_lock); + thread_mutex_lock(&msg_lock); #endif } void unlock_msg(void) { #if HAVE_PTHREAD - pthread_mutex_unlock(&msg_lock); + thread_mutex_unlock(&msg_lock); #endif } void lock_memory(void) { #if HAVE_PTHREAD - pthread_mutex_lock(&memory_lock); + thread_mutex_lock(&memory_lock); #endif } void unlock_memory(void) { #if HAVE_PTHREAD - pthread_mutex_unlock(&memory_lock); + thread_mutex_unlock(&memory_lock); #endif } @@ -62,16 +62,16 @@ void lock_init(void) { #if HAVE_PTHREAD /* initialize the locks as first operation as log_fatal depends on them */ - pthread_mutex_init(&msg_lock, 0); - pthread_mutex_init(&memory_lock, 0); + thread_mutex_init(&msg_lock, 0); + thread_mutex_init(&memory_lock, 0); #endif } void lock_done(void) { #if HAVE_PTHREAD - pthread_mutex_destroy(&msg_lock); - pthread_mutex_destroy(&memory_lock); + thread_mutex_destroy(&msg_lock); + thread_mutex_destroy(&memory_lock); #endif } @@ -1114,6 +1114,96 @@ int smartctl_flush(FILE* f, const char* file, const char* name) /* thread */ #if HAVE_PTHREAD +void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr) +{ + if (pthread_mutex_init(mutex, attr) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_init().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_mutex_destroy(pthread_mutex_t* mutex) +{ + if (pthread_mutex_destroy(mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_destroy().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_mutex_lock(pthread_mutex_t* mutex) +{ + if (pthread_mutex_lock(mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_lock().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_mutex_unlock(pthread_mutex_t* mutex) +{ + if (pthread_mutex_unlock(mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_unlock().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr) +{ + if (pthread_cond_init(cond, attr) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_init().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_destroy(pthread_cond_t* cond) +{ + if (pthread_cond_destroy(cond) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_destroy().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_signal(pthread_cond_t* cond) +{ + if (pthread_cond_signal(cond) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_signal().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_broadcast(pthread_cond_t* cond) +{ + if (pthread_cond_broadcast(cond) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_broadcast().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) +{ + if (pthread_cond_wait(cond, mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_wait().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + /** * Implementation note about conditional variables. * @@ -1141,40 +1231,61 @@ int smartctl_flush(FILE* f, const char* file, const char* name) /** * Control when to signal the condition variables. */ -int pthread_cond_signal_outside = 0; +int thread_cond_signal_outside = 0; -void pthread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) +void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) { - if (pthread_cond_signal_outside) { + if (thread_cond_signal_outside) { /* without the thread checker unlock before signaling, */ /* this reduces the number of context switches */ - pthread_mutex_unlock(mutex); + thread_mutex_unlock(mutex); } - pthread_cond_signal(cond); + thread_cond_signal(cond); - if (!pthread_cond_signal_outside) { + if (!thread_cond_signal_outside) { /* with the thread checker unlock after signaling */ /* to make explicit the condition and mutex relation */ - pthread_mutex_unlock(mutex); + thread_mutex_unlock(mutex); } } -void pthread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) +void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) { - if (pthread_cond_signal_outside) { + if (thread_cond_signal_outside) { /* without the thread checker unlock before signaling, */ /* this reduces the number of context switches */ - pthread_mutex_unlock(mutex); + thread_mutex_unlock(mutex); } - pthread_cond_broadcast(cond); + thread_cond_broadcast(cond); - if (!pthread_cond_signal_outside) { + if (!thread_cond_signal_outside) { /* with the thread checker unlock after signaling */ /* to make explicit the condition and mutex relation */ - pthread_mutex_unlock(mutex); + thread_mutex_unlock(mutex); } } + +void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg) +{ + if (pthread_create(thread, attr, func, arg) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_create().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_join(pthread_t thread, void** retval) +{ + if (pthread_join(thread, retval) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_join().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + #endif diff --git a/cmdline/support.h b/cmdline/support.h index ad1a04fe..20e5a227 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -371,13 +371,24 @@ int smartctl_flush(FILE* f, const char* file, const char* name); * * Ensure to change that before starting any thread. */ -int pthread_cond_signal_outside; +int thread_cond_signal_outside; /** - * Signal and unlock condition variables. + * Thread wrappers to handle error conditions. */ -void pthread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); -void pthread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); +void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr); +void thread_mutex_destroy(pthread_mutex_t* mutex); +void thread_mutex_lock(pthread_mutex_t* mutex); +void thread_mutex_unlock(pthread_mutex_t* mutex); +void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr); +void thread_cond_destroy(pthread_cond_t* cond); +void thread_cond_signal(pthread_cond_t* cond); +void thread_cond_broadcast(pthread_cond_t* cond); +void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex); +void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); +void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); +void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg); +void thread_join(pthread_t thread, void** retval); #endif #endif diff --git a/cmdline/unix.c b/cmdline/unix.c index 2776e072..0d9419e0 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -1021,12 +1021,7 @@ static int device_thread(tommy_list* list, void* (*func)(void* arg)) for (i = tommy_list_head(list); i != 0; i = i->next) { devinfo_t* devinfo = i->data; - if (pthread_create(&devinfo->thread, 0, func, devinfo) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to create thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_create(&devinfo->thread, 0, func, devinfo); } /* join all threads */ @@ -1034,12 +1029,7 @@ static int device_thread(tommy_list* list, void* (*func)(void* arg)) devinfo_t* devinfo = i->data; void* retval; - if (pthread_join(devinfo->thread, &retval) != 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to join thread.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } + thread_join(devinfo->thread, &retval); if (retval != 0) ++fail;