Esempio n. 1
0
// realloc: this is a bit more complex. First we identify the correct memory
// pool and try to realloc there. If this doesn't work, we try to realloc in 
// another pool before giving up.
void* _realloc_r( struct _reent* r, void* ptr, size_t size )
{
  void* temp;
  u32 lstart, lend;
  unsigned i = 0;
  size_t prevsize;
  
  // Realloc with ptr == NULL : malloc
  // Realloc with size == 0 : free
  if( !ptr )
    return size ? _malloc_r( r, size ) : NULL;
  else if( !size )
  {
    _free_r( r, ptr );
    return NULL;
  }

  // At this point we know that this is an actual realloc
  // Identify the memory pool
  while( 1 )
  {
    if( ( lstart = ( u32 )platform_get_first_free_ram( i ) ) == 0 )
      return NULL;
    lstart = ( u32 )tlsf_elua_align_addr( ( void* )lstart );
    lend = ( u32 )platform_get_last_free_ram( i );
    if( ( lstart <= ( u32 )ptr ) && ( ( u32 )ptr <= lend ) )
      break;
    i ++;
  }    
  
  // Easy case: realloc succeeds in the same memory pool
  if( ( temp = realloc_ex( ptr, size, ( void* )lstart ) ) != NULL )
    return temp;
  
  // If realloc returned NULL, look for another pool
  prevsize = tlsf_elua_get_block_size( ptr );
  i = 0;
  while( 1 )
  {
    if( ( temp = platform_get_first_free_ram( i ) ) == NULL )
      break;
    temp = tlsf_elua_align_addr( temp );
    if( ( u32 )temp != lstart )
    {
      if( ( temp = malloc_ex( size, temp ) ) != NULL )
      {
        memcpy( temp, ptr, prevsize < size ? prevsize : size );
        free_ex( ptr, ( void* )lstart );
        break;      
      }
    }
    i ++;
  }
  return temp;
}
Esempio n. 2
0
void freelocale(struct __locale_t *locobj)
{
  /* Nothing to do on !_MB_CAPABLE targets. */
#ifdef _MB_CAPABLE
  /* Sanity check.  The "C" locale is static, don't try to free it. */
  if (!locobj || locobj == __get_C_locale () || locobj == LC_GLOBAL_LOCALE)
    return;
#ifdef __HAVE_LOCALE_INFO__
  for (int i = 1; i < _LC_LAST; ++i)
    if (locobj->lc_cat[i].buf)
      {
	_free_r (p, (void *) locobj->lc_cat[i].ptr);
	_free_r (p, locobj->lc_cat[i].buf);
      }
#endif /* __HAVE_LOCALE_INFO__ */
  _free_r (p, locobj);
#else
	/* Silence warning */
	_CRT_UNUSED(locobj);
#endif /* _MB_CAPABLE */
}
Esempio n. 3
0
static int
funcloser (struct _reent *ptr,
       void *cookie)
{
  int result = 0;
  funcookie *c = (funcookie *) cookie;
  if (c->closefn)
    {
      errno = 0;
      if ((result = c->closefn (c->cookie)) < 0 && errno)
	__errno_r(ptr) = errno;
    }
  _free_r (ptr, c);
  return result;
}
Esempio n. 4
0
void * _realloc_r(struct _reent *r, void *ptr, size_t size)
{
   if (!ptr)
      return _malloc_r(r, size);

   if (_malloc_usable_size_r(r, ptr) >= size)
      return ptr;

   void *realloc_ptr = _malloc_r(r, size);

   if(!realloc_ptr)
      return NULL;

   memcpy(realloc_ptr, ptr, _malloc_usable_size_r(r, ptr));
   _free_r(r, ptr);

   return realloc_ptr;
}
Esempio n. 5
0
FILE *
_freopen64_r (struct _reent *ptr,
	const char *file,
	const char *mode,
	register FILE *fp)
{
  register int f;
  int flags, oflags, oflags2;
  int e = 0;


  CHECK_INIT (ptr, fp);

  /* We can't use the _newlib_flockfile_XXX macros here due to the
     interlocked locking with the sfp_lock. */
#ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  int __oldcancel;
  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel);
#endif
  oflags2 = fp->_flags2;
  if (!(oflags2 & __SNLK))
    _flockfile (fp);

  if ((flags = __sflags (ptr, mode, &oflags)) == 0)
    {
      if (!(oflags2 & __SNLK))
	_funlockfile (fp);
#ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
      pthread_setcancelstate (__oldcancel, &__oldcancel);
#endif
      _fclose_r (ptr, fp);
      return NULL;
    }

  /*
   * Remember whether the stream was open to begin with, and
   * which file descriptor (if any) was associated with it.
   * If it was attached to a descriptor, defer closing it,
   * so that, e.g., freopen("/dev/stdin", "r", stdin) works.
   * This is unnecessary if it was not a Unix file.
   */

  if (fp->_flags == 0)
    fp->_flags = __SEOF;	/* hold on to it */
  else
    {
      if (fp->_flags & __SWR)
	_fflush_r (ptr, fp);
      /*
       * If close is NULL, closing is a no-op, hence pointless.
       * If file is NULL, the file should not be closed.
       */
      if (fp->_close != NULL && file != NULL)
	fp->_close (ptr, fp->_cookie);
    }

  /*
   * Now get a new descriptor to refer to the new file, or reuse the
   * existing file descriptor if file is NULL.
   */

  if (file != NULL)
    {
      f = _open64_r (ptr, (char *) file, oflags, 0666);
      e = __errno_r(ptr);
    }
  else
    {
#ifdef HAVE_FCNTL
      int oldflags;
      /*
       * Reuse the file descriptor, but only if the new access mode is
       * equal or less permissive than the old.  F_SETFL correctly
       * ignores creation flags.
       */
      f = fp->_file;
      if ((oldflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1
	  || ! ((oldflags & O_ACCMODE) == O_RDWR
		|| ((oldflags ^ oflags) & O_ACCMODE) == 0)
	  || _fcntl_r (ptr, f, F_SETFL, oflags) == -1)
	f = -1;
#else
      /* We cannot modify without fcntl support.  */
      f = -1;
#endif

#ifdef __SCLE
      /*
       * F_SETFL doesn't change textmode.  Don't mess with modes of ttys.
       */
      if (0 <= f && ! isatty (f)
	  && setmode (f, oflags & (O_BINARY | O_TEXT)) == -1)
	f = -1;
#endif

      if (f < 0)
	{
	  e = EBADF;
	  if (fp->_close != NULL)
	    fp->_close (ptr, fp->_cookie);
	}
    }

  /*
   * Finish closing fp.  Even if the open succeeded above,
   * we cannot keep fp->_base: it may be the wrong size.
   * This loses the effect of any setbuffer calls,
   * but stdio has always done this before.
   */

  if (fp->_flags & __SMBF)
    _free_r (ptr, (char *) fp->_bf._base);
  fp->_w = 0;
  fp->_r = 0;
  fp->_p = NULL;
  fp->_bf._base = NULL;
  fp->_bf._size = 0;
  fp->_lbfsize = 0;
  if (HASUB (fp))
    FREEUB (ptr, fp);
  fp->_ub._size = 0;
  if (HASLB (fp))
    FREELB (ptr, fp);
  fp->_lb._size = 0;
  fp->_flags &= ~__SORD;
  fp->_flags2 &= ~__SWID;
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));

  if (f < 0)
    {				/* did not get it after all */
      __sfp_lock_acquire ();
      fp->_flags = 0;		/* set it free */
      __errno_r(ptr) = e;		/* restore in case _close clobbered */
      if (!(oflags2 & __SNLK))
	_funlockfile (fp);
#ifndef __SINGLE_THREAD__
      __lock_close_recursive (fp->_lock);
#endif
      __sfp_lock_release ();
#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS)
      pthread_setcancelstate (__oldcancel, &__oldcancel);
#endif
      return NULL;
    }

  fp->_flags = flags;
  fp->_file = f;
  fp->_cookie = (void *) fp;
  fp->_read = __sread;
  fp->_write = __swrite64;
  fp->_seek = __sseek;
  fp->_seek64 = __sseek64;
  fp->_close = __sclose;

