mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Error check all the thread operations
No error is expected, and this enforces that expectation.
This commit is contained in:
parent
d13cd42784
commit
0707b1f446
8 changed files with 206 additions and 151 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
100
cmdline/io.c
100
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue