memp.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /**
  2. * @file
  3. * Dynamic pool memory manager
  4. *
  5. * lwIP has dedicated pools for many structures (netconn, protocol control blocks,
  6. * packet buffers, ...). All these pools are managed here.
  7. */
  8. /*
  9. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without modification,
  13. * are permitted provided that the following conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. * 3. The name of the author may not be used to endorse or promote products
  21. * derived from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  24. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  25. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  26. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  28. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  31. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  32. * OF SUCH DAMAGE.
  33. *
  34. * This file is part of the lwIP TCP/IP stack.
  35. *
  36. * Author: Adam Dunkels <adam@sics.se>
  37. *
  38. */
  39. #include "lwip/opt.h"
  40. #include "lwip/memp.h"
  41. #include "lwip/pbuf.h"
  42. #include "lwip/udp.h"
  43. #include "lwip/raw.h"
  44. #include "lwip/tcp_impl.h"
  45. #include "lwip/igmp.h"
  46. #include "lwip/api.h"
  47. #include "lwip/api_msg.h"
  48. #include "lwip/tcpip.h"
  49. #include "lwip/sys.h"
  50. #include "lwip/timers.h"
  51. #include "lwip/stats.h"
  52. #include "netif/etharp.h"
  53. #include "lwip/ip_frag.h"
  54. #include "lwip/snmp_structs.h"
  55. #include "lwip/snmp_msg.h"
  56. #include "lwip/dns.h"
  57. #include "netif/ppp_oe.h"
  58. #include <string.h>
  59. #if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */
  60. struct memp {
  61. struct memp *next;
  62. #if MEMP_OVERFLOW_CHECK
  63. const char *file;
  64. int line;
  65. #endif /* MEMP_OVERFLOW_CHECK */
  66. };
  67. #if MEMP_OVERFLOW_CHECK
  68. /* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning
  69. * and at the end of each element, initialize them as 0xcd and check
  70. * them later. */
  71. /* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free,
  72. * every single element in each pool is checked!
  73. * This is VERY SLOW but also very helpful. */
  74. /* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in
  75. * lwipopts.h to change the amount reserved for checking. */
  76. #ifndef MEMP_SANITY_REGION_BEFORE
  77. #define MEMP_SANITY_REGION_BEFORE 16
  78. #endif /* MEMP_SANITY_REGION_BEFORE*/
  79. #if MEMP_SANITY_REGION_BEFORE > 0
  80. #define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE)
  81. #else
  82. #define MEMP_SANITY_REGION_BEFORE_ALIGNED 0
  83. #endif /* MEMP_SANITY_REGION_BEFORE*/
  84. #ifndef MEMP_SANITY_REGION_AFTER
  85. #define MEMP_SANITY_REGION_AFTER 16
  86. #endif /* MEMP_SANITY_REGION_AFTER*/
  87. #if MEMP_SANITY_REGION_AFTER > 0
  88. #define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER)
  89. #else
  90. #define MEMP_SANITY_REGION_AFTER_ALIGNED 0
  91. #endif /* MEMP_SANITY_REGION_AFTER*/
  92. /* MEMP_SIZE: save space for struct memp and for sanity check */
  93. #define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED)
  94. #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED)
  95. #else /* MEMP_OVERFLOW_CHECK */
  96. /* No sanity checks
  97. * We don't need to preserve the struct memp while not allocated, so we
  98. * can save a little space and set MEMP_SIZE to 0.
  99. */
  100. #define MEMP_SIZE 0
  101. #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
  102. #endif /* MEMP_OVERFLOW_CHECK */
  103. /** This array holds the first free element of each pool.
  104. * Elements form a linked list. */
  105. static struct memp *memp_tab[MEMP_MAX];
  106. #else /* MEMP_MEM_MALLOC */
  107. #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
  108. #endif /* MEMP_MEM_MALLOC */
  109. /** This array holds the element sizes of each pool. */
  110. #if !MEM_USE_POOLS && !MEMP_MEM_MALLOC
  111. static
  112. #endif
  113. const u16_t memp_sizes[MEMP_MAX] = {
  114. #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size),
  115. #include "lwip/memp_std.h"
  116. };
  117. #if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */
  118. /** This array holds the number of elements in each pool. */
  119. static const u16_t memp_num[MEMP_MAX] = {
  120. #define LWIP_MEMPOOL(name,num,size,desc) (num),
  121. #include "lwip/memp_std.h"
  122. };
  123. /** This array holds a textual description of each pool. */
  124. #ifdef LWIP_DEBUG
  125. static const char *memp_desc[MEMP_MAX] = {
  126. #define LWIP_MEMPOOL(name,num,size,desc) (desc),
  127. #include "lwip/memp_std.h"
  128. };
  129. #endif /* LWIP_DEBUG */
  130. #if MEMP_SEPARATE_POOLS
  131. /** This creates each memory pool. These are named memp_memory_XXX_base (where
  132. * XXX is the name of the pool defined in memp_std.h).
  133. * To relocate a pool, declare it as extern in cc.h. Example for GCC:
  134. * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[];
  135. */
  136. #define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \
  137. [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))];
  138. #include "lwip/memp_std.h"
  139. /** This array holds the base of each memory pool. */
  140. static u8_t *const memp_bases[] = {
  141. #define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base,
  142. #include "lwip/memp_std.h"
  143. };
  144. #else /* MEMP_SEPARATE_POOLS */
  145. /** This is the actual memory used by the pools (all pools in one big block). */
  146. static u8_t memp_memory[MEM_ALIGNMENT - 1
  147. #define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) )
  148. #include "lwip/memp_std.h"
  149. ];
  150. #endif /* MEMP_SEPARATE_POOLS */
  151. #if MEMP_SANITY_CHECK
  152. /**
  153. * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
  154. */
  155. static int
  156. memp_sanity(void)
  157. {
  158. s16_t i;
  159. struct memp *t, *h;
  160. for (i = 0; i < MEMP_MAX; i++) {
  161. t = memp_tab[i];
  162. if(t != NULL) {
  163. for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
  164. h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) {
  165. if (t == h) {
  166. return 0;
  167. }
  168. }
  169. }
  170. }
  171. return 1;
  172. }
  173. #endif /* MEMP_SANITY_CHECK*/
  174. #if MEMP_OVERFLOW_CHECK
  175. #if defined(LWIP_DEBUG) && MEMP_STATS
  176. static const char * memp_overflow_names[] = {
  177. #define LWIP_MEMPOOL(name,num,size,desc) "/"desc,
  178. #include "lwip/memp_std.h"
  179. };
  180. #endif
  181. /**
  182. * Check if a memp element was victim of an overflow
  183. * (e.g. the restricted area after it has been altered)
  184. *
  185. * @param p the memp element to check
  186. * @param memp_type the pool p comes from
  187. */
  188. static void
  189. memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type)
  190. {
  191. u16_t k;
  192. u8_t *m;
  193. #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
  194. m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type];
  195. for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
  196. if (m[k] != 0xcd) {
  197. char errstr[128] = "detected memp overflow in pool ";
  198. char digit[] = "0";
  199. if(memp_type >= 10) {
  200. digit[0] = '0' + (memp_type/10);
  201. strcat(errstr, digit);
  202. }
  203. digit[0] = '0' + (memp_type%10);
  204. strcat(errstr, digit);
  205. #if defined(LWIP_DEBUG) && MEMP_STATS
  206. strcat(errstr, memp_overflow_names[memp_type]);
  207. #endif
  208. LWIP_ASSERT(errstr, 0);
  209. }
  210. }
  211. #endif
  212. }
  213. /**
  214. * Check if a memp element was victim of an underflow
  215. * (e.g. the restricted area before it has been altered)
  216. *
  217. * @param p the memp element to check
  218. * @param memp_type the pool p comes from
  219. */
  220. static void
  221. memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type)
  222. {
  223. u16_t k;
  224. u8_t *m;
  225. #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
  226. m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
  227. for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
  228. if (m[k] != 0xcd) {
  229. char errstr[128] = "detected memp underflow in pool ";
  230. char digit[] = "0";
  231. if(memp_type >= 10) {
  232. digit[0] = '0' + (memp_type/10);
  233. strcat(errstr, digit);
  234. }
  235. digit[0] = '0' + (memp_type%10);
  236. strcat(errstr, digit);
  237. #if defined(LWIP_DEBUG) && MEMP_STATS
  238. strcat(errstr, memp_overflow_names[memp_type]);
  239. #endif
  240. LWIP_ASSERT(errstr, 0);
  241. }
  242. }
  243. #endif
  244. }
  245. /**
  246. * Do an overflow check for all elements in every pool.
  247. *
  248. * @see memp_overflow_check_element for a description of the check
  249. */
  250. static void
  251. memp_overflow_check_all(void)
  252. {
  253. u16_t i, j;
  254. struct memp *p;
  255. p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
  256. for (i = 0; i < MEMP_MAX; ++i) {
  257. p = p;
  258. for (j = 0; j < memp_num[i]; ++j) {
  259. memp_overflow_check_element_overflow(p, i);
  260. p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
  261. }
  262. }
  263. p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
  264. for (i = 0; i < MEMP_MAX; ++i) {
  265. p = p;
  266. for (j = 0; j < memp_num[i]; ++j) {
  267. memp_overflow_check_element_underflow(p, i);
  268. p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
  269. }
  270. }
  271. }
  272. /**
  273. * Initialize the restricted areas of all memp elements in every pool.
  274. */
  275. static void
  276. memp_overflow_init(void)
  277. {
  278. u16_t i, j;
  279. struct memp *p;
  280. u8_t *m;
  281. p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
  282. for (i = 0; i < MEMP_MAX; ++i) {
  283. p = p;
  284. for (j = 0; j < memp_num[i]; ++j) {
  285. #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
  286. m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
  287. memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED);
  288. #endif
  289. #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
  290. m = (u8_t*)p + MEMP_SIZE + memp_sizes[i];
  291. memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED);
  292. #endif
  293. p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
  294. }
  295. }
  296. }
  297. #endif /* MEMP_OVERFLOW_CHECK */
  298. /**
  299. * Initialize this module.
  300. *
  301. * Carves out memp_memory into linked lists for each pool-type.
  302. */
  303. void
  304. memp_init(void)
  305. {
  306. struct memp *memp;
  307. u16_t i, j;
  308. for (i = 0; i < MEMP_MAX; ++i) {
  309. MEMP_STATS_AVAIL(used, i, 0);
  310. MEMP_STATS_AVAIL(max, i, 0);
  311. MEMP_STATS_AVAIL(err, i, 0);
  312. MEMP_STATS_AVAIL(avail, i, memp_num[i]);
  313. }
  314. #if !MEMP_SEPARATE_POOLS
  315. memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
  316. #endif /* !MEMP_SEPARATE_POOLS */
  317. /* for every pool: */
  318. for (i = 0; i < MEMP_MAX; ++i) {
  319. memp_tab[i] = NULL;
  320. #if MEMP_SEPARATE_POOLS
  321. memp = (struct memp*)memp_bases[i];
  322. #endif /* MEMP_SEPARATE_POOLS */
  323. /* create a linked list of memp elements */
  324. for (j = 0; j < memp_num[i]; ++j) {
  325. memp->next = memp_tab[i];
  326. memp_tab[i] = memp;
  327. memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]
  328. #if MEMP_OVERFLOW_CHECK
  329. + MEMP_SANITY_REGION_AFTER_ALIGNED
  330. #endif
  331. );
  332. }
  333. }
  334. #if MEMP_OVERFLOW_CHECK
  335. memp_overflow_init();
  336. /* check everything a first time to see if it worked */
  337. memp_overflow_check_all();
  338. #endif /* MEMP_OVERFLOW_CHECK */
  339. }
  340. /**
  341. * Get an element from a specific pool.
  342. *
  343. * @param type the pool to get an element from
  344. *
  345. * the debug version has two more parameters:
  346. * @param file file name calling this function
  347. * @param line number of line where this function is called
  348. *
  349. * @return a pointer to the allocated memory or a NULL pointer on error
  350. */
  351. void *
  352. #if !MEMP_OVERFLOW_CHECK
  353. memp_malloc(memp_t type)
  354. #else
  355. memp_malloc_fn(memp_t type, const char* file, const int line)
  356. #endif
  357. {
  358. struct memp *memp;
  359. SYS_ARCH_DECL_PROTECT(old_level);
  360. LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
  361. SYS_ARCH_PROTECT(old_level);
  362. #if MEMP_OVERFLOW_CHECK >= 2
  363. memp_overflow_check_all();
  364. #endif /* MEMP_OVERFLOW_CHECK >= 2 */
  365. memp = memp_tab[type];
  366. if (memp != NULL) {
  367. memp_tab[type] = memp->next;
  368. #if MEMP_OVERFLOW_CHECK
  369. memp->next = NULL;
  370. memp->file = file;
  371. memp->line = line;
  372. #endif /* MEMP_OVERFLOW_CHECK */
  373. MEMP_STATS_INC_USED(used, type);
  374. LWIP_ASSERT("memp_malloc: memp properly aligned",
  375. ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
  376. memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE);
  377. } else {
  378. LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
  379. MEMP_STATS_INC(err, type);
  380. }
  381. SYS_ARCH_UNPROTECT(old_level);
  382. return memp;
  383. }
  384. /**
  385. * Put an element back into its pool.
  386. *
  387. * @param type the pool where to put mem
  388. * @param mem the memp element to free
  389. */
  390. void
  391. memp_free(memp_t type, void *mem)
  392. {
  393. struct memp *memp;
  394. SYS_ARCH_DECL_PROTECT(old_level);
  395. if (mem == NULL) {
  396. return;
  397. }
  398. LWIP_ASSERT("memp_free: mem properly aligned",
  399. ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
  400. memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
  401. SYS_ARCH_PROTECT(old_level);
  402. #if MEMP_OVERFLOW_CHECK
  403. #if MEMP_OVERFLOW_CHECK >= 2
  404. memp_overflow_check_all();
  405. #else
  406. memp_overflow_check_element_overflow(memp, type);
  407. memp_overflow_check_element_underflow(memp, type);
  408. #endif /* MEMP_OVERFLOW_CHECK >= 2 */
  409. #endif /* MEMP_OVERFLOW_CHECK */
  410. MEMP_STATS_DEC(used, type);
  411. memp->next = memp_tab[type];
  412. memp_tab[type] = memp;
  413. #if MEMP_SANITY_CHECK
  414. LWIP_ASSERT("memp sanity", memp_sanity());
  415. #endif /* MEMP_SANITY_CHECK */
  416. SYS_ARCH_UNPROTECT(old_level);
  417. }
  418. #endif /* MEMP_MEM_MALLOC */