Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  *  sbrk.c
0003  *
0004  * Authorship
0005  * ----------
0006  * This software was created by
0007  *     Till Straumann <strauman@slac.stanford.edu>, 2002,
0008  *        Stanford Linear Accelerator Center, Stanford University.
0009  *
0010  * Acknowledgement of sponsorship
0011  * ------------------------------
0012  * This software was produced by
0013  *     the Stanford Linear Accelerator Center, Stanford University,
0014  *        under Contract DE-AC03-76SFO0515 with the Department of Energy.
0015  *
0016  * Government disclaimer of liability
0017  * ----------------------------------
0018  * Neither the United States nor the United States Department of Energy,
0019  * nor any of their employees, makes any warranty, express or implied, or
0020  * assumes any legal liability or responsibility for the accuracy,
0021  * completeness, or usefulness of any data, apparatus, product, or process
0022  * disclosed, or represents that its use would not infringe privately owned
0023  * rights.
0024  *
0025  * Stanford disclaimer of liability
0026  * --------------------------------
0027  * Stanford University makes no representations or warranties, express or
0028  * implied, nor assumes any liability for the use of this software.
0029  *
0030  * Stanford disclaimer of copyright
0031  * --------------------------------
0032  * Stanford University, owner of the copyright, hereby disclaims its
0033  * copyright and all other rights in this software.  Hence, anyone may
0034  * freely use it for any purpose without restriction.
0035  *
0036  * Maintenance of notices
0037  * ----------------------
0038  * In the interest of clarity regarding the origin and status of this
0039  * SLAC software, this and all the preceding Stanford University notices
0040  * are to remain affixed to any copy or derivative of this software made
0041  * or distributed by the recipient and are to be affixed to any copy of
0042  * software made or distributed by the recipient that contains a copy or
0043  * derivative of this software.
0044  *
0045  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0046  */
0047 
0048 /*
0049  *  Hack around the 32bit powerpc 32M problem:
0050  *
0051  *  GCC by default uses relative branches which can not jump
0052  *  farther than 32M. Hence all program text is confined to
0053  *  a single 32M segment.
0054  *  This hack gives the RTEMS malloc region all memory below
0055  *  32M at startup. Only when this region is exhausted will sbrk
0056  *  add more memory. Loading modules may fail at that point, hence
0057  *  the user is expected to load all modules at startup _prior_
0058  *  to malloc()ing lots of memory...
0059  *
0060  *  NOTE: it would probably be better to have a separate region
0061  *        for module code.
0062  */
0063 
0064 #include <errno.h>
0065 #include <unistd.h>
0066 
0067 #include <bsp.h>
0068 #include <bsp/bootcard.h>
0069 
0070 #include <rtems/sysinit.h>
0071 
0072 #ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
0073 
0074 #define INVALID_REMAINING_START ((uintptr_t) -1)
0075 
0076 static uintptr_t remaining_start = INVALID_REMAINING_START;
0077 static uintptr_t remaining_size = 0;
0078 
0079 /* App. may provide a value by defining the BSP_sbrk_policy
0080  * variable.
0081  *
0082  *  (-1) -> give all memory to the heap at initialization time
0083  *  > 0  -> value used as sbrk amount; initially give 32M
0084  *    0  -> limit memory effectively to 32M.
0085  *
0086  */
0087 extern uintptr_t        BSP_sbrk_policy[] __attribute__((weak));
0088 
0089 #define LIMIT_32M  0x02000000
0090 
0091 /**
0092  * @brief Gives the BSP a chance to reduce the work area size with sbrk()
0093  * adding more later.
0094  *
0095  * bsp_sbrk_init() may reduce the work area size passed in. The routine
0096  * returns the 'sbrk_amount' to be used when extending the heap.  Note that
0097  * the return value may be zero.
0098  *
0099  * In case the @a mem area size is altered, then the remaining size of the
0100  * @a mem area must be greater than or equal to @a min_size.
0101  */
0102 static ptrdiff_t bsp_sbrk_init(const Memory_Information *mem, uintptr_t min_size)
0103 {
0104   uintptr_t         rval = 0;
0105   uintptr_t         policy;
0106   uintptr_t         remaining_end;
0107   Memory_Area      *area;
0108 
0109   area = &mem->areas[ 0 ];
0110   remaining_start = (uintptr_t) _Memory_Get_free_begin(area);
0111   remaining_size  = _Memory_Get_free_size(area);
0112   remaining_end   = (uintptr_t) _Memory_Get_end(area);
0113 
0114   if (remaining_start < LIMIT_32M &&
0115       remaining_end > LIMIT_32M &&
0116       min_size <= LIMIT_32M - remaining_start) {
0117     /* clip at LIMIT_32M */
0118     rval = remaining_end - LIMIT_32M;
0119     _Memory_Set_end(area, (void *) (LIMIT_32M - remaining_start));
0120     remaining_start = LIMIT_32M;
0121     remaining_size  = rval;
0122   }
0123 
0124   policy = (0 == BSP_sbrk_policy[0] ? (uintptr_t)(-1) : BSP_sbrk_policy[0]);
0125   switch ( policy ) {
0126       case (uintptr_t)(-1):
0127         _Memory_Set_end(area, (const char *) _Memory_Get_end(area) + rval);
0128         remaining_start = (uintptr_t) _Memory_Get_end(area);
0129         remaining_size  = 0;
0130       break;
0131 
0132       case 0:
0133         remaining_size = 0;
0134       break;
0135 
0136       default:
0137         if ( rval > policy )
0138           rval = policy;
0139       break;
0140   }
0141 
0142   return (ptrdiff_t) (rval <= PTRDIFF_MAX ? rval : rval / 2);
0143 }
0144 
0145 void *sbrk(ptrdiff_t incr)
0146 {
0147   void *rval=(void*)-1;
0148 
0149   if ( remaining_start != INVALID_REMAINING_START && incr <= remaining_size) {
0150     remaining_size-=incr;
0151     rval = (void *) remaining_start;
0152     remaining_start += incr;
0153   }
0154 
0155   /*
0156    * sbrk() is a Legacy POSIX method which means it is no longer part of the
0157    * POSIX standard. Historically, it was required to set errno to ENOMEM if
0158    * the extension failed. This implementation does not do that for two
0159    * reasons. First, this method is only called from the RTEMS malloc()
0160    * implementation and does not expect errno to be set when -1 is returned.
0161    * Second, setting errno implicitly pulls in some of the newlib reentrancy
0162    * support. Not setting errno avoids this method forcing that support
0163    * into every application for every BSP that uses this method.
0164    */
0165 
0166   #ifdef DEBUG
0167     printk("************* SBRK 0x%08x (ret 0x%08x) **********\n", incr, rval);
0168   #endif
0169   return rval;
0170 }
0171 
0172 static void bsp_sbrk_initialize(void)
0173 {
0174   uintptr_t overhead = _Heap_Area_overhead(CPU_HEAP_ALIGNMENT);
0175   uintptr_t work_space_size = rtems_configuration_get_work_space_size();
0176   ptrdiff_t sbrk_amount = bsp_sbrk_init(
0177     _Memory_Get(),
0178     work_space_size
0179       + overhead
0180       + (rtems_configuration_get_unified_work_area() ? 0 : overhead)
0181   );
0182 
0183   rtems_heap_set_sbrk_amount(sbrk_amount);
0184 }
0185 
0186 RTEMS_SYSINIT_ITEM(
0187   bsp_sbrk_initialize,
0188   RTEMS_SYSINIT_SBRK,
0189   RTEMS_SYSINIT_ORDER_MIDDLE
0190 );
0191 
0192 #endif /* CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK */