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