source: svn/trunk/newcon3bcm2_21bu/dta/src/bcmmemmgr.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 29.8 KB
Line 
1/***************************************************************
2**
3**  Broadcom Corp. Confidential
4**  Copyright 1998-2000 Broadcom Corp.  All Rights Reserved.
5**
6**  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
7**  SOFTWARE LICENSE AGREEMENT  BETWEEN THE USER AND BROADCOM.
8**  YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
9**  SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
10**
11**  File:         bcmMemMgr.c
12**  Description:  Broadcom Hardware Device Memory Manager
13**  Created:      03/14/00 Jeffrey Fisher
14**
15**  REVISION:
16**
17**  $Log: bcmmemmgr.c,v $
18**  Revision 1.1.1.1  2003/11/21 18:44:37  root
19**  Initial DP922 Checkin
20**
21**
22**
23****************************************************************/
24#include "bcmmemmgr.h"
25#include "ministd.h"
26
27#ifndef BSTD_INLINE
28#define BSTD_INLINE inline
29#endif
30
31#ifdef BCM_DEBUG
32/* Warn everyone that by default memory checker is disabled even in debug build */
33/* TODO  Remove in warning in production environment. */
34#warning "RUNTIME MEMORY DEBUG TURNED OFF, makes UI software slow, define MEM_DEBUG to enable."
35//#define MEM_DEBUG
36#endif
37
38/* heap chunk */
39struct bcm_chunk_t
40{
41#ifdef MEM_DEBUG
42        unsigned long           sig[MEM_SIGLEN];/* a pattern to help catch corruption bugs */
43#endif
44#ifdef BCM_DEBUG
45        char                            file[MEM_MAX_FILENAME];
46        int                                     line;
47#endif
48        unsigned long           padding;        /* number of bytes to pad the buffer to achieve proper alignment */
49        unsigned long           size;           /* number of bytes allocated to the chunk including header and pad */
50        struct bcm_chunk_t      *prev;          /* reference to previous free chunk */
51        struct bcm_chunk_t      *next;          /* reference to next free chunk */
52};
53
54#ifdef MEM_DEBUG
55        #define kGuardBandLength 16
56#else
57        #define kGuardBandLength 0
58#endif
59
60/* Memory manager uses critical sections, TODO  implement OS Specific version */
61#if 0
62        #include "ucos.h"
63        static unsigned int critical_flags = 0;
64        static int in_critical = 0;
65        void bcmKNIEnterCriticalSection(void)
66        {
67                if (in_critical > 0)
68                {
69                        BDBG_MSG(("NESTED CRITICAL SECTION NOT ALLOWED\n"));
70                        return;
71                }
72                OS_ENTER_CRITICAL(critical_flags);
73                in_critical++;
74        }
75        void bcmKNILeaveCriticalSection(void)
76        {
77                if (--in_critical != 0)
78                {
79                        BDBG_MSG(("NESTED CRITICAL SECTION NOT ALLOWED\n"));
80                        return;
81                }
82                OS_EXIT_CRITICAL(critical_flags);
83        }
84#else
85#if (BCHP_CHIP!=7550) &&  (BCHP_CHIP!=7552)
86        #define bcmKNIEnterCriticalSection()    {unsigned critical_flags = bos_enter_critical();
87        #define bcmKNILeaveCriticalSection()    bos_exit_critical(critical_flags);}
88#else
89        #define bcmKNIEnterCriticalSection()    ((void)0)
90        #define bcmKNILeaveCriticalSection()    ((void)0)
91#endif
92#endif
93
94/*-----------------------------------------------------------------------------
95 - PRIVATE FUNCTIONS
96 -----------------------------------------------------------------------------*/
97#if 0
98static char mem_chkoverlap(bcm_heap_t *p_heap);
99static void* chunk_to_pointer(bcm_chunk_t *p_chunk );
100static bcm_chunk_t* pointer_to_chunk(void *p_ptr );
101static bcm_chunk_t * heap_getfree(bcm_heap_t *p_heap,unsigned long numbytes, char alignbits );
102static bcm_chunk_t * heap_newchunk(bcm_heap_t *p_heap,
103                                                                   unsigned long numbytes, char alignbits );
104static char contiguous(bcm_chunk_t * chunk1,bcm_chunk_t * chunk2);
105static void heap_deletechunk(bcm_heap_t *p_heap,bcm_chunk_t *p_chunk);
106#endif
107
108/**
109* Until there's a programmatic way to set level for a message in
110* brcm_dbg.h, BRCM_DBG_XXX will have to do. You can also define HACK_BRCM_DEBUG
111* to get memory debugging output without having BRCM_DEBUG turned on.
112*/
113#ifdef BCM_DEBUG
114
115        #define kBrcmDbgOutputMsg 0
116        #define kBrcmDbgOutputWrn 1
117        #define kBrcmDbgOutputErr 2
118        static const int debugOutputLevel = kBrcmDbgOutputWrn;
119       
120        #define BRCM_DBG_ERR(ARGS)      printf ARGS
121        #define BRCM_DBG_WRN(ARGS)      printf ARGS
122        #define BRCM_DBG_MSG(ARGS)      printf ARGS
123       
124       
125        #define BRCM_DBG_XXX(LEVEL,ARGS) \
126                ((LEVEL)==kBrcmDbgOutputErr?BRCM_DBG_ERR(ARGS): \
127                 (LEVEL)==kBrcmDbgOutputWrn?BRCM_DBG_WRN(ARGS): \
128                 BRCM_DBG_MSG(ARGS))
129                 
130        #define chunk_info_err(CHUNK) chunk_info(CHUNK, kBrcmDbgOutputErr)
131       
132        #define chunk_info_wrn(CHUNK) chunk_info(CHUNK, kBrcmDbgOutputWrn)
133       
134        #define chunk_info_msg(CHUNK) chunk_info(CHUNK, kBrcmDbgOutputMsg)
135#else
136
137        #define BRCM_DBG_ERR(ARGS)      ((void)0)
138        #define BRCM_DBG_WRN(ARGS)      ((void)0)
139        #define BRCM_DBG_MSG(ARGS)      ((void)0)
140        #define BRCM_DBG_XXX(LEVEL,ARGS)        ((void)0)
141
142#endif
143
144/******************************************************************************
145* void* chunk_to_pointer(bcm_chunk_t *p_chunk )
146*
147* INPUTS:       p_chunk = chunk reference
148* OUTPUTS:      None.
149* RETURNS:      return the payload pointer
150* FUNCTION: convert a chunk to a pointer
151******************************************************************************/
152BSTD_INLINE void* chunk_to_pointer(bcm_chunk_t *p_chunk )
153{
154        return(void*)(((unsigned long)p_chunk) + sizeof(bcm_chunk_t));
155}
156/******************************************************************************
157* bcm_chunk_t* pointer_to_chunk(void *p_ptr )
158*
159* INPUTS:       p_ptr = pointer to chunk payload
160* OUTPUTS:      None.
161* RETURNS:      return the chunk pointer
162* FUNCTION: convert a pointer to a chunk reference (always in cached space)
163******************************************************************************/
164BSTD_INLINE bcm_chunk_t* pointer_to_chunk(void *p_ptr )
165{
166        return(bcm_chunk_t*)((((unsigned long)p_ptr) - sizeof(bcm_chunk_t))&~0x20000000);
167}
168
169/******************************************************************************
170* void chunk_info(bcm_chunk_t *p_chunk, int debugoutputlevel)
171*
172* INPUTS:       p_chunk = chunk reference
173* OUTPUTS:      None.
174* RETURNS:      none
175* FUNCTION: Print chunk members to debug output
176******************************************************************************/
177static void chunk_info(bcm_chunk_t *p_chunk, int debugOutputLevel)
178{
179        BRCM_DBG_XXX(debugOutputLevel, ("Chunk: 0x%p(ptr = 0x%p)\n",p_chunk,chunk_to_pointer(p_chunk)));
180        if(p_chunk == NULL)
181                return;
182
183#ifdef MEM_DEBUG
184        BRCM_DBG_XXX(debugOutputLevel, (" %s:%d\n",p_chunk->file,p_chunk->line));
185        {
186                int i;
187                for (i = 0; i < MEM_SIGLEN; ++i)
188                {
189                        BRCM_DBG_XXX(debugOutputLevel, (" 0x%08lx\n",p_chunk->sig[i]));
190                }
191        }
192#endif
193        BRCM_DBG_XXX(debugOutputLevel, (" %ld\n",p_chunk->padding));
194        BRCM_DBG_XXX(debugOutputLevel, (" %ld\n",p_chunk->size));
195        BRCM_DBG_XXX(debugOutputLevel, (" 0x%p\n",p_chunk->next));
196        BRCM_DBG_XXX(debugOutputLevel, (" 0x%p\n",p_chunk->prev));
197}
198
199/******************************************************************************
200* void fillguardband(bcm_chunk_t *p_chunk )
201*
202* INPUTS:       p_chunk = chunk reference
203* OUTPUTS:      None.
204* RETURNS:      none
205* FUNCTION: fill in the guard band for the chunk
206******************************************************************************/
207#ifdef BCM_DEBUG
208
209static const unsigned long signature = 0xDEADBEEF;
210static const unsigned long free_signature = 0xB00BB00B;
211BSTD_INLINE void fillguardband(bcm_chunk_t *p_chunk)
212{
213#ifdef MEM_DEBUG
214        unsigned long *ptr;
215        unsigned long i;
216
217        ptr = (unsigned long*) (((unsigned long)p_chunk) + p_chunk->size - p_chunk->padding);
218        for (i = 0; i < p_chunk->padding/4; ++i)
219        {
220                ptr[i] = signature;
221        }
222#endif /* MEM_DEBUG */
223
224}
225/******************************************************************************
226* char checksignature(bcm_chunk_t *p_chunk)
227*
228* INPUTS:       p_chunk = chunk reference
229* OUTPUTS:      None.
230* RETURNS:      none-zero if signature is ok, zero if there is a problem
231* FUNCTION: Validate the signature.
232******************************************************************************/
233static char checksignature(bcm_chunk_t *p_chunk, int isfree)
234{
235#ifdef MEM_DEBUG
236        int i;
237        for (i = 0; i < MEM_SIGLEN; ++i)
238        {
239                if (p_chunk->sig[i] != (isfree ? free_signature : signature))
240                {
241                        BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID\n"));
242                        chunk_info_err(p_chunk);
243                        BRCM_DBG_ERR(("POSSIBLE CULPRIT p_chunk->prev = 0x%p\n",p_chunk->prev));
244                        chunk_info_err(p_chunk->prev);
245                        return 0;
246                }
247        }
248#endif /* MEM_DEBUG */
249        return 1;
250}
251
252/******************************************************************************
253* char validateguardband(bcm_chunk_t *p_chunk)
254*
255* INPUTS:       p_chunk = chunk reference
256* OUTPUTS:      None.
257* RETURNS:      none-zero if guard band is ok, zero if there is a problem
258* FUNCTION: Validate the guard band.
259******************************************************************************/
260static char validateguardband(bcm_chunk_t *p_chunk)
261{
262#ifdef MEM_DEBUG
263        unsigned long *ptr;
264        unsigned long i;
265        char result;
266        if (!checksignature(p_chunk,0))
267        {
268                BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID validateguardband p_chunk->prev = 0x%p\n",p_chunk->prev));
269                if (p_chunk->prev)
270                {
271                        if (validateguardband(p_chunk->prev) == 0)
272                        {
273                                BRCM_DBG_ERR(("POSSIBLE CULPRIT p_chunk->prev = 0x%p\n",p_chunk->prev));
274                                chunk_info_err(p_chunk->prev);
275                        }
276                }
277                return 0;
278        }
279
280        ptr = (unsigned long*) (((unsigned long)p_chunk) + p_chunk->size - p_chunk->padding);
281        result = 1;
282        for (i = 0; i < p_chunk->padding/4; ++i)
283        {
284                if (ptr[i] != signature)
285                {
286                        BRCM_DBG_MSG((" 0x%08lx\n",ptr[i]));
287/*                      if ((((i + 1) % 4) == 0) && (i != 0))
288                                BRCM_DBG_MSG(("\n\n"));*/
289                        result = 0;
290                }
291        }
292/*      if (result == 0)
293                BRCM_DBG_MSG(("\n\n")); */
294        return result;
295#else /* MEM_DEBUG */
296        return 1;
297#endif /* MEM_DEBUG */
298}
299#endif /* BCM_DEBUG */
300
301
302/******************************************************************************
303* bcm_chunk_t * heap_getfree(bcm_heap_t *p_heap,unsigned long isize)
304*
305* INPUTS:       p_heap = reference to a heap structure
306*                       numbytes = size of chunk payload
307*                       alignbits = playload must be aligned to start on alignbits boundry
308* OUTPUTS:      None.
309* RETURNS:      reference to the free chunk
310* FUNCTION: scan the heap looking for a free chunk with enough space
311******************************************************************************/
312BSTD_INLINE bcm_chunk_t * heap_getfree(bcm_heap_t *p_heap,unsigned long numbytes, char alignbits )
313{
314        bcm_chunk_t * chunk = p_heap->last_free;
315        unsigned long offs = (1L << alignbits);
316        unsigned long mask = offs - 1;
317        unsigned long val,nval,pad;
318
319
320        while (chunk != 0L)
321        {
322                val = ((unsigned long)chunk) + chunk->size - numbytes - kGuardBandLength;
323
324                /* pointer is not aligned so calculate a pad */
325                if (val & mask)
326                {
327                        nval = val & ~(mask);
328                        pad     = val - nval;
329                }
330                else
331                        pad     = 0;
332
333                val = ((unsigned long)chunk) + chunk->size - numbytes - kGuardBandLength - pad;
334
335                if (val & mask)
336                {
337                        BRCM_DBG_ERR(("PTR Not aligned properly \n"));
338                }
339
340                /* if the chunk is large enough return */
341                val = (numbytes + pad + sizeof(bcm_chunk_t) + kGuardBandLength);
342                if (val < chunk->size)
343                {
344                        if ((val + sizeof(bcm_chunk_t)) > chunk->size) /* the free chunk can not be split */
345                        {
346                                if (((unsigned long)chunk_to_pointer(chunk)) & mask)
347                                {
348                                        chunk = chunk->prev;
349                                        continue; /* the chunk would not result in an aligned pointer */
350                                }
351                        }
352                        chunk->padding = pad + kGuardBandLength;
353                        return chunk;
354                }
355                chunk = chunk->prev;
356        }
357
358        return 0L;
359}
360
361/******************************************************************************
362* void append_alloced(bcm_heap_t *p_heap,bcm_chunk_t * p_chunk)
363*
364* INPUTS:       p_heap = reference to a heap structure
365*                       p_chunk = chunk to add to alloced list
366* OUTPUTS:      None.
367* RETURNS:      None
368* FUNCTION: Append the chunk to the list of allocated chunks
369******************************************************************************/
370BSTD_INLINE void append_alloced(bcm_heap_t *p_heap,bcm_chunk_t * p_chunk)
371{
372        p_chunk->next = 0L;
373        p_chunk->prev = 0L;
374        if (p_heap->last == 0L)
375        {
376                p_heap->first = p_chunk;
377                p_heap->last = p_chunk;
378        }
379        else
380        {
381                p_heap->last->next = p_chunk;
382                p_chunk->prev = p_heap->last;
383                p_heap->last = p_chunk;
384        }
385#ifdef MEM_DEBUG
386        {
387                int i;
388                for (i = 0; i < MEM_SIGLEN; ++i)
389                        p_chunk->sig[i] = signature;
390        }
391#endif
392#ifdef BCM_DEBUG
393        p_chunk->file[0] = 0;
394        p_chunk->line = 0;
395#endif
396}
397
398/******************************************************************************
399* void delete_alloced(bcm_heap_t *p_heap,bcm_chunk_t * p_chunk)
400*
401* INPUTS:       p_heap = reference to a heap structure
402*                       p_chunk = chunk to delete from alloced list
403* OUTPUTS:      None.
404* RETURNS:      None
405* FUNCTION: Delete the chunk from the list of allocated chunks
406******************************************************************************/
407BSTD_INLINE void delete_alloced(bcm_heap_t *p_heap,bcm_chunk_t * p_chunk)
408{
409        if (p_chunk == p_heap->first)
410        {
411                if (p_chunk->next == 0L)
412                {
413                        p_heap->last = 0L;
414                        p_heap->first = 0L;
415                }
416                else
417                {
418                        p_heap->first = p_chunk->next;
419                        p_heap->first->prev = 0L;
420                }
421        }
422        else
423        {
424                if (p_chunk == p_heap->last)
425                {
426                        p_chunk->prev->next = 0L;
427                        p_heap->last = p_chunk->prev;
428                }
429                else
430                {
431                        p_chunk->next->prev = p_chunk->prev;
432                        p_chunk->prev->next = p_chunk->next;
433                }
434        }
435        p_chunk->next = 0L;
436        p_chunk->prev = 0L;
437#ifdef MEM_DEBUG
438        /* write a new pattern where the chunk was to insure the chunk will not be freed again */
439        {
440                int i;
441                for (i = 0; i < MEM_SIGLEN; ++i)
442                        p_chunk->sig[i] = free_signature;
443        }
444#endif
445}
446
447/******************************************************************************
448* bcm_chunk_t * heap_newchunk(bcm_heap_t *p_heap, unsigned long numbytes )
449*
450* INPUTS:       p_heap = reference to a heap structure
451*                       numbytes = number of bytes in chunk payload
452*                       alignbits = playload must be aligned to start on alignbits boundry
453* OUTPUTS:      None.
454* RETURNS:      reference to the new chunks
455* FUNCTION: allocate a new chunk from the elements in the free list
456******************************************************************************/
457BSTD_INLINE bcm_chunk_t * heap_newchunk(bcm_heap_t *p_heap,
458                                                                   unsigned long numbytes, char alignbits )
459{
460        unsigned long unusedBytes,chunkSize;
461    unsigned long free_size;
462        bcm_chunk_t * freeChunk, *newChunk;
463   
464    free_size = 0;
465        while (1)
466        {
467                freeChunk = heap_getfree(p_heap, numbytes, alignbits);
468
469                if (freeChunk != 0L)    /* if a large enough free chunk was found */
470                {
471                        newChunk = 0L;
472
473                        chunkSize = numbytes + freeChunk->padding + sizeof(bcm_chunk_t);
474
475                        unusedBytes = freeChunk->size - chunkSize;
476
477                        if (sizeof(bcm_chunk_t) <= unusedBytes) /* split the free chunk */
478                        {
479                                freeChunk->size -= chunkSize;
480#ifdef MEM_DEBUG
481                                {
482                                        int i;
483                                        for (i = 0; i < MEM_SIGLEN; ++i)
484                                                freeChunk->sig[i] = free_signature;
485                                }
486#endif
487#ifdef BCM_DEBUG
488                                freeChunk->file[0] = 0;
489                                freeChunk->line = 0;
490#endif
491                                newChunk = (bcm_chunk_t*)(((unsigned long)freeChunk) + freeChunk->size);
492
493                                newChunk->size = chunkSize;
494                                newChunk->padding = freeChunk->padding;
495                        }
496                        else /* use the free chunk without splitting it apart */
497                        {
498                                if (freeChunk->prev) /* if this is not the first chunk */
499                                {
500                                        freeChunk->prev->next = freeChunk->next;
501                                }
502                                else
503                                        p_heap->first_free = freeChunk->next;
504
505                                if (freeChunk->next) /* if this is not the last chunk */
506                                {
507                                        freeChunk->next->prev = freeChunk->prev;
508                                }
509                                else
510                                        p_heap->last_free       = freeChunk->prev;
511
512                                newChunk = freeChunk;
513                        }
514
515                        append_alloced(p_heap,newChunk);
516
517                        return newChunk;
518                }
519                else /* there is not a chunk big enough */
520                {
521                        return(bcm_chunk_t *)0L;
522                }
523        }
524        return(bcm_chunk_t *)0L;
525}
526
527/******************************************************************************
528* char contiguous(bcm_chunk_t * chunk1,bcm_chunk_t * chunk2)
529*
530* INPUTS:       chunk1 = first chunck
531*                       chunk2 = second chunk
532* OUTPUTS:      None.
533* RETURNS:      non-zero if the chunks are contiguous
534* FUNCTION: determine that chunks are contiguous
535******************************************************************************/
536static char contiguous(bcm_chunk_t * chunk1,bcm_chunk_t * chunk2)
537{
538        if (chunk1 < chunk2)
539        {
540                chunk1 = (bcm_chunk_t *) (((unsigned long)chunk1) + chunk1->size);
541        }
542        else
543        {
544                chunk2  = (bcm_chunk_t *) (((unsigned long)chunk2) + chunk2->size);
545        }
546
547        return(char)(chunk1 == chunk2);
548}
549/******************************************************************************
550* void heap_deletechunk(bcm_heap_t *p_heap,bcm_chunk_t *p_chunk)
551*
552* INPUTS:       p_heap = reference to a heap structure
553*                       p_chunk = chunk to delete
554* OUTPUTS:      None.
555* RETURNS:      none
556* FUNCTION: Delete the chunk and return the chunk to the free list
557******************************************************************************/
558
559BSTD_INLINE void heap_deletechunk(bcm_heap_t *p_heap,bcm_chunk_t *p_chunk)
560{
561        bcm_chunk_t * freeChunk, *next, *prev;
562        freeChunk = (bcm_chunk_t *) p_chunk;
563
564        freeChunk->padding = 0;
565
566        delete_alloced(p_heap, freeChunk);
567
568        if (p_heap->first_free || p_heap->last_free)
569        {
570                next = p_heap->first_free;
571
572                while (next && next < freeChunk)
573                        next = next->next;
574
575                prev = next ? next->prev : p_heap->last_free;
576
577                freeChunk->prev = prev;
578
579                if (prev)
580                {
581                        if (contiguous(prev,freeChunk)) /* if contiguous merge into single chunk */
582                        {
583                                prev->size += freeChunk->size;
584                                freeChunk = prev;
585                        }
586                        else
587                                prev->next = freeChunk;
588                }
589                else
590                        p_heap->first_free = freeChunk;
591
592                freeChunk->next = next;
593
594                if (next)
595                {
596                        if (contiguous(freeChunk,next))
597                        {
598                                freeChunk->size += next->size;
599
600                                freeChunk->next = next->next;
601
602                                if (freeChunk->next)
603                                {
604                                        freeChunk->next->prev = freeChunk;
605                                }
606                                else
607                                        p_heap->last_free = freeChunk;
608                        }
609                        else
610                                next->prev = freeChunk;
611                }
612                else
613                        p_heap->last_free = freeChunk;
614        }
615        else /* free list is empty */
616        {
617                freeChunk->next = 0L;
618                freeChunk->prev = 0L;
619
620                p_heap->first_free = p_heap->last_free = freeChunk;
621        }
622}
623
624/******************************************************************************
625* void heap_init(bcm_heap_t *p_heap,unsigned long *p_buf,unsigned long numbytes)
626*
627* INPUTS:       p_heap = reference to a heap structure to initialize
628*                       p_buf = memory address to manage
629*                       numbytes = number of bytes starting at p_buf to manage
630* OUTPUTS:      None.
631* RETURNS:      None
632* FUNCTION: This function allocates and initializes a bcm_heap_t structure.  p_buf
633*                       should be on a granularity boundry.
634******************************************************************************/
635void  heap_init(bcm_heap_t *p_heap, unsigned long *p_buf,
636                                unsigned long numbytes)
637{
638        p_heap->start_addr = p_buf;
639        p_heap->end_addr = (bcm_chunk_t*)(((unsigned long)p_buf) + numbytes);
640
641        p_heap->last_free = (bcm_chunk_t*)p_buf; /* allocate chunk in heap buffer */
642        p_heap->first_free = p_heap->last_free;
643
644#ifdef MEM_DEBUG
645        {
646                int i;
647                for (i = 0; i < MEM_SIGLEN; ++i)
648                        p_heap->first_free->sig[i] = free_signature;
649                p_heap->first_free->file[0] = 0;
650                p_heap->first_free->line = 0;
651        }
652#endif
653        p_heap->first_free->padding = 0;
654        p_heap->first_free->size    = numbytes;
655
656        p_heap->first_free->next = 0L;
657        p_heap->first_free->prev = 0L;
658}
659/******************************************************************************
660* unsigned long mem_available(bcm_heap_t *p_heap)
661*
662* INPUTS:       p_heap = reference to a heap structure to initialize
663* OUTPUTS:      None.
664* RETURNS:      largest free chunk
665* FUNCTION: Find the larget free chunk available.
666******************************************************************************/
667unsigned long mem_available(bcm_heap_t *p_heap)
668{
669        bcm_chunk_t * chunk = 0L;
670        unsigned long size = 0;
671
672        bcmKNIEnterCriticalSection();
673        for (chunk = p_heap->first_free ; chunk ; chunk = chunk->next)
674        {
675#ifdef MEM_DEBUG
676                if (!checksignature(chunk,1))
677                {
678                        BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_available\n"));
679                        return 0;
680                }
681#endif
682                if (chunk->size > size)
683                {
684                        size = chunk->size;
685                }
686        }
687        bcmKNILeaveCriticalSection();
688        return size - sizeof(bcm_chunk_t);
689}
690
691/******************************************************************************
692* void * mem_alloc(bcm_heap_t* p_heap, unsigned long size)
693*
694* INPUTS:       p_heap = reference to a heap structure to initialize
695*                       size = playload size
696*                       alignbits = playload must be aligned to start on alignbits boundry
697* OUTPUTS:      None.
698* RETURNS:      largest free chunk
699* FUNCTION: Find the larget free chunk available.
700******************************************************************************/
701void * mem_tagalloc(bcm_heap_t* p_heap, unsigned long size, char alignbits, char* file, int line)
702{
703        bcm_chunk_t *chunk;
704        unsigned long * ptr = 0L;
705
706        bcmKNIEnterCriticalSection();
707        chunk = heap_newchunk(p_heap,size,alignbits);
708
709
710        if (chunk)
711        {
712                ptr = (unsigned long*)chunk_to_pointer(chunk);
713
714#ifdef BCM_DEBUG
715                if (file)
716                {
717                        /* if it doesn't fit, chop off the beginning which
718                        usually contains unhelpful path information */
719                        int len = strlen(file);
720                        if (len > MEM_MAX_FILENAME-1)
721                                file = file + len - (MEM_MAX_FILENAME-1);
722                        memcpy(chunk->file,file,MEM_MAX_FILENAME-1);
723                        chunk->file[MEM_MAX_FILENAME-1] = '\0';
724                }
725                else
726                        chunk->file[0] = 0;
727                chunk->line = line;
728
729#endif
730#ifdef MEM_DEBUG
731                fillguardband(chunk);
732#endif
733        }
734
735        bcmKNILeaveCriticalSection();
736#ifdef MEM_DEBUG
737        if (chunk && file) {
738                mem_validate(p_heap);
739        }
740#endif
741        return ptr;
742}
743
744/******************************************************************************
745* void mem_tagfree(bcm_heap_t* p_heap, void* p_ref, char *file, int line)
746*
747* INPUTS:       p_heap = reference to a heap structure to initialize
748*                       p_ref = ptr to memory to be freed
749*                       file = file of calling code (__FILE__)
750*                       line = line of calling code (__LINE__)
751* OUTPUTS:      None.
752* RETURNS:      largest free chunk
753* FUNCTION: Frees memory allocated by mem_tagalloc()
754******************************************************************************/
755void mem_tagfree(bcm_heap_t* p_heap, void* p_ref, char *file, int line)
756{
757        bcm_chunk_t * chunk = 0L;
758        if (p_ref == 0L)
759                return;
760
761        chunk = pointer_to_chunk(p_ref);
762
763#ifdef MEM_DEBUG
764        if (!checksignature(chunk,0))
765        {
766                BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_free\n"));
767                return;
768        }
769#endif
770        bcmKNIEnterCriticalSection();
771        heap_deletechunk(p_heap,chunk);
772        bcmKNILeaveCriticalSection();
773#ifdef MEM_DEBUG
774        /* need to validate after a free */
775        if (!mem_validate(p_heap))
776                BRCM_DBG_ERR(("mem_tagfree error: %s, line %d\n", file, line));
777#endif
778}
779
780/******************************************************************************
781* void mem_report(bcm_heap_t *p_heap)
782*
783* INPUTS:       p_heap = reference to a heap structure to initialize
784* OUTPUTS:      None.
785* RETURNS:      None
786* FUNCTION: Ouput a debug report describing the heap.
787******************************************************************************/
788
789#ifdef BCM_DEBUG
790
791void mem_report(bcm_heap_t *p_heap)
792{
793        bcm_chunk_t * chunk = 0L;
794        unsigned long size = 0;
795
796        for (chunk = p_heap->first ; chunk ; chunk = chunk->next)
797        {
798                if (!checksignature(chunk,0))
799                {
800                        BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_report alloced\n"));
801                        return;
802                }
803                BRCM_DBG_MSG(("\n <<<<< Alloced Chunk\n"));
804                chunk_info_msg(chunk);
805                size += chunk->size;
806        }
807        BRCM_DBG_MSG(("\nTotal Alloced Size = %ld\n",size));
808        size = 0;
809
810        for (chunk = p_heap->first_free ; chunk ; chunk = chunk->next)
811        {
812                if (!checksignature(chunk,1))
813                {
814                        BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_report free\n"));
815                        return;
816                }
817                BRCM_DBG_MSG(("\n<<<<< Free Chunk\n"));
818                chunk_info_msg(chunk);
819                size += chunk->size;
820        }
821        BRCM_DBG_MSG(("\nTotal Free Size = %ld\n",size));
822}
823
824void mem_reportbrief(bcm_heap_t *p_heap)
825{
826        bcm_chunk_t * chunk = 0L;
827        unsigned long size = 0;
828        mem_validate(p_heap);
829        BRCM_DBG_MSG(("Allocated chunks:\n"));
830        for (chunk = p_heap->first ; chunk ; chunk = chunk->next)
831        {
832                if (!checksignature(chunk,0))
833                {
834                        BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_report alloced\n"));
835                        return;
836                }
837                BRCM_DBG_MSG((" %s:%d\t\t%#x[%ld]\n",chunk->file,chunk->line,chunk_to_pointer(chunk),chunk->size));
838                size += chunk->size;
839        }
840        BRCM_DBG_MSG(("Total Alloced Size = %ld\n",size));
841        size = 0;
842
843        BRCM_DBG_MSG(("Free chunks:\n"));
844        for (chunk = p_heap->first_free ; chunk ; chunk = chunk->next)
845        {
846                if (!checksignature(chunk,1))
847                {
848                        BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_report free\n"));
849                        return;
850                }
851                BRCM_DBG_MSG((" %ld\n",chunk->size));
852                size += chunk->size;
853        }
854        BRCM_DBG_MSG(("Total Free Size = %ld\n",size));
855}
856
857/******************************************************************************
858* char mem_chkoverlap(bcm_heap_t *p_heap)
859*
860* INPUTS:       p_heap = reference to a heap structure to initialize
861* OUTPUTS:      None.
862* RETURNS:      returns non-zero if the guard bands are all valid, zero otherwise.
863* FUNCTION: Verify no allocation chunk overlaps another.
864******************************************************************************/
865BSTD_INLINE char mem_chkoverlap(bcm_heap_t *p_heap)
866{
867        bcm_chunk_t * chunk = 0L;
868        bcm_chunk_t * ochunk = 0L;
869        unsigned long cstart,cend,ostart;
870
871        for (chunk = p_heap->first ; chunk ; chunk = chunk->next)
872        {
873                cstart = (unsigned long)chunk;
874                cend = cstart + chunk->size;
875                for (ochunk = p_heap->first ; ochunk ; ochunk = ochunk->next)
876                {
877                        ostart = (unsigned long)ochunk;
878                        if ((chunk != ochunk) && (ostart > cstart) && (ostart < cend))
879                        {
880                                BRCM_DBG_ERR(("\nChunks Overlap\n"));
881                                chunk_info_err(chunk);
882                                BRCM_DBG_ERR(("-------------\n"));
883                                chunk_info_err(ochunk);
884                                return 0;
885                        }
886                }
887        }
888        return 1;
889}
890
891/******************************************************************************
892* char mem_validate(bcm_heap_t *p_heap)
893*
894* INPUTS:       p_heap = reference to a heap structure to initialize
895* OUTPUTS:      None.
896* RETURNS:      returns non-zero if the guard bands are all valid, zero otherwise.
897* FUNCTION: Validate chunk guard bands.
898******************************************************************************/
899char mem_validate(bcm_heap_t *p_heap)
900{
901        char rc = 1;
902        bcm_chunk_t * chunk = 0L;
903
904        bcmKNIEnterCriticalSection();
905        for (chunk = p_heap->first ; chunk ; chunk = chunk->next)
906        {
907                if (validateguardband(chunk) == 0)
908                {
909                        /* Guard band has been overwritten */
910                        BRCM_DBG_ERR(("\nMemory guard band violated.\n"));
911                        chunk_info_err(chunk);
912                        rc = 0;
913                }
914        }
915        if (rc)
916                for (chunk = p_heap->first_free ; chunk ; chunk = chunk->next)
917                {
918                        if (!checksignature(chunk,1))
919                        {
920                                BRCM_DBG_ERR(("\nMemory guard band of free chunk violated.\n"));
921                                chunk_info_err(chunk);
922                                rc = 0;
923                        }
924                }
925        if (rc)
926                rc = mem_chkoverlap(p_heap);
927        bcmKNILeaveCriticalSection();
928        return rc;
929}
930
931
932/******************************************************************************
933* void mem_debug(bcm_heap_t *p_heap,unsigned char* buf,
934*                                       int width, int height, int bpp )
935*
936* INPUTS:       p_heap = reference to a heap structure to initialize
937*                       buf = display buffer to map memory into
938*                       width = number of pixels in a row
939*                       height = number of rows
940* OUTPUTS:      None.
941* RETURNS:      largest free chunk
942* FUNCTION: Map the memory into a 565 pixelmap (2 bytes per pixel).
943******************************************************************************/
944void mem_debug(bcm_heap_t *p_heap,unsigned char* buf,
945                           int width, int height )
946{
947        bcm_chunk_t * chunk = 0L;
948        int i,minoff,maxoff;
949        unsigned long size = ((unsigned long)p_heap->end_addr) - ((unsigned long)p_heap->start_addr);
950        unsigned long offset;
951        int bpp = (int)(size / (width * height)) + 1; /* bytes per pixel */
952
953        for (i = 0; i < (width * height); ++i)
954                ((unsigned short*)buf)[i] = 0x001F;
955
956        for (chunk = p_heap->first ; chunk ; chunk = chunk->next)
957        {
958
959                offset = ((unsigned long)chunk) - ((unsigned long)(p_heap->start_addr));
960
961                minoff = (offset/bpp);
962                maxoff = minoff + chunk->size/bpp;
963
964                if (minoff > width * height)
965                        break;
966                if (maxoff > width * height)
967                        maxoff = width * height;
968
969                /* paint the allocated chunks */
970                for (i = minoff; i < (int)maxoff; ++i)
971                {
972                        ((unsigned short*)buf)[i] = 0xF800;
973                }
974
975                offset = ((unsigned long)chunk) - ((unsigned long)(p_heap->start_addr));
976                offset += chunk->padding;
977
978                minoff = (offset/bpp);
979                maxoff = minoff + chunk->padding/bpp;
980
981                if (minoff > width * height)
982                        break;
983                if (maxoff > width * height)
984                        maxoff = width * height;
985
986                /* paint the padding */
987                for (i = minoff; i < (int)maxoff; ++i)
988                {
989
990                        ((unsigned short*)buf)[i] = 0x7e0;
991                }
992        }
993}
994
995#if SUPPORT_DST_PLATFORM        /*from CB3*/
996/*
997        return zero if no error.
998        return err value if heap is not valid or damaged.
999*/
1000int mem_status(bcm_heap_t *p_heap, struct bcm_heap_status *p_status)
1001{
1002        bcm_chunk_t * chunk;
1003        unsigned long size, num_chunk;
1004        struct bcm_heap_status heap_status;
1005
1006        memset(&heap_status, 0, sizeof(heap_status));
1007
1008#if 0
1009        // this is too slow if number of chunk is large.
1010        // checking overlay is bottleneck.
1011        // todo: is there any good algorithm to check overlap?
1012        if (!mem_validate(p_heap))
1013                return -1;
1014#endif
1015
1016        // total heap size
1017        heap_status.size_heap = (uint32_t)p_heap->end_addr - (uint32_t)p_heap->start_addr;
1018
1019        // scan alloc chunks   
1020        size = num_chunk = 0;
1021
1022        for (chunk = p_heap->first ; chunk ; chunk = chunk->next) {
1023                if (!checksignature(chunk,0)) {
1024                        //BRCM_DBG_ERR(("%s invalid sig alloc\n", __func__));
1025                        return -2;
1026                }
1027                size += chunk->size;
1028                num_chunk++;
1029        }
1030        printf("num chunk: %d\n", num_chunk);
1031        heap_status.size_alloc = size;
1032        heap_status.num_alloc_chunk = num_chunk;
1033
1034        // scan free chunks
1035        size = num_chunk = 0;
1036        for (chunk = p_heap->first_free ; chunk ; chunk = chunk->next)
1037        {
1038                if (!checksignature(chunk,1))
1039                {
1040                        //BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_report free\n"));
1041                        return -3;
1042                }
1043                size += chunk->size;
1044                num_chunk++;
1045        }
1046        heap_status.size_free = size;
1047        heap_status.num_free_chunk = num_chunk;
1048
1049        if (p_status) *p_status = heap_status;
1050       
1051        return 0;
1052}
1053
1054void mem_reportbrief_ex(bcm_heap_t *p_heap, int threshold)
1055{
1056        bcm_chunk_t * chunk = 0L;
1057        unsigned long size = 0;
1058        unsigned long run_size = 0xffffffff;
1059        int max_size_lower_than_run = 0;
1060
1061        mem_validate(p_heap);
1062        BRCM_DBG_MSG(("Allocated chunks:\n"));
1063
1064        while (run_size > 0)
1065        {
1066                // search maximum size that is smaller than chunk_size.
1067                max_size_lower_than_run = 0;
1068                for (chunk = p_heap->first ; chunk ; chunk = chunk->next) {
1069                        if (!checksignature(chunk,0))
1070                                return;
1071                        if (chunk->size < run_size && chunk->size > max_size_lower_than_run)
1072                                max_size_lower_than_run = chunk->size;
1073                }
1074                if (max_size_lower_than_run == 0)
1075                        break;
1076               
1077                // print all max_size chunk.
1078                for (chunk = p_heap->first ; chunk ; chunk = chunk->next) {
1079                        if (chunk->size == max_size_lower_than_run) {
1080                                if (chunk->size > threshold)
1081                                        BRCM_DBG_MSG(("[%7ld] %08x %s:%d\n",
1082                                                chunk->size,chunk_to_pointer(chunk),chunk->file,chunk->line));
1083                                size += chunk->size;
1084                        }
1085                }
1086                run_size = max_size_lower_than_run;
1087        }
1088       
1089        BRCM_DBG_MSG(("Total Alloced Size = %ld\n",size));
1090        size = 0;
1091
1092        BRCM_DBG_MSG(("Free chunks:\n"));
1093        for (chunk = p_heap->first_free ; chunk ; chunk = chunk->next)
1094        {
1095                if (!checksignature(chunk,1))
1096                {
1097                        BRCM_DBG_ERR(("CHUNK SIGNATURE INVALID mem_report free\n"));
1098                        return;
1099                }
1100                BRCM_DBG_MSG((" %ld\n",chunk->size));
1101                size += chunk->size;
1102        }
1103        BRCM_DBG_MSG(("Total Free Size = %ld\n",size));
1104}
1105#endif
1106
1107#else
1108void mem_reportbrief(bcm_heap_t *p_heap)
1109{
1110        return;
1111}
1112#endif /* MEM_DEBUG */
1113
1114
Note: See TracBrowser for help on using the repository browser.