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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [rtems_webserver/] [balloc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 * balloc.c -- Block allocation module
3
 *
4
 * Copyright (c) GoAhead Software Inc., 1995-2000. 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 module 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
/*
42
 *      Define B_STATS if you wish to track memory block and stack usage
43
 */
44
#if B_STATS
45
/*
46
 *      Optional statistics
47
 */
48
 
49
typedef struct {
50
        long    alloc;                                                          /* Block allocation calls */
51
        long    inuse;                                                          /* Blocks in use */
52
} bStatsType;
53
 
54
typedef struct {
55
        char_t  file[FNAMESIZE];
56
        long    allocated;                                                      /* Bytes currently allocated */
57
        long    count;                                                          /* Current block count */
58
        long    times;                                                          /* Count of alloc attempts */
59
        long    largest;                                                        /* largest allocated here */
60
        int             q;
61
} bStatsFileType;
62
 
63
/*
64
 *      This one is very expensive but great stats
65
 */
66
typedef struct {
67
        void                    *ptr;                                           /* Pointer to memory */
68
        bStatsFileType  *who;                                           /* Who allocated the memory */
69
} bStatsBlkType;
70
 
71
static bStatsType               bStats[B_MAX_CLASS];    /* Per class stats */
72
static bStatsFileType   bStatsFiles[B_MAX_FILES];/* Per file stats */
73
static bStatsBlkType    bStatsBlks[B_MAX_BLOCKS];/* Per block stats */
74
static int                              bStatsBlksMax = 0;               /* Max block entry */
75
static int                              bStatsFilesMax = 0;              /* Max file entry */
76
static int                              bStatsMemInUse = 0;              /* Memory currently in use */
77
static int                              bStatsBallocInUse = 0;   /* Memory currently balloced */
78
static int                              bStatsMemMax = 0;                /* Max memory ever used */
79
static int                              bStatsBallocMax = 0;     /* Max memory ever balloced */
80
static void                             *bStackMin = (void*) -1;/* Miniumum stack position */
81
static void                             *bStackStart;                   /* Starting stack position */
82
static int                              bStatsMemMalloc = 0;     /* Malloced memory */
83
#endif /* B_STATS */
84
 
85
/*
86
 *      ROUNDUP4(size) returns the next higher integer value of size that is
87
 *      divisible by 4, or the value of size if size is divisible by 4.
88
 *      ROUNDUP4() is used in aligning memory allocations on 4-byte boundaries.
89
 *
90
 *      Note:  ROUNDUP4() is only required on some operating systems (IRIX).
91
 */
92
 
93
#define ROUNDUP4(size) ((size) % 4) ? (size) + (4 - ((size) % 4)) : (size)
94
 
95
/********************************** Locals ************************************/
96
/*
97
 *      bQhead blocks are created as the original memory allocation is freed up.
98
 *      See bfree.
99
 */
100
static bType                    *bQhead[B_MAX_CLASS];   /* Per class block q head */
101
static char                             *bFreeBuf;                              /* Pointer to free memory */
102
static char                             *bFreeNext;                             /* Pointer to next free mem */
103
static int                              bFreeSize;                              /* Size of free memory */
104
static int                              bFreeLeft;                              /* Size of free left for use */
105
static int                              bFlags = B_USE_MALLOC;  /* Default to auto-malloc */
106
static int                              bopenCount = 0;                  /* Num tasks using balloc */
107
 
108
/*************************** Forward Declarations *****************************/
109
 
110
#if B_STATS
111
static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size);
112
static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size);
113
static void bstatsWrite(int handle, char_t *fmt, ...);
114
static int      bStatsFileSort(const void *cp1, const void *cp2);
115
#endif /* B_STATS */
116
 
117
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
118
static void bFillBlock(void *buf, int bufsize);
119
#endif
120
 
121
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
122
static void verifyUsedBlock(bType *bp, int q);
123
static void verifyFreeBlock(bType *bp, int q);
124
void verifyBallocSpace();
125
#endif
126
 
127
static int ballocGetSize(int size, int *q);
128
 
129
/********************************** Code **************************************/
130
/*
131
 *      Initialize the balloc module. bopen should be called the very first thing
132
 *      after the application starts and bclose should be called the last thing
133
 *      before exiting. If bopen is not called, it will be called on the first
134
 *      allocation with default values. "buf" points to memory to use of size
135
 *      "bufsize". If buf is NULL, memory is allocated using malloc. flags may
136
 *      be set to B_USE_MALLOC if using malloc is okay. This routine will allocate
137
 *      an initial buffer of size bufsize for use by the application.
138
 */
