301 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * Copyright (c) 2021 OceanBase
 | |
|  * OceanBase CE is licensed under Mulan PubL v2.
 | |
|  * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | |
|  * You may obtain a copy of Mulan PubL v2 at:
 | |
|  *          http://license.coscl.org.cn/MulanPubL-2.0
 | |
|  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | |
|  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | |
|  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | |
|  * See the Mulan PubL v2 for more details.
 | |
|  */
 | |
| 
 | |
| #include "memory/easy_mem_slab.h"
 | |
| #include <easy_test.h>
 | |
| #include <pthread.h>
 | |
| 
 | |
| #define Mbyte(s) (s * 1024 * 1024)
 | |
| #define Kbyte(s, d) (s * 1024 + d)
 | |
| extern easy_mem_mgr_t easy_mem_mgr_var;
 | |
| 
 | |
| TEST(easy_mem_slab, init)
 | |
| {
 | |
|   int ret;
 | |
|   EXPECT_EQ(easy_mem_mgr_var.started, 0);
 | |
| 
 | |
|   ret = easy_mem_slab_init(Mbyte(1), Mbyte(16));
 | |
|   EXPECT_EQ(ret, EASY_OK);
 | |
| 
 | |
|   EXPECT_EQ(easy_mem_mgr_var.started, 1);
 | |
|   easy_mem_slab_destroy();
 | |
| }
 | |
| 
 | |
| typedef struct test_1_t {
 | |
|   int size;
 | |
|   int idx;
 | |
|   int in;
 | |
| } test_1_t;
 | |
| static int test_1_check(test_1_t* t)
 | |
