示例#1
0
文件: arena.c 项目: ddstreet/glibc
void
__malloc_fork_unlock_child (void)
{
  if (__malloc_initialized < 1)
    return;

  /* Push all arenas to the free list, except thread_arena, which is
     attached to the current thread.  */
  __libc_lock_init (free_list_lock);
  if (thread_arena != NULL)
    thread_arena->attached_threads = 1;
  free_list = NULL;
  for (mstate ar_ptr = &main_arena;; )
    {
      __libc_lock_init (ar_ptr->mutex);
      if (ar_ptr != thread_arena)
        {
	  /* This arena is no longer attached to any thread.  */
	  ar_ptr->attached_threads = 0;
          ar_ptr->next_free = free_list;
          free_list = ar_ptr;
        }
      ar_ptr = ar_ptr->next;
      if (ar_ptr == &main_arena)
        break;
    }

  __libc_lock_init (list_lock);
}
示例#2
0
/* Open a directory stream on a file descriptor in Hurd internal form.
   We do no checking here on the descriptor.  */
DIR *
_hurd_fd_opendir (struct hurd_fd *d)
{
  DIR *dirp;

  if (d == NULL)
    {
      errno = EBADF;
      return NULL;
    }

  dirp = (DIR *) malloc (sizeof (DIR));
  if (dirp == NULL)
    return NULL;

  /* Set the descriptor to close on exec. */
  HURD_CRITICAL_BEGIN;
  __spin_lock (&d->port.lock);
  d->flags |= FD_CLOEXEC;
  __spin_unlock (&d->port.lock);
  HURD_CRITICAL_END;

  dirp->__fd = d;
  dirp->__data = dirp->__ptr = NULL;
  dirp->__entry_data = dirp->__entry_ptr = 0;
  dirp->__allocation = 0;
  dirp->__size = 0;

  __libc_lock_init (dirp->__lock);

  return dirp;
}
示例#3
0
internal_function
__alloc_dir (int fd, bool close_fd, const struct stat64 *statp)
{
  /* We always have to set the close-on-exit flag if the user provided
     the file descriptor.  Otherwise only if we have no working
     O_CLOEXEC support.  */
#ifdef O_CLOEXEC
  if (! close_fd || ! check_have_o_cloexec (fd))
#endif
    {
      if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
	goto lose;
    }

  const size_t default_allocation = (BUFSIZ < sizeof (struct dirent64)
				     ? sizeof (struct dirent64) : BUFSIZ);
  size_t allocation;
#ifdef _STATBUF_ST_BLKSIZE
  if (__builtin_expect ((size_t) statp->st_blksize >= sizeof (struct dirent64),
			1))
    allocation = statp->st_blksize;
  else
#endif
    allocation = default_allocation;

  DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation);
  if (dirp == NULL)
    {
#ifdef _STATBUF_ST_BLKSIZE
      if (allocation == statp->st_blksize
	  && allocation != default_allocation)
	{
	  allocation = default_allocation;
	  dirp = (DIR *) malloc (sizeof (DIR) + allocation);
	}
      if (dirp == NULL)
#endif
      lose:
	{
	  if (close_fd)
	    {
	      int save_errno = errno;
	      close_not_cancel_no_status (fd);
	      __set_errno (save_errno);
	    }
	  return NULL;
	}
    }

  dirp->fd = fd;
#ifndef NOT_IN_libc
  __libc_lock_init (dirp->lock);
