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 /** Byte 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_byte_pool.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _tx_byte_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 memory bytes in the specified */
45 /* memory area. */
46 /* */
47 /* INPUT */
48 /* */
49 /* pool_ptr Pointer to pool control block */
50 /* name_ptr Pointer to byte pool name */
51 /* pool_start Address of beginning of pool area */
52 /* pool_size Number of bytes in the byte pool */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* TX_SUCCESS Successful completion status */
57 /* */
58 /* CALLS */
59 /* */
60 /* None */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* Application Code */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
71 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
72 /* resulting in version 6.1 */
73 /* */
74 /**************************************************************************/
_tx_byte_pool_create(TX_BYTE_POOL * pool_ptr,CHAR * name_ptr,VOID * pool_start,ULONG pool_size)75 UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size)
76 {
77
78 TX_INTERRUPT_SAVE_AREA
79
80 UCHAR *block_ptr;
81 UCHAR **block_indirect_ptr;
82 UCHAR *temp_ptr;
83 TX_BYTE_POOL *next_pool;
84 TX_BYTE_POOL *previous_pool;
85 ALIGN_TYPE *free_ptr;
86
87
88 /* Initialize the byte pool control block to all zeros. */
89 TX_MEMSET(pool_ptr, 0, (sizeof(TX_BYTE_POOL)));
90
91 /* Round the pool size down to something that is evenly divisible by
92 an ULONG. */
93 pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
94
95 /* Setup the basic byte pool fields. */
96 pool_ptr -> tx_byte_pool_name = name_ptr;
97
98 /* Save the start and size of the pool. */
99 pool_ptr -> tx_byte_pool_start = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
100 pool_ptr -> tx_byte_pool_size = pool_size;
101
102 /* Setup memory list to the beginning as well as the search pointer. */
103 pool_ptr -> tx_byte_pool_list = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
104 pool_ptr -> tx_byte_pool_search = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
105
106 /* Initially, the pool will have two blocks. One large block at the
107 beginning that is available and a small allocated block at the end
108 of the pool that is there just for the algorithm. Be sure to count
109 the available block's header in the available bytes count. */
110 pool_ptr -> tx_byte_pool_available = pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE)));
111 pool_ptr -> tx_byte_pool_fragments = ((UINT) 2);
112
113 /* Each block contains a "next" pointer that points to the next block in the pool followed by a ALIGN_TYPE
114 field that contains either the constant TX_BYTE_BLOCK_FREE (if the block is free) or a pointer to the
115 owning pool (if the block is allocated). */
116
117 /* Calculate the end of the pool's memory area. */
118 block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
119 block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, pool_size);
120
121 /* Backup the end of the pool pointer and build the pre-allocated block. */
122 block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE)));
123
124 /* Cast the pool pointer into a ULONG. */
125 temp_ptr = TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
126 block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
127 *block_indirect_ptr = temp_ptr;
128
129 block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *)));
130 block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
131 *block_indirect_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
132
133 /* Now setup the large available block in the pool. */
134 temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
135 block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr);
136 *block_indirect_ptr = block_ptr;
137 block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
138 block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *)));
139 free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr);
140 *free_ptr = TX_BYTE_BLOCK_FREE;
141
142 /* Clear the owner id. */
143 pool_ptr -> tx_byte_pool_owner = TX_NULL;
144
145 /* Disable interrupts to place the byte pool on the created list. */
146 TX_DISABLE
147
148 /* Setup the byte pool ID to make it valid. */
149 pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID;
150
151 /* Place the byte pool on the list of created byte pools. First,
152 check for an empty list. */
153 if (_tx_byte_pool_created_count == TX_EMPTY)
154 {
155
156 /* The created byte pool list is empty. Add byte pool to empty list. */
157 _tx_byte_pool_created_ptr = pool_ptr;
158 pool_ptr -> tx_byte_pool_created_next = pool_ptr;
159 pool_ptr -> tx_byte_pool_created_previous = pool_ptr;
160 }
161 else
162 {
163
164 /* This list is not NULL, add to the end of the list. */
165 next_pool = _tx_byte_pool_created_ptr;
166 previous_pool = next_pool -> tx_byte_pool_created_previous;
167
168 /* Place the new byte pool in the list. */
169 next_pool -> tx_byte_pool_created_previous = pool_ptr;
170 previous_pool -> tx_byte_pool_created_next = pool_ptr;
171
172 /* Setup this byte pool's created links. */
173 pool_ptr -> tx_byte_pool_created_previous = previous_pool;
174 pool_ptr -> tx_byte_pool_created_next = next_pool;
175 }
176
177 /* Increment the number of created byte pools. */
178 _tx_byte_pool_created_count++;
179
180 /* Optional byte pool create extended processing. */
181 TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
182
183 /* If trace is enabled, register this object. */
184 TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BYTE_POOL, pool_ptr, name_ptr, pool_size, 0)
185
186 /* If trace is enabled, insert this event into the trace buffer. */
187 TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), pool_size, TX_POINTER_TO_ULONG_CONVERT(&block_ptr), TX_TRACE_BYTE_POOL_EVENTS)
188
189 /* Log this kernel call. */
190 TX_EL_BYTE_POOL_CREATE_INSERT
191
192 /* Restore interrupts. */
193 TX_RESTORE
194
195 /* Return TX_SUCCESS. */
196 return(TX_SUCCESS);
197 }
198
199