Mercurial > hg > xemacs-beta
comparison src/malloc.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | abe6d1db359e |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
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 USG | |
155 #define USG | |
156 #endif | |
157 #else /* SIGTSTP */ | |
158 #ifdef SIGIO | |
159 #define BSD4_2 | |
160 #endif /* SIGIO */ | |
161 #endif /* SIGTSTP */ | |
162 | |
163 #if defined(hpux) | |
164 #define USG | |
165 #endif | |
166 | |
167 #endif /* not emacs */ | |
168 | |
169 #include <stddef.h> | |
170 | |
171 /* Define getpagesize () if the system does not. */ | |
172 #include "getpagesize.h" | |
173 | |
174 #ifdef HAVE_ULIMIT_H | |
175 #include <ulimit.h> | |
176 #endif | |
177 | |
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__) && !defined(__OpenBSD__) | |
192 extern void *sbrk (ptrdiff_t); | |
193 #else | |
194 extern char *sbrk (); | |
195 #endif /* __NetBSD__ or __OpenBSD__ */ | |
196 #endif /* HPUX */ | |
197 #else | |
198 extern void *sbrk (); | |
199 #endif /* __STDC__ */ | |
200 | |
201 extern char *start_of_data (void); | |
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 | |
308 static void getpool (void); | |
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 cp = sbrk (0); | |
369 siz = cp - data_space_start; | |
370 | |
371 if (warnfunction) | |
372 switch (warnlevel) | |
373 { | |
374 case 0: | |
375 if (siz > (lim_data / 4) * 3) | |
376 { | |
377 warnlevel++; | |
378 (*warnfunction) ("Warning: past 75% of memory limit"); | |
379 } | |
380 break; | |
381 case 1: | |
382 if (siz > (lim_data / 20) * 17) | |
383 { | |
384 warnlevel++; | |
385 (*warnfunction) ("Warning: past 85% of memory limit"); | |
386 } | |
387 break; | |
388 case 2: | |
389 if (siz > (lim_data / 20) * 19) | |
390 { | |
391 warnlevel++; | |
392 (*warnfunction) ("Warning: past 95% of memory limit"); | |
393 } | |
394 break; | |
395 } | |
396 | |
397 if ((int) cp & 0x3ff) /* land on 1K boundaries */ | |
398 sbrk (1024 - ((int) cp & 0x3ff)); | |
399 | |
400 /* Take at least 2k, and figure out how many blocks of the desired size | |
401 we're about to get */ | |
402 nblks = 1; | |
403 if ((siz = nu) < 8) | |
404 nblks = 1 << ((siz = 8) - nu); | |
405 | |
406 if ((cp = sbrk (1 << (siz + 3))) == (char *) -1) | |
407 { | |
408 #ifdef BSD | |
409 #ifndef BSD4_1 | |
410 sigsetmask (oldmask); | |
411 #endif | |
412 #endif | |
413 return; /* no more room! */ | |
414 } | |
415 malloc_sbrk_used = siz; | |
416 malloc_sbrk_unused = lim_data - siz; | |
417 | |
418 if ((int) cp & 7) | |
419 { /* shouldn't happen, but just in case */ | |
420 cp = (char *) (((int) cp + 8) & ~7); | |
421 nblks--; | |
422 } | |
423 | |
424 /* save new header and link the nblks blocks together */ | |
425 nextf[nu] = (struct mhead *) cp; | |
426 siz = 1 << (nu + 3); | |
427 while (1) | |
428 { | |
429 ((struct mhead *) cp) -> mh_alloc = ISFREE; | |
430 ((struct mhead *) cp) -> mh_index = nu; | |
431 if (--nblks <= 0) break; | |
432 CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz); | |
433 cp += siz; | |
434 } | |
435 CHAIN ((struct mhead *) cp) = 0; | |
436 | |
437 #ifdef BSD | |
438 #ifndef BSD4_1 | |
439 sigsetmask (oldmask); | |
440 #endif | |
441 #endif | |
442 } | |
443 | |
444 static void | |
445 getpool (void) | |
446 { | |
447 int nu; | |
448 char *cp = sbrk (0); | |
449 | |
450 if ((int) cp & 0x3ff) /* land on 1K boundaries */ | |
451 sbrk (1024 - ((int) cp & 0x3ff)); | |
452 | |
453 /* Record address of start of space allocated by malloc. */ | |
454 if (_malloc_base == 0) | |
455 _malloc_base = cp; | |
456 | |
457 /* Get 2k of storage */ | |
458 | |
459 cp = sbrk (04000); | |
460 if (cp == (char *) -1) | |
461 return; | |
462 | |
463 /* Divide it into an initial 8-word block | |
464 plus one block of size 2**nu for nu = 3 ... 10. */ | |
465 | |
466 CHAIN (cp) = nextf[0]; | |
467 nextf[0] = (struct mhead *) cp; | |
468 ((struct mhead *) cp) -> mh_alloc = ISFREE; | |
469 ((struct mhead *) cp) -> mh_index = 0; | |
470 cp += 8; | |
471 | |
472 for (nu = 0; nu < 7; nu++) | |
473 { | |
474 CHAIN (cp) = nextf[nu]; | |
475 nextf[nu] = (struct mhead *) cp; | |
476 ((struct mhead *) cp) -> mh_alloc = ISFREE; | |
477 ((struct mhead *) cp) -> mh_index = nu; | |
478 cp += 8 << nu; | |
479 } | |
480 } | |
481 | |
482 char * | |
483 malloc (n) /* get a block */ | |
484 unsigned n; | |
485 { | |
486 struct mhead *p; | |
487 unsigned int nbytes; | |
488 int nunits = 0; | |
489 | |
490 /* Figure out how many bytes are required, rounding up to the nearest | |
491 multiple of 8, then figure out which nestf[] area to use. | |
492 Both the beginning of the header and the beginning of the | |
493 block should be on an eight byte boundary. */ | |
494 nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; | |
495 { | |
496 unsigned int shiftr = (nbytes - 1) >> 2; | |
497 | |
498 while (shiftr >>= 1) | |
499 nunits++; | |
500 } | |
501 | |
502 /* In case this is reentrant use of malloc from signal handler, | |
503 pick a block size that no other malloc level is currently | |
504 trying to allocate. That's the easiest harmless way not to | |
505 interfere with the other level of execution. */ | |
506 while (busy[nunits]) nunits++; | |
507 busy[nunits] = 1; | |
508 | |
509 /* If there are no blocks of the appropriate size, go get some */ | |
510 /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ | |
511 if (nextf[nunits] == 0) | |
512 morecore (nunits); | |
513 | |
514 /* Get one block off the list, and set the new list head */ | |
515 if ((p = nextf[nunits]) == 0) | |
516 { | |
517 busy[nunits] = 0; | |
518 return 0; | |
519 } | |
520 nextf[nunits] = CHAIN (p); | |
521 busy[nunits] = 0; | |
522 | |
523 /* Check for free block clobbered */ | |
524 /* If not for this check, we would gobble a clobbered free chain ptr */ | |
525 /* and bomb out on the NEXT allocate of this size block */ | |
526 if (p -> mh_alloc != ISFREE || p -> mh_index != nunits) | |
527 #ifdef rcheck | |
528 botch ("block on free list clobbered"); | |
529 #else /* not rcheck */ | |
530 abort (); | |
531 #endif /* not rcheck */ | |
532 | |
533 /* Fill in the info, and if range checking, set up the magic numbers */ | |
534 p -> mh_alloc = ISALLOC; | |
535 #ifdef rcheck | |
536 p -> mh_nbytes = n; | |
537 p -> mh_magic4 = MAGIC4; | |
538 { | |
539 /* Get the location n after the beginning of the user's space. */ | |
540 char *m = (char *) p + ((sizeof *p + 7) & ~7) + n; | |
541 | |
542 *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; | |
543 } | |
544 #else /* not rcheck */ | |
545 p -> mh_size = n; | |
546 #endif /* not rcheck */ | |
547 #ifdef MSTATS | |
548 nmalloc[nunits]++; | |
549 nmal++; | |
550 #endif /* MSTATS */ | |
551 return (char *) p + ((sizeof *p + 7) & ~7); | |
552 } | |
553 | |
554 void | |
555 free (mem) | |
556 char *mem; | |
557 { | |
558 struct mhead *p; | |
559 { | |
560 char *ap = mem; | |
561 | |
562 if (ap == 0) | |
563 return; | |
564 | |
565 p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); | |
566 if (p -> mh_alloc == ISMEMALIGN) | |
567 { | |
568 ap -= p->mh_size; | |
569 p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); | |
570 } | |
571 | |
572 #ifndef rcheck | |
573 if (p -> mh_alloc != ISALLOC) | |
574 abort (); | |
575 | |
576 #else /* rcheck */ | |
577 if (p -> mh_alloc != ISALLOC) | |
578 { | |
579 if (p -> mh_alloc == ISFREE) | |
580 botch ("free: Called with already freed block argument\n"); | |
581 else | |
582 botch ("free: Called with bad argument\n"); | |
583 } | |
584 | |
585 ASSERT (p -> mh_magic4 == MAGIC4); | |
586 ap += p -> mh_nbytes; | |
587 ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); | |
588 ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1); | |
589 #endif /* rcheck */ | |
590 } | |
591 { | |
592 int nunits = p -> mh_index; | |
593 | |
594 ASSERT (nunits <= 29); | |
595 p -> mh_alloc = ISFREE; | |
596 | |
597 /* Protect against signal handlers calling malloc. */ | |
598 busy[nunits] = 1; | |
599 /* Put this block on the free list. */ | |
600 CHAIN (p) = nextf[nunits]; | |
601 nextf[nunits] = p; | |
602 busy[nunits] = 0; | |
603 | |
604 #ifdef MSTATS | |
605 nmalloc[nunits]--; | |
606 nfre++; | |
607 #endif /* MSTATS */ | |
608 } | |
609 } | |
610 | |
611 char * | |
612 realloc (mem, n) | |
613 char *mem; | |
614 unsigned n; | |
615 { | |
616 struct mhead *p; | |
617 unsigned int tocopy; | |
618 unsigned int nbytes; | |
619 int nunits; | |
620 | |
621 if (mem == 0) | |
622 return malloc (n); | |
623 p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7)); | |
624 nunits = p -> mh_index; | |
625 ASSERT (p -> mh_alloc == ISALLOC); | |
626 #ifdef rcheck | |
627 ASSERT (p -> mh_magic4 == MAGIC4); | |
628 { | |
629 char *m = mem + (tocopy = p -> mh_nbytes); | |
630 ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); | |
631 ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); | |
632 } | |
633 #else /* not rcheck */ | |
634 if (p -> mh_index >= 13) | |
635 tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7); | |
636 else | |
637 tocopy = p -> mh_size; | |
638 #endif /* not rcheck */ | |
639 | |
640 /* See if desired size rounds to same power of 2 as actual size. */ | |
641 nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; | |
642 | |
643 /* If ok, use the same block, just marking its size as changed. */ | |
644 if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) | |
645 { | |
646 #ifdef rcheck | |
647 char *m = mem + tocopy; | |
648 *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; | |
649 p-> mh_nbytes = n; | |
650 m = mem + n; | |
651 *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; | |
652 #else /* not rcheck */ | |
653 p -> mh_size = n; | |
654 #endif /* not rcheck */ | |
655 return mem; | |
656 } | |
657 | |
658 if (n < tocopy) | |
659 tocopy = n; | |
660 { | |
661 char *new; | |
662 | |
663 if ((new = malloc (n)) == 0) | |
664 return 0; | |
665 memcpy (new, mem, tocopy); | |
666 free (mem); | |
667 return new; | |
668 } | |
669 } | |
670 | |
671 | |
672 char * | |
673 memalign (alignment, size) | |
674 unsigned alignment, size; | |
675 { | |
676 char *ptr = malloc (size + alignment); | |
677 char *aligned; | |
678 struct mhead *p; | |
679 | |
680 if (ptr == 0) | |
681 return 0; | |
682 /* If entire block has the desired alignment, just accept it. */ | |
683 if (((int) ptr & (alignment - 1)) == 0) | |
684 return ptr; | |
685 /* Otherwise, get address of byte in the block that has that alignment. */ | |
686 aligned = (char *) (((int) ptr + alignment - 1) & -alignment); | |
687 | |
688 /* Store a suitable indication of how to free the block, | |
689 so that free can find the true beginning of it. */ | |
690 p = (struct mhead *) aligned - 1; | |
691 p -> mh_size = aligned - ptr; | |
692 p -> mh_alloc = ISMEMALIGN; | |
693 return aligned; | |
694 } | |
695 | |
696 #ifndef __hpux | |
697 /* This runs into trouble with getpagesize on HPUX. | |
698 Patching out seems cleaner than the ugly fix needed. */ | |
699 char * | |
700 valloc (size) | |
701 unsigned size; | |
702 { | |
703 return memalign (getpagesize (), size); | |
704 } | |
705 #endif /* not __hpux */ | |
706 | |
707 #ifdef MSTATS | |
708 /* Return statistics describing allocation of blocks of size 2**n. */ | |
709 | |
710 struct mstats_value | |
711 { | |
712 int blocksize; | |
713 int nfree; | |
714 int nused; | |
715 }; | |
716 | |
717 struct mstats_value | |
718 malloc_stats (size) | |
719 int size; | |
720 { | |
721 struct mstats_value v; | |
722 int i; | |
723 struct mhead *p; | |
724 | |
725 v.nfree = 0; | |
726 | |
727 if (size < 0 || size >= 30) | |
728 { | |
729 v.blocksize = 0; | |
730 v.nused = 0; | |
731 return v; | |
732 } | |
733 | |
734 v.blocksize = 1 << (size + 3); | |
735 v.nused = nmalloc[size]; | |
736 | |
737 for (p = nextf[size]; p; p = CHAIN (p)) | |
738 v.nfree++; | |
739 | |
740 return v; | |
741 } | |
742 int | |
743 malloc_mem_used () | |
744 { | |
745 int i; | |
746 int size_used; | |
747 | |
748 size_used = 0; | |
749 | |
750 for (i = 0; i < 30; i++) | |
751 { | |
752 int allocation_size = 1 << (i + 3); | |
753 struct mhead *p; | |
754 | |
755 size_used += nmalloc[i] * allocation_size; | |
756 } | |
757 | |
758 return size_used; | |
759 } | |
760 | |
761 int | |
762 malloc_mem_free () | |
763 { | |
764 int i; | |
765 int size_unused; | |
766 | |
767 size_unused = 0; | |
768 | |
769 for (i = 0; i < 30; i++) | |
770 { | |
771 int allocation_size = 1 << (i + 3); | |
772 struct mhead *p; | |
773 | |
774 for (p = nextf[i]; p ; p = CHAIN (p)) | |
775 size_unused += allocation_size; | |
776 } | |
777 | |
778 return size_unused; | |
779 } | |
780 #endif /* MSTATS */ | |
781 | |
782 /* | |
783 * This function returns the total number of bytes that the process | |
784 * will be allowed to allocate via the sbrk(2) system call. On | |
785 * BSD systems this is the total space allocatable to stack and | |
786 * data. On USG systems this is the data space only. | |
787 */ | |
788 | |
789 #ifdef USG | |
790 | |
791 static void | |
792 get_lim_data () | |
793 { | |
794 #ifdef ULIMIT_BREAK_VALUE | |
795 lim_data = ULIMIT_BREAK_VALUE; | |
796 #else | |
797 lim_data = ulimit (3, 0); | |
798 #endif | |
799 | |
800 lim_data -= (long) data_space_start; | |
801 } | |
802 | |
803 #else /* not USG */ | |
804 #ifndef BSD4_2 | |
805 | |
806 static void | |
807 get_lim_data () | |
808 { | |
809 lim_data = vlimit (LIM_DATA, -1); | |
810 } | |
811 | |
812 #else /* BSD4_2 */ | |
813 | |
814 static void | |
815 get_lim_data () | |
816 { | |
817 struct rlimit XXrlimit; | |
818 | |
819 getrlimit (RLIMIT_DATA, &XXrlimit); | |
820 #ifdef RLIM_INFINITY | |
821 lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */ | |
822 #else | |
823 lim_data = XXrlimit.rlim_cur; /* soft limit */ | |
824 #endif | |
825 } | |
826 | |
827 #endif /* BSD4_2 */ | |
828 #endif /* not USG */ | |
829 |