#endif
  dirp->allocation = allocation;
  dirp->size = 0;
  dirp->offset = 0;
  dirp->filepos = 0;

  return dirp;
}
示例#4
0
/* Open a directory stream on NAME.  */
DIR *
__opendir (const char *name)
{
  DIR *dirp;
  int fd;
  struct hurd_fd *d;

  if (name[0] == '\0')
    {
      /* POSIX.1-1990 says an empty name gets ENOENT;
	 but `open' might like it fine.  */
      __set_errno (ENOENT);
      return NULL;
    }

  {
    /* Append trailing slash to directory name to force ENOTDIR
       if it's not a directory.  */
    size_t len = strlen (name);
    if (name[len - 1] == '/')
      fd = __open (name, O_RDONLY);
    else
      {
	char n[len + 2];
	memcpy (n, name, len);
	n[len] = '/';
	n[len + 1] = '\0';
	fd = __open (n, O_RDONLY);
      }
  }
  if (fd < 0)
    return NULL;

  dirp = (DIR *) malloc (sizeof (DIR));
  if (dirp == NULL)
    {
      __close (fd);
      return NULL;
    }

  /* Extract the pointer to the descriptor structure.  */
  __mutex_lock (&_hurd_dtable_lock);
  d = dirp->__fd = _hurd_dtable[fd];
  __mutex_unlock (&_hurd_dtable_lock);

  /* Set the descriptor to close on exec. */
  __spin_lock (&d->port.lock);
  d->flags |= FD_CLOEXEC;
  __spin_unlock (&d->port.lock);

  dirp->__data = dirp->__ptr = NULL;
  dirp->__entry_data = dirp->__entry_ptr = 0;
  dirp->__allocation = 0;
  dirp->__size = 0;

  __libc_lock_init (dirp->__lock);

  return dirp;
}
示例#5
0
internal_function
__alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
{
  /* We always have to set the close-on-exit flag if the user provided
     the file descriptor.  Otherwise only if we have no working
     O_CLOEXEC support.  */
#ifdef O_CLOEXEC
  if ((! close_fd && (flags & O_CLOEXEC) == 0)
      || ! check_have_o_cloexec (fd))
#endif
    {
      if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
	goto lose;
    }

  const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64)
				     ? sizeof (struct dirent64) : 4 * BUFSIZ);
  const size_t small_allocation = (BUFSIZ < sizeof (struct dirent64)
				   ? sizeof (struct dirent64) : BUFSIZ);
  size_t allocation = default_allocation;
#ifdef _STATBUF_ST_BLKSIZE
  /* Increase allocation if requested, but not if the value appears to
     be bogus.  */
  if (statp != NULL)
    allocation = MIN (MAX ((size_t) statp->st_blksize, default_allocation),
		      MAX_DIR_BUFFER_SIZE);
#endif

  DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation);
  if (dirp == NULL)
    {
      allocation = small_allocation;
      dirp = (DIR *) malloc (sizeof (DIR) + allocation);

      if (dirp == NULL)
      lose:
	{
	  if (close_fd)
	    {
	      int save_errno = errno;
	      close_not_cancel_no_status (fd);
	      __set_errno (save_errno);
	    }
	  return NULL;
	}
    }

  dirp->fd = fd;
#if IS_IN (libc)
  __libc_lock_init (dirp->lock);
