Ejemplo n.º 1
0
/* Return any pending signal or wait for one for the given time.  */
int
__sigtimedwait (const sigset_t *set, siginfo_t *info,
		const struct timespec *timeout)
{
  if (SINGLE_THREAD_P)
    return do_sigtimedwait (set, info, timeout);

  int oldtype = LIBC_CANCEL_ASYNC ();

  /* XXX The size argument hopefully will have to be changed to the
     real size of the user-level sigset_t.  */
  int result = do_sigtimedwait (set, info, timeout);

  LIBC_CANCEL_RESET (oldtype);

  return result;
}
Ejemplo n.º 2
0
/* We have to provide a default version of this function since the
   standards demand it.  The version which is a bit more reasonable is
   the BSD version.  So make this the default.  */
int sigpause (int mask)
{
#ifdef __UCLIBC_HAS_THREADS_NATIVE__
    if (SINGLE_THREAD_P)
        return __sigpause (mask, 0);

    int oldtype = LIBC_CANCEL_ASYNC ();

    int result = __sigpause (mask, 0);

    LIBC_CANCEL_RESET (oldtype);

    return result;
#else
    return __sigpause (mask, 0);
#endif
}
ssize_t __libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
	unsigned long args[3];

	args[0] = sockfd;
	args[1] = (unsigned long) msg;
	args[2] = flags;

	if (SINGLE_THREAD_P)
		return (__socketcall(SYS_SENDMSG, args));

#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = __socketcall(SYS_SENDMSG, args);
	LIBC_CANCEL_RESET (oldtype);
	return result;
#endif
}
int __libc_connect(int sockfd, const struct sockaddr *saddr, socklen_t addrlen)
{
	unsigned long args[3];

	args[0] = sockfd;
	args[1] = (unsigned long) saddr;
	args[2] = addrlen;

	if (SINGLE_THREAD_P)
		return __socketcall(SYS_CONNECT, args);

#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = __socketcall(SYS_CONNECT, args);
	LIBC_CANCEL_RESET (oldtype);
	return result;
#endif
}
Ejemplo n.º 5
0
ssize_t
__libc_send (int sockfd, const void *buffer, size_t len, int flags)
{
  ssize_t result;

  if (SINGLE_THREAD_P)
    result = INLINE_SYSCALL (sendto, 6, sockfd, buffer, len, flags, NULL, 0);
  else
    {
      int oldtype = LIBC_CANCEL_ASYNC ();

      result = INLINE_SYSCALL (sendto, 6, sockfd, buffer, len, flags, NULL, 0);

      LIBC_CANCEL_RESET (oldtype);
    }

  return result;
}
int __libc_accept(int s, struct sockaddr *addr, socklen_t * addrlen)
{
	unsigned long args[3];

	args[0] = s;
	args[1] = (unsigned long) addr;
	args[2] = (unsigned long) addrlen;

	if (SINGLE_THREAD_P)
		return __socketcall(SYS_ACCEPT, args);

#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = __socketcall(SYS_ACCEPT, args);
	LIBC_CANCEL_RESET (oldtype);
	return result;
#endif
}
Ejemplo n.º 7
0
int fcntl64(int fd, int cmd, ...)
{
	long arg;
	va_list list;

	va_start(list, cmd);
	arg = va_arg(list, long);
	va_end(list);

	if (SINGLE_THREAD_P || (cmd != F_SETLKW64))
		return __NC(fcntl64)(fd, cmd, arg);
# ifdef __NEW_THREADS
	int oldtype = LIBC_CANCEL_ASYNC();
	int result = __NC(fcntl64)(fd, cmd, arg);
	LIBC_CANCEL_RESET(oldtype);
	return result;
# endif
}
/* send, sendto added by [email protected] */
ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags)
{
	unsigned long args[4];

	args[0] = sockfd;
	args[1] = (unsigned long) buffer;
	args[2] = len;
	args[3] = flags;

	if (SINGLE_THREAD_P)
		return (__socketcall(SYS_SEND, args));

#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = __socketcall(SYS_SEND, args);
	LIBC_CANCEL_RESET (oldtype);
	return result;
#endif
}
int
__libc_system (const char *line)
{
  if (line == NULL)
    /* Check that we have a command processor available.  It might
       not be available after a chroot(), for example.  */
    return do_system ("exit 0") == 0;

  if (SINGLE_THREAD_P)
    return do_system (line);

  int oldtype = LIBC_CANCEL_ASYNC ();

  int result = do_system (line);

  LIBC_CANCEL_RESET (oldtype);

  return result;
}
Ejemplo n.º 10
0
int accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags)
{
	unsigned long args[4];

	args[0] = fd;
	args[1] = (unsigned long) addr;
	args[2] = (unsigned long) addrlen;
	args[3] = flags;
	if (SINGLE_THREAD_P)
		return __socketcall(SYS_ACCEPT4, args);
#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	else {
		int oldtype = LIBC_CANCEL_ASYNC ();
		int result = __socketcall(SYS_ACCEPT4, args);
		LIBC_CANCEL_RESET (oldtype);
		return result;
	}
