]>
git.saurik.com Git - apple/xnu.git/blob - libsa/malloc.c
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
32 #include <mach/mach_types.h>
34 #include <kern/kern_types.h>
35 #include <kern/queue.h>
36 #include <kern/kalloc.h>
37 #include <kern/lock.h>
38 #include <kern/assert.h>
40 #include <vm/vm_kern.h>
42 #include "libsa/malloc.h"
44 extern void panic(const char *string
, ...);
46 /*********************************************************************
47 * Structure for a client memory block. Contains linked-list pointers,
48 * a size field giving the TOTAL size of the block, including this
49 * header, and the address of the client's block. The client block
50 * field is guaranteed to lie on a 16-byte boundary.
51 *********************************************************************/
52 typedef struct malloc_block
{
54 struct malloc_block
*malFwd
;
55 struct malloc_block
*malBwd
;
60 static malloc_block malAnchor
= {&malAnchor
, &malAnchor
, 0, 0};
62 static int malInited
= 0;
63 static mutex_t
*malloc_lock
;
66 void * malloc(size_t size
) {
69 unsigned int nmem
, rmem
;
74 nsize
= size
+ sizeof(malloc_block
) + 15; /* Make sure we get enough to fit */
76 nmem
= (unsigned int)kalloc(nsize
); /* Get some */
77 if(!nmem
) { /* Got any? */
78 panic("malloc: no memory for a %08X sized request\n", nsize
);
81 rmem
= (nmem
+ 15) & -16; /* Round to 16 byte boundary */
82 amem
= (malloc_block
*)rmem
; /* Point to the block */
83 amem
->malActl
= nmem
; /* Set the actual address */
84 amem
->malSize
= nsize
; /* Size */
86 mutex_lock(malloc_lock
);
88 amem
->malFwd
= malAnchor
.malFwd
; /* Move anchor to our forward */
89 amem
->malBwd
= &malAnchor
; /* We point back to anchor */
90 malAnchor
.malFwd
->malBwd
= amem
; /* The old forward's back points to us */
91 malAnchor
.malFwd
= amem
; /* Now we point the anchor to us */
93 mutex_unlock(malloc_lock
); /* Unlock now */
95 return (void *)(rmem
+ 16); /* Return the block */
100 /*********************************************************************
103 *********************************************************************/
105 void free(void * address
) {
108 malloc_block
*amem
, *fore
, *aft
;
110 if(!(unsigned int)address
) return; /* Leave if they try to free nothing */
113 amem
= (malloc_block
*)((unsigned int)address
- sizeof(malloc_block
)); /* Point to the header */
115 mutex_lock(malloc_lock
);
117 fore
= amem
->malFwd
; /* Get the guy in front */
118 aft
= amem
->malBwd
; /* And the guy behind */
119 fore
->malBwd
= aft
; /* The next guy's previous is now my previous */
120 aft
->malFwd
= fore
; /* The previous guy's forward is now mine */
122 mutex_unlock(malloc_lock
); /* Unlock now */
124 kfree(amem
->malActl
, amem
->malSize
); /* Toss it */
130 /*********************************************************************
133 * Allocate the mutual exclusion lock that protect malloc's data.
134 *********************************************************************/
135 __private_extern__
void
138 malloc_lock
= mutex_alloc(0);
143 /*********************************************************************
146 * Walks through the list of VM-allocated regions, destroying them
147 * all. Any subsequent access by clients to allocated data will cause
148 * a segmentation fault.
149 *********************************************************************/
151 void malloc_reset(void) {
153 malloc_block
*amem
, *bmem
;
155 mutex_lock(malloc_lock
);
157 amem
= malAnchor
.malFwd
; /* Get the first one */
159 while(amem
!= &malAnchor
) { /* Go until we hit the anchor */
161 bmem
= amem
->malFwd
; /* Next one */
162 kfree(amem
->malActl
, amem
->malSize
); /* Toss it */
163 amem
= bmem
; /* Skip to it */
167 malAnchor
.malFwd
= (struct malloc_block
*) 0x666; /* Cause a fault if we try again */
168 malAnchor
.malBwd
= (struct malloc_block
*) 0x666; /* Cause a fault if we try again */
170 mutex_unlock(malloc_lock
); /* Unlock now */
172 mutex_free(malloc_lock
);
175 } /* malloc_reset() */
178 /*********************************************************************
181 * This function simply allocates a new block and copies the existing
182 * data into it. Nothing too clever here, as cleanup and efficient
183 * memory usage are not important in this allocator package.
184 *********************************************************************/
186 void * realloc(void * address
, size_t new_client_size
) {
190 amem
= (malloc_block
*)((unsigned int)address
- sizeof(malloc_block
)); /* Point to allocation block */
192 new_address
= malloc(new_client_size
); /* get a new one */
193 if(!new_address
) { /* Did we get it? */
194 panic("realloc: can not reallocate one of %08X size\n", new_client_size
);
197 memcpy(new_address
, address
, amem
->malSize
- sizeof(malloc_block
)); /* Copy the old in */
199 free(address
); /* Toss the old one */