From d1d218d6df8fd21a6db5cd011ce7bb99cd3c1c94 Mon Sep 17 00:00:00 2001 From: Dongju Chae Date: Wed, 17 Jul 2019 17:10:20 +0900 Subject: [PATCH] [N71] Split the compaction algorithm into two-step one This commit splits the compaction algorithm into two-step one. Signed-off-by: Dongju Chae --- core/npu-engine/src/ne-mem.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/core/npu-engine/src/ne-mem.c b/core/npu-engine/src/ne-mem.c index 0a8204b..a825016 100644 --- a/core/npu-engine/src/ne-mem.c +++ b/core/npu-engine/src/ne-mem.c @@ -453,11 +453,20 @@ chunk_compact_try (uint64_t *offset_dst) { chunk *target = NULL; + /** + * For chunk compaction, we use two-stage compactions, depending on the status of free chunks. + * At first, we can move used chunks to free chunks if there're enough large free chunks. + * In most cases, it would be enough. Otherwise, we need to re-arrange free chunks + * by shifting them to the bottom. It's heavy-weight and requires more memory copies. + */ + + /* we first try to perform 1st stage (light-weight) */ + /* find a target chunk starting at top */ list_for_each_entry_reverse (target, mpriv.used_chunks, list) { /* should be not busy (i.e., no processing here) and other conditions (TBD)? */ if (chunk_set_state (target, CHUNK_STATE_MODIFIED, false) == 0) { - chunk *next_chunk, *free_chunk = NULL; + chunk *free_chunk = NULL; /* find a free chunk starting at bottom */ list_for_each_entry (free_chunk, mpriv.free_chunks, list) { @@ -465,7 +474,7 @@ chunk_compact_try (uint64_t *offset_dst) if (free_chunk->offset > target->offset) break; - /* case 1) there is a free slot where this chunk moves */ + /* there is a free slot where this chunk moves */ if (free_chunk->size >= target->size) { *offset_dst = free_chunk->offset; @@ -483,11 +492,29 @@ chunk_compact_try (uint64_t *offset_dst) list_del (&mpriv.used_chunks, &target->list); return target; - } else - /* case 2) this chunk is directly attached to the free chunk */ + } + } + + /* failure */ + assert (target->state == CHUNK_STATE_MODIFIED); + target->state = CHUNK_STATE_FREE; + } + } + + /* If there is no avaialble free chunk, let's go to 2nd stage (heavy-weight) */ + + /* we shift a used chunk to its left free chunk, starting at bottom */ + list_for_each_entry (target, mpriv.used_chunks, list) { + if (chunk_set_state (target, CHUNK_STATE_MODIFIED, false) == 0) { + chunk *free_chunk = NULL; + + /* find a free chunk starting at bottom */ + list_for_each_entry (free_chunk, mpriv.free_chunks, list) { + /* this chunk is directly attached to the free chunk */ if (free_chunk->offset + free_chunk->size == target->offset) { - *offset_dst = target->offset - free_chunk->size; + chunk *next_chunk; + *offset_dst = target->offset - free_chunk->size; free_chunk->offset += target->size; /* check merge */ @@ -720,7 +747,7 @@ buffer_change_state (buffer_priv *priv, buffer_state state) case BUFFER_STATE_EMPTY: /* when the output buffer was returned */ if (priv->state == BUFFER_STATE_OUTPUT_RETURN || - /* when the previous input need to be discarded (e.g., NPU processing is too slow) */ + /* when the previous input need to be discarded (e.g., NPU processing is too slow) */ priv->state == BUFFER_STATE_INPUT_READY) state_changed = true; break; @@ -783,7 +810,7 @@ mem_init (uint64_t size_in, uint64_t *size_out) uint32_t handle; int fd; - if (size_in % MEM_BASE_SIZE != 0 || size_in > UINT32_MAX) { + if (size_in == 0 || size_in % MEM_BASE_SIZE != 0 || size_in > UINT32_MAX) { logerr(MEM_TAG, "Invalid memory size: 0x%lx\n", size_in); return -EINVAL; } -- 2.7.4