#ifdef __SCLE
  if (__stextmode(fp->_file))
    fp->_flags |= __SCLE;
#endif

  fp->_flags |= __SL64;

  if (!(oflags2 & __SNLK))
    _funlockfile (fp);
#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS)
  pthread_setcancelstate (__oldcancel, &__oldcancel);
#endif
  return fp;
}
Esempio n. 6
0
double
_wcstod_l (struct _reent *ptr, const wchar_t *nptr, wchar_t **endptr,
	   locale_t loc)
{
        static const mbstate_t initial;
        mbstate_t mbs;
        double val;
        char *buf, *end;
        const wchar_t *wcp;
        size_t len;

        while (iswspace_l(*nptr, loc))
                nptr++;

        /*
         * Convert the supplied numeric wide char. string to multibyte.
         *
         * We could attempt to find the end of the numeric portion of the
         * wide char. string to avoid converting unneeded characters but
         * choose not to bother; optimising the uncommon case where
         * the input string contains a lot of text after the number
         * duplicates a lot of strtod()'s functionality and slows down the
         * most common cases.
         */
        wcp = nptr;
        mbs = initial;
        if ((len = _wcsnrtombs_l(ptr, NULL, &wcp, (size_t) -1, 0, &mbs, loc))
	    == (size_t) -1) {
                if (endptr != NULL)
                        *endptr = (wchar_t *)nptr;
                return (0.0);
        }
        if ((buf = _malloc_r(ptr, len + 1)) == NULL)
                return (0.0);
        mbs = initial;
        _wcsnrtombs_l(ptr, buf, &wcp, (size_t) -1, len + 1, &mbs, loc);

        /* Let strtod() do most of the work for us. */
        val = _strtod_l(ptr, buf, &end, loc);

        /*
         * We only know where the number ended in the _multibyte_
         * representation of the string. If the caller wants to know
         * where it ended, count multibyte characters to find the
         * corresponding position in the wide char string.
         */
        if (endptr != NULL) {
		/* The only valid multibyte char in a float converted by
		   strtod/wcstod is the radix char.  What we do here is,
		   figure out if the radix char was in the valid leading
		   float sequence in the incoming string.  If so, the
		   multibyte float string is strlen(radix char) - 1 bytes
		   longer than the incoming wide char string has characters.
		   To fix endptr, reposition end as if the radix char was
		   just one byte long.  The resulting difference (end - buf)
		   is then equivalent to the number of valid wide characters
		   in the input string. */
		len = strlen (__localeconv_l (loc)->decimal_point);
		if (len > 1) {
			char *d = strstr (buf,
					  __localeconv_l (loc)->decimal_point);
			if (d && d < end)
				end -= len - 1;
		}
                *endptr = (wchar_t *)nptr + (end - buf);
	}

        _free_r(ptr, buf);

        return (val);
}
Esempio n. 7
0
struct __locale_t *
_newlocale_r (struct _reent *p, int category_mask, const char *locale,
	      struct __locale_t *base)
{
#ifndef _MB_CAPABLE
  return __get_C_locale ();
#else /* _MB_CAPABLE */
  char new_categories[_LC_LAST][ENCODING_LEN + 1];
  struct __locale_t tmp_locale, *new_locale;
  int i;

