2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
35 #include "lwip/memp.h"
37 #include "lwip/pbuf.h"
42 #include "lwip/api_msg.h"
43 #include "lwip/tcpip.h"
46 #include "lwip/stats.h"
56 static struct memp
*memp_tab
[MEMP_MAX
];
58 static const u16_t memp_sizes
[MEMP_MAX
] = {
60 sizeof(struct raw_pcb
),
61 sizeof(struct udp_pcb
),
62 sizeof(struct tcp_pcb
),
63 sizeof(struct tcp_pcb_listen
),
64 sizeof(struct tcp_seg
),
65 sizeof(struct netbuf
),
66 sizeof(struct netconn
),
67 sizeof(struct api_msg
),
68 sizeof(struct tcpip_msg
),
69 sizeof(struct sys_timeout
)
72 static const u16_t memp_num
[MEMP_MAX
] = {
77 MEMP_NUM_TCP_PCB_LISTEN
,
86 static u8_t memp_memory
[(MEMP_NUM_PBUF
*
87 MEM_ALIGN_SIZE(sizeof(struct pbuf
) +
88 sizeof(struct memp
)) +
90 MEM_ALIGN_SIZE(sizeof(struct raw_pcb
) +
91 sizeof(struct memp
)) +
93 MEM_ALIGN_SIZE(sizeof(struct udp_pcb
) +
94 sizeof(struct memp
)) +
96 MEM_ALIGN_SIZE(sizeof(struct tcp_pcb
) +
97 sizeof(struct memp
)) +
98 MEMP_NUM_TCP_PCB_LISTEN
*
99 MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen
) +
100 sizeof(struct memp
)) +
102 MEM_ALIGN_SIZE(sizeof(struct tcp_seg
) +
103 sizeof(struct memp
)) +
105 MEM_ALIGN_SIZE(sizeof(struct netbuf
) +
106 sizeof(struct memp
)) +
108 MEM_ALIGN_SIZE(sizeof(struct netconn
) +
109 sizeof(struct memp
)) +
111 MEM_ALIGN_SIZE(sizeof(struct api_msg
) +
112 sizeof(struct memp
)) +
114 MEM_ALIGN_SIZE(sizeof(struct tcpip_msg
) +
115 sizeof(struct memp
)) +
116 MEMP_NUM_SYS_TIMEOUT
*
117 MEM_ALIGN_SIZE(sizeof(struct sys_timeout
) +
118 sizeof(struct memp
)))];
121 #if !SYS_LIGHTWEIGHT_PROT
122 static sys_sem_t mutex
;
125 #ifndef LWIP_NOASSERT
132 for(i
= 0; i
< MEMP_MAX
; i
++) {
133 for(m
= memp_tab
[i
]; m
!= NULL
; m
= m
->next
) {
135 for(n
= memp_tab
[i
]; n
!= NULL
; n
= n
->next
) {
139 if (c
< 0) return 0; /* LW was: abort(); */
145 #endif /* LWIP_DEBUG */
150 struct memp
*m
, *memp
;
155 for(i
= 0; i
< MEMP_MAX
; ++i
) {
156 lwip_stats
.memp
[i
].used
= lwip_stats
.memp
[i
].max
=
157 lwip_stats
.memp
[i
].err
= 0;
158 lwip_stats
.memp
[i
].avail
= memp_num
[i
];
160 #endif /* MEMP_STATS */
162 memp
= (struct memp
*)&memp_memory
[0];
163 for(i
= 0; i
< MEMP_MAX
; ++i
) {
164 size
= MEM_ALIGN_SIZE(memp_sizes
[i
] + sizeof(struct memp
));
165 if (memp_num
[i
] > 0) {
169 for(j
= 0; j
< memp_num
[i
]; ++j
) {
170 m
->next
= (struct memp
*)MEM_ALIGN((u8_t
*)m
+ size
);
181 #if !SYS_LIGHTWEIGHT_PROT
182 mutex
= sys_sem_new(1);
189 memp_malloc(memp_t type
)
193 #if SYS_LIGHTWEIGHT_PROT
194 SYS_ARCH_DECL_PROTECT(old_level
);
197 LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type
< MEMP_MAX
);
199 #if SYS_LIGHTWEIGHT_PROT
200 SYS_ARCH_PROTECT(old_level
);
201 #else /* SYS_LIGHTWEIGHT_PROT */
203 #endif /* SYS_LIGHTWEIGHT_PROT */
205 memp
= memp_tab
[type
];
208 memp_tab
[type
] = memp
->next
;
211 ++lwip_stats
.memp
[type
].used
;
212 if (lwip_stats
.memp
[type
].used
> lwip_stats
.memp
[type
].max
) {
213 lwip_stats
.memp
[type
].max
= lwip_stats
.memp
[type
].used
;
215 #endif /* MEMP_STATS */
216 #if SYS_LIGHTWEIGHT_PROT
217 SYS_ARCH_UNPROTECT(old_level
);
218 #else /* SYS_LIGHTWEIGHT_PROT */
219 sys_sem_signal(mutex
);
220 #endif /* SYS_LIGHTWEIGHT_PROT */
221 LWIP_ASSERT("memp_malloc: memp properly aligned",
222 ((u32_t
)MEM_ALIGN((u8_t
*)memp
+ sizeof(struct memp
)) % MEM_ALIGNMENT
) == 0);
224 mem
= MEM_ALIGN((u8_t
*)memp
+ sizeof(struct memp
));
227 LWIP_DEBUGF(MEMP_DEBUG
| 2, ("memp_malloc: out of memory in pool %d\n", type
));
229 ++lwip_stats
.memp
[type
].err
;
230 #endif /* MEMP_STATS */
231 #if SYS_LIGHTWEIGHT_PROT
232 SYS_ARCH_UNPROTECT(old_level
);
233 #else /* SYS_LIGHTWEIGHT_PROT */
234 sys_sem_signal(mutex
);
235 #endif /* SYS_LIGHTWEIGHT_PROT */
241 memp_free(memp_t type
, void *mem
)
244 #if SYS_LIGHTWEIGHT_PROT
245 SYS_ARCH_DECL_PROTECT(old_level
);
246 #endif /* SYS_LIGHTWEIGHT_PROT */
251 memp
= (struct memp
*)((u8_t
*)mem
- sizeof(struct memp
));
253 #if SYS_LIGHTWEIGHT_PROT
254 SYS_ARCH_PROTECT(old_level
);
255 #else /* SYS_LIGHTWEIGHT_PROT */
257 #endif /* SYS_LIGHTWEIGHT_PROT */
260 lwip_stats
.memp
[type
].used
--;
261 #endif /* MEMP_STATS */
263 memp
->next
= memp_tab
[type
];
264 memp_tab
[type
] = memp
;
266 LWIP_ASSERT("memp sanity", memp_sanity());
268 #if SYS_LIGHTWEIGHT_PROT
269 SYS_ARCH_UNPROTECT(old_level
);
270 #else /* SYS_LIGHTWEIGHT_PROT */
271 sys_sem_signal(mutex
);
272 #endif /* SYS_LIGHTWEIGHT_PROT */