#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,
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];
};
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);
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;
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);
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);
ctx->thread = 0;
TAILQ_INIT(&ctx->ioq);
+ ctx->ioq_len = 0;
pthread_mutex_init(&ctx->mutex, NULL);
pthread_mutex_init(&ctx->sync_mutex, NULL);