#endif
  dirp->allocation = allocation;
  dirp->size = 0;
  dirp->offset = 0;
  dirp->filepos = 0;
  dirp->errcode = 0;

  return dirp;
}
示例#6
0
文件: ptfork.c 项目: Jaden-J/uClibc
static pid_t __fork(void)
{
  pid_t pid;
  struct handler_list * prepare, * child, * parent;

  __pthread_mutex_lock(&pthread_atfork_lock);
  prepare = pthread_atfork_prepare;
  child = pthread_atfork_child;
  parent = pthread_atfork_parent;
  pthread_call_handlers(prepare);

  __pthread_once_fork_prepare();
#ifdef __MALLOC__
  __pthread_mutex_lock(&__malloc_sbrk_lock);
  __pthread_mutex_lock(&__malloc_heap_lock);
#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
  __pthread_mutex_lock(&__malloc_mmb_heap_lock);
#endif
#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__)
  __pthread_mutex_lock(&__malloc_lock);
#endif

  pid = __libc_fork();
  if (pid == 0) {
#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__)
    __libc_lock_init_recursive(__malloc_lock);
#elif defined(__MALLOC__)
#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
    __libc_lock_init_adaptive(__malloc_mmb_heap_lock);
#endif
    __libc_lock_init_adaptive(__malloc_heap_lock);
    __libc_lock_init(__malloc_sbrk_lock);
#endif
    __libc_lock_init_adaptive(pthread_atfork_lock);
    __pthread_reset_main_thread();
    __fresetlockfiles();
    __pthread_once_fork_child();
    pthread_call_handlers(child);
  } else {
#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__)
    __pthread_mutex_unlock(&__malloc_lock);
#elif defined(__MALLOC__)
#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__
    __pthread_mutex_unlock(&__malloc_mmb_heap_lock);
#endif
    __pthread_mutex_unlock(&__malloc_heap_lock);
    __pthread_mutex_unlock(&__malloc_sbrk_lock);
#endif
    __pthread_mutex_unlock(&pthread_atfork_lock);
    __pthread_once_fork_parent();
    pthread_call_handlers(parent);
  }
  return pid;
}
internal_function
__alloc_dir (int fd, bool close_fd, const struct stat64 *statp)
{
  if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
    goto lose;

  size_t allocation;
#ifdef _STATBUF_ST_BLKSIZE
  if (__builtin_expect ((size_t) statp->st_blksize >= sizeof (struct dirent64),
			1))
    allocation = statp->st_blksize;
  else
#endif
    allocation = (BUFSIZ < sizeof (struct dirent64)
		  ? sizeof (struct dirent64) : BUFSIZ);

  const int pad = -sizeof (DIR) % __alignof__ (struct dirent64);

  DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation + pad);
  if (dirp == NULL)
  lose:
    {
      if (close_fd)
	{
	  int save_errno = errno;
	  close_not_cancel_no_status (fd);
	  __set_errno (save_errno);
	}
      return NULL;
    }
  memset (dirp, '\0', sizeof (DIR));
  dirp->data = (char *) (dirp + 1) + pad;
  dirp->allocation = allocation;
  dirp->fd = fd;

  __libc_lock_init (dirp->lock);

  return dirp;
}
示例#8
0
/* Open a directory stream on NAME.  */
DIR *
__opendir (const char *name)
{
  DIR *dirp;
  int fd;
  struct hurd_fd *d;

  fd = __open (name, O_RDONLY);
  if (fd < 0)
    return NULL;

  dirp = (DIR *) malloc (sizeof (DIR));
  if (dirp == NULL)
    {
      __close (fd);
      return NULL;
    }

  /* Extract the pointer to the descriptor structure.  */
  __mutex_lock (&_hurd_dtable_lock);
  d = dirp->__fd = _hurd_dtable[fd];
  __mutex_unlock (&_hurd_dtable_lock);

  /* Set the descriptor to close on exec. */
  __spin_lock (&d->port.lock);
  d->flags |= FD_CLOEXEC;
  __spin_unlock (&d->port.lock);

  dirp->__data = dirp->__ptr = NULL;
  dirp->__entry_data = dirp->__entry_ptr = 0;
  dirp->__allocation = 0;
  dirp->__size = 0;

  __libc_lock_init (dirp->__lock);

  return dirp;
}
示例#9
0
/* Open a directory stream on NAME.  */
DIR *
__opendir (const char *name)
{
    DIR *dirp;
    struct stat64 statbuf;
    int fd;
    size_t allocation;
    int save_errno;

    if (__builtin_expect (name[0], '\1') == '\0')
    {
        /* POSIX.1-1990 says an empty name gets ENOENT;
        but `open' might like it fine.  */
        __set_errno (ENOENT);
        return NULL;
    }

#ifdef O_DIRECTORY
    /* Test whether O_DIRECTORY works.  */
    if (o_directory_works == 0)
        tryopen_o_directory ();

    /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
    if (o_directory_works < 0)
#endif
    {
        /* We first have to check whether the name is for a directory.  We
        cannot do this after the open() call since the open/close operation
         performed on, say, a tape device might have undesirable effects.  */
        if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0)
            return NULL;
        if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
        {
            __set_errno (ENOTDIR);
            return NULL;
        }
    }

    fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE);
    if (__builtin_expect (fd, 0) < 0)
        return NULL;

    /* Now make sure this really is a directory and nothing changed since
       the `stat' call.  We do not have to perform the test for the
       descriptor being associated with a directory if we know the
       O_DIRECTORY flag is honored by the kernel.  */
    if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0)
        goto lose;
