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