include stdlib instead of malloc.h
[obnox/wireshark/wip.git] / epan / emem.c
1 /* emem.c
2  * Ethereal memory management and garbage collection functions
3  * Ronnie Sahlberg 2005
4  *
5  * $Id$
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <glib.h>
29 #include "emem.h"
30
31 /* When required, allocate more memory from the OS in this size chunks */
32 #define EMEM_PACKET_CHUNK_SIZE 10485760
33
34 typedef struct _emem_chunk_t {
35         struct _emem_chunk_t *next;
36         unsigned int    amount_free;
37         unsigned int    free_offset;
38         char *buf;
39 } emem_chunk_t;
40
41 typedef struct _emem_header_t {
42   emem_chunk_t *free_list;
43   emem_chunk_t *used_list;
44 } emem_header_t;
45
46 static emem_header_t emem_packet_mem;
47
48 /* Initialize the packet-lifetime memory allocation pool.
49  * This function should be called only once when Etehreal or Tethereal starts
50  * up.
51  */
52 void
53 ep_init_chunk(void)
54 {
55         emem_packet_mem.free_list=NULL; 
56         emem_packet_mem.used_list=NULL; 
57 }
58
59 /* allocate 'size' amount of memory with an allocation lifetime until the
60  * next packet.
61  */
62 void *
63 ep_alloc(size_t size)
64 {
65         void *buf;
66
67         /* round up to 8 byte boundary */
68         if(size&0x07){
69                 size=(size+7)&0xfffffff8;
70         }
71
72         /* make sure we dont try to allocate too much (arbitrary limit) */
73         g_assert(size<(EMEM_PACKET_CHUNK_SIZE>>2));
74
75         /* we dont have any free data, so we must allocate a new one */
76         if(!emem_packet_mem.free_list){
77                 emem_chunk_t *npc;
78                 npc=g_malloc(sizeof(emem_chunk_t));
79                 npc->next=NULL;
80                 npc->amount_free=EMEM_PACKET_CHUNK_SIZE;
81                 npc->free_offset=0;
82                 npc->buf=g_malloc(EMEM_PACKET_CHUNK_SIZE);
83                 emem_packet_mem.free_list=npc;
84         }
85
86         /* oops, we need to allocate more memory to serve this request
87          * than we have free. move this node to the used list and try again
88          */
89         if(size>emem_packet_mem.free_list->amount_free){
90                 emem_chunk_t *npc;
91                 npc=emem_packet_mem.free_list;
92                 emem_packet_mem.free_list=emem_packet_mem.free_list->next;
93                 npc->next=emem_packet_mem.used_list;
94                 emem_packet_mem.used_list=npc;
95         }
96
97         /* we dont have any free data, so we must allocate a new one */
98         if(!emem_packet_mem.free_list){
99                 emem_chunk_t *npc;
100                 npc=g_malloc(sizeof(emem_chunk_t));
101                 npc->next=NULL;
102                 npc->amount_free=EMEM_PACKET_CHUNK_SIZE;
103                 npc->free_offset=0;
104                 npc->buf=g_malloc(EMEM_PACKET_CHUNK_SIZE);
105                 emem_packet_mem.free_list=npc;
106         }
107
108
109         buf=emem_packet_mem.free_list->buf+emem_packet_mem.free_list->free_offset;
110
111         emem_packet_mem.free_list->amount_free-=size;
112         emem_packet_mem.free_list->free_offset+=size;
113
114         return buf;
115 }
116
117 /* release all allocated memory back to the pool.
118  */
119 void
120 ep_free_all(void)
121 {
122         emem_chunk_t *npc;
123
124         /* move all used chunks ove to the free list */
125         while(emem_packet_mem.used_list){
126                 npc=emem_packet_mem.used_list;
127                 emem_packet_mem.used_list=emem_packet_mem.used_list->next;
128                 npc->next=emem_packet_mem.free_list;
129                 emem_packet_mem.free_list=npc;
130         }
131
132         /* clear them all out */
133         for(npc=emem_packet_mem.free_list;npc;npc=npc->next){
134                 npc->amount_free=EMEM_PACKET_CHUNK_SIZE;
135                 npc->free_offset=0;
136         }
137 }
138                 
139
140