1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/*
* LIB/ALLOC.C - memory allocation
*
* These routines are used to allocate buffers with the express intent
* of being able to *truely* deallocate the memory when we free it.
* malloc()/free() does not normally do this, which will bloat the binary
* and cause inefficiencies on fork().
*
* If you are running a large number of incoming connections or outgoing
* feeds, using either USE_ANON_MMAP or USE_FALL_MMAP is an absolute
* requirement. If you are not, then it doesn't matter.
*
* USE_ANON_MMAP is supported on BSDish platforms. It uses MAP_ANON to
* allocate areas of swap-backed memory.
*
* USE_FALL_MMAP should be supported on all platforms. It creates a file
* in /tmp and maps it MAP_PRIVATE, then remove()s the file.
* Since this is a private map, the file is not actually used
* for backing store so there is no real filesystem overhead.
* The memory winds up being swap-backed.
*
* If neither option is set, malloc/free is used. This is not recommended
* if you run more then 10 feeds.
*/
#include "defs.h"
Prototype void *pagealloc(int *psize, int bytes);
Prototype void pagefree(void *p, int bytes);
Prototype int ZoneFd; /* only necessary for USE_FALL_MMAP */
static int PageSize;
static int PageMask;
int ZoneFd = -1; /* only necessary for USE_FALL_MMAP */
#if USE_ANON_MMAP
/*
* Our first choice is to use MAP_ANON if the system understands it
*/
void *
pagealloc(int *psize, int bytes)
{
void *b;
if (PageSize == 0) {
PageSize = getpagesize();
PageMask = PageSize - 1;
}
bytes = (bytes + PageMask) & ~PageMask;
*psize = bytes;
b = (void *)mmap((caddr_t)0, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
if (b == NULL || b == (void *)-1) {
syslog(LOG_EMERG, "mmap/allocation/1 failed: %s", strerror(errno));
exit(1);
}
return(b);
}
void
pagefree(void *page, int bytes)
{
bytes = (bytes + PageMask) & ~PageMask;
if (page != NULL) {
munmap((caddr_t)page, bytes);
}
}
#else
#if USE_FALL_MMAP
/*
* Our second choice is to use a MAP_PRIVATE file mmap()
*/
void *
pagealloc(int *psize, int bytes)
{
void *b;
if (PageSize == 0) {
PageSize = getpagesize();
PageMask = PageSize - 1;
}
bytes = (bytes + PageMask) & ~PageMask;
if (ZoneFd < 0) {
int i;
int pid = (int)getpid();
for (i = 0; i < 1000; ++i) {
char path[256];
sprintf(path, "/tmp/diablo.zone.%d.%d", pid, i);
if ((ZoneFd=open(path, O_CREAT|O_TRUNC|O_RDWR|O_EXCL, 0600)) >= 0){
remove(path);
break;
}
}
if (ZoneFd < 0) {
syslog(LOG_EMERG, "unable to create %dK zone file in /tmp: %s",
bytes / 1024,
strerror(errno)
);
exit(1);
}
if (ftruncate(ZoneFd, bytes) < 0) {
syslog(LOG_EMERG, "unable to extend zone file in /tmp: %s",
strerror(errno)
);
exit(1);
}
fcntl(ZoneFd, F_SETFD, 1); /* set close-on-exec */
}
*psize = bytes;
b = (void *)mmap((caddr_t)0, bytes, PROT_READ|PROT_WRITE, MAP_PRIVATE, ZoneFd, 0);
if (b == NULL || b == (void *)-1) {
syslog(LOG_EMERG, "mmap/allocation/2 failed: %s", strerror(errno));
exit(1);
}
return(b);
}
void
pagefree(void *page, int bytes)
{
bytes = (bytes + PageMask) & ~PageMask;
if (page != NULL) {
munmap((caddr_t)page, bytes);
}
}
#else
void *
pagealloc(int *psize, int bytes)
{
void *b;
if (PageSize == 0) {
PageSize = getpagesize();
PageMask = PageSize - 1;
}
bytes = (bytes + PageMask) & ~PageMask;
*psize = bytes;
b = malloc(bytes);
if (b == NULL) {
syslog(LOG_EMERG, "mmap/allocation/3 failed: %s", strerror(errno));
exit(1);
}
bzero(b, bytes);
return(b);
}
void
pagefree(void *page, int bytes)
{
/* bytes = (bytes + PageMask) & ~PageMask; */
if (page != NULL) {
free(page);
}
}
#endif
#endif
|