  /* Convert LC_ALL_MASK to a mask containing all valid MASK values.
     This simplifies the code below. */
  if (category_mask & LC_ALL_MASK)
    {
      category_mask &= ~LC_ALL_MASK;
      category_mask |= LC_VALID_MASK;
    }
  /* Check for invalid mask values and valid locale ptr. */
  if ((category_mask & ~LC_VALID_MASK) || !locale)
    {
      p->_errno = EINVAL;
      return NULL;
    }
  /* If the new locale is supposed to be all default locale, just return
     a pointer to the default locale. */
  if ((!base && category_mask == 0)
      || (category_mask == LC_VALID_MASK
	  && (!strcmp (locale, "C") || !strcmp (locale, "POSIX"))))
    return __get_C_locale ();
  /* Start with setting all values to the default locale values. */
  tmp_locale = *__get_C_locale ();
  /* Fill out new category strings. */
  for (i = 1; i < _LC_LAST; ++i)
    {
      if (((1 << i) & category_mask) != 0)
	{
	  /* If locale is "", fetch from environment.  Otherwise use locale
	     name verbatim. */
	  const char *cat = (locale[0] == '\0') ? __get_locale_env (p, i)
						: locale;
	  if (strlen (cat) > ENCODING_LEN)
	    {
	      p->_errno = EINVAL;
	      return NULL;
	    }
	  strcpy (new_categories[i], cat);
	}
      else
	strcpy (new_categories[i], base ? base->categories[i] : "C");
    }
  /* Now go over all categories and set them. */
  for (i = 1; i < _LC_LAST; ++i)
    {
      /* If we have a base locale, and the category is not in category_mask
	 or the new category is the base categroy, just copy over. */
      if (base && (((1 << i) & category_mask) == 0
		   || !strcmp (base->categories[i], new_categories[i])))
	{
	  strcpy (tmp_locale.categories[i], new_categories[i]);
	  if (i == LC_CTYPE)
	    {
	      tmp_locale.wctomb = base->wctomb;
	      tmp_locale.mbtowc = base->mbtowc;
	      tmp_locale.cjk_lang = base->cjk_lang;
	      tmp_locale.ctype_ptr = base->ctype_ptr;
	    }
#ifdef __HAVE_LOCALE_INFO__
	  /* Mark the values as "has still to be copied".  We do this in
	     two steps to simplify freeing new locale types in case of a
	     subsequent error. */
	  tmp_locale.lc_cat[i].ptr = base->lc_cat[i].ptr;
	  tmp_locale.lc_cat[i].buf = (void *) -1;
#else /* !__HAVE_LOCALE_INFO__ */
	  if (i == LC_CTYPE)
	    strcpy (tmp_locale.ctype_codeset, base->ctype_codeset);
	  else if (i == LC_MESSAGES)
	    strcpy (tmp_locale.message_codeset, base->message_codeset);
#endif /* !__HAVE_LOCALE_INFO__ */
	}
      /* Otherwise, if the category is in category_mask, create entry. */
      else if (((1 << i) & category_mask) != 0)
	{
	  /* Nothing to do for "C"/"POSIX" locale. */
	  if (!strcmp (new_categories[i], "C")
	      || !strcmp (new_categories[i], "POSIX"))
	    continue;
	  /* Otherwise load locale data. */
	  else if (!__loadlocale (&tmp_locale, i, new_categories[i]))
	    goto error;
	}
    }
  /* Allocate new locale_t. */
  new_locale = (struct __locale_t *) _calloc_r (p, 1, sizeof *new_locale);
  if (!new_locale)
    goto error;
  if (base)
    {
#ifdef __HAVE_LOCALE_INFO__
      /* Step 2 of copying over..  Make sure to invalidate the copied buffer
	 pointers in base, so the subsequent _freelocale_r (base) doesn't free
	 the buffers now used in the new locale. */
      for (i = 1; i < _LC_LAST; ++i)
	if (tmp_locale.lc_cat[i].buf == (const void *) -1)
	  {
	    tmp_locale.lc_cat[i].buf = base->lc_cat[i].buf;
	    base->lc_cat[i].ptr = base->lc_cat[i].buf = NULL;
	  }
#endif /* __HAVE_LOCALE_INFO__ */
      _freelocale_r (p, base);
    }

