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);
if (ret < frame->len) {
fprintf(stdout, "Error occurs while flashing\n");
- error = 1;
+ state = DFU_THREAD_STATE_ERROR;
}
progress += frame->len;
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);
}
}
- 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;
}
return ret;
}
-
int dfu_init(struct tfm_context *ctx, const char *dfu_info_file)
{
int ret;
void dfu_exit(struct tfm_context *ctx)
{
+ pthread_cancel(ctx->dfu_thread);
pthread_join(ctx->dfu_thread, NULL);
destroy_dfu_info();
if (ctx->connect) {