Error check all the thread operations

No error is expected, and this enforces that expectation.
This commit is contained in:
Andrea Mazzoleni 2016-02-13 15:35:23 +01:00
parent d13cd42784
commit 0707b1f446
8 changed files with 206 additions and 151 deletions

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;