#endif
}
Ejemplo n.º 11
0
int __libc_fcntl (int fd, int cmd, ...)
{
	va_list ap;
	void *arg;

	va_start (ap, cmd);
	arg = va_arg (ap, void *);
	va_end (ap);

#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	if (SINGLE_THREAD_P || (cmd != F_SETLKW && cmd != F_SETLKW64))
# if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64
		return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
# else
		return __syscall_fcntl(fd, cmd, arg);
# endif

	int oldtype = LIBC_CANCEL_ASYNC ();

# if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64
	int result = INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
# else
	int result = __syscall_fcntl(fd, cmd, arg);
# endif

	LIBC_CANCEL_RESET (oldtype);

	return result;
#else
# if __WORDSIZE == 32
	if (cmd == F_GETLK64 || cmd == F_SETLK64 || cmd == F_SETLKW64) {
#  if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64
		return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
#  else
		__set_errno(ENOSYS);
		return -1;
#  endif
	}
# endif
	return __syscall_fcntl(fd, cmd, arg);
#endif
}
Ejemplo n.º 12
0
/* Helper function to support starting threads for SIGEV_THREAD.  */
static void *
timer_helper_thread (void *arg)
{
  /* Wait for the SIGTIMER signal and none else.  */
  sigset_t ss;
  sigemptyset (&ss);
  sigaddset (&ss, SIGTIMER);

  /* Endless loop of waiting for signals.  The loop is only ended when
     the thread is canceled.  */
  while (1)
    {
      siginfo_t si;

      /* sigwaitinfo cannot be used here, since it deletes
	 SIGCANCEL == SIGTIMER from the set.  */

      int oldtype = LIBC_CANCEL_ASYNC ();

      /* XXX The size argument hopefully will have to be changed to the
	 real size of the user-level sigset_t.  */
      int result = INLINE_SYSCALL (rt_sigtimedwait, 4, &ss, &si, NULL,
				   _NSIG / 8);

      LIBC_CANCEL_RESET (oldtype);

      if (result > 0)
	{
	  if (si.si_code == SI_TIMER)
	    {
	      struct timer *tk = (struct timer *) si.si_ptr;

	      /* That the signal we are waiting for.  */
	      pthread_t th;
	      (void) pthread_create (&th, &tk->attr, timer_sigev_thread, tk);
	    }
	  else if (si.si_code == SI_TKILL)
	    /* The thread is canceled.  */
	    pthread_exit (NULL);
	}
    }
}
Ejemplo n.º 13
0
/* Reserve storage for the data of the file associated with FD.  */
int
fallocate (int fd, int mode, __off_t offset, __off_t len)
{
#ifdef __NR_fallocate
  if (SINGLE_THREAD_P)
    return INLINE_SYSCALL (fallocate, 4, fd, mode, offset, len);

  int result;
  int oldtype = LIBC_CANCEL_ASYNC ();

  result = INLINE_SYSCALL (fallocate, 4, fd, mode, offset, len);

  LIBC_CANCEL_RESET (oldtype);

  return result;
#else
  __set_errno (ENOSYS);
  return -1;
#endif
}
Ejemplo n.º 14
0
int ioctl(int fd, unsigned long int request, ...)
{
	void *arg;
	va_list list;

	va_start(list, request);
	arg = va_arg(list, void *);

	va_end(list);

	if (SINGLE_THREAD_P)
		return __syscall_ioctl(fd, request, arg);

#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = __syscall_ioctl(fd, request, arg);
	LIBC_CANCEL_RESET (oldtype);
	return result;
#endif
}
Ejemplo n.º 15
0
int open(const char *file, int oflag, ...)
{
	mode_t mode = 0;

	if (oflag & O_CREAT) {
		va_list arg;
		va_start(arg, oflag);
		mode = va_arg(arg, mode_t);
		va_end(arg);
	}

	if (SINGLE_THREAD_P)
		return __NC(open)(file, oflag, mode);
#ifdef __NEW_THREADS
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = __NC(open)(file, oflag, mode);
	LIBC_CANCEL_RESET (oldtype);
	return result;
#endif
}
Ejemplo n.º 16
0
int
__libc_fcntl (int fd, int cmd, ...)
{
  va_list ap;
  void *arg;

  va_start (ap, cmd);
  arg = va_arg (ap, void *);
  va_end (ap);

  if (SINGLE_THREAD_P || cmd != F_SETLKW)
    return do_fcntl (fd, cmd, arg);

  int oldtype = LIBC_CANCEL_ASYNC ();

  int result = do_fcntl (fd, cmd, arg);

  LIBC_CANCEL_RESET (oldtype);

  return result;
}
Ejemplo n.º 17
0
int
__libc_connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t addrlen)
{
  socklen_t new_addrlen;

  new_addrlen = __libc_sa_len ((addr.__sockaddr__)->sa_family);

  /* Only allow a smaller size, otherwise it could lead to
    stack corruption */
  if ((new_addrlen != 0) && (new_addrlen < addrlen))
    addrlen = new_addrlen;

  /* We pass 3 arguments.  */
  if (SINGLE_THREAD_P)
    return INLINE_SYSCALL (connect, 3, fd, addr.__sockaddr__, addrlen);

  int oldtype = LIBC_CANCEL_ASYNC ();
  int result = INLINE_SYSCALL (connect, 3, fd, addr.__sockaddr__, addrlen);
  LIBC_CANCEL_RESET (oldtype);
  return result;
}
Ejemplo n.º 18
0
int
__libc_fcntl (int fd, int cmd, ...)
{
  va_list ap;
  void *arg;

  va_start (ap, cmd);
  arg = va_arg (ap, void *);
  va_end (ap);

  if (SINGLE_THREAD_P || (cmd != F_SETLKW && cmd != F_SETLKW64))
    return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);

  int oldtype = LIBC_CANCEL_ASYNC ();

  int result = INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);

  LIBC_CANCEL_RESET (oldtype);

  return result;
}
Ejemplo n.º 19
0
int
__select(int nfds, fd_set *readfds,
         fd_set *writefds, fd_set *exceptfds,
         struct timeval *timeout)
{
  int result;
  struct timespec ts, *tsp = NULL;

