dfu: Limit maximum length of io queue 33/223033/12
authorDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 17 Mar 2020 04:56:20 +0000 (13:56 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Wed, 18 Mar 2020 09:31:54 +0000 (18:31 +0900)
To prevent timeout due to fsync, the maximum length of io queue is
limited. Transfer may be blocked until the previous request is
fsync'ed, but it is not harmful to overall performance since fsync is
bottleneck; even transfer is faster, flashing time is not reduced
because elapsed time is mostly consumed in fsync.

Change-Id: I8b59c175eb8065f388487249c9e7f3ef1dbab5b6
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
src/dfu.c

index 4ae9145..0d481cb 100644 (file)
--- a/src/dfu.c
+++ b/src/dfu.c
@@ -38,6 +38,8 @@
 #define DFU_INFO_MODE_PARTITION        'p'
 #define DFU_INFO_MODE_FILE     'f'
 
+#define DFU_IOQ_MAXLEN         5
+
 enum dfu_entry_attr {
        DFU_INFO_MODE = 0,
        DFU_INFO_PARTITION,
@@ -66,6 +68,7 @@ struct dfu_context {
        pthread_cond_t write_done;
        pthread_cond_t sync_done;
        TAILQ_HEAD(tailhead, dfu_frame) ioq;
+       int ioq_len;
 
        char *dfu_entry_list[DFU_ENTRY_LIST_MAXLEN][DFU_INFO_MAX];
 };
@@ -119,13 +122,19 @@ int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len)
        frame->buf = buffer;
        frame->len = len;
 
+retry:
        pthread_mutex_lock(&ctx->mutex);
-
-       if (TAILQ_EMPTY(&ctx->ioq))
+       if (TAILQ_EMPTY(&ctx->ioq)) {
                notify = 1;
+       } else if (ctx->ioq_len >= DFU_IOQ_MAXLEN) {
+               pthread_mutex_unlock(&ctx->mutex);
+               usleep(1000);
+               goto retry;
+       }
 
        /* dfu_thread_main() de-queues i/o request and processes it */
        TAILQ_INSERT_TAIL(&ctx->ioq, frame, entry);
+       ctx->ioq_len++;
 
        pthread_mutex_unlock(&ctx->mutex);
 
@@ -255,20 +264,15 @@ static void *dfu_thread_main(void *ptr)
                        state = DFU_THREAD_STATE_IDLE;
                        pthread_cond_wait(&ctx->data_arrived, &ctx->mutex);
                }
+               frame = TAILQ_FIRST(&ctx->ioq);
+               pthread_mutex_unlock(&ctx->mutex);
 
                if (state == DFU_THREAD_STATE_IDLE) {
                        state = DFU_THREAD_STATE_FLASHING;
                        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
                }
 
-               frame = TAILQ_FIRST(&ctx->ioq);
-
-               TAILQ_REMOVE(&ctx->ioq, frame, entry);
-
-               pthread_mutex_unlock(&ctx->mutex);
-
                ret = write(e->fd, frame->buf, frame->len);
-
                if (ret < frame->len) {
                        fprintf(stderr, "Error occurs while flashing\n");
                        state = DFU_THREAD_STATE_ERROR;
@@ -276,6 +280,13 @@ static void *dfu_thread_main(void *ptr)
 
                progress += frame->len;
 
+               fsync(e->fd);
+
+               pthread_mutex_lock(&ctx->mutex);
+               TAILQ_REMOVE(&ctx->ioq, frame, entry);
+               ctx->ioq_len--;
+               pthread_mutex_unlock(&ctx->mutex);
+
                fprintf(stdout, "#");
                fflush(stdout);
 
@@ -409,18 +420,10 @@ void dfu_sync(struct dfu_entry *e)
                pthread_cond_wait(&ctx->write_done, &ctx->sync_mutex);
        pthread_mutex_unlock(&ctx->sync_mutex);
 
-       switch (*info[DFU_INFO_MODE]) {
-       case DFU_INFO_MODE_FILE:
-               fsync(e->fd);
-               close(e->fd);
+       close(e->fd);
+
+       if (*info[DFU_INFO_MODE] == DFU_INFO_MODE_FILE)
                umount_dev();
-               break;
-       case DFU_INFO_MODE_PARTITION:
-               close(e->fd);
-               break;
-       default:
-               break;
-       }
 
        pthread_cond_signal(&ctx->sync_done);
 
@@ -501,6 +504,7 @@ struct dfu_context *dfu_alloc_context(void)
 
        ctx->thread = 0;
        TAILQ_INIT(&ctx->ioq);
+       ctx->ioq_len = 0;
 
        pthread_mutex_init(&ctx->mutex, NULL);
        pthread_mutex_init(&ctx->sync_mutex, NULL);