139
 
140
int bopen(void *buf, int bufsize, int flags)
141
{
142
        bFlags = flags;
143
 
144
#if BASTARD_TESTING
145
        srand(time(0L));
146
#endif /* BASTARD_TESTING */
147
 
148
/*
149
 *      If bopen already called by a shared process, just increment the count
150
 *      and return;
151
 */
152
        if (++bopenCount > 1) {
153
                return 0;
154
        }
155
 
156
        if (buf == NULL) {
157
                if (bufsize == 0) {
158
                        bufsize = B_DEFAULT_MEM;
159
                }
160
#ifdef IRIX
161
                bufsize = ROUNDUP4(bufsize);
162
#endif
163
                if ((buf = malloc(bufsize)) == NULL) {
164
                        return -1;
165
                }
166
#if B_STATS
167
                bStatsMemMalloc += bufsize;
168
#endif
169
        } else {
170
                bFlags |= B_USER_BUF;
171
        }
172
 
173
        bFreeSize = bFreeLeft = bufsize;
174
        bFreeBuf = bFreeNext = buf;
175
        memset(bQhead, 0, sizeof(bQhead));
176
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
177
        bFillBlock(buf, bufsize);
178
#endif
179
#if B_STATS
180
        bStackStart = &buf;
181
#endif
182
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
183
        verifyFreeBlock(buf, bufsize);
184
#endif
185
        return 0;
186
}
187
 
188
/******************************************************************************/
189
/*
190
 *      Close down the balloc module and free all malloced memory.
191
 */
192
 
193
void bclose()
194
{
195
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
196
        verifyBallocSpace();
197
#endif
198
        if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) {
199
                free(bFreeBuf);
200
                bopenCount = 0;
201
        }
202
}
203
 
204
/******************************************************************************/
205
/*
206
 *      Allocate a block of the requested size. First check the block
207
 *      queues for a suitable one.
208
 */
209
 
210
void *balloc(B_ARGS_DEC, int size)
211
{
212
        bType   *bp;
213
        int             q, memSize;
214
 
215
/*
216
 *      Call bopen with default values if the application has not yet done so
217
 */
218
        if (bFreeBuf == NULL) {
219
                if (bopen(NULL, B_DEFAULT_MEM, 0) < 0) {
220
                        return NULL;
221
                }
222
        }
223
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
224
        verifyBallocSpace();
225
#endif
226
        if (size < 0) {
227
                return NULL;
228
        }
229
 
230
#if BASTARD_TESTING
231
        if (rand() == 0x7fff) {
232
                return NULL;
233
        }
234
#endif /* BASTARD_TESTING */
235
 
236
 
237
        memSize = ballocGetSize(size, &q);
238
 
239
        if (q >= B_MAX_CLASS) {
240
/*
241
 *              Size if bigger than the maximum class. Malloc if use has been okayed
242
 */
243
                if (bFlags & B_USE_MALLOC) {
244
#if B_STATS
245
                        bstats(0, NULL);
246
#endif
247
#ifdef IRIX
248
                        memSize = ROUNDUP4(memSize);
249
#endif
250
                        bp = (bType*) malloc(memSize);
251
                        if (bp == NULL) {
252
                                traceRaw(T("B: malloc failed\n"));
253
                                return NULL;
254
                        }
255
#if B_STATS
256
                        bStatsMemMalloc += memSize;
257
#endif
258
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
259
                        bFillBlock(bp, memSize);
260
#endif
261
 
262
                } else {
263
                        traceRaw(T("B: malloc failed\n"));
264
                        return NULL;
265
                }
266
 
267
/*
268
 *              the u.size is the actual size allocated for data
269
 */
270
                bp->u.size = memSize - sizeof(bType);
271
                bp->flags = B_MALLOCED;
272
 
273
        } else if ((bp = bQhead[q]) != NULL) {
274
/*
275
 *              Take first block off the relevant q if non-empty
276
 */
277
                bQhead[q] = bp->u.next;
278
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
279
                verifyFreeBlock(bp, q);
280
#endif
281
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
282
                bFillBlock(bp, memSize);
283
#endif
284
                bp->u.size = memSize - sizeof(bType);
285
                bp->flags = 0;
286
 
287
        } else {
288
                if (bFreeLeft > memSize) {
289
/*
290
 *                      The q was empty, and the free list has spare memory so
291
 *                      create a new block out of the primary free block
292
 */
293
                        bp = (bType*) bFreeNext;
294
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
295
                        verifyFreeBlock(bp, q);
296
#endif
297
                        bFreeNext += memSize;
298
                        bFreeLeft -= memSize;
299
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
300
                        bFillBlock(bp, memSize);
301
#endif
302
                        bp->u.size = memSize - sizeof(bType);
303
                        bp->flags = 0;
304
 
305
                } else if (bFlags & B_USE_MALLOC) {
306
#if B_STATS
307
                        static int once = 0;
308
                        if (once++ == 0) {
309
                                bstats(0, NULL);
310
                        }
311
#endif
312
/*
313
 *                      Nothing left on the primary free list, so malloc a new block
314
 */
315
#ifdef IRIX
316
                        memSize = ROUNDUP4(memSize);
317
#endif
318
                        if ((bp = (bType*) malloc(memSize)) == NULL) {
319
                                traceRaw(T("B: malloc failed\n"));
320
                                return NULL;
321
                        }
322
#if B_STATS
323
                        bStatsMemMalloc += memSize;
324
#endif
325
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
326
                        bFillBlock(bp, memSize);
327
#endif
328
                        bp->u.size = memSize - sizeof(bType);
329
                        bp->flags = B_MALLOCED;
330
 
331
                } else {
332
                        traceRaw(T("B: malloc failed\n"));
333
                        return NULL;
334
                }
335
        }
336
 
337
#if B_STATS
338
        bStatsAlloc(B_ARGS, bp, q, memSize);
339
#endif
340
        bp->flags |= B_INTEGRITY;
341
 
342
/*
343
 *      The following is a good place to put a breakpoint when trying to reduce
344
 *      determine and reduce maximum memory use.
345
 */
346
#if 0
347
#if B_STATS
348
        if (bStatsBallocInUse == bStatsBallocMax) {
349
                bstats(0, NULL);
350
        }
351
#endif
352
#endif
353
        return (void*) ((char*) bp + sizeof(bType));
354
}
355
 
