1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1991-2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 /* 28 * zmalloc - use mmap(2) to allocate memory from /dev/zero. 29 * zfree - use munmap(2) to unmap (free) memory. 30 * 31 * These functions should be better than malloc(3) for large memory allocation. 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <fcntl.h> 37 #include <unistd.h> 38 #include <sys/types.h> 39 #include <sys/mman.h> 40 #include <sys/stat.h> 41 42 #include <zmalloc.h> 43 44 /* 45 * a utility structure to keep track of the (possibly) multiple mmaps 46 * that we have done... 47 */ 48 struct buffer_map { 49 struct buffer_map *bm_next; 50 char *bm_buffer; 51 int bm_size; 52 }; 53 54 static void *bm_empty = (void *) ""; /* special buffer */ 55 static struct buffer_map *bm_list; /* NULL by default */ 56 57 static struct buffer_map * 58 insert_bm(char *buf, size_t size) 59 { 60 struct buffer_map *bm; 61 62 bm = (struct buffer_map *)malloc(sizeof (struct buffer_map)); 63 bm->bm_buffer = buf; 64 bm->bm_size = size; 65 bm->bm_next = bm_list; 66 67 bm_list = bm; 68 69 return (bm_list); 70 } 71 72 static size_t 73 delete_bm(char *buf) 74 { 75 size_t size; 76 register struct buffer_map *p_curr; 77 register struct buffer_map *p_prev; 78 79 p_prev = NULL; 80 p_curr = bm_list; 81 while (p_curr != NULL) { 82 if (p_curr->bm_buffer == buf) { 83 if (p_prev == NULL) 84 bm_list = p_curr->bm_next; 85 else 86 p_prev->bm_next = p_curr->bm_next; 87 size = p_curr->bm_size; 88 free(p_curr); 89 return (size); 90 } 91 92 p_prev = p_curr; 93 p_curr = p_curr->bm_next; 94 } 95 return (0); 96 } 97 98 void * 99 zmalloc(size_t size) 100 { 101 int fd; 102 caddr_t mbuf; 103 104 /* XXX - Special case: never allocate 0 bytes, use a special buffer */ 105 if (size == 0) 106 return ((void *)NULL); /* return (bm_empty); */ 107 108 if ((fd = open("/dev/zero", O_RDWR)) < 0) { 109 perror("/dev/zero"); 110 return ((void *) NULL); 111 } 112 113 mbuf = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 114 (void) close(fd); 115 116 if (mbuf == (caddr_t)-1) { 117 perror("zmalloc: mmap"); 118 return ((void *) NULL); 119 } 120 121 (void) insert_bm(mbuf, size); 122 123 return ((void *) mbuf); 124 } 125 126 void 127 zfree(void* mbuf) 128 { 129 size_t size; 130 131 if (mbuf == bm_empty) 132 return; 133 134 if (mbuf != NULL) { 135 if ((size = delete_bm((caddr_t)mbuf)) != 0) { 136 if (munmap((char *)mbuf, size) < 0) 137 perror("zfree: munmap"); 138 } 139 } 140 } 141