source: rtems/cpukit/httpd/balloc.c @ 4bf1801

4.104.114.84.95
Last change on this file since 4bf1801 was c1cdaa0, checked in by Joel Sherrill <joel.sherrill@…>, on 10/27/99 at 12:50:33

Patch from Emmanuel Raguet <raguet@…> and Eric Valette
<valette@…> to add a port of the GoAhead? web server
(httpd) to the RTEMS build tree. They have successfully used
this BSP on i386/pc386 and PowerPC/mcp750.

Mark and Joel spoke with Nick Berliner <nickb@…> on
26 Oct 1999 about this port and got verbal approval to include
it in RTEMS distributions.

  • Property mode set to 100644
File size: 20.4 KB
Line 
1/*
2 * balloc.c -- Block allocation module
3 *
4 * Copyright (c) GoAhead Software Inc., 1995-1999. All Rights Reserved.
5 *
6 * See the file "license.txt" for usage and redistribution license requirements
7 */
8
9/******************************** Description *********************************/
10
11/*
12 *      This module implements a very fast block allocation scheme suitable for
13 *      ROMed environments. It maintains block class queues for rapid allocation
14 *      and minimal fragmentation. This modules does not coalesce blocks. The
15 *      storage space may be populated statically or via the traditional malloc
16 *      mechanisms. Large blocks greater than the maximum class size may be
17 *      allocated from the O/S or run-time system via malloc. To permit the use
18 *      of malloc, call bopen with flags set to B_USE_MALLOC (this is the default).
19 *      It is recommended that bopen be called first thing in the application.
20 *      If it is not, it will be called with default values on the first call to
21 *      balloc(). Note that this code is not designed for multi-threading purposes
22 *      and it depends on newly declared variables being initialized to zero.
23 */ 
24
25/********************************* Includes ***********************************/
26
27#define IN_BALLOC
28
29#if UEMF
30        #include        "uemf.h"
31#else
32        #include        "basic/basicInternal.h"
33#endif
34
35#include        <stdarg.h>
36#include        <stdlib.h>
37
38#if !NO_BALLOC
39/********************************* Defines ************************************/
40
41typedef struct {
42        union {
43                void    *next;                                                  /* Pointer to next in q */
44                int             size;                                                   /* Actual requested size */
45        } u;
46        int                     flags;                                                  /* Per block allocation flags */
47} bType;
48
49/*
50 *      Define B_STATS if you wish to track memory block and stack usage
51 */
52#if B_STATS
53/*
54 *      Optional statistics
55 */
56
57typedef struct {
58        long    alloc;                                                          /* Block allocation calls */
59        long    inuse;                                                          /* Blocks in use */
60} bStatsType;
61
62typedef struct {
63        char_t  file[FNAMESIZE];
64        long    allocated;                                                      /* Bytes currently allocated */
65        long    count;                                                          /* Current block count */
66        long    allocs;                                                         /* Count of alloc attempts */
67} bStatsFileType;
68
69/*
70 *      This one is very expensive but great stats
71 */
72typedef struct {
73        void                    *ptr;                                           /* Pointer to memory */
74        bStatsFileType  *who;                                           /* Who allocated the memory */
75} bStatsBlkType;
76
77static bStatsType               bStats[B_MAX_CLASS];    /* Per class stats */
78static bStatsFileType   bStatsFiles[B_MAX_FILES];/* Per file stats */
79static bStatsBlkType    bStatsBlks[B_MAX_BLOCKS];/* Per block stats */
80static int                              bStatsBlksMax;                  /* Max block entry */
81static int                              bStatsFilesMax;                 /* Max file entry */
82static int                              bStatsMemInUse;                 /* Memory currently in use */
83static int                              bStatsMemMax;                   /* Max memory ever used */
84static void                             *bStackMin = (void*) -1;/* Miniumum stack position */
85static void                             *bStackStart;                   /* Starting stack position */
86static int                              bStatsMemMalloc;                /* Malloced memory */
87#endif /* B_STATS */
88
89
90/********************************** Locals ************************************/
91/*
92 *      bQhead blocks are created as the original memory allocation is freed up.
93 *      See bfree.
94 */
95static bType                    *bQhead[B_MAX_CLASS];   /* Per class block q head */
96static char                             *bFreeBuf;                              /* Pointer to free memory */
97static char                             *bFreeNext;                             /* Pointer to next free mem */
98static int                              bFreeSize;                              /* Size of free memory */
99static int                              bFreeLeft;                              /* Size of free left for use */
100static int                              bFlags = B_USE_MALLOC;  /* Default to auto-malloc */
101
102/*************************** Forward Declarations *****************************/
103
104#if B_STATS
105static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size);
106static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size);
107static void bstatsWrite(int handle, char_t *fmt, ...);
108static int      bStatsFileSort(const void *cp1, const void *cp2);
109#endif /* B_STATS */
110
111#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
112static void bFillBlock(void *buf, int bufsize);
113#endif
114
115#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
116static void verifyUsedBlock(bType *bp, int q);
117static void verifyFreeBlock(bType *bp, int q);
118static void verifyBallocSpace();
119#endif
120
121/********************************** Code **************************************/
122/*
123 *      Initialize the balloc module. bopen should be called the very first thing
124 *      after the application starts and bclose should be called the last thing
125 *      before exiting. If bopen is not called, it will be called on the first
126 *      allocation with default values. "buf" points to memory to use of size
127 *      "bufsize". If buf is NULL, memory is allocated using malloc. flags may
128 *      be set to B_USE_MALLOC if using malloc is okay. This routine will allocate
129 *      an initial buffer of size bufsize for use by the application.
130 */
131
132int bopen(void *buf, int bufsize, int flags)
133{
134        bFlags = flags;
135
136        if (buf == NULL) {
137                if (bufsize == 0) {
138                        bufsize = B_DEFAULT_MEM;
139                }
140                if ((buf = malloc(bufsize)) == NULL) {
141                        return -1;
142                }
143#if B_STATS
144                bStatsMemMalloc += bufsize;
145#endif
146        } else {
147                bFlags |= B_USER_BUF;
148        }
149
150        bFreeSize = bFreeLeft = bufsize;
151        bFreeBuf = bFreeNext = buf;
152#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
153        bFillBlock(buf, bufsize);
154#endif
155#if B_STATS
156        bStackStart = &buf;
157#endif
158#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
159        verifyFreeBlock(buf, bufsize);
160#endif
161        return 0;
162}
163
164/******************************************************************************/
165/*
166 *      Close down the balloc module and free all malloced memory.
167 */
168
169void bclose()
170{
171#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
172        verifyBallocSpace();
173#endif
174        if (! (bFlags & B_USER_BUF)) {
175                free(bFreeBuf);
176        }
177}
178
179/******************************************************************************/
180/*
181 *      Allocate a block of the requested size. First check the block
182 *      queues for a suitable one.
183 */
184
185void *balloc(B_ARGS_DEC, int size)
186{
187        bType   *bp;
188        int             q, memSize, mask;
189
190/*
191 *      Call bopen with default values if the application has not yet done so
192 */
193        if (bFreeBuf == NULL) {
194                if (bopen(NULL, B_DEFAULT_MEM , 0) < 0) {
195                        return NULL;
196                }
197        }
198#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
199        verifyBallocSpace();
200#endif
201        if (size < 0) {
202                return NULL;
203        }
204
205/*
206 *      Determine the relevant block queue with a block big enough -- 
207 *      include room for the block header.
208 */
209        mask = (size + sizeof(bType)) >> B_SHIFT;
210        for (q = 0; mask; mask >>= 1) {
211                q++;
212        }
213
214        a_assert(0 <= q && q <= B_MAX_CLASS);
215        memSize = (1 << (B_SHIFT + q));
216
217        if (q >= B_MAX_CLASS) {
218/*
219 *              Size if bigger than the maximum class. Malloc if use has been okayed
220 */
221                if (bFlags & B_USE_MALLOC) {
222#if B_STATS
223                        bstats(0, NULL);
224#endif
225                        bp = (bType*) malloc(memSize);
226                        if (bp == NULL) {
227                                trace(0, T("B: malloc failed for %s:%d, size %d\n"),
228                                        B_ARGS, memSize);
229                                return NULL;
230                        }
231#if B_STATS
232                        bStatsMemMalloc += memSize;
233#endif
234#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
235                        bFillBlock(bp, memSize);
236#endif
237
238                } else {
239                        trace(0, T("B: balloc failed for %s:%d, size %d\n"),
240                                B_ARGS, memSize);
241                        return NULL;
242                }
243                bp->u.size = size;
244                bp->flags = B_MALLOCED;
245
246        } else if ((bp = bQhead[q]) != NULL) {
247/*
248 *              Take first block off the relevant q if non-empty
249 */
250                bQhead[q] = bp->u.next;
251#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
252                verifyFreeBlock(bp, q);
253#endif
254#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
255                bFillBlock(bp, memSize);
256#endif
257                bp->u.size = size;
258                bp->flags = 0;
259
260        } else {
261                if (bFreeLeft > memSize) {
262/*
263 *                      The q was empty, and the free list has spare memory so
264 *                      create a new block out of the primary free block
265 */
266                        bp = (bType*) bFreeNext;
267#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
268                        verifyFreeBlock(bp, q);
269#endif
270                        bFreeNext += memSize;
271                        bFreeLeft -= memSize;
272#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
273                        bFillBlock(bp, memSize);
274#endif
275                        bp->u.size = size;
276                        bp->flags = 0;
277
278                } else if (bFlags & B_USE_MALLOC) {
279                        static int once = 0;
280                        if (once++ < 20) {
281#if B_STATS
282                                bstats(0, NULL);
283#endif
284                        }
285/*
286 *                      Nothing left on the primary free list, so malloc a new block
287 */
288                        if ((bp = (bType*) malloc(memSize)) == NULL) {
289                                trace(0, T("B: malloc failed for %s:%d size %d\n"),
290                                        B_ARGS, memSize);
291                                return NULL;
292                        }
293#if B_STATS
294                        bStatsMemMalloc += memSize;
295#endif
296#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
297                        bFillBlock(bp, memSize);
298#endif
299                        bp->u.size = size;
300                        bp->flags = B_MALLOCED;
301
302                } else {
303                        trace(0, T("B: alloc failed for %s:%d size %d\n"), B_ARGS, size);
304                        return NULL;
305                }
306        }
307
308#if B_STATS
309        bStatsAlloc(B_ARGS, bp, q, size);
310#endif
311        bp->flags |= B_INTEGRITY;
312
313        return (void*) ((char*) bp + sizeof(bType));
314}
315
316/******************************************************************************/
317/*
318 *      Free a block back to the relevant free q. We don't free back to the O/S
319 *      or run time system unless the block is greater than the maximum class size.
320 *      We also do not coalesce blocks.
321 */
322
323void bfree(B_ARGS_DEC, void *mp)
324{
325        bType   *bp;
326        int             mask, q;
327
328#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
329        verifyBallocSpace();
330#endif
331        a_assert(mp);
332
333        bp = (bType*) ((char*) mp - sizeof(bType));
334        a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
335        if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) {
336                return;
337        }
338
339/*
340 *      Determine the relevant block queue
341 */
342        mask = (bp->u.size + sizeof(bType)) >> B_SHIFT;
343        for (q = 0; mask; mask >>= 1) {
344                q++;
345        }
346        a_assert(0 <= q && q <= B_MAX_CLASS);
347
348#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
349        verifyUsedBlock(bp,q);
350#endif
351        if (bp->flags & B_MALLOCED) {
352                free(bp);
353                return;
354        }
355               
356#if B_STATS
357        bStatsFree(B_ARGS, bp, q, bp->u.size);
358#endif
359#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
360        bFillBlock(bp, 1 << (B_SHIFT + q));
361#endif
362
363/*
364 *      Simply link onto the head of the relevant q
365 */
366        bp->u.next = bQhead[q];
367        bQhead[q] = bp;
368}
369
370/******************************************************************************/
371/*
372 *      Safe free
373 */
374
375void bfreeSafe(B_ARGS_DEC, void *mp)
376{
377        if (mp) {
378                bfree(B_ARGS, mp);
379        }
380}
381
382/******************************************************************************/
383#if UNICODE
384/*
385 *      Duplicate a string, allow NULL pointers and then dup an empty string.
386 */
387
388char *bstrdupA(B_ARGS_DEC, char *s)
389{
390        char    *cp;
391        int             len;
392
393        if (s == NULL) {
394                s = "";
395        }
396        len = strlen(s) + 1;
397        if (cp = balloc(B_ARGS, len)) {
398                strcpy(cp, s);
399        }
400        return cp;
401}
402
403#endif /* UNICODE */
404/******************************************************************************/
405/*
406 *      Duplicate an ascii string, allow NULL pointers and then dup an empty string.
407 *      If UNICODE, bstrdup above works with wide chars, so we need this routine
408 *      for ascii strings.
409 */
410
411char_t *bstrdup(B_ARGS_DEC, char_t *s)
412{
413        char_t  *cp;
414        int             len;
415
416        if (s == NULL) {
417                s = T("");
418        }
419        len = gstrlen(s) + 1;
420        if ((cp = balloc(B_ARGS, len * sizeof(char_t))) != NULL) {
421                gstrcpy(cp, s);
422        }
423        return cp;
424}
425
426/******************************************************************************/
427/*
428 *      Reallocate a block. Allow NULL pointers and just do a malloc.
429 *      Note: if the realloc fails, we return NULL and the previous buffer is
430 *      preserved.
431 */
432
433void *brealloc(B_ARGS_DEC, void *mp, int newsize)
434{
435        bType*  bp;
436        void    *newbuf;
437
438        if (mp == NULL) {
439                return balloc(B_ARGS, newsize);
440        }
441        bp = (bType*) ((char*) mp - sizeof(bType));
442        a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
443        if ((newbuf = balloc(B_ARGS, newsize)) != NULL) {
444                memcpy(newbuf, mp, bp->u.size);
445                bfree(B_ARGS, mp);
446        }
447        return newbuf;
448}
449
450
451/******************************************************************************/
452#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
453/*
454 *      Fill the block (useful during development to catch zero fill assumptions)
455 */
456
457static void bFillBlock(void *buf, int bufsize)
458{
459        memset(buf, B_FILL_CHAR, bufsize);
460}
461#endif
462
463/******************************************************************************/
464#if B_STATS
465/*
466 *      Statistics. Do output via calling the writefn callback function with
467 *      "handle" as the output file handle.
468 */
469
470void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
471{
472        bStatsFileType  *fp;
473        bType                   *bp;
474        int                             q, count, mem, total;
475        static  int     recurseProtect = 0;
476
477        if (recurseProtect++ > 0) {
478                return;
479        }
480
481        if (writefn == NULL) {
482                writefn = bstatsWrite;
483        }
484
485/*
486 *      Print stats for each memory block
487 */
488        (*writefn)(handle, T("\nMemory Stats\n"));
489
490/*
491 *      The following tabular format is now used for the output.
492 *   Q  Size  Free Bytes Inuse Bytes Allocs
493 *      dd ddddd   ddd ddddd  dddd ddddd   dddd
494 */
495        (*writefn)(handle, " Q  Size  Free Bytes Inuse Bytes Allocs\n");
496
497        total = 0;
498        for (q = 0; q < B_MAX_CLASS; q++) {
499                count = 0;
500                for (bp = bQhead[q]; bp; bp = bp->u.next) {
501                        a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
502                        count++;
503                }
504                mem = count * (1 << (q + B_SHIFT));
505                total += mem;
506                (*writefn)(handle,
507                        T("%2d %5d   %3d %5d  %4d %5d   %4d\n"),
508                        q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse,
509                        bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc);
510        }
511
512        (*writefn)(handle, T("\n"));
513
514/*
515 *      Print summary stats
516 */
517        (*writefn)(handle, T("Initial free list size    %7d\n"), bFreeSize);
518        (*writefn)(handle, T("Max memory malloced       %7d\n"), bStatsMemMalloc);
519        (*writefn)(handle, T("Max memory ever used      %7d\n"), bStatsMemMax);
520        (*writefn)(handle, T("Memory currently in use   %7d\n"), bStatsMemInUse);
521        (*writefn)(handle, T("Max blocks allocated      %7d\n"), bStatsBlksMax);
522        (*writefn)(handle, T("Maximum stack used        %7d\n"),
523                (int) bStackStart - (int) bStackMin);
524
525        (*writefn)(handle, T("Free memory on all queues %7d\n"), total);
526        (*writefn)(handle, T("Free list buffer left     %7d\n"), bFreeLeft);
527        (*writefn)(handle, T("Total free memory         %7d\n"), bFreeLeft + total);
528
529/*
530 *      Print per file allocation stats
531 */
532        qsort(bStatsFiles, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
533        (*writefn)(handle, T("\nPer File Memory Stats\n"));
534        total = 0;
535        for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) {
536                if (fp->file[0]) {
537                        (*writefn)(handle,
538                                T("%18s, bytes %7d, blocks in use %5d, total allocs %6d\n"),
539                                fp->file, fp->allocated, fp->count, fp->allocs);
540                        total += fp->allocated;
541                }
542        }
543        (*writefn)(handle, T("\nTotal allocated %7d\n"), total);
544        recurseProtect--;
545}
546
547/******************************************************************************/
548/*
549 *      File sort function. Used to sort per file stats
550 */
551
552static int bStatsFileSort(const void *cp1, const void *cp2)
553{
554        bStatsFileType  *s1, *s2;
555
556        s1 = (bStatsFileType*) cp1;
557        s2 = (bStatsFileType*) cp2;
558
559        if (s1->allocated < s2->allocated)
560                return -1;
561        else if (s1->allocated == s2->allocated)
562                return 0;
563        return 1;
564}
565
566/******************************************************************************/
567/*
568 *      Default output function. Just send to trace channel.
569 */
570
571static void bstatsWrite(int handle, char_t *fmt, ...)
572{
573        va_list         args;
574        char_t          *buf;
575
576        va_start(args, fmt);
577        buf = NULL;
578        gvsnprintf(&buf, VALUE_MAX_STRING, fmt, args);
579        va_end(args);
580        trace(0, buf);
581        if (buf) {
582                bfree(B_L, buf);
583        }
584}
585
586/******************************************************************************/
587/*
588 *      Accumulate allocation statistics
589 */
590
591static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
592{
593        bStatsFileType  *fp;
594        bStatsBlkType   *bp;
595        char_t                  name[FNAMESIZE + 10];
596
597        a_assert(file && *file);
598        a_assert(0 <= q && q <= B_MAX_CLASS);
599        a_assert(size > 0);
600
601        gsprintf(name, T("%s:%d"), B_ARGS);
602
603        bStats[q].alloc++;
604        bStats[q].inuse++;
605        bStatsMemInUse += size;
606
607        if (bStatsMemInUse > bStatsMemMax) {
608                bStatsMemMax = bStatsMemInUse;
609        }
610
611/*
612 *      Track maximum stack usage. Assumes a stack growth down. Approximate as
613 *      we only measure this on block allocation.
614 */
615        if ((void*) &file < bStackMin) {
616                bStackMin = (void*) &file;
617        }
618
619/*
620 *      Find the file and adjust the stats for this file
621 */
622        for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) {
623                if (fp->file[0] == file[0] && gstrcmp(fp->file, name) == 0) {
624                        fp->allocated += size;
625                        fp->count++;
626                        fp->allocs++;
627                        break;
628                }
629        }
630
631/*
632 *      Find the first free slot for this file and add current block size.
633 */
634        if (fp >= &bStatsFiles[bStatsFilesMax]) {
635                for (fp = bStatsFiles; fp < &bStatsFiles[B_MAX_FILES]; fp++) {
636                        if (fp->file[0] == '\0') {
637                                gstrncpy(fp->file, name, TSZ(fp->file));
638                                fp->allocated += size;
639                                fp->count++;
640                                fp->allocs++;
641                                if ((fp - bStatsFiles) >= bStatsFilesMax) {
642                                        bStatsFilesMax = (fp - bStatsFiles) + 1;
643                                }
644                                break;
645                        }
646                }
647        }
648
649/*
650 *      Update the per block stats. Allocate a new slot.
651 */
652        for (bp = bStatsBlks; bp < &bStatsBlks[B_MAX_BLOCKS]; bp++) {
653                if (bp->ptr == NULL) {
654                        bp->ptr = ptr;
655                        bp->who = fp;
656                        if ((bp - bStatsBlks) >= bStatsBlksMax) {
657                                bStatsBlksMax = (bp - bStatsBlks) + 1;
658                        }
659                        break;
660                }
661        }
662}
663
664/******************************************************************************/
665/*
666 *      Free statistics
667 */
668
669static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size)
670{
671        bStatsFileType  *fp;
672        bStatsBlkType   *bp;
673        char_t                  name[FNAMESIZE + 10];
674
675        a_assert(file && *file);
676        a_assert(0 <= q && q <= B_MAX_CLASS);
677        a_assert(size > 0);
678
679        bStatsMemInUse -= size;
680        bStats[q].inuse--;
681
682        gsprintf(name, T("%s:%d"), B_ARGS);
683
684/*
685 *      Update the per block stats
686 */
687        for (bp = bStatsBlks; bp < &bStatsBlks[bStatsBlksMax]; bp++) {
688                if (bp->ptr == ptr) {
689                        bp->ptr = NULL;
690                        fp = bp->who;
691                        fp->allocated -= size;
692                        fp->count--;
693                        return;
694                }
695        }
696        a_assert(0);
697
698}
699
700#else /* not B_STATS */
701/******************************************************************************/
702/*
703 *      Dummy bstats for external calls that aren't protected by #if B_STATS.
704 */
705
706void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
707{
708}
709#endif /* B_STATS */
710
711/******************************************************************************/
712#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
713/*
714 *      The following routines verify the integrity of the balloc memory space.
715 *      These functions depend use the B_FILL feature.  Corruption is defined
716 *      as bad integrity flags in allocated blocks or data other than B_FILL_CHAR
717 *      being found anywhere in the space which is unallocated and that is not a
718 *      next pointer in the free queues.  a_assert is called if any corruption is
719 *      found.  CAUTION:  These functions add severe processing overhead and should
720 *      only be used when searching for a tough corruption problem.
721 */
722
723/******************************************************************************/
724/*
725 *      verifyUsedBlock verifies that a block which was previously allocated is
726 *      still uncorrupted. 
727 */
728
729static void verifyUsedBlock(bType *bp, int q)
730{
731        int             memSize, size;
732        char    *p;
733
734        memSize = (1 << (B_SHIFT + q));
735        a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY );
736        size = bp->u.size;
737        for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) {
738                a_assert(*p == B_FILL_CHAR);
739        }
740}
741
742/******************************************************************************/
743/*
744 *      verifyFreeBlock verifies that a previously free'd block in one of the queues
745 *      is still uncorrupted.
746 */
747
748static void verifyFreeBlock(bType *bp, int q)
749{
750        int             memSize;
751        char    *p;
752
753        memSize = (1 << (B_SHIFT + q));
754        for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) {
755                a_assert(*p == B_FILL_CHAR);
756        }
757        bp = (bType *)p;
758        a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY ||
759                                bp->flags == B_FILL_WORD);
760}
761
762/******************************************************************************/
763/*
764 *      verifyBallocSpace reads through the entire balloc memory space and
765 *      verifies that all allocated blocks are uncorrupted and that with the
766 *      exception of free list next pointers all other unallocated space is
767 *      filled with B_FILL_CHAR.
768 */
769
770static void verifyBallocSpace()
771{
772        char    *p;
773        bType   *bp;
774
775        p = bFreeBuf;
776        while (p < (bFreeBuf + bFreeSize)) {
777                bp = (bType *)p;
778                if (bp->u.size > 0xFFFFF) {
779                        p += sizeof(bp->u);
780                        while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
781                                p++;
782                        }
783                } else {
784                        a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) ||
785                                                bp->flags == B_FILL_WORD);
786                        p += (sizeof(bType) + bp->u.size);
787                        while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
788                                p++;
789                        }
790                }
791        }
792}
793#endif /* B_VERIFY_CAUSES_SEVERE_OVERHEAD */
794
795/******************************************************************************/
796
797#else /* NO_BALLOC */
798int bopen(void *buf, int bufsize, int flags)
799{
800        return 0;
801}
802
803/******************************************************************************/
804
805void bclose()
806{
807}
808
809/******************************************************************************/
810#if UNICODE
811char_t* bstrdupNoBalloc(char_t* s)
812{
813        if (s) {
814                return wcsdup(s);
815        } else {
816                return wcsdup(T(""));
817        }
818}
819#endif /* UNICODE */
820
821/******************************************************************************/
822char* bstrdupANoBalloc(char* s)
823{
824        char*   buf;
825
826        if (s == NULL) {
827                s = "";
828        }
829        buf = malloc(strlen(s)+1);
830        strcpy(buf, s);
831        return buf;
832}
833
834#endif /* NO_BALLOC */
835/******************************************************************************/
836
Note: See TracBrowser for help on using the repository browser.