  if (timeout)
    {
      TIMEVAL_TO_TIMESPEC (timeout, &ts);
      tsp = &ts;
    }

  if (SINGLE_THREAD_P)
    {
      result = INLINE_SYSCALL (pselect6, 6, nfds, readfds, writefds, exceptfds,
                               tsp, NULL);
    }
  else
    {
      int oldtype = LIBC_CANCEL_ASYNC ();

      result = INLINE_SYSCALL (pselect6, 6, nfds, readfds, writefds, exceptfds,
                               tsp, NULL);

      LIBC_CANCEL_RESET (oldtype);
    }

  if (timeout)
    {
      /* Linux by default will update the timeout after a pselect6 syscall
         (though the pselect() glibc call suppresses this behavior).
         Since select() on Linux has the same behavior as the pselect6
         syscall, we update the timeout here.  */
      TIMESPEC_TO_TIMEVAL (timeout, &ts);
    }

  return result;
}
/* recv, recvfrom added by [email protected] */
ssize_t __libc_recvfrom(int sockfd, __ptr_t buffer, size_t len, int flags,
		 struct sockaddr *to, socklen_t * tolen)
{
	unsigned long args[6];

	args[0] = sockfd;
	args[1] = (unsigned long) buffer;
	args[2] = len;
	args[3] = flags;
	args[4] = (unsigned long) to;
	args[5] = (unsigned long) tolen;