  *new_locale = tmp_locale;
  return new_locale;

error:
  /* An error occured while we had already (potentially) allocated memory.
     Free memory and return NULL.  errno is supposed to be set already. */
#ifdef __HAVE_LOCALE_INFO__
  for (i = 1; i < _LC_LAST; ++i)
    if (((1 << i) & category_mask) != 0
	&& tmp_locale.lc_cat[i].buf
	&& tmp_locale.lc_cat[i].buf != (const void *) -1)
      {
	_free_r (p, (void *) tmp_locale.lc_cat[i].ptr);
	_free_r (p, tmp_locale.lc_cat[i].buf);
      }
#endif /* __HAVE_LOCALE_INFO__ */

  return NULL;
#endif /* _MB_CAPABLE */
}
Esempio n. 8
0
/**
Change stream buffering.
Changes the buffer to be used for I/O operations with the specified stream.
Size and mode for the buffer can be specified.
This function should be called once the file associated with the stream 
has been opened but before any input or output operation has been done.
The size of the buffer is specified by the size parameter,
and can be any value between 2 and 32767 in bytes, 
this value may be rounded down by some system due to specific alignment.
buffer can be NULL.
@return If the buffer is correctly assigned to the file a 0 value is returned.
On error, a non-zero value is returned. This can be because an invalid type or size has been specified or because an error allocating memory (if NULL buffer was specified).
@param fp pointer to an open file. 
@param buf User allocated buffer. Must have at least a size of size bytes. 
@param mode Specifies a mode for file buffering
@param Buffer size in bytes, must be more than 0 and less than 32768, this value may be rounded down by some systems due to specific alignment, in which case the minimum value should be 2.
*/
EXPORT_C int
setvbuf (FILE * fp, char *buf, int mode, size_t size)
{
  int ret = 0;
  CHECK_INIT (fp);

  /*
   * Verify arguments.  The `int' limit on `size' is due to this
   * particular implementation.
   */

  if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || (int) size < 0)
    return (EOF);

  /*
   * Write current buffer, if any; drop read count, if any.
   * Make sure putc() will not think fp is line buffered.
   * Free old buffer if it was from malloc().  Clear line and
   * non buffer flags, and clear malloc flag.
   */

  (void) fflush (fp);
  fp->_r = 0;
  fp->_lbfsize = 0;
  if (fp->_flags & __SMBF)
    _free_r (fp->_data, (void *) fp->_bf._base);
  fp->_flags &= ~(__SLBF | __SNBF | __SMBF);

  if (mode == _IONBF)
    goto nbf;

  /*
   * Allocate buffer if needed. */
  if (buf == NULL)
    {
      if ((buf = (char *)malloc (size)) == NULL)
	{
	  ret = EOF;
	  /* Try another size... */
	  buf = (char *)malloc (BUFSIZ);
	}
      if (buf == NULL)
	{
	  /* Can't allocate it, let's try another approach */
nbf:
	  fp->_flags |= __SNBF;
	  fp->_w = 0;
	  fp->_bf._base = fp->_p = fp->_nbuf;
	  fp->_bf._size = 1;
	  return (ret);
	}
      fp->_flags |= __SMBF;
    }
  /*
   * Now put back whichever flag is needed, and fix _lbfsize
   * if line buffered.  Ensure output flush on exit if the
   * stream will be buffered at all.
   * Force the buffer to be flushed and hence malloced on first use
   */

  switch (mode)
    {
    case _IOLBF:
      fp->_flags |= __SLBF;
      fp->_lbfsize = -(int)size;
      /* FALLTHROUGH */

    case _IOFBF:
      /* no flag */
      fp->_data->__cleanup = _cleanup_r;
      fp->_bf._base = fp->_p = (unsigned char *) buf;
      fp->_bf._size = size;
      break;
    }

  /*
   * Patch up write count if necessary.
   */

  if (fp->_flags & __SWR)
    fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : size;

  return 0;
}
Esempio n. 9
0
void free(void *p)
{
	_free_r(_REENT, p);
}