356
/******************************************************************************/
357
/*
358
 *      Free a block back to the relevant free q. We don't free back to the O/S
359
 *      or run time system unless the block is greater than the maximum class size.
360
 *      We also do not coalesce blocks.
361
 */
362
 
363
void bfree(B_ARGS_DEC, void *mp)
364
{
365
        bType   *bp;
366
        int             q, memSize;
367
 
368
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
369
        verifyBallocSpace();
370
#endif
371
        bp = (bType*) ((char*) mp - sizeof(bType));
372
 
373
        a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
374
 
375
        if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) {
376
                return;
377
        }
378
 
379
        memSize = ballocGetSize(bp->u.size, &q);
380
 
381
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
382
        verifyUsedBlock(bp,q);
383
#endif
384
#if B_STATS
385
        bStatsFree(B_ARGS, bp, q, bp->u.size+sizeof(bType));
386
#endif
387
        if (bp->flags & B_MALLOCED) {
388
                free(bp);
389
                return;
390
        }
391
 
392
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
393
        bFillBlock(bp, memSize);
394
#endif
395
 
396
/*
397
 *      Simply link onto the head of the relevant q
398
 */
399
        bp->u.next = bQhead[q];
400
        bQhead[q] = bp;
401
 
402
        bp->flags = B_FILL_WORD;
403
}
404
 
405
/******************************************************************************/
406
/*
407
 *      Safe free
408
 */
409
 
410
void bfreeSafe(B_ARGS_DEC, void *mp)
411
{
412
        if (mp) {
413
                bfree(B_ARGS, mp);
414
        }
415
}
416
 
417
/******************************************************************************/
418
#if UNICODE
419
/*
420
 *      Duplicate a string, allow NULL pointers and then dup an empty string.
421
 */
422
 
423
char *bstrdupA(B_ARGS_DEC, char *s)
424
{
425
        char    *cp;
426
        int             len;
427
 
428
        if (s == NULL) {
429
                s = "";
430
        }
431
        len = strlen(s) + 1;
432
        if (cp = balloc(B_ARGS, len)) {
433
                strcpy(cp, s);
434
        }
435
        return cp;
436
}
437
 
