0
|
1 /* dynamic memory allocation for GNU.
|
|
2 Copyright (C) 1985, 1987 Free Software Foundation, Inc.
|
|
3
|
|
4 NO WARRANTY
|
|
5
|
|
6 BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
|
|
7 NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
|
8 WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
|
|
9 RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
|
|
10 WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
11 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
12 FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
|
|
13 AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
|
14 DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
|
15 CORRECTION.
|
|
16
|
|
17 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
|
18 STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
|
|
19 WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
|
|
20 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
|
|
21 OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
22 USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
|
|
23 DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
|
|
24 A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
|
|
25 PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
26 DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
|
|
27
|
|
28 GENERAL PUBLIC LICENSE TO COPY
|
|
29
|
|
30 1. You may copy and distribute verbatim copies of this source file
|
|
31 as you receive it, in any medium, provided that you conspicuously and
|
|
32 appropriately publish on each copy a valid copyright notice "Copyright
|
|
33 (C) 1985 Free Software Foundation, Inc."; and include following the
|
|
34 copyright notice a verbatim copy of the above disclaimer of warranty
|
|
35 and of this License. You may charge a distribution fee for the
|
|
36 physical act of transferring a copy.
|
|
37
|
|
38 2. You may modify your copy or copies of this source file or
|
|
39 any portion of it, and copy and distribute such modifications under
|
|
40 the terms of Paragraph 1 above, provided that you also do the following:
|
|
41
|
|
42 a) cause the modified files to carry prominent notices stating
|
|
43 that you changed the files and the date of any change; and
|
|
44
|
|
45 b) cause the whole of any work that you distribute or publish,
|
|
46 that in whole or in part contains or is a derivative of this
|
|
47 program or any part thereof, to be licensed at no charge to all
|
|
48 third parties on terms identical to those contained in this
|
|
49 License Agreement (except that you may choose to grant more extensive
|
|
50 warranty protection to some or all third parties, at your option).
|
|
51
|
|
52 c) You may charge a distribution fee for the physical act of
|
|
53 transferring a copy, and you may at your option offer warranty
|
|
54 protection in exchange for a fee.
|
|
55
|
|
56 Mere aggregation of another unrelated program with this program (or its
|
|
57 derivative) on a volume of a storage or distribution medium does not bring
|
|
58 the other program under the scope of these terms.
|
|
59
|
|
60 3. You may copy and distribute this program (or a portion or derivative
|
|
61 of it, under Paragraph 2) in object code or executable form under the terms
|
|
62 of Paragraphs 1 and 2 above provided that you also do one of the following:
|
|
63
|
|
64 a) accompany it with the complete corresponding machine-readable
|
|
65 source code, which must be distributed under the terms of
|
|
66 Paragraphs 1 and 2 above; or,
|
|
67
|
|
68 b) accompany it with a written offer, valid for at least three
|
|
69 years, to give any third party free (except for a nominal
|
|
70 shipping charge) a complete machine-readable copy of the
|
|
71 corresponding source code, to be distributed under the terms of
|
|
72 Paragraphs 1 and 2 above; or,
|
|
73
|
|
74 c) accompany it with the information you received as to where the
|
|
75 corresponding source code may be obtained. (This alternative is
|
|
76 allowed only for noncommercial distribution and only if you
|
|
77 received the program in object code or executable form alone.)
|
|
78
|
|
79 For an executable file, complete source code means all the source code for
|
|
80 all modules it contains; but, as a special exception, it need not include
|
|
81 source code for modules which are standard libraries that accompany the
|
|
82 operating system on which the executable file runs.
|
|
83
|
|
84 4. You may not copy, sublicense, distribute or transfer this program
|
|
85 except as expressly provided under this License Agreement. Any attempt
|
|
86 otherwise to copy, sublicense, distribute or transfer this program is void and
|
|
87 your rights to use the program under this License agreement shall be
|
|
88 automatically terminated. However, parties who have received computer
|
|
89 software programs from you with this License Agreement will not have
|
|
90 their licenses terminated so long as such parties remain in full compliance.
|
|
91
|
|
92 5. If you wish to incorporate parts of this program into other free
|
|
93 programs whose distribution conditions are different, write to the
|
|
94 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
95 MA 02111-1307, USA.. We have not yet worked out a simple rule that
|
|
96 can be stated here, but we will often permit this. We will be guided
|
|
97 by the two goals of preserving the free status of all derivatives of
|
|
98 our free software and of promoting the sharing and reuse of software.
|
|
99
|
|
100
|
|
101 In other words, you are welcome to use, share and improve this program.
|
|
102 You are forbidden to forbid anyone else to use, share and improve
|
|
103 what you give them. Help stamp out software-hoarding! */
|
|
104
|
|
105 /* Synched up with: Not synched with FSF. */
|
|
106
|
|
107
|
|
108 /*
|
|
109 * @(#)nmalloc.c 1 (Caltech) 2/21/82
|
|
110 *
|
|
111 * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
|
|
112 *
|
|
113 * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
|
|
114 *
|
|
115 * This is a very fast storage allocator. It allocates blocks of a small
|
|
116 * number of different sizes, and keeps free lists of each size. Blocks
|
|
117 * that don't exactly fit are passed up to the next larger size. In this
|
|
118 * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
|
|
119 * This is designed for use in a program that uses vast quantities of
|
|
120 * memory, but bombs when it runs out. To make it a little better, it
|
|
121 * warns the user when he starts to get near the end.
|
|
122 *
|
|
123 * June 84, ACT: modified rcheck code to check the range given to malloc,
|
|
124 * rather than the range determined by the 2-power used.
|
|
125 *
|
|
126 * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
|
|
127 * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
|
|
128 * You should call malloc_init to reinitialize after loading dumped Emacs.
|
|
129 * Call malloc_stats to get info on memory stats if MSTATS turned on.
|
|
130 * realloc knows how to return same block given, just changing its size,
|
|
131 * if the power of 2 is correct.
|
|
132 */
|
|
133
|
|
134 /*
|
|
135 * nextf[i] is the pointer to the next free block of size 2^(i+3). The
|
|
136 * smallest allocatable block is 8 bytes. The overhead information will
|
|
137 * go in the first int of the block, and the returned pointer will point
|
|
138 * to the second.
|
|
139 *
|
|
140 #ifdef MSTATS
|
|
141 * nmalloc[i] is the difference between the number of mallocs and frees
|
|
142 * for a given block size.
|
|
143 #endif MSTATS
|
|
144 */
|
|
145
|
|
146 #ifdef emacs
|
|
147 /* config.h specifies which kind of system this is. */
|
|
148 #include <config.h>
|
|
149 #else
|
|
150
|
|
151 /* Determine which kind of system this is. */
|
|
152 #include <signal.h>
|
|
153 #ifndef SIGTSTP
|
|
154 #ifndef VMS
|
|
155 #ifndef USG
|
|
156 #define USG
|
|
157 #endif
|
|
158 #endif /* not VMS */
|
|
159 #else /* SIGTSTP */
|
|
160 #ifdef SIGIO
|
|
161 #define BSD4_2
|
|
162 #endif /* SIGIO */
|
|
163 #endif /* SIGTSTP */
|
|
164
|
|
165 #if defined(hpux)
|
|
166 #define USG
|
|
167 #endif
|
|
168
|
|
169 #endif /* not emacs */
|
|
170
|
|
171 /* Define getpagesize () if the system does not. */
|
|
172 #include "getpagesize.h"
|
|
173
|
169
|
174 #ifdef HAVE_ULIMIT_H
|
|
175 #include <ulimit.h>
|
|
176 #endif
|
|
177
|
0
|
178 #ifndef BSD4_2
|
|
179 #ifndef USG
|
|
180 #include <sys/vlimit.h> /* warn the user when near the end */
|
|
181 #endif /* not USG */
|
|
182 #else /* if BSD4_2 */
|
|
183 #include <sys/time.h>
|
|
184 #include <sys/resource.h>
|
|
185 #endif /* BSD4_2 */
|
|
186
|
|
187 #ifdef __STDC_
|
|
188 #ifndef HPUX
|
|
189 /* not sure where this for NetBSD should really go
|
|
190 and it probably applies to other systems */
|
|
191 #if !defined(__NetBSD__) && !defined(__bsdi__)
|
|
192 extern void *sbrk (ptrdiff_t);
|
|
193 #else
|
|
194 extern char *sbrk ();
|
|
195 #endif /* __NetBSD__ */
|
|
196 #endif /* HPUX */
|
|
197 #else
|
|
198 extern void *sbrk ();
|
|
199 #endif /* __STDC__ */
|
|
200
|
|
201 extern char *start_of_data ();
|
|
202
|
|
203 #ifdef BSD
|
|
204 #ifndef DATA_SEG_BITS
|
|
205 #define start_of_data() &etext
|
|
206 #endif
|
|
207 #endif
|
|
208
|
|
209 #ifndef emacs
|
|
210 #define start_of_data() &etext
|
|
211 #endif
|
|
212
|
|
213 #define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */
|
|
214 #define ISFREE ((char) 0x54) /* magic byte that implies free block */
|
|
215 /* this is for error checking only */
|
|
216 #define ISMEMALIGN ((char) 0xd6) /* Stored before the value returned by
|
|
217 memalign, with the rest of the word
|
|
218 being the distance to the true
|
|
219 beginning of the block. */
|
|
220
|
|
221 extern char etext;
|
|
222
|
|
223 /* These two are for user programs to look at, when they are interested. */
|
|
224
|
|
225 unsigned int malloc_sbrk_used; /* amount of data space used now */
|
|
226 unsigned int malloc_sbrk_unused; /* amount more we can have */
|
|
227
|
|
228 /* start of data space; can be changed by calling init_malloc */
|
|
229 static char *data_space_start;
|
|
230
|
|
231 #ifdef MSTATS
|
|
232 static int nmalloc[30];
|
|
233 static int nmal, nfre;
|
|
234 #endif /* MSTATS */
|
|
235
|
|
236 /* If range checking is not turned on, all we have is a flag indicating
|
|
237 whether memory is allocated, an index in nextf[], and a size field; to
|
|
238 realloc() memory we copy either size bytes or 1<<(index+3) bytes depending
|
|
239 on whether the former can hold the exact size (given the value of
|
|
240 'index'). If range checking is on, we always need to know how much space
|
|
241 is allocated, so the 'size' field is never used. */
|
|
242
|
|
243 struct mhead {
|
|
244 char mh_alloc; /* ISALLOC or ISFREE */
|
|
245 char mh_index; /* index in nextf[] */
|
|
246 /* Remainder are valid only when block is allocated */
|
|
247 unsigned short mh_size; /* size, if < 0x10000 */
|
|
248 #ifdef rcheck
|
|
249 unsigned mh_nbytes; /* number of bytes allocated */
|
|
250 int mh_magic4; /* should be == MAGIC4 */
|
|
251 #endif /* rcheck */
|
|
252 };
|
|
253
|
|
254 /* Access free-list pointer of a block.
|
|
255 It is stored at block + 4.
|
|
256 This is not a field in the mhead structure
|
|
257 because we want sizeof (struct mhead)
|
|
258 to describe the overhead for when the block is in use,
|
|
259 and we do not want the free-list pointer to count in that. */
|
|
260
|
|
261 #define CHAIN(a) \
|
|
262 (*(struct mhead **) (sizeof (char *) + (char *) (a)))
|
|
263
|
|
264 #ifdef rcheck
|
|
265
|
|
266 /* To implement range checking, we write magic values in at the beginning and
|
|
267 end of each allocated block, and make sure they are undisturbed whenever a
|
|
268 free or a realloc occurs. */
|
|
269 /* Written in each of the 4 bytes following the block's real space */
|
|
270 #define MAGIC1 0x55
|
|
271 /* Written in the 4 bytes before the block's real space */
|
|
272 #define MAGIC4 0x55555555
|
|
273 #define ASSERT(p) if (!(p)) botch("p"); else
|
|
274 #define EXTRA 4 /* 4 bytes extra for MAGIC1s */
|
|
275 #else
|
|
276 #define ASSERT(p)
|
|
277 #define EXTRA 0
|
|
278 #endif /* rcheck */
|
|
279
|
|
280
|
|
281 /* nextf[i] is free list of blocks of size 2**(i + 3) */
|
|
282
|
|
283 static struct mhead *nextf[30];
|
|
284
|
|
285 /* busy[i] is nonzero while allocation of block size i is in progress. */
|
|
286
|
|
287 static char busy[30];
|
|
288
|
|
289 /* Number of bytes of writable memory we can expect to be able to get */
|
|
290 extern unsigned int lim_data;
|
|
291
|
|
292 /* Level number of warnings already issued.
|
|
293 0 -- no warnings issued.
|
|
294 1 -- 75% warning already issued.
|
|
295 2 -- 85% warning already issued.
|
|
296 */
|
|
297 static int warnlevel;
|
|
298
|
|
299 /* Function to call to issue a warning;
|
|
300 0 means don't issue them. */
|
|
301 static void (*warnfunction) ();
|
|
302
|
|
303 /* nonzero once initial bunch of free blocks made */
|
|
304 static int gotpool;
|
|
305
|
|
306 char *_malloc_base;
|
|
307
|
169
|
308 static void getpool (void);
|
0
|
309
|
|
310 /* Cause reinitialization based on job parameters;
|
|
311 also declare where the end of pure storage is. */
|
|
312 void
|
|
313 malloc_init (start, warnfun)
|
|
314 char *start;
|
|
315 void (*warnfun) ();
|
|
316 {
|
|
317 if (start)
|
|
318 data_space_start = start;
|
|
319 lim_data = 0;
|
|
320 warnlevel = 0;
|
|
321 warnfunction = warnfun;
|
|
322 }
|
|
323
|
|
324 /* Return the maximum size to which MEM can be realloc'd
|
|
325 without actually requiring copying. */
|
|
326
|
|
327 int
|
|
328 malloc_usable_size (mem)
|
|
329 char *mem;
|
|
330 {
|
|
331 int blocksize = 8 << (((struct mhead *) mem) - 1) -> mh_index;
|
|
332
|
|
333 return blocksize - sizeof (struct mhead) - EXTRA;
|
|
334 }
|
|
335
|
|
336 static void get_lim_data ();
|
|
337
|
|
338 static void
|
|
339 morecore (nu) /* ask system for more memory */
|
|
340 int nu; /* size index to get more of */
|
|
341 {
|
|
342 char *cp;
|
|
343 int nblks;
|
|
344 unsigned int siz;
|
|
345 int oldmask;
|
|
346
|
|
347 #ifdef BSD
|
|
348 #ifndef BSD4_1
|
|
349 /* ?? There was a suggestion not to block SIGILL, somehow for GDB's sake. */
|
|
350 oldmask = sigsetmask (-1);
|
|
351 #endif
|
|
352 #endif
|
|
353
|
|
354 if (!data_space_start)
|
|
355 {
|
|
356 data_space_start = start_of_data ();
|
|
357 }
|
|
358
|
|
359 if (lim_data == 0)
|
|
360 get_lim_data ();
|
|
361
|
|
362 /* On initial startup, get two blocks of each size up to 1k bytes */
|
|
363 if (!gotpool)
|
|
364 { getpool (); getpool (); gotpool = 1; }
|
|
365
|
|
366 /* Find current end of memory and issue warning if getting near max */
|
|
367
|
|
368 #ifndef VMS
|
|
369 /* Maximum virtual memory on VMS is difficult to calculate since it
|
2
|
370 * depends on several dynamically changing things. Also, alignment
|
0
|
371 * isn't that important. That is why much of the code here is ifdef'ed
|
|
372 * out for VMS systems.
|
|
373 */
|
|
374 cp = sbrk (0);
|
|
375 siz = cp - data_space_start;
|
|
376
|
|
377 if (warnfunction)
|
|
378 switch (warnlevel)
|
|
379 {
|
|
380 case 0:
|
|
381 if (siz > (lim_data / 4) * 3)
|
|
382 {
|
|
383 warnlevel++;
|
|
384 (*warnfunction) ("Warning: past 75% of memory limit");
|
|
385 }
|
|
386 break;
|
|
387 case 1:
|
|
388 if (siz > (lim_data / 20) * 17)
|
|
389 {
|
|
390 warnlevel++;
|
|
391 (*warnfunction) ("Warning: past 85% of memory limit");
|
|
392 }
|
|
393 break;
|
|
394 case 2:
|
|
395 if (siz > (lim_data / 20) * 19)
|
|
396 {
|
|
397 warnlevel++;
|
|
398 (*warnfunction) ("Warning: past 95% of memory limit");
|
|
399 }
|
|
400 break;
|
|
401 }
|
|
402
|
|
403 if ((int) cp & 0x3ff) /* land on 1K boundaries */
|
|
404 sbrk (1024 - ((int) cp & 0x3ff));
|
|
405 #endif /* not VMS */
|
|
406
|
|
407 /* Take at least 2k, and figure out how many blocks of the desired size
|
|
408 we're about to get */
|
|
409 nblks = 1;
|
|
410 if ((siz = nu) < 8)
|
|
411 nblks = 1 << ((siz = 8) - nu);
|
|
412
|
|
413 if ((cp = sbrk (1 << (siz + 3))) == (char *) -1)
|
|
414 {
|
|
415 #ifdef BSD
|
|
416 #ifndef BSD4_1
|
|
417 sigsetmask (oldmask);
|
|
418 #endif
|
|
419 #endif
|
|
420 return; /* no more room! */
|
|
421 }
|
|
422 malloc_sbrk_used = siz;
|
|
423 malloc_sbrk_unused = lim_data - siz;
|
|
424
|
|
425 #ifndef VMS
|
|
426 if ((int) cp & 7)
|
|
427 { /* shouldn't happen, but just in case */
|
|
428 cp = (char *) (((int) cp + 8) & ~7);
|
|
429 nblks--;
|
|
430 }
|
|
431 #endif /* not VMS */
|
|
432
|
|
433 /* save new header and link the nblks blocks together */
|
|
434 nextf[nu] = (struct mhead *) cp;
|
|
435 siz = 1 << (nu + 3);
|
|
436 while (1)
|
|
437 {
|
|
438 ((struct mhead *) cp) -> mh_alloc = ISFREE;
|
|
439 ((struct mhead *) cp) -> mh_index = nu;
|
|
440 if (--nblks <= 0) break;
|
|
441 CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz);
|
|
442 cp += siz;
|
|
443 }
|
|
444 CHAIN ((struct mhead *) cp) = 0;
|
|
445
|
|
446 #ifdef BSD
|
|
447 #ifndef BSD4_1
|
|
448 sigsetmask (oldmask);
|
|
449 #endif
|
|
450 #endif
|
|
451 }
|
|
452
|
|
453 static void
|
169
|
454 getpool (void)
|
0
|
455 {
|
|
456 int nu;
|
|
457 char *cp = sbrk (0);
|
|
458
|
|
459 if ((int) cp & 0x3ff) /* land on 1K boundaries */
|
|
460 sbrk (1024 - ((int) cp & 0x3ff));
|
|
461
|
|
462 /* Record address of start of space allocated by malloc. */
|
|
463 if (_malloc_base == 0)
|
|
464 _malloc_base = cp;
|
|
465
|
|
466 /* Get 2k of storage */
|
|
467
|
|
468 cp = sbrk (04000);
|
|
469 if (cp == (char *) -1)
|
|
470 return;
|
|
471
|
|
472 /* Divide it into an initial 8-word block
|
|
473 plus one block of size 2**nu for nu = 3 ... 10. */
|
|
474
|
|
475 CHAIN (cp) = nextf[0];
|
|
476 nextf[0] = (struct mhead *) cp;
|
|
477 ((struct mhead *) cp) -> mh_alloc = ISFREE;
|
|
478 ((struct mhead *) cp) -> mh_index = 0;
|
|
479 cp += 8;
|
|
480
|
|
481 for (nu = 0; nu < 7; nu++)
|
|
482 {
|
|
483 CHAIN (cp) = nextf[nu];
|
|
484 nextf[nu] = (struct mhead *) cp;
|
|
485 ((struct mhead *) cp) -> mh_alloc = ISFREE;
|
|
486 ((struct mhead *) cp) -> mh_index = nu;
|
|
487 cp += 8 << nu;
|
|
488 }
|
|
489 }
|
|
490
|
|
491 char *
|
|
492 malloc (n) /* get a block */
|
|
493 unsigned n;
|
|
494 {
|
|
495 struct mhead *p;
|
|
496 unsigned int nbytes;
|
|
497 int nunits = 0;
|
|
498
|
|
499 /* Figure out how many bytes are required, rounding up to the nearest
|
|
500 multiple of 8, then figure out which nestf[] area to use.
|
|
501 Both the beginning of the header and the beginning of the
|
|
502 block should be on an eight byte boundary. */
|
|
503 nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
|
|
504 {
|
|
505 unsigned int shiftr = (nbytes - 1) >> 2;
|
|
506
|
|
507 while (shiftr >>= 1)
|
|
508 nunits++;
|
|
509 }
|
|
510
|
|
511 /* In case this is reentrant use of malloc from signal handler,
|
|
512 pick a block size that no other malloc level is currently
|
|
513 trying to allocate. That's the easiest harmless way not to
|
|
514 interfere with the other level of execution. */
|
|
515 while (busy[nunits]) nunits++;
|
|
516 busy[nunits] = 1;
|
|
517
|
|
518 /* If there are no blocks of the appropriate size, go get some */
|
|
519 /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */
|
|
520 if (nextf[nunits] == 0)
|
|
521 morecore (nunits);
|
|
522
|
|
523 /* Get one block off the list, and set the new list head */
|
|
524 if ((p = nextf[nunits]) == 0)
|
|
525 {
|
|
526 busy[nunits] = 0;
|
|
527 return 0;
|
|
528 }
|
|
529 nextf[nunits] = CHAIN (p);
|
|
530 busy[nunits] = 0;
|
|
531
|
|
532 /* Check for free block clobbered */
|
|
533 /* If not for this check, we would gobble a clobbered free chain ptr */
|
|
534 /* and bomb out on the NEXT allocate of this size block */
|
|
535 if (p -> mh_alloc != ISFREE || p -> mh_index != nunits)
|
|
536 #ifdef rcheck
|
|
537 botch ("block on free list clobbered");
|
|
538 #else /* not rcheck */
|
|
539 abort ();
|
|
540 #endif /* not rcheck */
|
|
541
|
|
542 /* Fill in the info, and if range checking, set up the magic numbers */
|
|
543 p -> mh_alloc = ISALLOC;
|
|
544 #ifdef rcheck
|
|
545 p -> mh_nbytes = n;
|
|
546 p -> mh_magic4 = MAGIC4;
|
|
547 {
|
|
548 /* Get the location n after the beginning of the user's space. */
|
|
549 char *m = (char *) p + ((sizeof *p + 7) & ~7) + n;
|
|
550
|
|
551 *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1;
|
|
552 }
|
|
553 #else /* not rcheck */
|
|
554 p -> mh_size = n;
|
|
555 #endif /* not rcheck */
|
|
556 #ifdef MSTATS
|
|
557 nmalloc[nunits]++;
|
|
558 nmal++;
|
|
559 #endif /* MSTATS */
|
|
560 return (char *) p + ((sizeof *p + 7) & ~7);
|
|
561 }
|
|
562
|
|
563 void
|
|
564 free (mem)
|
|
565 char *mem;
|
|
566 {
|
|
567 struct mhead *p;
|
|
568 {
|
|
569 char *ap = mem;
|
|
570
|
|
571 if (ap == 0)
|
|
572 return;
|
|
573
|
|
574 p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
|
|
575 if (p -> mh_alloc == ISMEMALIGN)
|
|
576 {
|
|
577 ap -= p->mh_size;
|
|
578 p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
|
|
579 }
|
|
580
|
|
581 #ifndef rcheck
|
|
582 if (p -> mh_alloc != ISALLOC)
|
|
583 abort ();
|
|
584
|
|
585 #else /* rcheck */
|
|
586 if (p -> mh_alloc != ISALLOC)
|
|
587 {
|
|
588 if (p -> mh_alloc == ISFREE)
|
|
589 botch ("free: Called with already freed block argument\n");
|
|
590 else
|
|
591 botch ("free: Called with bad argument\n");
|
|
592 }
|
|
593
|
|
594 ASSERT (p -> mh_magic4 == MAGIC4);
|
|
595 ap += p -> mh_nbytes;
|
|
596 ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
|
|
597 ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1);
|
|
598 #endif /* rcheck */
|
|
599 }
|
|
600 {
|
|
601 int nunits = p -> mh_index;
|
|
602
|
|
603 ASSERT (nunits <= 29);
|
|
604 p -> mh_alloc = ISFREE;
|
|
605
|
|
606 /* Protect against signal handlers calling malloc. */
|
|
607 busy[nunits] = 1;
|
|
608 /* Put this block on the free list. */
|
|
609 CHAIN (p) = nextf[nunits];
|
|
610 nextf[nunits] = p;
|
|
611 busy[nunits] = 0;
|
|
612
|
|
613 #ifdef MSTATS
|
|
614 nmalloc[nunits]--;
|
|
615 nfre++;
|
|
616 #endif /* MSTATS */
|
|
617 }
|
|
618 }
|
|
619
|
|
620 char *
|
|
621 realloc (mem, n)
|
|
622 char *mem;
|
|
623 unsigned n;
|
|
624 {
|
|
625 struct mhead *p;
|
|
626 unsigned int tocopy;
|
|
627 unsigned int nbytes;
|
|
628 int nunits;
|
|
629
|
|
630 if (mem == 0)
|
|
631 return malloc (n);
|
|
632 p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7));
|
|
633 nunits = p -> mh_index;
|
|
634 ASSERT (p -> mh_alloc == ISALLOC);
|
|
635 #ifdef rcheck
|
|
636 ASSERT (p -> mh_magic4 == MAGIC4);
|
|
637 {
|
|
638 char *m = mem + (tocopy = p -> mh_nbytes);
|
|
639 ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
|
|
640 ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1);
|
|
641 }
|
|
642 #else /* not rcheck */
|
|
643 if (p -> mh_index >= 13)
|
|
644 tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7);
|
|
645 else
|
|
646 tocopy = p -> mh_size;
|
|
647 #endif /* not rcheck */
|
|
648
|
|
649 /* See if desired size rounds to same power of 2 as actual size. */
|
|
650 nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
|
|
651
|
|
652 /* If ok, use the same block, just marking its size as changed. */
|
|
653 if (nbytes > (4 << nunits) && nbytes <= (8 << nunits))
|
|
654 {
|
|
655 #ifdef rcheck
|
|
656 char *m = mem + tocopy;
|
|
657 *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0;
|
|
658 p-> mh_nbytes = n;
|
|
659 m = mem + n;
|
|
660 *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1;
|
|
661 #else /* not rcheck */
|
|
662 p -> mh_size = n;
|
|
663 #endif /* not rcheck */
|
|
664 return mem;
|
|
665 }
|
|
666
|
|
667 if (n < tocopy)
|
|
668 tocopy = n;
|
|
669 {
|
|
670 char *new;
|
|
671
|
|
672 if ((new = malloc (n)) == 0)
|
|
673 return 0;
|
|
674 memcpy (new, mem, tocopy);
|
|
675 free (mem);
|
|
676 return new;
|
|
677 }
|
|
678 }
|
|
679
|
|
680 #ifndef VMS
|
|
681
|
|
682 char *
|
|
683 memalign (alignment, size)
|
|
684 unsigned alignment, size;
|
|
685 {
|
|
686 char *ptr = malloc (size + alignment);
|
|
687 char *aligned;
|
|
688 struct mhead *p;
|
|
689
|
|
690 if (ptr == 0)
|
|
691 return 0;
|
|
692 /* If entire block has the desired alignment, just accept it. */
|
|
693 if (((int) ptr & (alignment - 1)) == 0)
|
|
694 return ptr;
|
|
695 /* Otherwise, get address of byte in the block that has that alignment. */
|
|
696 aligned = (char *) (((int) ptr + alignment - 1) & -alignment);
|
|
697
|
|
698 /* Store a suitable indication of how to free the block,
|
|
699 so that free can find the true beginning of it. */
|
|
700 p = (struct mhead *) aligned - 1;
|
|
701 p -> mh_size = aligned - ptr;
|
|
702 p -> mh_alloc = ISMEMALIGN;
|
|
703 return aligned;
|
|
704 }
|
|
705
|
|
706 #ifndef __hpux
|
|
707 /* This runs into trouble with getpagesize on HPUX.
|
|
708 Patching out seems cleaner than the ugly fix needed. */
|
|
709 char *
|
|
710 valloc (size)
|
|
711 unsigned size;
|
|
712 {
|
|
713 return memalign (getpagesize (), size);
|
|
714 }
|
|
715 #endif /* not __hpux */
|
|
716 #endif /* not VMS */
|
|
717
|
|
718 #ifdef MSTATS
|
|
719 /* Return statistics describing allocation of blocks of size 2**n. */
|
|
720
|
|
721 struct mstats_value
|
|
722 {
|
|
723 int blocksize;
|
|
724 int nfree;
|
|
725 int nused;
|
|
726 };
|
|
727
|
|
728 struct mstats_value
|
|
729 malloc_stats (size)
|
|
730 int size;
|
|
731 {
|
|
732 struct mstats_value v;
|
|
733 int i;
|
|
734 struct mhead *p;
|
|
735
|
|
736 v.nfree = 0;
|
|
737
|
|
738 if (size < 0 || size >= 30)
|
|
739 {
|
|
740 v.blocksize = 0;
|
|
741 v.nused = 0;
|
|
742 return v;
|
|
743 }
|
|
744
|
|
745 v.blocksize = 1 << (size + 3);
|
|
746 v.nused = nmalloc[size];
|
|
747
|
|
748 for (p = nextf[size]; p; p = CHAIN (p))
|
|
749 v.nfree++;
|
|
750
|
|
751 return v;
|
|
752 }
|
|
753 int
|
|
754 malloc_mem_used ()
|
|
755 {
|
|
756 int i;
|
|
757 int size_used;
|
|
758
|
|
759 size_used = 0;
|
|
760
|
|
761 for (i = 0; i < 30; i++)
|
|
762 {
|
|
763 int allocation_size = 1 << (i + 3);
|
|
764 struct mhead *p;
|
|
765
|
|
766 size_used += nmalloc[i] * allocation_size;
|
|
767 }
|
|
768
|
|
769 return size_used;
|
|
770 }
|
|
771
|
|
772 int
|
|
773 malloc_mem_free ()
|
|
774 {
|
|
775 int i;
|
|
776 int size_unused;
|
|
777
|
|
778 size_unused = 0;
|
|
779
|
|
780 for (i = 0; i < 30; i++)
|
|
781 {
|
|
782 int allocation_size = 1 << (i + 3);
|
|
783 struct mhead *p;
|
|
784
|
|
785 for (p = nextf[i]; p ; p = CHAIN (p))
|
|
786 size_unused += allocation_size;
|
|
787 }
|
|
788
|
|
789 return size_unused;
|
|
790 }
|
|
791 #endif /* MSTATS */
|
|
792
|
|
793 /*
|
|
794 * This function returns the total number of bytes that the process
|
|
795 * will be allowed to allocate via the sbrk(2) system call. On
|
|
796 * BSD systems this is the total space allocatable to stack and
|
|
797 * data. On USG systems this is the data space only.
|
|
798 */
|
|
799
|
|
800 #ifdef USG
|
|
801
|
|
802 static void
|
|
803 get_lim_data ()
|
|
804 {
|
|
805 #ifdef ULIMIT_BREAK_VALUE
|
|
806 lim_data = ULIMIT_BREAK_VALUE;
|
|
807 #else
|
|
808 lim_data = ulimit (3, 0);
|
|
809 #endif
|
|
810
|
|
811 lim_data -= (long) data_space_start;
|
|
812 }
|
|
813
|
|
814 #else /* not USG */
|
|
815 #ifndef BSD4_2
|
|
816
|
|
817 static void
|
|
818 get_lim_data ()
|
|
819 {
|
|
820 lim_data = vlimit (LIM_DATA, -1);
|
|
821 }
|
|
822
|
|
823 #else /* BSD4_2 */
|
|
824
|
|
825 static void
|
|
826 get_lim_data ()
|
|
827 {
|
|
828 struct rlimit XXrlimit;
|
|
829
|
|
830 getrlimit (RLIMIT_DATA, &XXrlimit);
|
|
831 #ifdef RLIM_INFINITY
|
|
832 lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */
|
|
833 #else
|
|
834 lim_data = XXrlimit.rlim_cur; /* soft limit */
|
|
835 #endif
|
|
836 }
|
|
837
|
|
838 #endif /* BSD4_2 */
|
|
839 #endif /* not USG */
|
|
840
|
|
841 #ifdef VMS
|
|
842 /* There is a problem when dumping and restoring things on VMS. Calls
|
|
843 * to SBRK don't necessarily result in contiguous allocation. Dumping
|
|
844 * doesn't work when it isn't. Therefore, we make the initial
|
|
845 * allocation contiguous by allocating a big chunk, and do SBRKs from
|
|
846 * there. Once Emacs has dumped there is no reason to continue
|
|
847 * contiguous allocation, malloc doesn't depend on it.
|
|
848 *
|
|
849 * There is a further problem of using brk and sbrk while using VMS C
|
|
850 * run time library routines malloc, calloc, etc. The documentation
|
|
851 * says that this is a no-no, although I'm not sure why this would be
|
|
852 * a problem. In any case, we remove the necessity to call brk and
|
|
853 * sbrk, by calling calloc (to assure zero filled data) rather than
|
|
854 * sbrk.
|
|
855 *
|
|
856 * VMS_ALLOCATION_SIZE is the size of the allocation array. This
|
|
857 * should be larger than the malloc size before dumping. Making this
|
|
858 * too large will result in the startup procedure slowing down since
|
|
859 * it will require more space and time to map it in.
|
|
860 *
|
|
861 * The value for VMS_ALLOCATION_SIZE in the following define was determined
|
|
862 * by running emacs linked (and a large allocation) with the debugger and
|
|
863 * looking to see how much storage was used. The allocation was 201 pages,
|
|
864 * so I rounded it up to a power of two.
|
|
865 */
|
|
866 #ifndef VMS_ALLOCATION_SIZE
|
|
867 #define VMS_ALLOCATION_SIZE (512*256)
|
|
868 #endif
|
|
869
|
|
870 /* Use VMS RTL definitions */
|
|
871 #undef sbrk
|
|
872 #undef brk
|
|
873 #undef malloc
|
|
874 int vms_out_initial = 0;
|
|
875 char vms_initial_buffer[VMS_ALLOCATION_SIZE];
|
|
876 static char *vms_current_brk = &vms_initial_buffer;
|
|
877 static char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1];
|
|
878
|
|
879 #include <stdio.h>
|
|
880
|
|
881 char *
|
|
882 sys_sbrk (incr)
|
|
883 int incr;
|
|
884 {
|
|
885 char *sbrk(), *temp, *ptr;
|
|
886
|
|
887 if (vms_out_initial)
|
|
888 {
|
|
889 /* out of initial allocation... */
|
|
890 if (!(temp = malloc (incr)))
|
|
891 temp = (char *) -1;
|
|
892 }
|
|
893 else
|
|
894 {
|
|
895 /* otherwise, go out of our area */
|
|
896 ptr = vms_current_brk + incr; /* new current_brk */
|
|
897 if (ptr <= vms_end_brk)
|
|
898 {
|
|
899 temp = vms_current_brk;
|
|
900 vms_current_brk = ptr;
|
|
901 }
|
|
902 else
|
|
903 {
|
|
904 vms_out_initial = 1; /* mark as out of initial allocation */
|
|
905 if (!(temp = malloc (incr)))
|
|
906 temp = (char *) -1;
|
|
907 }
|
|
908 }
|
|
909 return temp;
|
|
910 }
|
|
911 #endif /* VMS */
|