Improve dfu thread state for safe exit 62/195662/2
authorDongwoo Lee <dwoo08.lee@samsung.com>
Mon, 10 Dec 2018 07:48:43 +0000 (16:48 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Thu, 20 Dec 2018 07:59:53 +0000 (16:59 +0900)
To acomplish exit process safely when tfm fails to flash image, this
patch improves dfu thread state. Since this, dfu thread could be
canceled only when flashing is not proceed to protect the target.

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

index 5fe2854..4abfdf1 100644 (file)
--- a/src/dfu.c
+++ b/src/dfu.c
@@ -338,19 +338,45 @@ int dfu_start(struct tfm_context *ctx, const char *entity)
        return 0;
 }
 
+static void dfu_thread_cleanup(void *ptr)
+{
+       struct tfm_context *ctx = ptr;
+       struct dfu_frame *frame;
+
+       while (!TAILQ_EMPTY(&ctx->dfu_ioq_head)) {
+               frame = TAILQ_FIRST(&ctx->dfu_ioq_head);
+
+               TAILQ_REMOVE(&ctx->dfu_ioq_head, frame, entry);
+
+               dfu_put_buffer(frame->buf);
+               free(frame);
+       }
+}
+
 static void *dfu_thread_main(void *ptr)
 {
        struct tfm_context *ctx = ptr;
        struct dfu_frame *frame;
-       int error = 0;
+       int state = DFU_THREAD_STATE_IDLE;
        uint64_t progress = 0;
        int ret;
 
-       while (!error) {
+       pthread_cleanup_push(dfu_thread_cleanup, ptr);
+
+       while (state != DFU_THREAD_STATE_ERROR) {
                pthread_mutex_lock(&ctx->dfu_mutex);
 
-               while (TAILQ_EMPTY(&ctx->dfu_ioq_head))
+               while (TAILQ_EMPTY(&ctx->dfu_ioq_head)) {
+                       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
                        pthread_cond_wait(&ctx->dfu_data_arrive, &ctx->dfu_mutex);
+               }
+
+               if (state == DFU_THREAD_STATE_IDLE) {
+                       pthread_mutex_unlock(&ctx->dfu_mutex);
+                       state = DFU_THREAD_STATE_FLASHING;
+                       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+                       pthread_mutex_lock(&ctx->dfu_mutex);
+               }
 
                frame = TAILQ_FIRST(&ctx->dfu_ioq_head);
 
@@ -362,7 +388,7 @@ static void *dfu_thread_main(void *ptr)
 
                if (ret < frame->len) {
                        fprintf(stdout, "Error occurs while flashing\n");
-                       error = 1;
+                       state = DFU_THREAD_STATE_ERROR;
                }
 
                progress += frame->len;
@@ -371,10 +397,13 @@ static void *dfu_thread_main(void *ptr)
                free(frame);
 
                /* transfer finished */
-               if (!error && progress >= ctx->thor_file_size) {
+               if (state != DFU_THREAD_STATE_ERROR && progress >= ctx->thor_file_size) {
                        progress = 0;
                        ctx->transfer_done = 1;
 
+                       state = DFU_THREAD_STATE_IDLE;
+                       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
                        pthread_cond_signal(&ctx->dfu_write_done);
 
                        pthread_mutex_lock(&ctx->dfu_sync_mutex);
@@ -384,16 +413,7 @@ static void *dfu_thread_main(void *ptr)
                }
        }
 
-       pthread_mutex_lock(&ctx->dfu_mutex);
-       while (!TAILQ_EMPTY(&ctx->dfu_ioq_head)) {
-               frame = TAILQ_FIRST(&ctx->dfu_ioq_head);
-
-               TAILQ_REMOVE(&ctx->dfu_ioq_head, frame, entry);
-
-               dfu_put_buffer(frame->buf);
-               free(frame);
-       }
-       pthread_mutex_unlock(&ctx->dfu_mutex);
+       pthread_cleanup_pop(1);
 
        return NULL;
 }
@@ -463,7 +483,6 @@ err_free_all:
        return ret;
 }
 
-
 int dfu_init(struct tfm_context *ctx, const char *dfu_info_file)
 {
        int ret;
@@ -493,6 +512,7 @@ int dfu_init(struct tfm_context *ctx, const char *dfu_info_file)
 
 void dfu_exit(struct tfm_context *ctx)
 {
+       pthread_cancel(ctx->dfu_thread);
        pthread_join(ctx->dfu_thread, NULL);
        destroy_dfu_info();
        if (ctx->connect) {
index 4138acf..afc3e28 100644 (file)
--- a/src/dfu.h
+++ b/src/dfu.h
@@ -32,6 +32,12 @@ enum dfu_info_entry {
        DFU_INFO_MAX,
 };
 
+enum dfu_thread_state {
+       DFU_THREAD_STATE_ERROR = -1,
+       DFU_THREAD_STATE_IDLE,
+       DFU_THREAD_STATE_FLASHING,
+};
+
 struct dfu_frame {
        void *buf;
        unsigned long len;