438
#endif /* UNICODE */
439
/******************************************************************************/
440
/*
441
 *      Duplicate an ascii string, allow NULL pointers and then dup an empty string.
442
 *      If UNICODE, bstrdup above works with wide chars, so we need this routine
443
 *      for ascii strings.
444
 */
445
 
446
char_t *bstrdup(B_ARGS_DEC, char_t *s)
447
{
448
        char_t  *cp;
449
        int             len;
450
 
451
        if (s == NULL) {
452
                s = T("");
453
        }
454
        len = gstrlen(s) + 1;
455
        if ((cp = balloc(B_ARGS, len * sizeof(char_t))) != NULL) {
456
                gstrcpy(cp, s);
457
        }
458
        return cp;
459
}
460
 
461
/******************************************************************************/
462
/*
463
 *      Reallocate a block. Allow NULL pointers and just do a malloc.
464
 *      Note: if the realloc fails, we return NULL and the previous buffer is
465
 *      preserved.
466
 */
467
 
468
void *brealloc(B_ARGS_DEC, void *mp, int newsize)
469
{
470
        bType   *bp;
471
        void    *newbuf;
472
 
473
        if (mp == NULL) {
474
                return balloc(B_ARGS, newsize);
475
        }
476
        bp = (bType*) ((char*) mp - sizeof(bType));
477
        a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
478
 
479
/*
480
 *      If the allocated memory already has enough room just return the previously
481
 *      allocated address.
482
 */
483
        if (bp->u.size >= newsize) {
484
                return mp;
485
        }
486
        if ((newbuf = balloc(B_ARGS, newsize)) != NULL) {
487
                memcpy(newbuf, mp, bp->u.size);
488
                bfree(B_ARGS, mp);
489
        }
490
        return newbuf;
491
}
492
 
493
/******************************************************************************/
494
/*
495
 *      Find the size of the block to be balloc'ed.  It takes in a size, finds the
496
 *      smallest binary block it fits into, adds an overhead amount and returns.
497
 *      q is the binary size used to keep track of block sizes in use.  Called
498
 *      from both balloc and bfree.
499
 */
500
 
501
static int ballocGetSize(int size, int *q)
502
{
503
        int     mask;
504
 
505
        mask = (size == 0) ? 0 : (size-1) >> B_SHIFT;
506
        for (*q = 0; mask; mask >>= 1) {
507
                *q = *q + 1;
508
        }
509
        return ((1 << (B_SHIFT + *q)) + sizeof(bType));
510
}
511
 
512
/******************************************************************************/
513
#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD
514
/*
515
 *      Fill the block (useful during development to catch zero fill assumptions)
516
 */
517
 
518
static void bFillBlock(void *buf, int bufsize)
519
{
520
        memset(buf, B_FILL_CHAR, bufsize);
521
}
522
#endif
523
 
524
/******************************************************************************/
525
#if B_STATS
526
/*
527
 *      Statistics. Do output via calling the writefn callback function with
528
 *      "handle" as the output file handle.
529
 */
530
 
