openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

alloc.c (16710B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File: 	alloc.c
      8  * Purpose:	Defines sal routines for memory allocation
      9  */
     10 
     11 #ifdef LINUX_SAL_DMA_ALLOC_OVERRIDE
     12 /* Keep local functions, but use a different name */
     13 #define sal_dma_alloc sal_sim_dma_alloc
     14 #define sal_dma_free sal_sim_dma_free
     15 #endif
     16 
     17 #include <sys/types.h>
     18 #ifdef PTRS_ARE_64BITS
     19 #include <unistd.h>
     20 #include <sys/mman.h>
     21 #endif
     22 #include <stdlib.h>
     23 #include <assert.h>
     24 
     25 #include <sal/types.h>
     26 #include <sal/core/thread.h>
     27 #include <sal/core/memlog.h>
     28 
     29 #ifdef MEMORY_MEASUREMENT_DIAGNOSTICS
     30 #include <shared/mem_measure_tool.h>
     31 #endif
     32 
     33 #ifndef USE_EXTERNAL_MEM_CHECKING
     34 /* { */
     35 #define USE_EXTERNAL_MEM_CHECKING 0
     36 /* } */
     37 #endif
     38 #if USE_EXTERNAL_MEM_CHECKING
     39 /* { */
     40 #define EXT_DEBUG_ALLOC(_sz) do { return malloc(_sz); } while(0)
     41 #define EXT_DEBUG_FREE(_addr) do { free(_addr); return; } while(0)
     42 /* } */
     43 #else
     44 /* { */
     45 #define EXT_DEBUG_ALLOC(_sz)
     46 #define EXT_DEBUG_FREE(_addr)
     47 /* } */
     48 #endif
     49 
     50 #ifndef AGGRESSIVE_ALLOC_DEBUG_TESTING
     51 /* { */
     52 #define AGGRESSIVE_ALLOC_DEBUG_TESTING 0
     53 /* } */
     54 #endif
     55 #if AGGRESSIVE_ALLOC_DEBUG_TESTING
     56 /* { */
     57 #if USE_EXTERNAL_MEM_CHECKING
     58 /* { */
     59 #error "USE_EXTERNAL_MEM_CHECKING and AGGRESSIVE_ALLOC_DEBUG_TESTING can\'t be set both."
     60 /* } */
     61 #endif
     62 #ifndef AGGRESSIVE_ALLOC_DEBUG_TESTING_KEEP_ORDER
     63 /* { */
     64 /* The allocations stored in array.
     65  * When freeing allocation in the middle of the array,
     66  * the last entry in the array replace it.
     67  * if this flags is set, all the entries next to the free allocation will be pushed down,
     68  * and hence, the order will be kept.
     69  */
     70 #define AGGRESSIVE_ALLOC_DEBUG_TESTING_KEEP_ORDER 0
     71 /* } */
     72 #endif
     73 #include "alloc_debug.h"
     74 #define AGGR_DEBUG_ALLOC(_p, _sz, _s) sal_alloc_debug_alloc(_p, _sz, _s)
     75 #define AGGR_DEBUG_FREE(_addr) sal_alloc_debug_free(_addr)
     76 #define AGGR_DEBUG_PRINT_BAD_ADDR(_addr) sal_alloc_debug_print_bad_addr(_addr)
     77 /* } */
     78 #else
     79 /* { */
     80 #define AGGR_DEBUG_ALLOC(_p, _sz, _s)
     81 #define AGGR_DEBUG_FREE(_addr)
     82 #define AGGR_DEBUG_PRINT_BAD_ADDR(addr)
     83 /* } */
     84 #endif /* AGGRESSIVE_ALLOC_DEBUG_TESTING */
     85 
     86 
     87 /* To do: use real data segment limits for bad pointer detection */
     88 #define BAD_PTR(p)						\
     89         (PTR_TO_UINTPTR(p) < 0x1000UL ||			\
     90          PTR_TO_UINTPTR(p) > ~0xfffUL)
     91 #define CORRUPT(p)						\
     92 	(p[-1] != 0xaaaaaaaa ||					\
     93 	 p[p[-2]] != 0xbbbbbbbb)
     94 #define FREED_PTR(p)    ((p[-1] == 0xcccccccc) && (p[p[-2]] == 0xdddddddd))
     95 
     96 static unsigned long	sal_alloc_bytes;
     97 static unsigned long	sal_alloc_calls;
     98 static unsigned long	sal_free_bytes;
     99 static unsigned long	sal_free_calls;
    100 
    101 static unsigned long    sal_alloc_bytes_main_thr;
    102 static unsigned long    sal_free_bytes_main_thr;
    103 
    104 #ifdef BROADCOM_DEBUG
    105 /* { */
    106 #ifdef INCLUDE_BCM_SAL_PROFILE
    107 /* { */
    108 static unsigned int _sal_alloc_max = 0 ;
    109 static unsigned int _sal_alloc_curr = 0 ;
    110 
    111 #define SAL_ALLOC_RESOURCE_USAGE_INCR(a_curr, a_max, a_size, ilock)     \
    112         a_curr += (a_size);                                             \
    113         a_max = ((a_curr) > (a_max)) ? (a_curr) : (a_max)
    114 
    115 #define SAL_ALLOC_RESOURCE_USAGE_DECR(a_curr, a_size, ilock)            \
    116         a_curr -= (a_size)                                              \
    117 
    118 /*
    119  * Function:
    120  *      sal_alloc_resource_usage_get
    121  * Purpose:
    122  *      Provides Current/Maximum memory allocation.
    123  * Parameters:
    124  *      alloc_curr - Current memory usage.
    125  *      alloc_max - Memory usage high water mark
    126  */
    127 
    128 void 
    129 sal_alloc_resource_usage_get(uint32 *alloc_curr, uint32 *alloc_max)
    130 {
    131     if (alloc_curr != NULL) {
    132         *alloc_curr = _sal_alloc_curr;
    133     }
    134     if (alloc_max != NULL) {
    135         *alloc_max = _sal_alloc_max;
    136     }
    137 }
    138 static unsigned int _sal_dma_alloc_max;
    139 static unsigned int _sal_dma_alloc_curr;
    140 
    141 #define SAL_DMA_ALLOC_RESOURCE_USAGE_INCR(a_curr, a_max, a_size, ilock) \
    142         a_curr += (a_size);                                             \
    143         a_max = ((a_curr) > (a_max)) ? (a_curr) : (a_max)
    144 
    145 #define SAL_DMA_ALLOC_RESOURCE_USAGE_DECR(a_curr, a_size, ilock)        \
    146         a_curr -= (a_size)
    147 
    148 /*
    149  * Function:
    150  *      sal_dma_alloc_resource_usage_get
    151  * Purpose:
    152  *      Provides Current/Maximum memory allocation.
    153  * Parameters:
    154  *      alloc_curr - Current memory usage.
    155  *      alloc_max - Memory usage high water mark
    156  */
    157 
    158 void 
    159 sal_dma_alloc_resource_usage_get(uint32 *alloc_curr, uint32 *alloc_max)
    160 {
    161     if (alloc_curr != NULL) {
    162         *alloc_curr = _sal_dma_alloc_curr;
    163     }
    164     if (alloc_max != NULL) {
    165         *alloc_max = _sal_dma_alloc_max;
    166     }
    167 }
    168 /* } */
    169 #endif
    170 /*
    171  * Function:
    172  *      sal_alloc_stat
    173  * Purpose:
    174  *      Dump the current allocations
    175  * Parameters:
    176  *      param - integer used to change behavior.
    177  * Notes:
    178  *      If the parameter is non-zero, the routine will not
    179  *      display successive entries with the same description.
    180  */
    181 void
    182 sal_alloc_stat(void *param)
    183 {
    184 }
    185 /* } */
    186 #endif /* BROADCOM_DEBUG */
    187 
    188 /**
    189  * \brief
    190  *     Get the main thread allocated and freed bytes counters.
    191  * \param [out] alloc_bytes_count -
    192  *     Pointer to alloc bytes counter storage.
    193  * \param [out] free_bytes_count -
    194  *     Pointer to free bytes counter storage.
    195  * \return
    196  *     (void)
    197  * \remark
    198  * * None
    199  * \see
    200  * * None
    201  */
    202 void sal_get_alloc_counters_main_thr(unsigned long *alloc_bytes_count,unsigned long *free_bytes_count)
    203 {
    204     *alloc_bytes_count = sal_alloc_bytes_main_thr;
    205     *free_bytes_count = sal_free_bytes_main_thr;
    206 }
    207 
    208 /**
    209  * \brief
    210  *     Offsets the main thread allocated and freed bytes counters
    211  * \param [out] alloc_bytes_count_offset -
    212  *     Value that is substracted from the alloc bytes counter.
    213  * \param [out] free_bytes_count_offset -
    214  *     Value that is substracted from the free bytes counter.
    215  * \return
    216  *     (void)
    217  * \remark
    218  * * Used by sw state internals to offset the sal_alloc and sal_free counters
    219  * \see
    220  * * dnxc_sw_state_alloc_plain
    221  */
    222 void sal_set_alloc_counters_offset_main_thr(unsigned long alloc_bytes_count_offset, unsigned long free_bytes_count_offset)
    223 {
    224     sal_alloc_bytes_main_thr -= alloc_bytes_count_offset;
    225     sal_free_bytes_main_thr -= free_bytes_count_offset;
    226 }
    227 
    228 /**
    229  * \brief
    230  *     Get the allocated and freed bytes counters.
    231  *     Pointer to alloc bytes counter storage.
    232  * \param [out] free_bytes_count -
    233  *     Pointer to free bytes counter storage.
    234  * \return
    235  *     (void)
    236  * \remark
    237  * * None
    238  * \see
    239  * * None
    240  */
    241 void sal_get_alloc_counters(unsigned long *alloc_bytes_count,unsigned long *free_bytes_count)
    242 {
    243     *alloc_bytes_count = sal_alloc_bytes;
    244     *free_bytes_count = sal_free_bytes;
    245 }
    246 
    247 /**
    248  * \brief
    249  *     Offsets the  allocated and freed bytes counters.
    250  * \param [out] alloc_bytes_count_offset -
    251  *     Value that is substracted from the alloc bytes counter.
    252  * \param [out] free_bytes_count_offset -
    253  *     Value that is substracted from the free bytes counter.
    254  * \return
    255  *     (void)
    256  * \remark
    257  * * Used by sw state internals to offset the sal_alloc and sal_free counters
    258  * \see
    259  * * dnxc_sw_state_alloc_plain
    260  */
    261 void sal_set_alloc_counters_offset(unsigned long alloc_bytes_count_offset, unsigned long free_bytes_count_offset)
    262 {
    263     sal_alloc_bytes -= alloc_bytes_count_offset;
    264     sal_free_bytes -= free_bytes_count_offset;
    265 }
    266 
    267 /*
    268  * Function:
    269  *	sal_alloc
    270  * Purpose:
    271  *	Allocate general purpose system memory.
    272  * Parameters:
    273  *	sz - size of memory block to allocate.
    274  *	s - optional user description of memory block for debugging.
    275  * Returns:
    276  *	Pointer to memory block
    277  * Notes:
    278  *	Memory allocated by this routine is not guaranteed to be safe
    279  *	for hardware DMA read/write.
    280  */
    281 
    282 void *
    283 sal_alloc(unsigned int sz, char *s)
    284 {
    285     unsigned int orig_sz, alloc_sz;
    286     uint32	*p;
    287 
    288 #ifdef MEMORY_MEASUREMENT_DIAGNOSTICS
    289     uint32 idx;
    290 #endif
    291 
    292     EXT_DEBUG_ALLOC(sz);
    293 
    294     /*
    295      * Round up size to accommodate corruption detection sentinels.
    296      * Place sentinels at the beginning and end of the data area to
    297      * detect memory corruption.  These are verified on free.
    298      */
    299 
    300     orig_sz = sz;
    301 
    302     sz = (sz + 3) & ~3;
    303 
    304     /* Check for wrap caused by bad input */
    305     alloc_sz = sz + 12;
    306     if (alloc_sz < orig_sz) {
    307         return NULL;
    308     }
    309 
    310     sal_alloc_calls += 1;
    311 
    312     if ((p = malloc(alloc_sz)) == 0) {
    313         return p;
    314     }
    315 
    316     assert(UINTPTR_TO_PTR(PTR_TO_UINTPTR(p)) == p);
    317 
    318     if (sal_thread_self() == sal_thread_main_get())
    319     {
    320         sal_alloc_bytes_main_thr += sz;
    321     }
    322 
    323     sal_alloc_bytes += sz;
    324 
    325     p[0] = sz / 4;
    326     p[1] = 0xaaaaaaaa;
    327     p[2 + sz / 4] = 0xbbbbbbbb;
    328 
    329 #ifdef MEMORY_MEASUREMENT_DIAGNOSTICS
    330     MEMORY_MEASUREMENT_INITIALIZE;
    331     for(idx = 0;idx < memory_measurement_tool.count;idx++) {
    332         if(memory_measurement_tool.elements[idx].is_active && (memory_measurement_tool.elements[idx].thread_id == sal_thread_self())) {
    333             memory_measurement_tool.elements[idx].sal_size += sz;
    334         }
    335     }
    336 #endif
    337 
    338 #ifdef BROADCOM_DEBUG
    339 /* { */
    340 #ifdef INCLUDE_BCM_SAL_PROFILE
    341 /* { */
    342     SAL_ALLOC_RESOURCE_USAGE_INCR(
    343         _sal_alloc_curr,
    344         _sal_alloc_max,
    345         (sz),
    346         ilock);
    347 
    348 /* } */
    349 #endif
    350 /* } */
    351 #endif /* BROADCOM_DEBUG */
    352 
    353     AGGR_DEBUG_ALLOC(p, sz, s);
    354 
    355     MEMLOG_ALLOC("sal_alloc", (void *)&p[0], orig_sz, s);
    356 
    357     return (void *) &p[2];
    358 }
    359 
    360 /*
    361  * Function:
    362  *	sal_free
    363  * Purpose:
    364  *	Free memory block allocate by sal_alloc
    365  * Parameters:
    366  *	addr - Address returned by sal_alloc
    367  */
    368 
    369 void 
    370 sal_free(void *addr)
    371 {
    372     uint32	*p	= (uint32 *)addr;
    373     uint32  *ap = p; /* Originally Allocated Pointer */
    374 
    375 #ifdef MEMORY_MEASUREMENT_DIAGNOSTICS
    376     uint32 idx;
    377 #endif
    378 
    379     EXT_DEBUG_FREE(addr);
    380 
    381     /*
    382      * Verify sentinels on free.  If this assertion fails, it means that
    383      * memory corruption was detected.
    384      */
    385 
    386 #ifdef SAL_FREE_NULL_IGNORE
    387 /* { */
    388     if (addr == NULL)
    389     {
    390         return;
    391     }
    392 /* } */
    393 #endif
    394 
    395     AGGR_DEBUG_FREE(addr);
    396 
    397     if (BAD_PTR(p) || FREED_PTR(p) || CORRUPT(p)) {
    398         AGGR_DEBUG_PRINT_BAD_ADDR(addr);
    399         assert(!BAD_PTR(p));	/* Use macro to beautify assert message */
    400         assert(!FREED_PTR(p));  /* Detect double freed memory */
    401         assert(!CORRUPT(p));	/* Use macro to beautify assert message */
    402     }
    403 
    404     /* Adjust for Corruption detection Sentinels */
    405     ap--;
    406     ap--;
    407 
    408     if (sal_thread_self() == sal_thread_main_get())
    409     {
    410         sal_free_bytes_main_thr += ap[0] * 4;
    411     }
    412 
    413     sal_free_calls += 1;
    414     sal_free_bytes += ap[0] * 4;
    415 
    416 #ifdef MEMORY_MEASUREMENT_DIAGNOSTICS
    417     for(idx = 0;idx < memory_measurement_tool.count;idx++) {
    418         if(memory_measurement_tool.elements[idx].is_active && (memory_measurement_tool.elements[idx].thread_id == sal_thread_self())) {
    419             memory_measurement_tool.elements[idx].sal_size -= (ap[0] * 4);
    420         }
    421     }
    422 #endif
    423 
    424 #ifdef BROADCOM_DEBUG
    425 /* { */
    426 #ifdef INCLUDE_BCM_SAL_PROFILE
    427 /* { */
    428     SAL_ALLOC_RESOURCE_USAGE_DECR(
    429         _sal_alloc_curr,
    430         (ap[0] * 4),
    431         ilock);
    432 
    433 /* } */
    434 #endif
    435 /* } */
    436 #endif /* BROADCOM_DEBUG */
    437 
    438     MEMLOG_FREE("sal_free", (void *)&p[-2]);
    439 
    440     ap[1] = 0xcccccccc;    /* Detect redundant frees */
    441     ap[2 + ap[0]] = 0xdddddddd;
    442     /*    coverity[address_free : FALSE]    */
    443     free(ap);
    444 }
    445 
    446 /*
    447  * Function:
    448  *	sal_dma_alloc
    449  * Purpose:
    450  *	Allocate memory that can be DMA'd into/out of.
    451  * Parameters:
    452  *	sz - number of bytes to allocate
    453  *	s - string associated with allocate
    454  * Returns:
    455  *	Pointer to allocated memory or NULL if out of memory.
    456  * Notes:
    457  *	Memory allocated by this routine is not guaranteed to be safe
    458  *	for hardware DMA read/write. This is for use only on sim platform.
    459  */
    460 
    461 void *
    462 sal_dma_alloc(size_t sz, char *s)
    463 {
    464     uint32	*p;
    465     size_t  new_sz;
    466 #if defined(PTRS_ARE_64BITS) && defined(MAP_32BIT)
    467     long pagesz = sysconf(_SC_PAGESIZE);
    468 #endif
    469 
    470     /*
    471      * Round up size to accommodate corruption detection sentinels.
    472      * Place sentinels at the beginning and end of the data area to
    473      * detect memory corruption.  These are verified on free.
    474      */
    475     sz = (sz + 3) & ~3;
    476 
    477     /* Add bytes for holding sentinals */
    478     new_sz = sz + 12;
    479 
    480 #if defined(PTRS_ARE_64BITS) && defined(MAP_32BIT)
    481     /* For 64 bit SDK simulation image use mmap with MAP_32BIT flag for
    482      * allocation as we need allocated region to be addressable in 32bit
    483      * address space. Normal malloc would return memory in 64 bit virtual
    484      * address space. Also allign the size to a page boundary as mmap
    485      * allocates memory in pages
    486      */
    487     new_sz = (new_sz + (size_t)(pagesz-1)) & ~(pagesz-1);
    488     p = mmap(NULL,
    489              new_sz,
    490              PROT_READ|PROT_WRITE,
    491              MAP_ANONYMOUS|MAP_SHARED|MAP_32BIT,
    492              -1,
    493              0);
    494     if (MAP_FAILED == p) {
    495         return NULL;
    496     }
    497 #else
    498     if ((p = malloc(new_sz)) == 0) {
    499         return p;
    500     }
    501 #endif
    502 
    503     assert(INT_TO_PTR(PTR_TO_INT(p)) == p);
    504 
    505     p[0] = sz / 4;
    506     p[1] = 0xaaaaaaaa;
    507     p[2 + sz / 4] = 0xbbbbbbbb;
    508 #ifdef BROADCOM_DEBUG
    509 /* { */
    510 #ifdef INCLUDE_BCM_SAL_PROFILE
    511 /* { */
    512     SAL_DMA_ALLOC_RESOURCE_USAGE_INCR(
    513         _sal_dma_alloc_curr,
    514         _sal_dma_alloc_max,
    515         (sz),
    516         ilock);
    517 /* } */
    518 #endif
    519 /* } */
    520 #endif /* BROADCOM_DEBUG */
    521 
    522     MEMLOG_ALLOC("sal_dma_alloc", &p[0], new_sz, s);
    523 
    524     return (void *) &p[2];
    525 }
    526 
    527 /*
    528  * Function:
    529  *	sal_dma_free
    530  * Purpose:
    531  *	Free memory allocated by sal_dma_alloc
    532  * Parameters:
    533  *	addr - pointer to memory to free.
    534  * Returns:
    535  *	Nothing.
    536  */
    537 
    538 void
    539 sal_dma_free(void *addr)
    540 {
    541 #if defined(PTRS_ARE_64BITS) && defined(MAP_32BIT)
    542     int org_sz;
    543     long pagesz = sysconf(_SC_PAGESIZE);
    544 #endif
    545     uint32	*p	= (uint32 *)addr;
    546     uint32  *ap = p; /* Originally Allocated Pointer */
    547 
    548     /*
    549      * Verify sentinels on free.  If this assertion fails, it means that
    550      * memory corruption was detected.
    551      */
    552 
    553     /*    coverity[conditional (1): FALSE]    */
    554     /*    coverity[conditional (2): FALSE]    */
    555     assert(!BAD_PTR(p));	/* Use macro to beautify assert message */
    556     /* Detect double freed memory */
    557     assert(!FREED_PTR(p));
    558     /*    coverity[conditional (3): FALSE]    */
    559     /*    coverity[conditional (4): FALSE]    */
    560     assert(!CORRUPT(p));	/* Use macro to beautify assert message */
    561 
    562 
    563     /* Adjust for Corruption detection Sentinels */
    564     ap--;
    565     ap--;
    566 
    567 #ifdef BROADCOM_DEBUG
    568 /* { */
    569 #ifdef INCLUDE_BCM_SAL_PROFILE
    570 /* { */
    571     SAL_DMA_ALLOC_RESOURCE_USAGE_DECR(
    572         _sal_dma_alloc_curr,
    573         (ap[0] * 4),
    574         ilock);
    575 /* } */
    576 #endif
    577 /* } */
    578 #endif /* BROADCOM_DEBUG */
    579 
    580     MEMLOG_FREE("sal_dma_free", ap);
    581 
    582     ap[1] = 0xcccccccc;  /* Detect redundant frees */
    583     ap[2 + ap[0]] = 0xdddddddd;
    584 #if defined(PTRS_ARE_64BITS) && defined(MAP_32BIT)
    585     /* For 64 bit SDK simulation image use  munmap as the allocation
    586      * was done using mmap. Also re-adjust the size such that it is
    587      * page alligned.
    588      */
    589     org_sz =  (ap[0] * 4) + 12; /* Add 12 for 3 sentinels */
    590     org_sz = (org_sz + (size_t)(pagesz-1)) & ~(pagesz-1);
    591     munmap(ap, org_sz);
    592 #else
    593     /*    coverity[address_free : FALSE]    */
    594     free(ap);
    595 #endif
    596 }
    597 
    598 /*
    599  * Function:
    600  *	sal_dma_flush
    601  * Purpose:
    602  *	Ensure modified cache is written out to memory.
    603  * Parameters:
    604  *	addr - beginning of address region
    605  *	len - size of address region
    606  * Notes:
    607  *	A region of memory should always be flushed before telling
    608  *	hardware to start a DMA read from that memory.
    609  */
    610 
    611 void
    612 sal_dma_flush(void *addr, int len)
    613 {
    614     COMPILER_REFERENCE(addr);
    615     COMPILER_REFERENCE(len);
    616 }
    617 
    618 /*
    619  * Function:
    620  *	sal_dma_inval
    621  * Purpose:
    622  *	Ensure cache memory is discarded and not written out to memory.
    623  * Parameters:
    624  *	addr - beginning of address region
    625  *	len - size of address region
    626  * Notes:
    627  *	A region of memory should always be invalidated before telling
    628  *	hardware to start a DMA write into that memory.
    629  */
    630 
    631 void
    632 sal_dma_inval(void *addr, int len)
    633 {
    634     COMPILER_REFERENCE(addr);
    635     COMPILER_REFERENCE(len);
    636 }
    637 
    638 /*
    639  * Function:
    640  *	sal_dma_vtop
    641  * Purpose:
    642  *	Convert a virtual memory address to physical.
    643  * Parameters:
    644  *	addr - address to convert
    645  * Returns:
    646  *	Physical address
    647  */
    648 
    649 void *
    650 sal_dma_vtop(void *addr)
    651 {
    652     return addr;
    653 }
    654 
    655 /*
    656  * Function:
    657  *	sal_dma_ptov
    658  * Purpose:
    659  *	Convert a physical memory address to virtual.
    660  * Parameters:
    661  *	addr - address to convert
    662  * Returns:
    663  *	Virtual address
    664  */
    665 
    666 void *
    667 sal_dma_ptov(void *addr)
    668 {
    669     return addr;
    670 }
    671 
    672 /*
    673  * Function:
    674  *	sal_memory_check
    675  * Purpose:
    676  *	Check an address in memory for existence and writability.
    677  * Parameters:
    678  *	addr - address to check
    679  * Returns:
    680  *	0 if writable, 1 if not
    681  * Notes:
    682  *	Should be written to catch SIGBUS and SIGSEGV.
    683  *	For now, just returns success.
    684  */
    685 
    686 int
    687 sal_memory_check(uint32 addr)
    688 {
    689     return 0;
    690 }