1 : /****************************************************************************\
2 : Copyright (c) 2002, NVIDIA Corporation.
3 :
4 : NVIDIA Corporation("NVIDIA") supplies this software to you in
5 : consideration of your agreement to the following terms, and your use,
6 : installation, modification or redistribution of this NVIDIA software
7 : constitutes acceptance of these terms. If you do not agree with these
8 : terms, please do not use, install, modify or redistribute this NVIDIA
9 : software.
10 :
11 : In consideration of your agreement to abide by the following terms, and
12 : subject to these terms, NVIDIA grants you a personal, non-exclusive
13 : license, under NVIDIA's copyrights in this original NVIDIA software (the
14 : "NVIDIA Software"), to use, reproduce, modify and redistribute the
15 : NVIDIA Software, with or without modifications, in source and/or binary
16 : forms; provided that if you redistribute the NVIDIA Software, you must
17 : retain the copyright notice of NVIDIA, this notice and the following
18 : text and disclaimers in all such redistributions of the NVIDIA Software.
19 : Neither the name, trademarks, service marks nor logos of NVIDIA
20 : Corporation may be used to endorse or promote products derived from the
21 : NVIDIA Software without specific prior written permission from NVIDIA.
22 : Except as expressly stated in this notice, no other rights or licenses
23 : express or implied, are granted by NVIDIA herein, including but not
24 : limited to any patent rights that may be infringed by your derivative
25 : works or by other works in which the NVIDIA Software may be
26 : incorporated. No hardware is licensed hereunder.
27 :
28 : THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
29 : WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
30 : INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
31 : NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
32 : ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
33 : PRODUCTS.
34 :
35 : IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
36 : INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37 : TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
38 : USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
39 : OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
40 : NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
41 : TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42 : NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 : \****************************************************************************/
44 : //
45 : #include <stddef.h>
46 : #include <stdlib.h>
47 : #include <string.h>
48 :
49 : #ifndef _MSC_VER
50 : #include <stdint.h>
51 : #endif
52 :
53 : #include "compiler/preprocessor/memory.h"
54 :
55 : // default alignment and chunksize, if called with 0 arguments
56 : #define CHUNKSIZE (64*1024)
57 : #define ALIGN 8
58 :
59 : // we need to call the `real' malloc and free, not our replacements
60 : #undef malloc
61 : #undef free
62 :
63 : struct chunk {
64 : struct chunk *next;
65 : };
66 :
67 : struct cleanup {
68 : struct cleanup *next;
69 : void (*fn)(void *);
70 : void *arg;
71 : };
72 :
73 : struct MemoryPool_rec {
74 : struct chunk *next;
75 : uintptr_t free, end;
76 : size_t chunksize;
77 : uintptr_t alignmask;
78 : struct cleanup *cleanup;
79 : };
80 :
81 0 : MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align)
82 : {
83 : MemoryPool *pool;
84 :
85 0 : if (align == 0) align = ALIGN;
86 0 : if (chunksize == 0) chunksize = CHUNKSIZE;
87 0 : if (align & (align-1)) return 0;
88 0 : if (chunksize < sizeof(MemoryPool)) return 0;
89 0 : if (chunksize & (align-1)) return 0;
90 0 : if (!(pool = malloc(chunksize))) return 0;
91 0 : pool->next = 0;
92 0 : pool->chunksize = chunksize;
93 0 : pool->alignmask = (uintptr_t)(align)-1;
94 0 : pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask;
95 0 : pool->end = (uintptr_t)pool + chunksize;
96 0 : pool->cleanup = 0;
97 0 : return pool;
98 : }
99 :
100 0 : void mem_FreePool(MemoryPool *pool)
101 : {
102 : struct cleanup *cleanup;
103 : struct chunk *p, *next;
104 :
105 0 : for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) {
106 0 : cleanup->fn(cleanup->arg);
107 : }
108 0 : for (p = (struct chunk *)pool; p; p = next) {
109 0 : next = p->next;
110 0 : free(p);
111 : }
112 0 : }
113 :
114 0 : void *mem_Alloc(MemoryPool *pool, size_t size)
115 : {
116 : struct chunk *ch;
117 0 : void *rv = (void *)pool->free;
118 0 : size = (size + pool->alignmask) & ~pool->alignmask;
119 0 : if (size <= 0) size = pool->alignmask;
120 0 : pool->free += size;
121 0 : if (pool->free > pool->end || pool->free < (uintptr_t)rv) {
122 0 : size_t minreq = (size + sizeof(struct chunk) + pool->alignmask)
123 0 : & ~pool->alignmask;
124 0 : pool->free = (uintptr_t)rv;
125 0 : if (minreq >= pool->chunksize) {
126 : // request size is too big for the chunksize, so allocate it as
127 : // a single chunk of the right size
128 0 : ch = malloc(minreq);
129 0 : if (!ch) return 0;
130 : } else {
131 0 : ch = malloc(pool->chunksize);
132 0 : if (!ch) return 0;
133 0 : pool->free = (uintptr_t)ch + minreq;
134 0 : pool->end = (uintptr_t)ch + pool->chunksize;
135 : }
136 0 : ch->next = pool->next;
137 0 : pool->next = ch;
138 0 : rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask);
139 : }
140 0 : return rv;
141 : }
142 :
143 0 : int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) {
144 : struct cleanup *cleanup;
145 :
146 0 : pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1);
147 0 : cleanup = mem_Alloc(pool, sizeof(struct cleanup));
148 0 : if (!cleanup) return -1;
149 0 : cleanup->next = pool->cleanup;
150 0 : cleanup->fn = fn;
151 0 : cleanup->arg = arg;
152 0 : pool->cleanup = cleanup;
153 0 : return 0;
154 : }
|