531
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
532
{
533
        bStatsFileType  *fp, *files;
534
        bStatsBlkType   *blkp;
535
        bType                   *bp;
536
        char_t                  *cp;
537
        int                             q, count, mem, total, len;
538
        static  int     recurseProtect = 0;
539
 
540
        if (recurseProtect++ > 0) {
541
                recurseProtect--;
542
                return;
543
        }
544
 
545
        if (writefn == NULL) {
546
                writefn = bstatsWrite;
547
        }
548
 
549
/*
550
 *      Print stats for each memory block
551
 */
552
        (*writefn)(handle, T("\nMemory Stats\n"));
553
 
554
/*
555
 *      The following tabular format is now used for the output.
556
 *   Q  Size  Free Bytes Inuse Bytes Allocs
557
 *      dd ddddd   ddd ddddd  dddd ddddd   dddd
558
 */
559
        (*writefn)(handle, " Q  Size   Free  Bytes Inuse Bytes Allocs\n");
560
 
561
        total = 0;
562
        for (q = 0; q < B_MAX_CLASS; q++) {
563
                count = 0;
564
                for (bp = bQhead[q]; bp; bp = bp->u.next) {
565
                        count++;
566
                }
567
                mem = count * (1 << (q + B_SHIFT));
568
                total += mem;
569
                (*writefn)(handle,
570
                        T("%2d %5d   %4d %6d  %4d %5d   %4d\n"),
571
                        q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse,
572
                        bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc);
573
        }
574
 
575
        (*writefn)(handle, T("\n"));
576
 
577
/*
578
 *      Print summary stats
579
 *
580
 *      bFreeSize                       Initial memory reserved with bopen call
581
 *      bStatsMemMalloc         memory from calls to system MALLOC
582
 *      bStatsMemMax
583
 *      bStatsBallocMax         largest amount of memory from balloc calls
584
 *      bStatsMemInUse
585
 *      bStatsBallocInUse       present balloced memory being used
586
 *      bStatsBlksMax);
587
 *      bStackStart
588
 *      bStackMin);
589
 *      total);
590
 *      bFreeLeft);
591
 *
592
 */
593
        (*writefn)(handle, T("Initial free list size    %7d\n"), bFreeSize);
594
        (*writefn)(handle, T("Max memory malloced       %7d\n"), bStatsMemMalloc);
595
        (*writefn)(handle, T("Max memory ever used      %7d\n"), bStatsMemMax);
596
        (*writefn)(handle, T("Max memory ever balloced  %7d\n"), bStatsBallocMax);
597
        (*writefn)(handle, T("Memory currently in use   %7d\n"), bStatsMemInUse);
598
        (*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse);
599
        (*writefn)(handle, T("Max blocks allocated      %7d\n"), bStatsBlksMax);
600
        (*writefn)(handle, T("Maximum stack used        %7d\n"),
601
                (int) bStackStart - (int) bStackMin);
602
 
603
        (*writefn)(handle, T("Free memory on all queues %7d\n"), total);
604
        (*writefn)(handle, T("Free list buffer left     %7d\n"), bFreeLeft);
605
        (*writefn)(handle, T("Total free memory         %7d\n"), bFreeLeft + total);
606
 
607
/*
608
 *      Print per file allocation stats. Sort the copied table.
609
 */
610
        len = sizeof(bStatsFileType) * B_MAX_FILES;
611
        files = malloc(len);
612
        if (files == NULL) {
613
                (*writefn)(handle, T("Can't allocate stats memory\n"));
614
                recurseProtect--;
615
                return;
616
        }
617
        memcpy(files, bStatsFiles, len);
618
        qsort(files, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
619
 
620
        (*writefn)(handle, T("\nMemory Currently Allocated\n"));
621
        total = 0;
622
        (*writefn)(handle,
623
                T("                      bytes, blocks in use, total times,")
624
                T("largest,   q\n"));
625
 
626
        for (fp = files; fp < &files[bStatsFilesMax]; fp++) {
627
                if (fp->file[0]) {
628
                        (*writefn)(handle, T("%18s, %7d,         %5d,      %6d, %7d,%4d\n"),
629
                                fp->file, fp->allocated, fp->count, fp->times, fp->largest,
630
                                fp->q);
631
                        total += fp->allocated;
632
                }
633
        }
634
        (*writefn)(handle, T("\nTotal allocated %7d\n\n"), total);
635
 
636
/*
637
 *      Dump the actual strings
638
 */
639
        (*writefn)(handle, T("\nStrings\n"));
640
        for (blkp = &bStatsBlks[bStatsBlksMax - 1]; blkp >= bStatsBlks; blkp--) {
641
                if (blkp->ptr) {
642
                        cp = (char_t*) ((char*) blkp->ptr + sizeof(bType));
643
                        fp = blkp->who;
644
                        if (gisalnum(*cp)) {
645
                                (*writefn)(handle, T("%-50s allocated by %s\n"), cp,
646
                                        fp->file);
647
                        }
648
                }
649
        }
650
        free(files);
651
        recurseProtect--;
652
}
653
 
654
/******************************************************************************/
655
/*
656
 *      File sort function. Used to sort per file stats
657
 */
658
 
659
static int bStatsFileSort(const void *cp1, const void *cp2)
660
{
661
        bStatsFileType  *s1, *s2;
662
 
663
        s1 = (bStatsFileType*) cp1;
664
        s2 = (bStatsFileType*) cp2;
665
 
666
        if (s1->allocated < s2->allocated)
667
                return -1;
668
        else if (s1->allocated == s2->allocated)
669
                return 0;
670
        return 1;
671
}
672
 
673
/******************************************************************************/
674
/*
675
 *      Accumulate allocation statistics
676
 */
677
 
678
static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
679
{
680
        int                             memSize;
681
        bStatsFileType  *fp;
682
        bStatsBlkType   *bp;
683
        char_t                  name[FNAMESIZE + 10];
684
 
685
        gsprintf(name, T("%s:%d"), B_ARGS);
686
 
687
        bStats[q].alloc++;
688
        bStats[q].inuse++;
689
        bStatsMemInUse += size;
690
        if (bStatsMemInUse > bStatsMemMax) {
691
                bStatsMemMax = bStatsMemInUse;
692
        }
693
        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
694
        bStatsBallocInUse += memSize;
695
        if (bStatsBallocInUse > bStatsBallocMax) {
696
                bStatsBallocMax = bStatsBallocInUse;
697
        }
698
 
699
/*
700
 *      Track maximum stack usage. Assumes a stack growth down. Approximate as
701
 *      we only measure this on block allocation.
702
 */
703
        if ((void*) &file < bStackMin) {
704
                bStackMin = (void*) &file;
705
        }
706
 
707
/*
708
 *      Find the file and adjust the stats for this file
709
 */
710
        for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) {
711
                if (fp->file[0] == file[0] && gstrcmp(fp->file, name) == 0) {
712
                        fp->allocated += size;
713
                        fp->count++;
714
                        fp->times++;
715
                        if (fp->largest < size) {
716
                                fp->largest = size;
717
                                fp->q = q;
718
                        }
719
                        break;
720
                }
721
        }
722
 
723
/*
724
 *      New entry: find the first free slot and create a new entry
725
 */
726
        if (fp >= &bStatsFiles[bStatsFilesMax]) {
727
                for (fp = bStatsFiles; fp < &bStatsFiles[B_MAX_FILES]; fp++) {
728
                        if (fp->file[0] == '\0') {
729
                                gstrncpy(fp->file, name, TSZ(fp->file));
730
                                fp->allocated += size;
731
                                fp->count++;
732
                                fp->times++;
733
                                fp->largest = size;
734
                                fp->q = q;
735
                                if ((fp - bStatsFiles) >= bStatsFilesMax) {
736
                                        bStatsFilesMax = (fp - bStatsFiles) + 1;
737
                                }
738
                                break;
739
                        }
740
                }
741
        }
742
 
743
/*
744
 *      Update the per block stats. Allocate a new slot.
745
 */
746
        for (bp = bStatsBlks; bp < &bStatsBlks[B_MAX_BLOCKS]; bp++) {
747
                if (bp->ptr == NULL) {
748
                        bp->ptr = ptr;
749
                        bp->who = fp;
750
                        if ((bp - bStatsBlks) >= bStatsBlksMax) {
751
                                bStatsBlksMax = (bp - bStatsBlks) + 1;
752
                        }
753
                        break;
754
                }
755
        }
756
}
757
 
