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