OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [rtems_webserver/] [balloc.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
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
 
41
typedef 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
 
57
typedef struct {
58
        long    alloc;                                                          /* Block allocation calls */
59
        long    inuse;                                                          /* Blocks in use */
60
} bStatsType;
61
 
62
typedef 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
 */
72
typedef struct {
73
        void                    *ptr;                                           /* Pointer to memory */
74
        bStatsFileType  *who;                                           /* Who allocated the memory */
75
} bStatsBlkType;
76
 
77
static bStatsType               bStats[B_MAX_CLASS];    /* Per class stats */
78
static bStatsFileType   bStatsFiles[B_MAX_FILES];/* Per file stats */
79
static bStatsBlkType    bStatsBlks[B_MAX_BLOCKS];/* Per block stats */
80
static int                              bStatsBlksMax;                  /* Max block entry */
81
static int                              bStatsFilesMax;                 /* Max file entry */
82
static int                              bStatsMemInUse;                 /* Memory currently in use */
83
static int                              bStatsMemMax;                   /* Max memory ever used */
84
static void                             *bStackMin = (void*) -1;/* Miniumum stack position */
85
static void                             *bStackStart;                   /* Starting stack position */
86
static 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
 */
95
static bType                    *bQhead[B_MAX_CLASS];   /* Per class block q head */
96
static char                             *bFreeBuf;                              /* Pointer to free memory */
97
static char                             *bFreeNext;                             /* Pointer to next free mem */
98
static int                              bFreeSize;                              /* Size of free memory */
99
static int                              bFreeLeft;                              /* Size of free left for use */
100
static int                              bFlags = B_USE_MALLOC;  /* Default to auto-malloc */
101
 
102
/*************************** Forward Declarations *****************************/
103
 
104
#if B_STATS
105
static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size);
106
static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size);
107
static void bstatsWrite(int handle, char_t *fmt, ...);
108
static int      bStatsFileSort(const void *cp1, const void *cp2);
109
#endif /* B_STATS */
110
 
111
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
112
static void bFillBlock(void *buf, int bufsize);
113
#endif
114
 
115
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
116
static void verifyUsedBlock(bType *bp, int q);
117
static void verifyFreeBlock(bType *bp, int q);
118
static 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
 
132
int 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
 
169
void 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
 
185
void *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
                                goahead_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
                        goahead_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
                                goahead_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
                        goahead_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
 
323
void 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
 
375
void 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
 
388
char *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
 
411
char_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
 
433
void *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
 
457
static 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
 
470
void 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
 
552
static 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
 
571
static 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
        goahead_trace(0, buf);
581
        if (buf) {
582
                bfree(B_L, buf);
583
        }
584
}
585
 
586
/******************************************************************************/
587
/*
588
 *      Accumulate allocation statistics
589
 */
590
 
591
static 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
 
669
static 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
 
706
void 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
 
729
static 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
 
748
static 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
 
770
static 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 */
798
int bopen(void *buf, int bufsize, int flags)
799
{
800
        return 0;
801
}
802
 
803
/******************************************************************************/
804
 
805
void bclose()
806
{
807
}
808
 
809
/******************************************************************************/
810
#if UNICODE
811
char_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
/******************************************************************************/
822
char* 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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.