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