1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** ThreadX Component                                                     */
16 /**                                                                       */
17 /**   Block Pool                                                          */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "tx_api.h"
28 #include "tx_trace.h"
29 #include "tx_block_pool.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _tx_block_pool_create                               PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    William E. Lamie, Microsoft Corporation                             */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function creates a pool of fixed-size memory blocks in the     */
45 /*    specified memory area.                                              */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    pool_ptr                          Pointer to pool control block     */
50 /*    name_ptr                          Pointer to block pool name        */
51 /*    block_size                        Number of bytes in each block     */
52 /*    pool_start                        Address of beginning of pool area */
53 /*    pool_size                         Number of bytes in the block pool */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    TX_SUCCESS                        Successful completion status      */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    None                                                                */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    Application Code                                                    */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
72 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
73 /*                                            resulting in version 6.1    */
74 /*                                                                        */
75 /**************************************************************************/
_tx_block_pool_create(TX_BLOCK_POOL * pool_ptr,CHAR * name_ptr,ULONG block_size,VOID * pool_start,ULONG pool_size)76 UINT  _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size,
77                     VOID *pool_start, ULONG pool_size)
78 {
79 
80 TX_INTERRUPT_SAVE_AREA
81 
82 UINT                blocks;
83 UINT                status;
84 ULONG               total_blocks;
85 UCHAR               *block_ptr;
86 UCHAR               **block_link_ptr;
87 UCHAR               *next_block_ptr;
88 TX_BLOCK_POOL       *next_pool;
89 TX_BLOCK_POOL       *previous_pool;
90 
91 
92     /* Initialize block pool control block to all zeros.  */
93     TX_MEMSET(pool_ptr, 0, (sizeof(TX_BLOCK_POOL)));
94 
95     /* Round the block size up to something that is evenly divisible by
96        an ALIGN_TYPE (typically this is a 32-bit ULONG). This helps guarantee proper alignment.  */
97     block_size =  (((block_size + (sizeof(ALIGN_TYPE))) - ((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
98 
99     /* Round the pool size down to something that is evenly divisible by
100        an ALIGN_TYPE (typically this is a 32-bit ULONG).  */
101     pool_size =   (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
102 
103     /* Setup the basic block pool fields.  */
104     pool_ptr -> tx_block_pool_name =             name_ptr;
105     pool_ptr -> tx_block_pool_start =            TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
106     pool_ptr -> tx_block_pool_size =             pool_size;
107     pool_ptr -> tx_block_pool_block_size =       (UINT) block_size;
108 
109     /* Calculate the total number of blocks.  */
110     total_blocks =  pool_size/(block_size + (sizeof(UCHAR *)));
111 
112     /* Walk through the pool area, setting up the available block list.  */
113     blocks =            ((UINT) 0);
114     block_ptr =         TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
115     next_block_ptr =    TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *))));
116     while(blocks < (UINT) total_blocks)
117     {
118 
119         /* Yes, we have another block.  Increment the block count.  */
120         blocks++;
121 
122         /* Setup the link to the next block.  */
123         block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
124         *block_link_ptr =  next_block_ptr;
125 
126         /* Advance to the next block.  */
127         block_ptr =   next_block_ptr;
128 
129         /* Update the next block pointer.  */
130         next_block_ptr =  TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *))));
131     }
132 
133     /* Save the remaining information in the pool control block.  */
134     pool_ptr -> tx_block_pool_available =  blocks;
135     pool_ptr -> tx_block_pool_total =      blocks;
136 
137     /* Quickly check to make sure at least one block is in the pool.  */
138     if (blocks != ((UINT) 0))
139     {
140 
141         /* Backup to the last block in the pool.  */
142         block_ptr =  TX_UCHAR_POINTER_SUB(block_ptr,(block_size + (sizeof(UCHAR *))));
143 
144         /* Set the last block's forward pointer to NULL.  */
145         block_link_ptr =  TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
146         *block_link_ptr =  TX_NULL;
147 
148         /* Setup the starting pool address.  */
149         pool_ptr -> tx_block_pool_available_list =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
150 
151         /* Disable interrupts to place the block pool on the created list.  */
152         TX_DISABLE
153 
154         /* Setup the block pool ID to make it valid.  */
155         pool_ptr -> tx_block_pool_id =  TX_BLOCK_POOL_ID;
156 
157         /* Place the block pool on the list of created block pools.  First,
158            check for an empty list.  */
159         if (_tx_block_pool_created_count == TX_EMPTY)
160         {
161 
162             /* The created block pool list is empty.  Add block pool to empty list.  */
163             _tx_block_pool_created_ptr =                  pool_ptr;
164             pool_ptr -> tx_block_pool_created_next =      pool_ptr;
165             pool_ptr -> tx_block_pool_created_previous =  pool_ptr;
166         }
167         else
168         {
169 
170             /* This list is not NULL, add to the end of the list.  */
171             next_pool =      _tx_block_pool_created_ptr;
172             previous_pool =  next_pool -> tx_block_pool_created_previous;
173 
174             /* Place the new block pool in the list.  */
175             next_pool -> tx_block_pool_created_previous =  pool_ptr;
176             previous_pool -> tx_block_pool_created_next =  pool_ptr;
177 
178             /* Setup this block pool's created links.  */
179             pool_ptr -> tx_block_pool_created_previous =  previous_pool;
180             pool_ptr -> tx_block_pool_created_next =      next_pool;
181         }
182 
183         /* Increment the created count.  */
184         _tx_block_pool_created_count++;
185 
186         /* Optional block pool create extended processing.  */
187         TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
188 
189         /* If trace is enabled, register this object.  */
190         TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, pool_ptr, name_ptr, pool_size, block_size)
191 
192         /* If trace is enabled, insert this event into the trace buffer.  */
193         TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), blocks, block_size, TX_TRACE_BLOCK_POOL_EVENTS)
194 
195         /* Log this kernel call.  */
196         TX_EL_BLOCK_POOL_CREATE_INSERT
197 
198         /* Restore interrupts.  */
199         TX_RESTORE
200 
201         /* Return successful status.  */
202         status =  TX_SUCCESS;
203     }
204     else
205     {
206 
207         /* Not enough memory for one block, return appropriate error.  */
208         status =  TX_SIZE_ERROR;
209     }
210 
211     /* Return completion status.  */
212     return(status);
213 }
214 
215