	if (SINGLE_THREAD_P)
		return (__socketcall(SYS_RECVFROM, args));

#ifdef __UCLIBC_HAS_THREADS_NATIVE__
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = __socketcall(SYS_RECVFROM, args);
	LIBC_CANCEL_RESET (oldtype);
	return result;
#endif
}
Ejemplo n.º 21
0
ssize_t
__libc_msgrcv (int msqid, void *msgp, size_t msgsz, long int msgtyp,
	       int msgflg)
{
  /* The problem here is that Linux' calling convention only allows up to
     fives parameters to a system call.  */
  struct ipc_kludge tmp;

  tmp.msgp = msgp;
  tmp.msgtyp = msgtyp;

  if (SINGLE_THREAD_P)
    return INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg, &tmp);

  int oldtype = LIBC_CANCEL_ASYNC ();

  ssize_t result = INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg,
				   &tmp);

   LIBC_CANCEL_RESET (oldtype);

  return result;
}
Ejemplo n.º 22
0
int
__poll (struct pollfd *fds, nfds_t nfds, int timeout)
{
  struct timespec timeout_ts;
  struct timespec *timeout_ts_p = NULL;

  if (timeout >= 0)
    {
      timeout_ts.tv_sec = timeout / 1000;
      timeout_ts.tv_nsec = (timeout % 1000) * 1000000;
      timeout_ts_p = &timeout_ts;
    }

  if (SINGLE_THREAD_P)
    return INLINE_SYSCALL (ppoll, 5, fds, nfds, timeout_ts_p, NULL, 0);

  int oldtype = LIBC_CANCEL_ASYNC ();

  int result = INLINE_SYSCALL (ppoll, 5, fds, nfds, timeout_ts_p, NULL, 0);

  LIBC_CANCEL_RESET (oldtype);

  return result;
}
Ejemplo n.º 23
0
/* Helper function to support starting threads for SIGEV_THREAD.  */
static void *
timer_helper_thread (void *arg)
{
    /* Wait for the SIGTIMER signal, allowing the setXid signal, and
       none else.  */
    sigset_t ss;
    sigemptyset (&ss);
    __sigaddset (&ss, SIGTIMER);

    syscall (SYS_thr_self, &__helper_tid);
    sem_post (&__helper_tid_semaphore);

    /* Endless loop of waiting for signals.  The loop is only ended when
       the thread is canceled.  */
    while (1)
    {
        siginfo_t si;

        /* sigwaitinfo cannot be used here, since it deletes
        SIGCANCEL == SIGTIMER from the set.  */

        int oldtype = LIBC_CANCEL_ASYNC ();

        /* XXX The size argument hopefully will have to be changed to the
        real size of the user-level sigset_t.  */
        int result = sigtimedwait (&ss, &si, NULL);

        LIBC_CANCEL_RESET (oldtype);

        if (result > 0)
        {
            if (si.si_code == SI_TIMER)
            {
                struct timer *tk = (struct timer *) si.si_value.sival_ptr;

                /* Check the timer is still used and will not go away
                while we are reading the values here.  */
                pthread_mutex_lock (&__active_timer_sigev_thread_lock);

                struct timer *runp = __active_timer_sigev_thread;
                while (runp != NULL)
                    if (runp == tk)
                        break;
                    else
                        runp = runp->next;

                if (runp != NULL)
                {
                    struct thread_start_data *td = malloc (sizeof (*td));

                    /* There is not much we can do if the allocation fails.  */
                    if (td != NULL)
                    {
                        /* This is the signal we are waiting for.  */
                        td->thrfunc = tk->thrfunc;
                        td->sival = tk->sival;

                        pthread_t th;
                        (void) pthread_create (&th, &tk->attr,
                                               timer_sigev_thread, td);
                    }
                }

                pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
            }
            else if (si.si_code == SI_LWP
                     /* Backward compatibility (see rev 211732 in -CURRENT).  */
                     || si.si_code == SI_USER)
                /* The thread is canceled.  */
                pthread_exit (NULL);
        }
    }
}
Ejemplo n.º 24
0
/* Spawn a new process executing PATH with the attributes describes in *ATTRP.
   Before running the process perform the actions described in FILE-ACTIONS. */