| {
 | |
|   unsigned char* ptr;
 | |
|   easy_mem_zone_t* z;
 | |
|   unsigned long a;
 | |
|   int ret, order;
 | |
|   easy_mem_slab_t* slab;
 | |
| 
 | |
|   z = easy_mem_mgr_var.zone;
 | |
|   ptr = (unsigned char*)easy_mem_slab_realloc(NULL, t->size);
 | |
| 
 | |
|   if (ptr == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   ret = 1;
 | |
| 
 | |
|   if (t->in == 0) {
 | |
|     if (ptr >= z->mem_start && ptr < z->mem_end) {
 | |
|       ret = 0;
 | |
|     }
 | |
|   } else {
 | |
|     order = (ptr - z->mem_start) >> EASY_MEM_PAGE_SHIFT;
 | |
|     order = (z->page_flags[order] & 0x0f);
 | |
|     a = (1 << (EASY_MEM_PAGE_SHIFT + order));
 | |
|     slab = (easy_mem_slab_t*)(((unsigned long)ptr) & ~(a - 1));
 | |
| 
 | |
|     if (slab->cache_idx != t->idx) {
 | |
|       ret = 0;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   easy_mem_slab_realloc(ptr, 0);
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| // void *easy_mem_slab_realloc(void *ptr, size_t size)
 | |
| TEST(easy_mem_slab, realloc)
 | |
| {
 | |
|   int i, ret, end, max_size, cnt;
 | |
|   test_1_t param[] = {
 | |
|       {511, 0, 1},
 | |
|       {512, 0, 1},
 | |
|       {513, 1, 1},
 | |
|       {Kbyte(1, -1), 1, 1},
 | |
|       {Kbyte(1, 0), 1, 1},
 | |
|       {Kbyte(1, 1), 2, 1},
 | |
|       {Kbyte(2, -1), 2, 1},
 | |
|       {Kbyte(2, 0), 2, 1},
 | |
|       {Kbyte(2, 1), 3, 1},
 | |
|       {Kbyte(4, -1), 3, 1},
 | |
|       {Kbyte(4, 0), 3, 1},
 | |
|       {Kbyte(4, 1), 4, 1},
 | |
|       {Kbyte(8, -1), 4, 1},
 | |
|       {Kbyte(8, 0), 4, 1},
 | |
|       {Kbyte(8, 1), 5, 1},
 | |
|       {Kbyte(16, -1), 5, 1},
 | |
|       {Kbyte(16, 0), 5, 1},
 | |
|       {Kbyte(16, 1), 6, 1},
 | |
|       {Kbyte(32, -1), 6, 1},
 | |
|       {Kbyte(32, 0), 6, 1},
 | |
|       {Kbyte(32, 1), 7, 1},
 | |
|       {Kbyte(64, -1), 7, 1},
 | |
|       {Kbyte(64, 0), 7, 1},
 | |
|       {Kbyte(64, 1), 8, 1},
 | |
|       {Kbyte(128, -1), 8, 1},
 | |
|       {Kbyte(128, 0), 8, 1},
 | |
|       {Kbyte(128, 1), 9, 1},
 | |
|       {Kbyte(256, -1), 9, 1},
 | |
|       {Kbyte(256, 0), 9, 1},
 | |
|       {Kbyte(256, 1), 10, 1},
 | |
|       {Kbyte(512, -1), 10, 1},
 | |
|       {Kbyte(512, 0), 10, 1},
 | |
|       {Kbyte(512, 1), 11, 1},
 | |
|       {Kbyte(1024, -1), 11, 1},
 | |
|       {Kbyte(1024, 0), 11, 1},
 | |
|       {Kbyte(1024, 1), 0, 0},
 | |
|       {Kbyte(2048, -1), 0, 0},
 | |
|       {Kbyte(2048, 0), 0, 0},
 | |
|       {Kbyte(2048, 1), 0, 0},
 | |
|   };
 | |
| 
 | |
|   // setup
 | |
|   EXPECT_EQ(easy_mem_mgr_var.started, 0);
 | |
|   ret = easy_mem_slab_init(Mbyte(1), Mbyte(16));
 | |
|   EXPECT_EQ(ret, EASY_OK);
 | |
|   EXPECT_EQ(easy_mem_mgr_var.started, 1);
 | |
| 
 | |
|   // 1.
 | |
|   end = easy_mem_mgr_var.cache_num - 1;
 | |
|   max_size = easy_mem_mgr_var.caches[end].buffer_size;
 | |
|   EXPECT_EQ(max_size, Mbyte(1));
 | |
| 
 | |
|   // 2.
 | |
|   cnt = sizeof(param) / sizeof(param[0]);
 | |
|   ret = 0;
 | |
| 
 | |
|   for (i = 0; i < cnt; i++) {
 | |
|     ret += test_1_check(¶m[i]);
 | |
|   }
 | |
| 
 | |
|   EXPECT_EQ(ret, cnt);
 | |
| 
 | |
|   // 3.
 | |
|   ret = 0;
 | |
| 
 | |
|   for (i = 0; i < cnt; i++) {
 | |
|     ret += test_1_check(¶m[cnt - 1 - i]);
 | |
|   }
 | |
| 
 | |
|   EXPECT_EQ(ret, cnt);
 | |
| 
 | |
|   // 4.
 | |
|   ret = 0;
 | |
|   end = 0;
 | |
|   srand(time(NULL));
 | |
| 
 | |
|   for (i = 0; i < 3000; i++) {
 | |
|     ret += test_1_check(¶m[rand() % cnt]);
 | |
|     end++;
 | |
|   }
 | |
| 
 | |
|   EXPECT_EQ(ret, end);
 | |
| 
 | |
|   // 5. other
 | |
|   char* ptr = NULL;
 | |
| 
 | |
|   for (i = Mbyte(1) - 5; i < Mbyte(1) + 5; i++) {
 | |
|     ptr = (char*)easy_mem_slab_realloc(ptr, i);
 | |
|     EXPECT_TRUE(ptr != NULL);
 | |
|   }
 | |
| 
 | |
|   cnt = 0;
 | |
| 
 | |
|   for (i = 0; i < 10; i++) {
 | |
|     ptr = (char*)easy_mem_slab_realloc(ptr, i);
 | |
| 
 | |
|     if (ptr)
 | |
|       cnt++;
 | |
|   }
 | |
| 
 | |
|   EXPECT_EQ(cnt, 9);
 | |
| 
 | |
|   // down
 | |
|   easy_mem_slab_destroy();
 | |
| }
 | |
| 
 | |
| void* test_mem_alloc(void* args)
 | |
| {
 | |
|   unsigned char *ptr[100], *str;
 | |
|   int i, cnt = 0, size, idx;
 | |
|   srand(pthread_self());
 | |
|   easy_mem_zone_t* z = easy_mem_mgr_var.zone;
 | |
| 
 | |
|   // 1.
 | |
|   for (i = 0; i < 10000; i++) {
 | |
|     size = ((rand() * 10243) & 0x7fffffff) % Mbyte(1) + 10;
 | |
|     ptr[0] = (unsigned char*)easy_mem_slab_realloc(NULL, size);
 | |
| 
 | |
|     if (ptr[0]) {
 | |
|       easy_mem_slab_realloc(ptr[0], 0);
 | |
|       cnt++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   EXPECT_EQ(cnt, 10000);
 | |
| 
 | |
|   // 2.
 | |
|   idx = 0;
 | |
|   cnt = 0;
 | |
| 
 | |
|   for (i = 0; i < 10000; i++) {
 | |
|     size = ((rand() * 10243) & 0x7fffffff) % Kbyte(4, 0) + 10;
 | |
|     str = (unsigned char*)easy_mem_slab_realloc(NULL, size);
 | |
| 
 | |
|     if (str < z->mem_start || str > z->mem_end)
 | |
|       abort();
 | |
| 
 | |
|     ptr[idx++] = str;
 | |
| 
 | |
|     if (idx >= 100) {
 | |
|       while (idx > 50) {
 | |
|         if (ptr[idx - 1]) {
 | |
|           easy_mem_slab_realloc(ptr[idx - 1], 0);
 | |
|           cnt++;
 | |
|         }
 | |
| 
 | |
|         idx--;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   while (idx > 0) {
 | |
|     if (ptr[idx - 1]) {
 | |
|       easy_mem_slab_realloc(ptr[idx - 1], 0);
 | |
|       cnt++;
 | |
|     }
 | |
| 
 | |
|     idx--;
 | |
|   }
 | |
| 
 | |
|   EXPECT_EQ(cnt, 10000);
 | |
|   return (void*)NULL;
 | |
| }
 | |
| 
 | |
| TEST(easy_mem_slab, mthread)
 | |
| {
 | |
|   int i, thread_cnt = 10;
 | |
|   pthread_t tid[thread_cnt];
 | |
| 
 | |
|   // setup
 | |
|   easy_mem_slab_init(Mbyte(1), Mbyte(32));
 | |
| 
 | |
|   for (i = 0; i < thread_cnt; i++) {
 | |
|     pthread_create(&tid[i], NULL, test_mem_alloc, NULL);
 | |
|   }
 | |
| 
 | |
|   for (i = 0; i < thread_cnt; i++) {
 | |
|     pthread_join(tid[i], NULL);
 | |
|   }
 | |
| 
 | |
|   // down
 | |
|   easy_mem_slab_destroy();
 | |
|   easy_mem_slab_destroy();
 | |
| }
 | |
| 
 | |
| TEST(easy_mem_slab, realloc_cmp)
 | |
| {
 | |
|   char *ptr, *ptr1;
 | |
|   char str[100];
 | |
| 
 | |
|   memset(str, 'A', 100);
 | |
|   easy_mem_slab_init(Mbyte(1), Mbyte(32));
 | |
| 
 | |
|   // 1.
 | |
|   ptr = (char*)easy_mem_slab_realloc(NULL, 1);
 | |
|   ptr1 = (char*)easy_mem_slab_realloc(ptr, 100);
 | |
|   EXPECT_TRUE(ptr == ptr1);
 | |
|   memcpy(ptr1, str, 100);
 | |
| 
 | |
|   // 2.
 | |
|   ptr = (char*)easy_mem_slab_realloc(ptr1, 10000);
 | |
|   EXPECT_FALSE(ptr == ptr1);
 | |
| 
 | |
|   if (memcmp(ptr, str, 100)) {
 | |
|     EXPECT_TRUE(0);
 | |
|   }
 | |
| 
 | |
|   ptr[9999] = 'B';
 | |
| 
 | |
|   // 3.
 | |
|   ptr1 = (char*)easy_mem_slab_realloc(ptr, Mbyte(1) + 1);
 | |
|   EXPECT_FALSE(ptr == ptr1);
 | |
| 
 | |
|   if (memcmp(ptr1, str, 100)) {
 | |
|     EXPECT_TRUE(0);
 | |
|   }
 | |
| 
 | |
|   EXPECT_TRUE(ptr1[9999] == 'B');
 | |
|   easy_mem_slab_realloc(ptr1, 0);
 | |
| 
 | |
|   easy_mem_slab_destroy();
 | |
| }
 | 
