mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-31 13:17:31 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			280 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			280 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2019 Intel Corporation.  All rights reserved.
 | |
|  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
|  */
 | |
| 
 | |
| #include "bh_vector.h"
 | |
| 
 | |
| static uint8 *
 | |
| alloc_vector_data(size_t length, size_t size_elem)
 | |
| {
 | |
|     uint64 total_size = ((uint64)size_elem) * length;
 | |
|     uint8 *data;
 | |
| 
 | |
|     if (length > UINT32_MAX || size_elem > UINT32_MAX
 | |
|         || total_size > UINT32_MAX) {
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     if ((data = BH_MALLOC((uint32)total_size))) {
 | |
|         memset(data, 0, (uint32)total_size);
 | |
|     }
 | |
| 
 | |
|     return data;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * every caller of `extend_vector` must provide
 | |
|  * a thread-safe environment.
 | |
|  */
 | |
| static bool
 | |
| extend_vector(Vector *vector, size_t length)
 | |
| {
 | |
|     uint8 *data;
 | |
| 
 | |
|     if (length <= vector->max_elems)
 | |
|         return true;
 | |
| 
 | |
|     if (length < vector->size_elem * 3 / 2)
 | |
|         length = vector->size_elem * 3 / 2;
 | |
| 
 | |
|     if (!(data = alloc_vector_data(length, vector->size_elem))) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     bh_memcpy_s(data, (uint32)(vector->size_elem * length), vector->data,
 | |
|                 (uint32)(vector->size_elem * vector->max_elems));
 | |
|     BH_FREE(vector->data);
 | |
| 
 | |
|     vector->data = data;
 | |
|     vector->max_elems = length;
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bh_vector_init(Vector *vector, size_t init_length, size_t size_elem,
 | |
|                bool use_lock)
 | |
| {
 | |
|     if (!vector) {
 | |
|         LOG_ERROR("Init vector failed: vector is NULL.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (init_length == 0) {
 | |
|         init_length = 4;
 | |
|     }
 | |
| 
 | |
|     if (!(vector->data = alloc_vector_data(init_length, size_elem))) {
 | |
|         LOG_ERROR("Init vector failed: alloc memory failed.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     vector->size_elem = size_elem;
 | |
|     vector->max_elems = init_length;
 | |
|     vector->num_elems = 0;
 | |
|     vector->lock = NULL;
 | |
| 
 | |
|     if (use_lock) {
 | |
|         if (!(vector->lock = BH_MALLOC(sizeof(korp_mutex)))) {
 | |
|             LOG_ERROR("Init vector failed: alloc locker failed.\n");
 | |
|             bh_vector_destroy(vector);
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         if (BHT_OK != os_mutex_init(vector->lock)) {
 | |
|             LOG_ERROR("Init vector failed: init locker failed.\n");
 | |
| 
 | |
|             BH_FREE(vector->lock);
 | |
|             vector->lock = NULL;
 | |
| 
 | |
|             bh_vector_destroy(vector);
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bh_vector_set(Vector *vector, uint32 index, const void *elem_buf)
 | |
| {
 | |
|     if (!vector || !elem_buf) {
 | |
|         LOG_ERROR("Set vector elem failed: vector or elem buf is NULL.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (index >= vector->num_elems) {
 | |
|         LOG_ERROR("Set vector elem failed: invalid elem index.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (vector->lock)
 | |
|         os_mutex_lock(vector->lock);
 | |
|     bh_memcpy_s(vector->data + vector->size_elem * index,
 | |
|                 (uint32)vector->size_elem, elem_buf, (uint32)vector->size_elem);
 | |
|     if (vector->lock)
 | |
|         os_mutex_unlock(vector->lock);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bh_vector_get(Vector *vector, uint32 index, void *elem_buf)
 | |
| {
 | |
|     if (!vector || !elem_buf) {
 | |
|         LOG_ERROR("Get vector elem failed: vector or elem buf is NULL.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (index >= vector->num_elems) {
 | |
|         LOG_ERROR("Get vector elem failed: invalid elem index.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (vector->lock)
 | |
|         os_mutex_lock(vector->lock);
 | |
|     bh_memcpy_s(elem_buf, (uint32)vector->size_elem,
 | |
|                 vector->data + vector->size_elem * index,
 | |
|                 (uint32)vector->size_elem);
 | |
|     if (vector->lock)
 | |
|         os_mutex_unlock(vector->lock);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf)
 | |
| {
 | |
|     size_t i;
 | |
|     uint8 *p;
 | |
|     bool ret = false;
 | |
| 
 | |
|     if (!vector || !elem_buf) {
 | |
|         LOG_ERROR("Insert vector elem failed: vector or elem buf is NULL.\n");
 | |
|         goto just_return;
 | |
|     }
 | |
| 
 | |
|     if (index >= vector->num_elems) {
 | |
|         LOG_ERROR("Insert vector elem failed: invalid elem index.\n");
 | |
|         goto just_return;
 | |
|     }
 | |
| 
 | |
|     if (vector->lock)
 | |
|         os_mutex_lock(vector->lock);
 | |
| 
 | |
|     if (!extend_vector(vector, vector->num_elems + 1)) {
 | |
|         LOG_ERROR("Insert vector elem failed: extend vector failed.\n");
 | |
|         goto unlock_return;
 | |
|     }
 | |
| 
 | |
|     p = vector->data + vector->size_elem * vector->num_elems;
 | |
|     for (i = vector->num_elems - 1; i > index; i--) {
 | |
|         bh_memcpy_s(p, (uint32)vector->size_elem, p - vector->size_elem,
 | |
|                     (uint32)vector->size_elem);
 | |
|         p -= vector->size_elem;
 | |
|     }
 | |
| 
 | |
|     bh_memcpy_s(p, (uint32)vector->size_elem, elem_buf,
 | |
|                 (uint32)vector->size_elem);
 | |
|     vector->num_elems++;
 | |
|     ret = true;
 | |
| 
 | |
| unlock_return:
 | |
|     if (vector->lock)
 | |
|         os_mutex_unlock(vector->lock);
 | |
| just_return:
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bh_vector_append(Vector *vector, const void *elem_buf)
 | |
| {
 | |
|     bool ret = false;
 | |
| 
 | |
|     if (!vector || !elem_buf) {
 | |
|         LOG_ERROR("Append vector elem failed: vector or elem buf is NULL.\n");
 | |
|         goto just_return;
 | |
|     }
 | |
| 
 | |
|     /* make sure one more slot is used by the thread who allocas it */
 | |
|     if (vector->lock)
 | |
|         os_mutex_lock(vector->lock);
 | |
| 
 | |
|     if (!extend_vector(vector, vector->num_elems + 1)) {
 | |
|         LOG_ERROR("Append ector elem failed: extend vector failed.\n");
 | |
|         goto unlock_return;
 | |
|     }
 | |
| 
 | |
|     bh_memcpy_s(vector->data + vector->size_elem * vector->num_elems,
 | |
|                 (uint32)vector->size_elem, elem_buf, (uint32)vector->size_elem);
 | |
|     vector->num_elems++;
 | |
|     ret = true;
 | |
| 
 | |
| unlock_return:
 | |
|     if (vector->lock)
 | |
|         os_mutex_unlock(vector->lock);
 | |
| just_return:
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf)
 | |
| {
 | |
|     uint32 i;
 | |
|     uint8 *p;
 | |
| 
 | |
|     if (!vector) {
 | |
|         LOG_ERROR("Remove vector elem failed: vector is NULL.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (index >= vector->num_elems) {
 | |
|         LOG_ERROR("Remove vector elem failed: invalid elem index.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (vector->lock)
 | |
|         os_mutex_lock(vector->lock);
 | |
|     p = vector->data + vector->size_elem * index;
 | |
| 
 | |
|     if (old_elem_buf) {
 | |
|         bh_memcpy_s(old_elem_buf, (uint32)vector->size_elem, p,
 | |
|                     (uint32)vector->size_elem);
 | |
|     }
 | |
| 
 | |
|     for (i = index; i < vector->num_elems - 1; i++) {
 | |
|         bh_memcpy_s(p, (uint32)vector->size_elem, p + vector->size_elem,
 | |
|                     (uint32)vector->size_elem);
 | |
|         p += vector->size_elem;
 | |
|     }
 | |
| 
 | |
|     vector->num_elems--;
 | |
|     if (vector->lock)
 | |
|         os_mutex_unlock(vector->lock);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| size_t
 | |
| bh_vector_size(const Vector *vector)
 | |
| {
 | |
|     return vector ? vector->num_elems : 0;
 | |
| }
 | |
| 
 | |
| bool
 | |
| bh_vector_destroy(Vector *vector)
 | |
| {
 | |
|     if (!vector) {
 | |
|         LOG_ERROR("Destroy vector elem failed: vector is NULL.\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (vector->data)
 | |
|         BH_FREE(vector->data);
 | |
| 
 | |
|     if (vector->lock) {
 | |
|         os_mutex_destroy(vector->lock);
 | |
|         BH_FREE(vector->lock);
 | |
|     }
 | |
| 
 | |
|     memset(vector, 0, sizeof(Vector));
 | |
|     return true;
 | |
| }
 | 