static int
__spawnix (pid_t * pid, const char *file,
	   const posix_spawn_file_actions_t * file_actions,
	   const posix_spawnattr_t * attrp, char *const argv[],
	   char *const envp[], int xflags,
	   int (*exec) (const char *, char *const *, char *const *))
{
  pid_t new_pid;
  struct posix_spawn_args args;
  int ec;

  if (__pipe2 (args.pipe, O_CLOEXEC))
    return errno;

  /* To avoid imposing hard limits on posix_spawn{p} the total number of
     arguments is first calculated to allocate a mmap to hold all possible
     values.  */
  ptrdiff_t argc = 0;
  /* Linux allows at most max (0x7FFFFFFF, 1/4 stack size) arguments
     to be used in a execve call.  We limit to INT_MAX minus one due the
     compatiblity code that may execute a shell script (maybe_script_execute)
     where it will construct another argument list with an additional
     argument.  */
  ptrdiff_t limit = INT_MAX - 1;
  while (argv[argc++] != NULL)
    if (argc == limit)
      {
	errno = E2BIG;
	return errno;
      }

  int prot = (PROT_READ | PROT_WRITE
	     | ((GL (dl_stack_flags) & PF_X) ? PROT_EXEC : 0));

  /* Add a slack area for child's stack.  */
  size_t argv_size = (argc * sizeof (void *)) + 512;
  size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
  void *stack = __mmap (NULL, stack_size, prot,
			MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
  if (__glibc_unlikely (stack == MAP_FAILED))
    {
      close_not_cancel (args.pipe[0]);
      close_not_cancel (args.pipe[1]);
      return errno;
    }

  /* Disable asynchronous cancellation.  */
  int cs = LIBC_CANCEL_ASYNC ();

  args.file = file;
  args.exec = exec;
  args.fa = file_actions;
  args.attr = attrp ? attrp : &(const posix_spawnattr_t) { 0 };
  args.argv = argv;
  args.argc = argc;
  args.envp = envp;
  args.xflags = xflags;

  __sigprocmask (SIG_BLOCK, &SIGALL_SET, &args.oldmask);

  /* The clone flags used will create a new child that will run in the same
     memory space (CLONE_VM) and the execution of calling thread will be
     suspend until the child calls execve or _exit.  These condition as
     signal below either by pipe write (_exit with SPAWN_ERROR) or
     a successful execve.
     Also since the calling thread execution will be suspend, there is not
     need for CLONE_SETTLS.  Although parent and child share the same TLS
     namespace, there will be no concurrent access for TLS variables (errno
     for instance).  */
  new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size,
		   CLONE_VM | CLONE_VFORK | SIGCHLD, &args);

  close_not_cancel (args.pipe[1]);

  if (new_pid > 0)
    {
      if (__read (args.pipe[0], &ec, sizeof ec) != sizeof ec)
	ec = 0;
      else
	__waitpid (new_pid, NULL, 0);
    }
  else
    ec = -new_pid;

  __munmap (stack, stack_size);

  close_not_cancel (args.pipe[0]);

  if (!ec && new_pid)
    *pid = new_pid;

  __sigprocmask (SIG_SETMASK, &args.oldmask, 0);

  LIBC_CANCEL_RESET (cs);

  return ec;
}

/* Spawn a new process executing PATH with the attributes describes in *ATTRP.
   Before running the process perform the actions described in FILE-ACTIONS. */
int
__spawni (pid_t * pid, const char *file,
	  const posix_spawn_file_actions_t * acts,
	  const posix_spawnattr_t * attrp, char *const argv[],
	  char *const envp[], int xflags)
{
  return __spawnix (pid, file, acts, attrp, argv, envp, xflags,
		    xflags & SPAWN_XFLAGS_USE_PATH ? __execvpe : __execve);
}