#ifdef O_DIRECTORY
    if (o_directory_works <= 0)
#endif
    {
        if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
        {
            save_errno = ENOTDIR;
            goto lose;
        }
    }

    if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
        goto lose;

#ifdef _STATBUF_ST_BLKSIZE
    if (__builtin_expect ((size_t) statbuf.st_blksize >= sizeof (struct dirent64),
                          1))
        allocation = statbuf.st_blksize;
    else
#endif
        allocation = (BUFSIZ < sizeof (struct dirent64)
                      ? sizeof (struct dirent64) : BUFSIZ);

    const int pad = -sizeof (DIR) % __alignof__ (struct dirent64);

    dirp = (DIR *) malloc (sizeof (DIR) + allocation + pad);
    if (dirp == NULL)
lose:
    {
        save_errno = errno;
        close_not_cancel_no_status (fd);
        __set_errno (save_errno);
        return NULL;
    }
    memset (dirp, '\0', sizeof (DIR));
    dirp->data = (char *) (dirp + 1) + pad;
    dirp->allocation = allocation;
    dirp->fd = fd;

    __libc_lock_init (dirp->lock);

    return dirp;
}
示例#10
0
文件: arena.c 项目: ddstreet/glibc
static mstate
_int_new_arena (size_t size)
{
  mstate a;
  heap_info *h;
  char *ptr;
  unsigned long misalign;

  h = new_heap (size + (sizeof (*h) + sizeof (*a) + MALLOC_ALIGNMENT),
                mp_.top_pad);
  if (!h)
    {
      /* Maybe size is too large to fit in a single heap.  So, just try
         to create a minimally-sized arena and let _int_malloc() attempt
         to deal with the large request via mmap_chunk().  */
      h = new_heap (sizeof (*h) + sizeof (*a) + MALLOC_ALIGNMENT, mp_.top_pad);
      if (!h)
        return 0;
    }
  a = h->ar_ptr = (mstate) (h + 1);
  malloc_init_state (a);
  a->attached_threads = 1;
  /*a->next = NULL;*/
  a->system_mem = a->max_system_mem = h->size;

  /* Set up the top chunk, with proper alignment. */
  ptr = (char *) (a + 1);
  misalign = (unsigned long) chunk2mem (ptr) & MALLOC_ALIGN_MASK;
  if (misalign > 0)
    ptr += MALLOC_ALIGNMENT - misalign;
  top (a) = (mchunkptr) ptr;
  set_head (top (a), (((char *) h + h->size) - ptr) | PREV_INUSE);

  LIBC_PROBE (memory_arena_new, 2, a, size);
  mstate replaced_arena = thread_arena;
  thread_arena = a;
  __libc_lock_init (a->mutex);

  __libc_lock_lock (list_lock);

  /* Add the new arena to the global list.  */
  a->next = main_arena.next;
  /* FIXME: The barrier is an attempt to synchronize with read access
     in reused_arena, which does not acquire list_lock while
     traversing the list.  */
  atomic_write_barrier ();
  main_arena.next = a;

  __libc_lock_unlock (list_lock);

  __libc_lock_lock (free_list_lock);
  detach_arena (replaced_arena);
  __libc_lock_unlock (free_list_lock);

  /* Lock this arena.  NB: Another thread may have been attached to
     this arena because the arena is now accessible from the
     main_arena.next list and could have been picked by reused_arena.
     This can only happen for the last arena created (before the arena
     limit is reached).  At this point, some arena has to be attached
     to two threads.  We could acquire the arena lock before list_lock
     to make it less likely that reused_arena picks this new arena,
     but this could result in a deadlock with
     __malloc_fork_lock_parent.  */

  __libc_lock_lock (a->mutex);

  return a;
}