xref: /nrf52832-nimble/rt-thread/components/lwp/lwp_mem.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2018-06-10     Bernard      first version
9*10465441SEvalZero  */
10*10465441SEvalZero 
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include <lwp.h>
13*10465441SEvalZero 
14*10465441SEvalZero #define DBG_ENABLE
15*10465441SEvalZero #define DBG_SECTION_NAME    "LWPMEM"
16*10465441SEvalZero #define DBG_COLOR
17*10465441SEvalZero #define DBG_LEVEL           DBG_WARNING
18*10465441SEvalZero #include <rtdbg.h>
19*10465441SEvalZero 
20*10465441SEvalZero // todo: remove repleat code
21*10465441SEvalZero #define RT_MEMHEAP_SIZE         RT_ALIGN(sizeof(struct rt_lwp_memheap_item), RT_ALIGN_SIZE)
22*10465441SEvalZero #define MEMITEM_SIZE(item)      ((rt_uint32_t)item->next - (rt_uint32_t)item - RT_MEMHEAP_SIZE)
23*10465441SEvalZero 
24*10465441SEvalZero #ifndef LWP_MEM_PAGE_SIZE
25*10465441SEvalZero     #define LWP_MEM_PAGE_SIZE       (4 * 1024)
26*10465441SEvalZero #endif
27*10465441SEvalZero 
28*10465441SEvalZero #ifndef LWP_MEM_MAX_PAGE_COUNT
29*10465441SEvalZero     #define LWP_MEM_MAX_PAGE_COUNT  (256 * 4)
30*10465441SEvalZero #endif
31*10465441SEvalZero 
rt_lwp_malloc_page(struct rt_lwp * lwp,rt_size_t npages)32*10465441SEvalZero static void *rt_lwp_malloc_page(struct rt_lwp *lwp, rt_size_t npages)
33*10465441SEvalZero {
34*10465441SEvalZero     void *chunk;
35*10465441SEvalZero     char name[6];
36*10465441SEvalZero     struct rt_lwp_memheap *lwp_heap;
37*10465441SEvalZero     rt_size_t page_cnt;
38*10465441SEvalZero 
39*10465441SEvalZero     RT_ASSERT(lwp != RT_NULL);
40*10465441SEvalZero 
41*10465441SEvalZero     page_cnt = lwp->heap_cnt + npages;
42*10465441SEvalZero     if (page_cnt > LWP_MEM_MAX_PAGE_COUNT)
43*10465441SEvalZero     {
44*10465441SEvalZero         dbg_log(DBG_ERROR, "alloc new page failed, lwp memory size out of limited: %d\n", page_cnt);
45*10465441SEvalZero         return RT_NULL;
46*10465441SEvalZero     }
47*10465441SEvalZero 
48*10465441SEvalZero     lwp_heap = rt_malloc(sizeof(struct rt_lwp_memheap));
49*10465441SEvalZero     if (lwp_heap == RT_NULL)
50*10465441SEvalZero     {
51*10465441SEvalZero         dbg_log(DBG_ERROR, "alloc new page head failed, out of memory : %d\n", page_cnt);
52*10465441SEvalZero         return RT_NULL;
53*10465441SEvalZero     }
54*10465441SEvalZero 
55*10465441SEvalZero     chunk = rt_malloc(npages * LWP_MEM_PAGE_SIZE);
56*10465441SEvalZero     if (chunk == RT_NULL)
57*10465441SEvalZero     {
58*10465441SEvalZero         dbg_log(DBG_ERROR, "alloc new page buffer failed, out of memory : %d\n", page_cnt);
59*10465441SEvalZero         rt_free(lwp_heap);
60*10465441SEvalZero         return RT_NULL;
61*10465441SEvalZero     }
62*10465441SEvalZero 
63*10465441SEvalZero     dbg_log(DBG_LOG, "lwp alloc page: %d\n", npages);
64*10465441SEvalZero 
65*10465441SEvalZero     rt_sprintf(name, "lwp%02x", lwp->heap_cnt);
66*10465441SEvalZero     rt_lwp_memheap_init(lwp_heap, name, chunk, npages * LWP_MEM_PAGE_SIZE);
67*10465441SEvalZero 
68*10465441SEvalZero     rt_list_insert_before(&lwp->hlist, &lwp_heap->mlist);
69*10465441SEvalZero 
70*10465441SEvalZero     lwp->heap_cnt += npages;
71*10465441SEvalZero 
72*10465441SEvalZero     return chunk;
73*10465441SEvalZero }
74*10465441SEvalZero 
rt_lwp_free_page(struct rt_lwp * lwp,struct rt_lwp_memheap * lwp_heap)75*10465441SEvalZero static void rt_lwp_free_page(struct rt_lwp *lwp, struct rt_lwp_memheap *lwp_heap)
76*10465441SEvalZero {
77*10465441SEvalZero     rt_size_t npages;
78*10465441SEvalZero 
79*10465441SEvalZero     RT_ASSERT(lwp != RT_NULL);
80*10465441SEvalZero     RT_ASSERT(lwp_heap != RT_NULL);
81*10465441SEvalZero     RT_ASSERT(lwp_heap->start_addr != RT_NULL);
82*10465441SEvalZero 
83*10465441SEvalZero     npages = lwp_heap->pool_size / LWP_MEM_PAGE_SIZE;
84*10465441SEvalZero     lwp->heap_cnt -= npages;
85*10465441SEvalZero 
86*10465441SEvalZero     dbg_log(DBG_LOG, "lwp free page: %d\n", npages);
87*10465441SEvalZero 
88*10465441SEvalZero     rt_list_remove(&lwp_heap->mlist);
89*10465441SEvalZero 
90*10465441SEvalZero     rt_free(lwp_heap->start_addr);
91*10465441SEvalZero     rt_free(lwp_heap);
92*10465441SEvalZero }
93*10465441SEvalZero 
rt_lwp_mem_init(struct rt_lwp * lwp)94*10465441SEvalZero void rt_lwp_mem_init(struct rt_lwp *lwp)
95*10465441SEvalZero {
96*10465441SEvalZero     RT_ASSERT(lwp != RT_NULL);
97*10465441SEvalZero     rt_list_init(&lwp->hlist);
98*10465441SEvalZero }
99*10465441SEvalZero 
rt_lwp_mem_deinit(struct rt_lwp * lwp)100*10465441SEvalZero void rt_lwp_mem_deinit(struct rt_lwp *lwp)
101*10465441SEvalZero {
102*10465441SEvalZero     struct rt_list_node *node;
103*10465441SEvalZero 
104*10465441SEvalZero     RT_ASSERT(lwp != RT_NULL);
105*10465441SEvalZero 
106*10465441SEvalZero     node = lwp->hlist.next;
107*10465441SEvalZero 
108*10465441SEvalZero     while (node != &(lwp->hlist))
109*10465441SEvalZero     {
110*10465441SEvalZero         struct rt_lwp_memheap *lwp_heap;
111*10465441SEvalZero 
112*10465441SEvalZero         lwp_heap = rt_list_entry(node, struct rt_lwp_memheap, mlist);
113*10465441SEvalZero         RT_ASSERT(lwp_heap != RT_NULL);
114*10465441SEvalZero 
115*10465441SEvalZero         /* update note before free page*/
116*10465441SEvalZero         node = node->next;
117*10465441SEvalZero 
118*10465441SEvalZero         rt_lwp_free_page(lwp, lwp_heap);
119*10465441SEvalZero     }
120*10465441SEvalZero }
121*10465441SEvalZero 
rt_lwp_mem_malloc(rt_uint32_t size)122*10465441SEvalZero void *rt_lwp_mem_malloc(rt_uint32_t size)
123*10465441SEvalZero {
124*10465441SEvalZero     struct rt_lwp *lwp;
125*10465441SEvalZero     struct rt_list_node *node;
126*10465441SEvalZero     void *addr = RT_NULL;
127*10465441SEvalZero     rt_uint32_t npages;
128*10465441SEvalZero 
129*10465441SEvalZero     if (size == 0)
130*10465441SEvalZero         return RT_NULL;
131*10465441SEvalZero 
132*10465441SEvalZero     lwp = rt_lwp_self();
133*10465441SEvalZero     RT_ASSERT(lwp != RT_NULL);
134*10465441SEvalZero 
135*10465441SEvalZero     for (node  = lwp->hlist.next; node != &(lwp->hlist); node = node->next)
136*10465441SEvalZero     {
137*10465441SEvalZero         struct rt_lwp_memheap *lwp_heap;
138*10465441SEvalZero         lwp_heap = rt_list_entry(node, struct rt_lwp_memheap, mlist);
139*10465441SEvalZero 
140*10465441SEvalZero         addr = rt_lwp_memheap_alloc(lwp_heap, size);
141*10465441SEvalZero         if (addr != RT_NULL)
142*10465441SEvalZero         {
143*10465441SEvalZero             dbg_log(DBG_LOG, "lwp alloc 0x%x/%d\n", addr, size);
144*10465441SEvalZero             return addr;
145*10465441SEvalZero         }
146*10465441SEvalZero     }
147*10465441SEvalZero 
148*10465441SEvalZero     npages = (size + rt_lwp_memheap_unavailable_size_get() + LWP_MEM_PAGE_SIZE) / LWP_MEM_PAGE_SIZE;
149*10465441SEvalZero     if (RT_NULL != rt_lwp_malloc_page(lwp, npages))
150*10465441SEvalZero         return rt_lwp_mem_malloc(size);
151*10465441SEvalZero     else
152*10465441SEvalZero         return RT_NULL;
153*10465441SEvalZero }
154*10465441SEvalZero 
rt_lwp_mem_free(void * addr)155*10465441SEvalZero void rt_lwp_mem_free(void *addr)
156*10465441SEvalZero {
157*10465441SEvalZero     struct rt_lwp_memheap_item *header_ptr;
158*10465441SEvalZero     struct rt_lwp_memheap *lwp_heap;
159*10465441SEvalZero 
160*10465441SEvalZero     if (addr == RT_NULL)
161*10465441SEvalZero         return ;
162*10465441SEvalZero 
163*10465441SEvalZero     /* get memory item */
164*10465441SEvalZero     header_ptr = (struct rt_lwp_memheap_item *)((rt_uint8_t *)addr - RT_MEMHEAP_SIZE);
165*10465441SEvalZero     RT_ASSERT(header_ptr);
166*10465441SEvalZero 
167*10465441SEvalZero     lwp_heap = header_ptr->pool_ptr;
168*10465441SEvalZero     RT_ASSERT(lwp_heap);
169*10465441SEvalZero 
170*10465441SEvalZero     dbg_log(DBG_LOG, "lwp free 0x%x\n", addr);
171*10465441SEvalZero     rt_lwp_memheap_free((void *)addr);
172*10465441SEvalZero 
173*10465441SEvalZero     if (rt_lwp_memheap_is_empty(lwp_heap))
174*10465441SEvalZero     {
175*10465441SEvalZero         rt_lwp_free_page(rt_lwp_self(), lwp_heap);
176*10465441SEvalZero     }
177*10465441SEvalZero }
178*10465441SEvalZero 
rt_lwp_mem_realloc(void * rmem,rt_size_t newsize)179*10465441SEvalZero void *rt_lwp_mem_realloc(void *rmem, rt_size_t newsize)
180*10465441SEvalZero {
181*10465441SEvalZero     void *new_ptr;
182*10465441SEvalZero     struct rt_lwp_memheap_item *header_ptr;
183*10465441SEvalZero 
184*10465441SEvalZero     if (rmem == RT_NULL)
185*10465441SEvalZero         return rt_lwp_mem_malloc(newsize);
186*10465441SEvalZero 
187*10465441SEvalZero     if (newsize == 0)
188*10465441SEvalZero     {
189*10465441SEvalZero         rt_lwp_mem_free(rmem);
190*10465441SEvalZero         return RT_NULL;
191*10465441SEvalZero     }
192*10465441SEvalZero 
193*10465441SEvalZero     /* get old memory item */
194*10465441SEvalZero     header_ptr = (struct rt_lwp_memheap_item *)
195*10465441SEvalZero                  ((rt_uint8_t *)rmem - RT_MEMHEAP_SIZE);
196*10465441SEvalZero 
197*10465441SEvalZero     new_ptr = rt_lwp_memheap_realloc(header_ptr->pool_ptr, rmem, newsize);
198*10465441SEvalZero     if (new_ptr == RT_NULL)
199*10465441SEvalZero     {
200*10465441SEvalZero         /* allocate memory block from other memheap */
201*10465441SEvalZero         new_ptr = rt_lwp_mem_malloc(newsize);
202*10465441SEvalZero         if (new_ptr != RT_NULL && rmem != RT_NULL)
203*10465441SEvalZero         {
204*10465441SEvalZero             rt_size_t oldsize;
205*10465441SEvalZero 
206*10465441SEvalZero             /* get the size of old memory block */
207*10465441SEvalZero             oldsize = MEMITEM_SIZE(header_ptr);
208*10465441SEvalZero             if (newsize > oldsize)
209*10465441SEvalZero                 rt_memcpy(new_ptr, rmem, oldsize);
210*10465441SEvalZero             else
211*10465441SEvalZero                 rt_memcpy(new_ptr, rmem, newsize);
212*10465441SEvalZero 
213*10465441SEvalZero             dbg_log(DBG_LOG, "lwp realloc with memcpy 0x%x -> 0x%x/%d\n", rmem, new_ptr, newsize);
214*10465441SEvalZero             rt_lwp_mem_free(rmem);
215*10465441SEvalZero 
216*10465441SEvalZero         }
217*10465441SEvalZero     }
218*10465441SEvalZero 
219*10465441SEvalZero     dbg_log(DBG_LOG, "lwp realloc in same address 0x%x/%d\n", rmem, newsize);
220*10465441SEvalZero 
221*10465441SEvalZero     return new_ptr;
222*10465441SEvalZero }
223