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 /** NetX Component */
16 /** */
17 /** Packet Pool Management (Packet) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_packet.h"
29
30 /* Bring in externs for caller checking code. */
31
32 NX_CALLER_CHECKING_EXTERNS
33
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _nxe_packet_pool_create PORTABLE C */
40 /* 6.1 */
41 /* AUTHOR */
42 /* */
43 /* Yuxin Zhou, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This function checks for errors in the packet pool create */
48 /* function call. */
49 /* */
50 /* INPUT */
51 /* */
52 /* pool_ptr Packet Pool control block */
53 /* name_ptr Packet Pool string pointer */
54 /* payload_size Size of packet payload */
55 /* pool_start Starting address of pool */
56 /* pool_size Number of bytes in pool */
57 /* pool_control_block_size Size of packet pool control */
58 /* block */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* status Completion status */
63 /* */
64 /* CALLS */
65 /* */
66 /* _nx_packet_pool_create Actual packet pool create */
67 /* function */
68 /* tx_thread_identify Get current thread pointer */
69 /* tx_thread_preemption_change Change preemption for thread */
70 /* */
71 /* CALLED BY */
72 /* */
73 /* Application Code */
74 /* */
75 /* RELEASE HISTORY */
76 /* */
77 /* DATE NAME DESCRIPTION */
78 /* */
79 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
80 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
81 /* resulting in version 6.1 */
82 /* */
83 /**************************************************************************/
_nxe_packet_pool_create(NX_PACKET_POOL * pool_ptr,CHAR * name_ptr,ULONG payload_size,VOID * pool_start,ULONG pool_size,UINT pool_control_block_size)84 UINT _nxe_packet_pool_create(NX_PACKET_POOL *pool_ptr, CHAR *name_ptr, ULONG payload_size,
85 VOID *pool_start, ULONG pool_size, UINT pool_control_block_size)
86 {
87
88 UINT status;
89 ULONG rounded_payload_size;
90 ULONG rounded_pool_size;
91 ULONG header_size;
92 UINT old_threshold = 0;
93 NX_PACKET_POOL *created_pool;
94 ULONG created_count;
95 CHAR *end_memory;
96 CHAR *created_end;
97 CHAR *payload_address;
98 VOID *rounded_pool_start;
99 TX_THREAD *current_thread;
100
101
102 /* Check for invalid input pointers. */
103 if ((pool_ptr == NX_NULL) || (pool_start == NX_NULL) || (pool_control_block_size != (UINT)sizeof(NX_PACKET_POOL)))
104 {
105 return(NX_PTR_ERROR);
106 }
107
108 /* Align the starting address to four bytes. */
109 /*lint -e{923} suppress cast between ULONG and pointer. */
110 rounded_pool_start = (VOID *)((((ALIGN_TYPE)pool_start + NX_PACKET_ALIGNMENT - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
111
112 /* Round the pool size down to something that is evenly divisible by alignment. */
113 /*lint -e{923} suppress cast between ULONG and pointer. */
114 rounded_pool_size = (ULONG)(((pool_size - ((ALIGN_TYPE)rounded_pool_start - (ALIGN_TYPE)pool_start)) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
115
116 /* Calculate the address of payload. */
117 /*lint -e{923} suppress cast between ULONG and pointer. */
118 payload_address = (CHAR *)((ALIGN_TYPE)rounded_pool_start + sizeof(NX_PACKET));
119
120 /* Align the address of payload. */
121 /*lint -e{923} suppress cast between ULONG and pointer. */
122 payload_address = (CHAR *)((((ALIGN_TYPE)payload_address + NX_PACKET_ALIGNMENT - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT);
123
124 /* Calculate the header size. */
125 /*lint -e{923} suppress cast between ULONG and pointer. */
126 header_size = (ULONG)((ALIGN_TYPE)payload_address - (ALIGN_TYPE)rounded_pool_start);
127
128 /* Round the packet size up to something that helps guarantee proper alignment for header and payload. */
129 rounded_payload_size = (ULONG)(((header_size + payload_size + NX_PACKET_ALIGNMENT - 1) / NX_PACKET_ALIGNMENT) * NX_PACKET_ALIGNMENT - header_size);
130
131 /* Check for an invalid pool and payload size. */
132 if ((pool_size <= NX_PACKET_ALIGNMENT) || (!payload_size) ||
133 ((rounded_payload_size + header_size) > rounded_pool_size))
134 {
135 return(NX_SIZE_ERROR);
136 }
137
138 /* Calculate the end of the pool memory area. */
139 end_memory = ((CHAR *)pool_start) + (pool_size - 1);
140
141 /* Pickup current thread pointer. */
142 current_thread = tx_thread_identify();
143
144 /* Disable preemption temporarily. */
145 if (current_thread)
146 {
147 tx_thread_preemption_change(current_thread, 0, &old_threshold);
148 }
149
150 /* Loop to check for the pool instance already created. */
151 created_pool = _nx_packet_pool_created_ptr;
152 created_count = _nx_packet_pool_created_count;
153 while (created_count--)
154 {
155
156 /* Calculate the created pool's end of memory. */
157 created_end = created_pool -> nx_packet_pool_start + (created_pool -> nx_packet_pool_size - 1);
158
159 /* Is the new pool already created? */
160 /*lint -e{946} suppress pointer subtraction, since it is necessary. */
161 if ((pool_ptr == created_pool) ||
162 ((pool_start >= (VOID *)created_pool -> nx_packet_pool_start) && (pool_start < (VOID *)created_end)) ||
163 ((end_memory >= created_pool -> nx_packet_pool_start) && (end_memory < created_end)))
164 {
165
166 /* Restore preemption. */
167 if (current_thread)
168 {
169
170 /*lint -e{644} suppress variable might not be initialized, since "old_threshold" was initialized by previous tx_thread_preemption_change. */
171 tx_thread_preemption_change(current_thread, old_threshold, &old_threshold);
172 }
173
174 /* Duplicate packet pool created, return an error! */
175 return(NX_PTR_ERROR);
176 }
177
178 /* Move to next entry. */
179 created_pool = created_pool -> nx_packet_pool_created_next;
180 }
181
182 /* Restore preemption. */
183 if (current_thread)
184 {
185 tx_thread_preemption_change(current_thread, old_threshold, &old_threshold);
186 }
187
188 /* Check for appropriate caller. */
189 NX_INIT_AND_THREADS_CALLER_CHECKING
190
191 /* Call actual packet pool create function. */
192 status = _nx_packet_pool_create(pool_ptr, name_ptr, payload_size, pool_start, pool_size);
193
194 /* Return completion status. */
195 return(status);
196 }
197
198