| 1 | /* EPIPHANY implementation of _sbrk () | 
|---|
| 2 |  | 
|---|
| 3 |    Copyright (c) 2011, Adapteva, Inc. | 
|---|
| 4 |    All rights reserved. | 
|---|
| 5 |  | 
|---|
| 6 |    Contributor Jeremy Bennett <jeremy.bennett@embecosm.com> for Adapteva Inc | 
|---|
| 7 |  | 
|---|
| 8 |    Redistribution and use in source and binary forms, with or without | 
|---|
| 9 |    modification, are permitted provided that the following conditions are met: | 
|---|
| 10 |     * Redistributions of source code must retain the above copyright notice, | 
|---|
| 11 |       this list of conditions and the following disclaimer. | 
|---|
| 12 |     * Redistributions in binary form must reproduce the above copyright | 
|---|
| 13 |       notice, this list of conditions and the following disclaimer in the | 
|---|
| 14 |       documentation and/or other materials provided with the distribution. | 
|---|
| 15 |     * Neither the name of Adapteva nor the names of its contributors may be | 
|---|
| 16 |       used to endorse or promote products derived from this software without | 
|---|
| 17 |       specific prior written permission. | 
|---|
| 18 |  | 
|---|
| 19 |    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
|---|
| 20 |    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|---|
| 21 |    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
|---|
| 22 |    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | 
|---|
| 23 |    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
|---|
| 24 |    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
|---|
| 25 |    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
|---|
| 26 |    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
|---|
| 27 |    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
|---|
| 28 |    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 
|---|
| 29 |    POSSIBILITY OF SUCH DAMAGE.                                               */ | 
|---|
| 30 | /* ------------------------------------------------------------------------- */ | 
|---|
| 31 | /* This implementation is suitable for use with the Verilator simulation of | 
|---|
| 32 |    the EPIPHANY. | 
|---|
| 33 |  | 
|---|
| 34 |    Commenting suitable for processing by Doxygen is provided throughout.     */ | 
|---|
| 35 | /* ------------------------------------------------------------------------- */ | 
|---|
| 36 | #include <sys/types.h> | 
|---|
| 37 | #include <errno.h> | 
|---|
| 38 | #include <stddef.h> | 
|---|
| 39 |  | 
|---|
| 40 | /* ------------------------------------------------------------------------- */ | 
|---|
| 41 | /*!Increase program data space | 
|---|
| 42 |  | 
|---|
| 43 |    This is a minimal implementation.  Assuming the heap is growing upwards | 
|---|
| 44 |    from __heap_start towards __heap_end. | 
|---|
| 45 |    See linker file for definition. | 
|---|
| 46 |  | 
|---|
| 47 |    @param[in] incr  The number of bytes to increment the stack by. | 
|---|
| 48 |  | 
|---|
| 49 |    @return  A pointer to the start of the new block of memory                */ | 
|---|
| 50 | /* ------------------------------------------------------------------------- */ | 
|---|
| 51 | void * | 
|---|
| 52 | _sbrk (int  incr) | 
|---|
| 53 | { | 
|---|
| 54 |         extern char __heap_start;//set by linker | 
|---|
| 55 |         extern char __heap_end;//set by linker | 
|---|
| 56 |  | 
|---|
| 57 |         static char *heap_end;          /* Previous end of heap or 0 if none */ | 
|---|
| 58 |         char        *prev_heap_end; | 
|---|
| 59 |  | 
|---|
| 60 |         if (0 == heap_end) { | 
|---|
| 61 |                 heap_end = &__heap_start;                       /* Initialize first time round */ | 
|---|
| 62 |         } | 
|---|
| 63 |  | 
|---|
| 64 |         prev_heap_end  = heap_end; | 
|---|
| 65 |         heap_end      += incr; | 
|---|
| 66 |         //check | 
|---|
| 67 |         if( heap_end < (&__heap_end)) { | 
|---|
| 68 |  | 
|---|
| 69 |         } else { | 
|---|
| 70 |                 errno = ENOMEM; | 
|---|
| 71 |                 return (char*)-1; | 
|---|
| 72 |         } | 
|---|
| 73 |         return (void *) prev_heap_end; | 
|---|
| 74 |  | 
|---|
| 75 | }       /* _sbrk () */ | 
|---|
| 76 |  | 
|---|
| 77 |  | 
|---|
| 78 |  | 
|---|
| 79 | ///* sbrk support */ | 
|---|
| 80 | // | 
|---|
| 81 | ///* The current plan is to have one sbrk handler for all cpus. | 
|---|
| 82 | //   Hence use `asm' for each global variable here to avoid the cpu prefix. | 
|---|
| 83 | //   We can't intrude on the user's namespace (another reason to use asm).  */ | 
|---|
| 84 | // | 
|---|
| 85 | //#include <sys/types.h> | 
|---|
| 86 | ///*#include <sys/syscall.h>*/ | 
|---|
| 87 | //#include <errno.h> | 
|---|
| 88 | //#include <stddef.h> | 
|---|
| 89 | // | 
|---|
| 90 | ///* These variables are publicly accessible for debugging purposes. | 
|---|
| 91 | //   The user is also free to set sbrk_size to something different. | 
|---|
| 92 | //   See mem-layout.c.  */ | 
|---|
| 93 | // | 
|---|
| 94 | //extern int sbrk_size asm ("sbrk_size"); | 
|---|
| 95 | // | 
|---|
| 96 | //caddr_t sbrk_start asm ("sbrk_start"); | 
|---|
| 97 | //caddr_t sbrk_loc asm ("sbrk_loc"); | 
|---|
| 98 | //extern char  end;                    /* Defined by linker.  */ | 
|---|
| 99 | // | 
|---|
| 100 | ///*caddr_t _sbrk_r (struct _reent *, size_t) asm ("__sbrk_r");*/ | 
|---|
| 101 | // | 
|---|
| 102 | // | 
|---|
| 103 | ///* This symbol can be defined with the --defsym linker option.  */ | 
|---|
| 104 | //extern char __heap_end __attribute__((weak)); | 
|---|
| 105 | // | 
|---|
| 106 | // | 
|---|
| 107 | ///* FIXME: We need a semaphore here.  */ | 
|---|
| 108 | // | 
|---|
| 109 | //caddr_t | 
|---|
| 110 | //_sbrk_r (struct _reent *r, size_t nbytes) | 
|---|
| 111 | //{ | 
|---|
| 112 | //   extern char  end;                  /* Defined by linker.  */ | 
|---|
| 113 | //   static char *heap_end;             /* Previous end of heap or 0 if none */ | 
|---|
| 114 | //   char        *prev_heap_end; | 
|---|
| 115 | //   register char* stack asm("sp"); | 
|---|
| 116 | // | 
|---|
| 117 | //   if (0 == heap_end) | 
|---|
| 118 | //     { | 
|---|
| 119 | //       heap_end = &end;                       /* Initialize first time round */ | 
|---|
| 120 | //     } | 
|---|
| 121 | // | 
|---|
| 122 | //   prev_heap_end  = heap_end; | 
|---|
| 123 | // | 
|---|
| 124 | //   if (stack < (prev_heap_end+nbytes)) { | 
|---|
| 125 | //     /* heap would overlap the current stack depth. | 
|---|
| 126 | //      * Future:  use sbrk() system call to make simulator grow memory beyond | 
|---|
| 127 | //      * the stack and allocate that | 
|---|
| 128 | //      */ | 
|---|
| 129 | //     errno = ENOMEM; | 
|---|
| 130 | //     return (char*)-1; | 
|---|
| 131 | //   } | 
|---|
| 132 | // | 
|---|
| 133 | //   heap_end      += nbytes; | 
|---|
| 134 | // | 
|---|
| 135 | //   return (caddr_t) prev_heap_end; | 
|---|
| 136 | // | 
|---|
| 137 | //}     /* _sbrk () */ | 
|---|
| 138 |  | 
|---|
| 139 |  | 
|---|
| 140 | //caddr_t | 
|---|
| 141 | //_sbrk_r (struct _reent *r, size_t nbytes) | 
|---|
| 142 | //{ | 
|---|
| 143 | //  caddr_t result; | 
|---|
| 144 | // | 
|---|
| 145 | //  void *heap_end; | 
|---|
| 146 | // | 
|---|
| 147 | //  heap_end = &__heap_end; | 
|---|
| 148 | //  if (!heap_end) | 
|---|
| 149 | //    heap_end = sbrk_start + sbrk_size; | 
|---|
| 150 | //  if ( | 
|---|
| 151 | //      /* Ensure we don't underflow.  */ | 
|---|
| 152 | //      sbrk_loc + nbytes < sbrk_start | 
|---|
| 153 | //      /* Ensure we don't overflow.  */ | 
|---|
| 154 | //      || sbrk_loc + nbytes > (caddr_t)heap_end) | 
|---|
| 155 | //    { | 
|---|
| 156 | //      errno = ENOMEM; | 
|---|
| 157 | //      return ((caddr_t) -1); | 
|---|
| 158 | //    } | 
|---|
| 159 | // | 
|---|
| 160 | //  if (0 == sbrk_loc) | 
|---|
| 161 | //    sbrk_loc = &end;                 /* Initialize first time round */ | 
|---|
| 162 | //  result = sbrk_loc; | 
|---|
| 163 | //  sbrk_loc += nbytes; | 
|---|
| 164 | //  return result; | 
|---|
| 165 | //} | 
|---|