758
/******************************************************************************/
759
/*
760
 *      Free statistics
761
 */
762
 
763
static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size)
764
{
765
        int                             memSize;
766
        bStatsFileType  *fp;
767
        bStatsBlkType   *bp;
768
 
769
        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
770
        bStatsMemInUse -= size;
771
        bStatsBallocInUse -= memSize;
772
        bStats[q].inuse--;
773
 
774
/*
775
 *      Update the per block stats. Try from the end first
776
 */
777
        for (bp = &bStatsBlks[bStatsBlksMax - 1]; bp >= bStatsBlks; bp--) {
778
                if (bp->ptr == ptr) {
779
                        bp->ptr = NULL;
780
                        fp = bp->who;
781
                        bp->who = NULL;
782
                        fp->allocated -= size;
783
                        fp->count--;
784
                        return;
785
                }
786
        }
787
}
788
 
789
/******************************************************************************/
790
/*
791
 *      Default output function. Just send to trace channel.
792
 */
793
 
794
#undef sprintf
795
static void bstatsWrite(int handle, char_t *fmt, ...)
796
{
797
        va_list         args;
798
        char_t          buf[BUF_MAX];
799
 
800
        va_start(args, fmt);
801
        vsprintf(buf, fmt, args);
802
        va_end(args);
803
        traceRaw(buf);
804
}
805
 
806
 
807
#else /* not B_STATS */
808
/******************************************************************************/
809
/*
810
 *      Dummy bstats for external calls that aren't protected by #if B_STATS.
811
 */
812
 
813
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
814
{
815
}
816
#endif /* B_STATS */
817
 
818
/******************************************************************************/
819
#if B_VERIFY_CAUSES_SEVERE_OVERHEAD
820
/*
821
 *      The following routines verify the integrity of the balloc memory space.
822
 *      These functions use the B_FILL feature.  Corruption is defined
823
 *      as bad integrity flags in allocated blocks or data other than B_FILL_CHAR
824
 *      being found anywhere in the space which is unallocated and that is not a
825
 *      next pointer in the free queues. a_assert is called if any corruption is
826
 *      found.  CAUTION:  These functions add severe processing overhead and should
827
 *      only be used when searching for a tough corruption problem.
828
 */
829
 
830
/******************************************************************************/
831
/*
832
 *      verifyUsedBlock verifies that a block which was previously allocated is
833
 *      still uncorrupted.
834
 */
835
 
836
static void verifyUsedBlock(bType *bp, int q)
837
{
838
        int             memSize, size;
839
        char    *p;
840
 
841
        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
842
        a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY);
843
        size = bp->u.size;
844
        for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) {
845
                a_assert(*p == B_FILL_CHAR);
846
        }
847
}
848
 
849
/******************************************************************************/
850
/*
851
 *      verifyFreeBlock verifies that a previously free'd block in one of the queues
852
 *      is still uncorrupted.
853
 */
854
 
855
static void verifyFreeBlock(bType *bp, int q)
856
{
857
        int             memSize;
858
        char    *p;
859
 
860
        memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
861
        for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) {
862
                a_assert(*p == B_FILL_CHAR);
863
        }
864
        bp = (bType *)p;
865
        a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY ||
866
                bp->flags == B_FILL_WORD);
867
}
868
 
869
/******************************************************************************/
870
/*
871
 *      verifyBallocSpace reads through the entire balloc memory space and
872
 *      verifies that all allocated blocks are uncorrupted and that, with the
873
 *      exception of free list next pointers, all other unallocated space is
874
 *      filled with B_FILL_CHAR.
875
 */
876
 
877
void verifyBallocSpace()
878
{
879
        int             q;
880
        char    *p;
881
        bType   *bp;
882
 
883
/*
884
 *      First verify all the free blocks.
885
 */
886
        for (q = 0; q < B_MAX_CLASS; q++) {
887
                for (bp = bQhead[q]; bp != NULL; bp = bp->u.next) {
888
                        verifyFreeBlock(bp, q);
889
                }
890
        }
891
 
892
/*
893
 *      Now verify other space
894
 */
895
        p = bFreeBuf;
896
        while (p < (bFreeBuf + bFreeSize)) {
897
                bp = (bType *)p;
898
                if (bp->u.size > 0xFFFFF) {
899
                        p += sizeof(bp->u);
900
                        while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
901
                                p++;
902
                        }
903
                } else {
904
                        a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) ||
905
                                bp->flags == B_FILL_WORD);
906
                        p += (sizeof(bType) + bp->u.size);
907
                        while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
908
                                p++;
909
                        }
910
                }
911
        }
912
}
913
#endif /* B_VERIFY_CAUSES_SEVERE_OVERHEAD */
914
 
915
/******************************************************************************/
916
 
917
#else /* NO_BALLOC */
918
int bopen(void *buf, int bufsize, int flags)
919
{
920
        return 0;
921
}
922
 
923
/******************************************************************************/
924
 
925
void bclose()
926
{
927
}
928
 
929
/******************************************************************************/
930
 
931
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
932
{
933
}
934
 
935
/******************************************************************************/
936
 
937
char_t *bstrdupNoBalloc(char_t *s)
938
{
939
#if UNICODE
940
        if (s) {
941
                return wcsdup(s);
942
        } else {
943
                return wcsdup(T(""));
944
        }
945
#else
946
        return bstrdupANoBalloc(s);
947
#endif
948
}
949
 
950
/******************************************************************************/
951
 
952
char *bstrdupANoBalloc(char *s)
953
{
954
        char*   buf;
955
 
956
        if (s == NULL) {
957
                s = "";
958
        }
959
        buf = malloc(strlen(s)+1);
960
        strcpy(buf, s);
961
        return buf;
962
}
963
 
964
#endif /* NO_BALLOC */
965
/******************************************************************************/
966
 

powered by: WebSVN 2.1.0

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