e91b87a3 |
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 Free |
94 | Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet |
95 | worked out a simple rule that can be stated here, but we will often permit |
96 | this. We will be guided by the two goals of preserving the free status of |
97 | all derivatives of our free software and of promoting the sharing and reuse of |
98 | 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 | |
106 | /* |
107 | * @(#)nmalloc.c 1 (Caltech) 2/21/82 |
108 | * |
109 | * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs |
110 | * |
111 | * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD. |
112 | * |
113 | * This is a very fast storage allocator. It allocates blocks of a small |
114 | * number of different sizes, and keeps free lists of each size. Blocks |
115 | * that don't exactly fit are passed up to the next larger size. In this |
116 | * implementation, the available sizes are (2^n)-4 (or -16) bytes long. |
117 | * This is designed for use in a program that uses vast quantities of |
118 | * memory, but bombs when it runs out. To make it a little better, it |
119 | * warns the user when he starts to get near the end. |
120 | * |
121 | * June 84, ACT: modified rcheck code to check the range given to malloc, |
122 | * rather than the range determined by the 2-power used. |
123 | * |
124 | * Jan 85, RMS: calls malloc_warning to issue warning on nearly full. |
125 | * No longer Emacs-specific; can serve as all-purpose malloc for GNU. |
126 | * You should call malloc_init to reinitialize after loading dumped Emacs. |
127 | * Call malloc_stats to get info on memory stats if MSTATS turned on. |
128 | * realloc knows how to return same block given, just changing its size, |
129 | * if the power of 2 is correct. |
130 | */ |
131 | |
132 | /* |
133 | * nextf[i] is the pointer to the next free block of size 2^(i+3). The |
134 | * smallest allocatable block is 8 bytes. The overhead information will |
135 | * go in the first int of the block, and the returned pointer will point |
136 | * to the second. |
137 | * |
138 | #ifdef MSTATS |
139 | * nmalloc[i] is the difference between the number of mallocs and frees |
140 | * for a given block size. |
141 | #endif MSTATS |
142 | */ |
143 | |
144 | #ifdef emacs |
4187119d |
145 | /* config.h specifies which kind of system this is. */ |
e91b87a3 |
146 | #include "config.h" |
4187119d |
147 | #else |
e91b87a3 |
148 | |
149 | /* Determine which kind of system this is. */ |
150 | #include <signal.h> |
151 | #ifndef SIGTSTP |
152 | #ifndef VMS |
153 | #ifndef USG |
154 | #define USG |
155 | #endif |
156 | #endif /* not VMS */ |
157 | #else /* SIGTSTP */ |
158 | #ifdef SIGIO |
4187119d |
159 | #define BSD4_2 |
e91b87a3 |
160 | #endif /* SIGIO */ |
161 | #endif /* SIGTSTP */ |
162 | |
4187119d |
163 | #if defined(hpux) |
164 | #define USG |
165 | #endif |
166 | |
167 | #endif /* not emacs */ |
168 | |
e91b87a3 |
169 | /* Define getpagesize () if the system does not. */ |
170 | #include "getpagesize.h" |
171 | |
4187119d |
172 | #ifndef BSD4_2 |
e91b87a3 |
173 | #ifndef USG |
174 | #include <sys/vlimit.h> /* warn the user when near the end */ |
175 | #endif /* not USG */ |
4187119d |
176 | #else /* if BSD4_2 */ |
e91b87a3 |
177 | #include <sys/time.h> |
178 | #include <sys/resource.h> |
4187119d |
179 | #endif /* BSD4_2 */ |
e91b87a3 |
180 | |
181 | extern char *start_of_data (); |
182 | |
183 | #ifdef BSD |
184 | #ifndef DATA_SEG_BITS |
185 | #define start_of_data() &etext |
186 | #endif |
187 | #endif |
188 | |
189 | #ifndef emacs |
190 | #define start_of_data() &etext |
191 | #endif |
192 | |
193 | #define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */ |
194 | #define ISFREE ((char) 0x54) /* magic byte that implies free block */ |
195 | /* this is for error checking only */ |
196 | #define ISMEMALIGN ((char) 0xd6) /* Stored before the value returned by |
197 | memalign, with the rest of the word |
198 | being the distance to the true |
199 | beginning of the block. */ |
200 | |
201 | extern char etext; |
202 | |
203 | /* These two are for user programs to look at, when they are interested. */ |
204 | |
205 | unsigned int malloc_sbrk_used; /* amount of data space used now */ |
206 | unsigned int malloc_sbrk_unused; /* amount more we can have */ |
207 | |
208 | /* start of data space; can be changed by calling init_malloc */ |
209 | static char *data_space_start; |
210 | |
211 | #ifdef MSTATS |
212 | static int nmalloc[30]; |
213 | static int nmal, nfre; |
214 | #endif /* MSTATS */ |
215 | |
216 | /* If range checking is not turned on, all we have is a flag indicating |
217 | whether memory is allocated, an index in nextf[], and a size field; to |
218 | realloc() memory we copy either size bytes or 1<<(index+3) bytes depending |
219 | on whether the former can hold the exact size (given the value of |
220 | 'index'). If range checking is on, we always need to know how much space |
221 | is allocated, so the 'size' field is never used. */ |
222 | |
223 | struct mhead { |
224 | char mh_alloc; /* ISALLOC or ISFREE */ |
225 | char mh_index; /* index in nextf[] */ |
226 | /* Remainder are valid only when block is allocated */ |
227 | unsigned short mh_size; /* size, if < 0x10000 */ |
228 | #ifdef rcheck |
229 | unsigned mh_nbytes; /* number of bytes allocated */ |
230 | int mh_magic4; /* should be == MAGIC4 */ |
231 | #endif /* rcheck */ |
232 | }; |
233 | |
234 | /* Access free-list pointer of a block. |
235 | It is stored at block + 4. |
236 | This is not a field in the mhead structure |
237 | because we want sizeof (struct mhead) |
238 | to describe the overhead for when the block is in use, |
239 | and we do not want the free-list pointer to count in that. */ |
240 | |
241 | #define CHAIN(a) \ |
242 | (*(struct mhead **) (sizeof (char *) + (char *) (a))) |
243 | |
244 | #ifdef rcheck |
245 | |
246 | /* To implement range checking, we write magic values in at the beginning and |
247 | end of each allocated block, and make sure they are undisturbed whenever a |
248 | free or a realloc occurs. */ |
249 | /* Written in each of the 4 bytes following the block's real space */ |
250 | #define MAGIC1 0x55 |
251 | /* Written in the 4 bytes before the block's real space */ |
252 | #define MAGIC4 0x55555555 |
253 | #define ASSERT(p) if (!(p)) botch("p"); else |
254 | #define EXTRA 4 /* 4 bytes extra for MAGIC1s */ |
255 | #else |
256 | #define ASSERT(p) |
257 | #define EXTRA 0 |
258 | #endif /* rcheck */ |
259 | |
260 | |
261 | /* nextf[i] is free list of blocks of size 2**(i + 3) */ |
262 | |
263 | static struct mhead *nextf[30]; |
264 | |
265 | /* busy[i] is nonzero while allocation of block size i is in progress. */ |
266 | |
267 | static char busy[30]; |
268 | |
269 | /* Number of bytes of writable memory we can expect to be able to get */ |
270 | static unsigned int lim_data; |
271 | |
272 | /* Level number of warnings already issued. |
273 | 0 -- no warnings issued. |
274 | 1 -- 75% warning already issued. |
275 | 2 -- 85% warning already issued. |
276 | */ |
277 | static int warnlevel; |
278 | |
279 | /* Function to call to issue a warning; |
280 | 0 means don't issue them. */ |
281 | static void (*warnfunction) (); |
282 | |
283 | /* nonzero once initial bunch of free blocks made */ |
284 | static int gotpool; |
285 | |
286 | char *_malloc_base; |
287 | |
288 | static void getpool (); |
289 | |
290 | /* Cause reinitialization based on job parameters; |
291 | also declare where the end of pure storage is. */ |
292 | void |
293 | malloc_init (start, warnfun) |
294 | char *start; |
295 | void (*warnfun) (); |
296 | { |
297 | if (start) |
298 | data_space_start = start; |
299 | lim_data = 0; |
300 | warnlevel = 0; |
301 | warnfunction = warnfun; |
302 | } |
303 | |
304 | /* Return the maximum size to which MEM can be realloc'd |
305 | without actually requiring copying. */ |
306 | |
307 | int |
308 | malloc_usable_size (mem) |
309 | char *mem; |
310 | { |
311 | int blocksize = 8 << (((struct mhead *) mem) - 1) -> mh_index; |
312 | |
313 | return blocksize - sizeof (struct mhead) - EXTRA; |
314 | } |
315 | \f |
316 | static void |
317 | morecore (nu) /* ask system for more memory */ |
318 | register int nu; /* size index to get more of */ |
319 | { |
320 | char *sbrk (); |
321 | register char *cp; |
322 | register int nblks; |
323 | register unsigned int siz; |
324 | int oldmask; |
325 | |
326 | #ifdef BSD |
327 | #ifndef BSD4_1 |
4187119d |
328 | /* ?? There was a suggestion not to block SIGILL, somehow for GDB's sake. */ |
e91b87a3 |
329 | oldmask = sigsetmask (-1); |
330 | #endif |
331 | #endif |
332 | |
333 | if (!data_space_start) |
334 | { |
335 | data_space_start = start_of_data (); |
336 | } |
337 | |
338 | if (lim_data == 0) |
339 | get_lim_data (); |
340 | |
341 | /* On initial startup, get two blocks of each size up to 1k bytes */ |
342 | if (!gotpool) |
343 | { getpool (); getpool (); gotpool = 1; } |
344 | |
345 | /* Find current end of memory and issue warning if getting near max */ |
346 | |
347 | #ifndef VMS |
348 | /* Maximum virtual memory on VMS is difficult to calculate since it |
349 | * depends on several dynmacially changing things. Also, alignment |
350 | * isn't that important. That is why much of the code here is ifdef'ed |
351 | * out for VMS systems. |
352 | */ |
353 | cp = sbrk (0); |
354 | siz = cp - data_space_start; |
e91b87a3 |
355 | |
356 | if (warnfunction) |
357 | switch (warnlevel) |
358 | { |
359 | case 0: |
360 | if (siz > (lim_data / 4) * 3) |
361 | { |
362 | warnlevel++; |
363 | (*warnfunction) ("Warning: past 75% of memory limit"); |
364 | } |
365 | break; |
366 | case 1: |
367 | if (siz > (lim_data / 20) * 17) |
368 | { |
369 | warnlevel++; |
370 | (*warnfunction) ("Warning: past 85% of memory limit"); |
371 | } |
372 | break; |
373 | case 2: |
374 | if (siz > (lim_data / 20) * 19) |
375 | { |
376 | warnlevel++; |
377 | (*warnfunction) ("Warning: past 95% of memory limit"); |
378 | } |
379 | break; |
380 | } |
381 | |
382 | if ((int) cp & 0x3ff) /* land on 1K boundaries */ |
383 | sbrk (1024 - ((int) cp & 0x3ff)); |
384 | #endif /* not VMS */ |
385 | |
386 | /* Take at least 2k, and figure out how many blocks of the desired size |
387 | we're about to get */ |
388 | nblks = 1; |
389 | if ((siz = nu) < 8) |
390 | nblks = 1 << ((siz = 8) - nu); |
391 | |
392 | if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) |
4187119d |
393 | { |
394 | #ifdef BSD |
395 | #ifndef BSD4_1 |
396 | sigsetmask (oldmask); |
397 | #endif |
398 | #endif |
399 | return; /* no more room! */ |
400 | } |
401 | malloc_sbrk_used = siz; |
402 | malloc_sbrk_unused = lim_data - siz; |
403 | |
e91b87a3 |
404 | #ifndef VMS |
405 | if ((int) cp & 7) |
406 | { /* shouldn't happen, but just in case */ |
407 | cp = (char *) (((int) cp + 8) & ~7); |
408 | nblks--; |
409 | } |
410 | #endif /* not VMS */ |
411 | |
412 | /* save new header and link the nblks blocks together */ |
413 | nextf[nu] = (struct mhead *) cp; |
414 | siz = 1 << (nu + 3); |
415 | while (1) |
416 | { |
417 | ((struct mhead *) cp) -> mh_alloc = ISFREE; |
418 | ((struct mhead *) cp) -> mh_index = nu; |
419 | if (--nblks <= 0) break; |
420 | CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); |
421 | cp += siz; |
422 | } |
423 | CHAIN ((struct mhead *) cp) = 0; |
424 | |
425 | #ifdef BSD |
426 | #ifndef BSD4_1 |
427 | sigsetmask (oldmask); |
428 | #endif |
429 | #endif |
430 | } |
431 | |
432 | static void |
433 | getpool () |
434 | { |
435 | register int nu; |
436 | char * sbrk (); |
437 | register char *cp = sbrk (0); |
438 | |
439 | if ((int) cp & 0x3ff) /* land on 1K boundaries */ |
440 | sbrk (1024 - ((int) cp & 0x3ff)); |
441 | |
442 | /* Record address of start of space allocated by malloc. */ |
443 | if (_malloc_base == 0) |
444 | _malloc_base = cp; |
445 | |
446 | /* Get 2k of storage */ |
447 | |
448 | cp = sbrk (04000); |
449 | if (cp == (char *) -1) |
450 | return; |
451 | |
452 | /* Divide it into an initial 8-word block |
453 | plus one block of size 2**nu for nu = 3 ... 10. */ |
454 | |
455 | CHAIN (cp) = nextf[0]; |
456 | nextf[0] = (struct mhead *) cp; |
457 | ((struct mhead *) cp) -> mh_alloc = ISFREE; |
458 | ((struct mhead *) cp) -> mh_index = 0; |
459 | cp += 8; |
460 | |
461 | for (nu = 0; nu < 7; nu++) |
462 | { |
463 | CHAIN (cp) = nextf[nu]; |
464 | nextf[nu] = (struct mhead *) cp; |
465 | ((struct mhead *) cp) -> mh_alloc = ISFREE; |
466 | ((struct mhead *) cp) -> mh_index = nu; |
467 | cp += 8 << nu; |
468 | } |
469 | } |
470 | \f |
471 | char * |
472 | malloc (n) /* get a block */ |
473 | unsigned n; |
474 | { |
475 | register struct mhead *p; |
476 | register unsigned int nbytes; |
477 | register int nunits = 0; |
478 | |
479 | /* Figure out how many bytes are required, rounding up to the nearest |
4187119d |
480 | multiple of 8, then figure out which nestf[] area to use. |
481 | Both the beginning of the header and the beginning of the |
482 | block should be on an eight byte boundary. */ |
483 | nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; |
e91b87a3 |
484 | { |
485 | register unsigned int shiftr = (nbytes - 1) >> 2; |
486 | |
487 | while (shiftr >>= 1) |
488 | nunits++; |
489 | } |
490 | |
491 | /* In case this is reentrant use of malloc from signal handler, |
492 | pick a block size that no other malloc level is currently |
493 | trying to allocate. That's the easiest harmless way not to |
494 | interfere with the other level of execution. */ |
495 | while (busy[nunits]) nunits++; |
496 | busy[nunits] = 1; |
497 | |
498 | /* If there are no blocks of the appropriate size, go get some */ |
499 | /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ |
500 | if (nextf[nunits] == 0) |
501 | morecore (nunits); |
502 | |
503 | /* Get one block off the list, and set the new list head */ |
504 | if ((p = nextf[nunits]) == 0) |
505 | { |
506 | busy[nunits] = 0; |
507 | return 0; |
508 | } |
509 | nextf[nunits] = CHAIN (p); |
510 | busy[nunits] = 0; |
511 | |
512 | /* Check for free block clobbered */ |
513 | /* If not for this check, we would gobble a clobbered free chain ptr */ |
514 | /* and bomb out on the NEXT allocate of this size block */ |
515 | if (p -> mh_alloc != ISFREE || p -> mh_index != nunits) |
516 | #ifdef rcheck |
517 | botch ("block on free list clobbered"); |
518 | #else /* not rcheck */ |
519 | abort (); |
520 | #endif /* not rcheck */ |
521 | |
522 | /* Fill in the info, and if range checking, set up the magic numbers */ |
523 | p -> mh_alloc = ISALLOC; |
524 | #ifdef rcheck |
525 | p -> mh_nbytes = n; |
526 | p -> mh_magic4 = MAGIC4; |
527 | { |
4187119d |
528 | /* Get the location n after the beginning of the user's space. */ |
529 | register char *m = (char *) p + ((sizeof *p + 7) & ~7) + n; |
e91b87a3 |
530 | |
531 | *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; |
532 | } |
533 | #else /* not rcheck */ |
534 | p -> mh_size = n; |
535 | #endif /* not rcheck */ |
536 | #ifdef MSTATS |
537 | nmalloc[nunits]++; |
538 | nmal++; |
539 | #endif /* MSTATS */ |
4187119d |
540 | return (char *) p + ((sizeof *p + 7) & ~7); |
e91b87a3 |
541 | } |
542 | |
543 | free (mem) |
544 | char *mem; |
545 | { |
546 | register struct mhead *p; |
547 | { |
548 | register char *ap = mem; |
549 | |
550 | if (ap == 0) |
551 | return; |
552 | |
4187119d |
553 | p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); |
e91b87a3 |
554 | if (p -> mh_alloc == ISMEMALIGN) |
555 | { |
556 | ap -= p->mh_size; |
4187119d |
557 | p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); |
e91b87a3 |
558 | } |
559 | |
560 | #ifndef rcheck |
561 | if (p -> mh_alloc != ISALLOC) |
562 | abort (); |
563 | |
4187119d |
564 | #else /* rcheck */ |
e91b87a3 |
565 | if (p -> mh_alloc != ISALLOC) |
566 | { |
567 | if (p -> mh_alloc == ISFREE) |
568 | botch ("free: Called with already freed block argument\n"); |
569 | else |
570 | botch ("free: Called with bad argument\n"); |
571 | } |
572 | |
573 | ASSERT (p -> mh_magic4 == MAGIC4); |
574 | ap += p -> mh_nbytes; |
575 | ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); |
576 | ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); |
577 | #endif /* rcheck */ |
578 | } |
579 | { |
580 | register int nunits = p -> mh_index; |
581 | |
582 | ASSERT (nunits <= 29); |
583 | p -> mh_alloc = ISFREE; |
584 | |
585 | /* Protect against signal handlers calling malloc. */ |
586 | busy[nunits] = 1; |
587 | /* Put this block on the free list. */ |
588 | CHAIN (p) = nextf[nunits]; |
589 | nextf[nunits] = p; |
590 | busy[nunits] = 0; |
591 | |
592 | #ifdef MSTATS |
593 | nmalloc[nunits]--; |
594 | nfre++; |
595 | #endif /* MSTATS */ |
596 | } |
597 | } |
598 | |
599 | char * |
600 | realloc (mem, n) |
601 | char *mem; |
602 | register unsigned n; |
603 | { |
604 | register struct mhead *p; |
605 | register unsigned int tocopy; |
606 | register unsigned int nbytes; |
607 | register int nunits; |
608 | |
4187119d |
609 | if (mem == 0) |
e91b87a3 |
610 | return malloc (n); |
4187119d |
611 | p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7)); |
e91b87a3 |
612 | nunits = p -> mh_index; |
613 | ASSERT (p -> mh_alloc == ISALLOC); |
614 | #ifdef rcheck |
615 | ASSERT (p -> mh_magic4 == MAGIC4); |
616 | { |
617 | register char *m = mem + (tocopy = p -> mh_nbytes); |
618 | ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); |
619 | ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); |
620 | } |
621 | #else /* not rcheck */ |
622 | if (p -> mh_index >= 13) |
4187119d |
623 | tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7); |
e91b87a3 |
624 | else |
625 | tocopy = p -> mh_size; |
626 | #endif /* not rcheck */ |
627 | |
628 | /* See if desired size rounds to same power of 2 as actual size. */ |
4187119d |
629 | nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; |
e91b87a3 |
630 | |
631 | /* If ok, use the same block, just marking its size as changed. */ |
632 | if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) |
633 | { |
634 | #ifdef rcheck |
635 | register char *m = mem + tocopy; |
636 | *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; |
637 | p-> mh_nbytes = n; |
638 | m = mem + n; |
639 | *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; |
640 | #else /* not rcheck */ |
641 | p -> mh_size = n; |
642 | #endif /* not rcheck */ |
643 | return mem; |
644 | } |
645 | |
646 | if (n < tocopy) |
647 | tocopy = n; |
648 | { |
649 | register char *new; |
650 | |
651 | if ((new = malloc (n)) == 0) |
652 | return 0; |
653 | bcopy (mem, new, tocopy); |
654 | free (mem); |
655 | return new; |
656 | } |
657 | } |
658 | |
659 | #ifndef VMS |
660 | |
661 | char * |
662 | memalign (alignment, size) |
663 | unsigned alignment, size; |
664 | { |
665 | register char *ptr = malloc (size + alignment); |
666 | register char *aligned; |
667 | register struct mhead *p; |
668 | |
669 | if (ptr == 0) |
670 | return 0; |
671 | /* If entire block has the desired alignment, just accept it. */ |
672 | if (((int) ptr & (alignment - 1)) == 0) |
673 | return ptr; |
674 | /* Otherwise, get address of byte in the block that has that alignment. */ |
675 | aligned = (char *) (((int) ptr + alignment - 1) & -alignment); |
676 | |
677 | /* Store a suitable indication of how to free the block, |
678 | so that free can find the true beginning of it. */ |
679 | p = (struct mhead *) aligned - 1; |
680 | p -> mh_size = aligned - ptr; |
681 | p -> mh_alloc = ISMEMALIGN; |
682 | return aligned; |
683 | } |
684 | |
4187119d |
685 | #ifndef hpux |
e91b87a3 |
686 | /* This runs into trouble with getpagesize on HPUX. |
687 | Patching out seems cleaner than the ugly fix needed. */ |
688 | char * |
689 | valloc (size) |
690 | { |
691 | return memalign (getpagesize (), size); |
692 | } |
4187119d |
693 | #endif /* not hpux */ |
e91b87a3 |
694 | #endif /* not VMS */ |
695 | \f |
696 | #ifdef MSTATS |
697 | /* Return statistics describing allocation of blocks of size 2**n. */ |
698 | |
699 | struct mstats_value |
700 | { |
701 | int blocksize; |
702 | int nfree; |
703 | int nused; |
704 | }; |
705 | |
706 | struct mstats_value |
707 | malloc_stats (size) |
708 | int size; |
709 | { |
710 | struct mstats_value v; |
711 | register int i; |
712 | register struct mhead *p; |
713 | |
714 | v.nfree = 0; |
715 | |
716 | if (size < 0 || size >= 30) |
717 | { |
718 | v.blocksize = 0; |
719 | v.nused = 0; |
720 | return v; |
721 | } |
722 | |
723 | v.blocksize = 1 << (size + 3); |
724 | v.nused = nmalloc[size]; |
725 | |
726 | for (p = nextf[size]; p; p = CHAIN (p)) |
727 | v.nfree++; |
728 | |
729 | return v; |
730 | } |
731 | int |
732 | malloc_mem_used () |
733 | { |
734 | int i; |
735 | int size_used; |
736 | |
737 | size_used = 0; |
738 | |
739 | for (i = 0; i < 30; i++) |
740 | { |
741 | int allocation_size = 1 << (i + 3); |
742 | struct mhead *p; |
743 | |
744 | size_used += nmalloc[i] * allocation_size; |
745 | } |
746 | |
747 | return size_used; |
748 | } |
749 | |
750 | int |
751 | malloc_mem_free () |
752 | { |
753 | int i; |
754 | int size_unused; |
755 | |
756 | size_unused = 0; |
757 | |
758 | for (i = 0; i < 30; i++) |
759 | { |
760 | int allocation_size = 1 << (i + 3); |
761 | struct mhead *p; |
762 | |
763 | for (p = nextf[i]; p ; p = CHAIN (p)) |
764 | size_unused += allocation_size; |
765 | } |
766 | |
767 | return size_unused; |
768 | } |
769 | #endif /* MSTATS */ |
770 | \f |
771 | /* |
772 | * This function returns the total number of bytes that the process |
773 | * will be allowed to allocate via the sbrk(2) system call. On |
774 | * BSD systems this is the total space allocatable to stack and |
775 | * data. On USG systems this is the data space only. |
776 | */ |
777 | |
778 | #ifdef USG |
779 | |
780 | get_lim_data () |
781 | { |
782 | extern long ulimit (); |
783 | |
784 | #ifdef ULIMIT_BREAK_VALUE |
785 | lim_data = ULIMIT_BREAK_VALUE; |
786 | #else |
787 | lim_data = ulimit (3, 0); |
788 | #endif |
789 | |
790 | lim_data -= (long) data_space_start; |
791 | } |
792 | |
793 | #else /* not USG */ |
4187119d |
794 | #ifndef BSD4_2 |
e91b87a3 |
795 | |
796 | get_lim_data () |
797 | { |
798 | lim_data = vlimit (LIM_DATA, -1); |
799 | } |
800 | |
4187119d |
801 | #else /* BSD4_2 */ |
e91b87a3 |
802 | |
803 | get_lim_data () |
804 | { |
805 | struct rlimit XXrlimit; |
806 | |
807 | getrlimit (RLIMIT_DATA, &XXrlimit); |
808 | #ifdef RLIM_INFINITY |
809 | lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ |
810 | #else |
811 | lim_data = XXrlimit.rlim_cur; /* soft limit */ |
812 | #endif |
813 | } |
814 | |
4187119d |
815 | #endif /* BSD4_2 */ |
e91b87a3 |
816 | #endif /* not USG */ |
817 | \f |
818 | #ifdef VMS |
819 | /* There is a problem when dumping and restoring things on VMS. Calls |
820 | * to SBRK don't necessarily result in contiguous allocation. Dumping |
821 | * doesn't work when it isn't. Therefore, we make the initial |
822 | * allocation contiguous by allocating a big chunk, and do SBRKs from |
823 | * there. Once Emacs has dumped there is no reason to continue |
824 | * contiguous allocation, malloc doesn't depend on it. |
825 | * |
826 | * There is a further problem of using brk and sbrk while using VMS C |
827 | * run time library routines malloc, calloc, etc. The documentation |
828 | * says that this is a no-no, although I'm not sure why this would be |
829 | * a problem. In any case, we remove the necessity to call brk and |
830 | * sbrk, by calling calloc (to assure zero filled data) rather than |
831 | * sbrk. |
832 | * |
833 | * VMS_ALLOCATION_SIZE is the size of the allocation array. This |
834 | * should be larger than the malloc size before dumping. Making this |
835 | * too large will result in the startup procedure slowing down since |
836 | * it will require more space and time to map it in. |
837 | * |
838 | * The value for VMS_ALLOCATION_SIZE in the following define was determined |
839 | * by running emacs linked (and a large allocation) with the debugger and |
840 | * looking to see how much storage was used. The allocation was 201 pages, |
841 | * so I rounded it up to a power of two. |
842 | */ |
843 | #ifndef VMS_ALLOCATION_SIZE |
844 | #define VMS_ALLOCATION_SIZE (512*256) |
845 | #endif |
846 | |
847 | /* Use VMS RTL definitions */ |
848 | #undef sbrk |
849 | #undef brk |
850 | #undef malloc |
851 | int vms_out_initial = 0; |
852 | char vms_initial_buffer[VMS_ALLOCATION_SIZE]; |
853 | static char *vms_current_brk = &vms_initial_buffer; |
854 | static char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1]; |
855 | |
856 | #include <stdio.h> |
857 | |
858 | char * |
859 | sys_sbrk (incr) |
860 | int incr; |
861 | { |
862 | char *sbrk(), *temp, *ptr; |
863 | |
864 | if (vms_out_initial) |
865 | { |
866 | /* out of initial allocation... */ |
867 | if (!(temp = malloc (incr))) |
868 | temp = (char *) -1; |
869 | } |
870 | else |
871 | { |
872 | /* otherwise, go out of our area */ |
873 | ptr = vms_current_brk + incr; /* new current_brk */ |
874 | if (ptr <= vms_end_brk) |
875 | { |
876 | temp = vms_current_brk; |
877 | vms_current_brk = ptr; |
878 | } |
879 | else |
880 | { |
881 | vms_out_initial = 1; /* mark as out of initial allocation */ |
882 | if (!(temp = malloc (incr))) |
883 | temp = (char *) -1; |
884 | } |
885 | } |
886 | return temp; |
887 | } |
888 | #endif /* VMS */ |