mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Signal the 'done' condition only at the waiting index
This reduces the number of context switches.
This commit is contained in:
parent
22d806a04f
commit
8e47e2b024
1 changed files with 55 additions and 37 deletions
92
cmdline/io.c
92
cmdline/io.c
|
|
@ -235,42 +235,51 @@ static void io_writer_sched_empty(struct snapraid_io* io, int index, block_off_t
|
|||
static struct snapraid_task* io_reader_step(struct snapraid_worker* worker)
|
||||
{
|
||||
struct snapraid_io* io = worker->io;
|
||||
struct snapraid_task* task = 0;
|
||||
|
||||
/* the synchronization is protected by the io mutex */
|
||||
pthread_mutex_lock(&io->mutex);
|
||||
|
||||
while (1) {
|
||||
unsigned index;
|
||||
unsigned next_index;
|
||||
|
||||
/* check if the worker has to exit */
|
||||
/* even if there is work to do */
|
||||
if (io->done)
|
||||
break;
|
||||
if (io->done) {
|
||||
pthread_mutex_unlock(&io->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get the next pending task */
|
||||
index = (worker->index + 1) % IO_MAX;
|
||||
next_index = (worker->index + 1) % IO_MAX;
|
||||
|
||||
/* if the queue of pending tasks is not empty */
|
||||
if (index != io->reader_index) {
|
||||
if (next_index != io->reader_index) {
|
||||
struct snapraid_task* task;
|
||||
|
||||
/* the index that the IO may be waiting for */
|
||||
unsigned waiting_index = io->reader_index;
|
||||
|
||||
/* the index that worker just completed */
|
||||
unsigned done_index = worker->index;
|
||||
|
||||
/* get the new working task */
|
||||
worker->index = index;
|
||||
worker->index = next_index;
|
||||
task = &worker->task_map[worker->index];
|
||||
|
||||
/* notify the io that a new read is complete */
|
||||
pthread_cond_signal(&io->read_done);
|
||||
/* 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(&io->read_done);
|
||||
|
||||
/* return the new task */
|
||||
break;
|
||||
pthread_mutex_unlock(&io->mutex);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
/* otherwise wait for a read_sched event */
|
||||
pthread_cond_wait(&io->read_sched, &io->mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&io->mutex);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -281,7 +290,6 @@ static struct snapraid_task* io_reader_step(struct snapraid_worker* worker)
|
|||
static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state)
|
||||
{
|
||||
struct snapraid_io* io = worker->io;
|
||||
struct snapraid_task* task = 0;
|
||||
int error_index;
|
||||
|
||||
/* the synchronization is protected by the io mutex */
|
||||
|
|
@ -293,36 +301,46 @@ static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int
|
|||
++io->writer_error[error_index];
|
||||
|
||||
while (1) {
|
||||
unsigned index;
|
||||
unsigned next_index;
|
||||
|
||||
/* get the next pending task */
|
||||
index = (worker->index + 1) % IO_MAX;
|
||||
next_index = (worker->index + 1) % IO_MAX;
|
||||
|
||||
/* if the queue of pending tasks is not empty */
|
||||
if (index != io->writer_index) {
|
||||
if (next_index != io->writer_index) {
|
||||
struct snapraid_task* task;
|
||||
|
||||
/* the index that the IO may be waiting for */
|
||||
unsigned waiting_index = (io->writer_index + 1) % IO_MAX;
|
||||
|
||||
/* the index that worker just completed */
|
||||
unsigned done_index = worker->index;
|
||||
|
||||
/* get the new working task */
|
||||
worker->index = index;
|
||||
worker->index = next_index;
|
||||
task = &worker->task_map[worker->index];
|
||||
|
||||
/* notify the io that a new writer is complete */
|
||||
pthread_cond_signal(&io->write_done);
|
||||
/* 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(&io->write_done);
|
||||
|
||||
/* return the new task */
|
||||
break;
|
||||
pthread_mutex_unlock(&io->mutex);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
/* check if the worker has to exit */
|
||||
/* but only if there is no work to do */
|
||||
if (io->done)
|
||||
break;
|
||||
if (io->done) {
|
||||
pthread_mutex_unlock(&io->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* otherwise wait for a write_sched event */
|
||||
pthread_cond_wait(&io->write_sched, &io->mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&io->mutex);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -416,12 +434,12 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base,
|
|||
|
||||
while (1) {
|
||||
unsigned char* let;
|
||||
unsigned index;
|
||||
unsigned busy_index;
|
||||
|
||||
/* get the index the caller is using */
|
||||
/* get the index the IO is using */
|
||||
/* we must ensure that this index has not a read in progress */
|
||||
/* to avoid a concurrent access */
|
||||
index = io->reader_index;
|
||||
busy_index = io->reader_index;
|
||||
|
||||
/* search for a worker that has already finished */
|
||||
let = &io->reader_list[0];
|
||||
|
|
@ -439,7 +457,7 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base,
|
|||
worker = &io->reader_map[i];
|
||||
|
||||
/* if the worker has finished this index */
|
||||
if (index != worker->index) {
|
||||
if (busy_index != worker->index) {
|
||||
struct snapraid_task* task;
|
||||
|
||||
task = &worker->task_map[io->reader_index];
|
||||
|
|
@ -483,14 +501,14 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos)
|
|||
|
||||
while (1) {
|
||||
unsigned char* let;
|
||||
unsigned index;
|
||||
unsigned busy_index;
|
||||
|
||||
/* get the next index the caller is going to use */
|
||||
/* get the next index the IO is going to use */
|
||||
/* we must ensure that this index has not a write in progress */
|
||||
/* to avoid a concurrent access */
|
||||
/* note that we are already sure that a write is not in progress */
|
||||
/* at the index the caller is using at now */
|
||||
index = (io->writer_index + 1) % IO_MAX;
|
||||
/* at the index the IO is using at now */
|
||||
busy_index = (io->writer_index + 1) % IO_MAX;
|
||||
|
||||
/* search for a worker that has already finished */
|
||||
let = &io->writer_list[0];
|
||||
|
|
@ -508,7 +526,7 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos)
|
|||
assert(io->writer_index != worker->index);
|
||||
|
||||
/* if the worker has finished this index */
|
||||
if (index != worker->index) {
|
||||
if (busy_index != worker->index) {
|
||||
pthread_mutex_unlock(&io->mutex);
|
||||
|
||||
/* mark the worker as processed */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue