Esempio n. 1
0
/* Create a device file named PATH relative to FD, with permission and
   special bits MODE and device number DEV (which can be constructed
   from major and minor device numbers with the `makedev' macro above).  */
int
__xmknodat (int vers, int fd, const char *file, mode_t mode, dev_t * dev)
{
  if (vers != _MKNOD_VER)
    {
      __set_errno (EINVAL);
      return -1;
    }

# ifndef __ASSUME_ATFCTS
  if (__have_atfcts >= 0)
# endif
    {
      int result;

      /* The FreeBSD mknod() system call cannot be used to create FIFOs; we
         must use the mkfifo() system call for this purpose.  */
      if (S_ISFIFO (mode))
	result = INLINE_SYSCALL (mkfifoat, 3, fd, file, mode);
      else
	result = INLINE_SYSCALL (mknodat, 4, fd, file, mode, *dev);

# ifndef __ASSUME_ATFCTS
      if (result == -1 && errno == ENOSYS)
	__have_atfcts = -1;
      else
# endif
	return result;
    }

#ifndef __ASSUME_ATFCTS
  if (fd != AT_FDCWD && file[0] != '/')
    {
      int mib[4];
      size_t kf_len = 0;
      char *kf_buf, *kf_bufp;
      size_t filelen;

      if (fd < 0)
	{
	  __set_errno (EBADF);
	  return -1;
	}

      filelen = strlen (file);
      if (__builtin_expect (filelen == 0, 0))
	{
	  __set_errno (ENOENT);
	  return -1;
	}

      mib[0] = CTL_KERN;
      mib[1] = KERN_PROC;
      mib[2] = KERN_PROC_FILEDESC;
      mib[3] = __getpid ();

      if (__sysctl (mib, 4, NULL, &kf_len, NULL, 0) != 0)
	{
	  __set_errno (ENOSYS);
	  return -1;
	}

      kf_buf = alloca (kf_len + filelen);
      if (__sysctl (mib, 4, kf_buf, &kf_len, NULL, 0) != 0)
	{
	  __set_errno (ENOSYS);
	  return -1;
	}

      kf_bufp = kf_buf;
      while (kf_bufp < kf_buf + kf_len)
	{
	  struct kinfo_file *kf = (struct kinfo_file *) (uintptr_t) kf_bufp;

	  if (kf->kf_fd == fd)
	    {
	      if (kf->kf_type != KF_TYPE_VNODE ||
		  kf->kf_vnode_type != KF_VTYPE_VDIR)
		{
		  __set_errno (ENOTDIR);
		  return -1;
		}

	      strcat (kf->kf_path, "/");
	      strcat (kf->kf_path, file);
	      file = kf->kf_path;
	      break;
	    }
	  kf_bufp += kf->kf_structsize;
	}

      if (kf_bufp >= kf_buf + kf_len)
	{
	  __set_errno (EBADF);
	  return -1;
	}
    }

  return __xmknod (vers, file, mode, dev);
#endif
}
Esempio n. 2
0
int _DkMutexLockTimeout (struct mutex_handle * mut, int timeout)
{
    int i, c = 0;

    if (timeout == -1)
        return -_DkMutexLock(mut);

    struct atomic_int * m = &mut->value;

    /* Spin and try to take lock */
    for (i = 0 ; i < MUTEX_SPINLOCK_TIMES ; i++)
    {
        c = atomic_dec_and_test(m);
        if (c)
            goto success;
        cpu_relax();
    }

    /* The lock is now contended */

    int ret;

    if (timeout == 0) {
        ret = c ? 0 : -PAL_ERROR_TRYAGAIN;
        goto out;
    }

    while (!c) {
        int val = atomic_read(m);
        if (val == 1)
            goto again;

        struct timespec waittime;
        long sec = timeout / 1000000;
        long microsec = timeout - (sec * 1000000);
        waittime.tv_sec = sec;
        waittime.tv_nsec = microsec * 1000;

        ret = INLINE_SYSCALL(futex, 6, m, FUTEX_WAIT, val, &waittime, NULL, 0);

        if (IS_ERR(ret) &&
            ERRNO(ret) != EWOULDBLOCK &&
            ERRNO(ret) != EINTR) {
            ret = unix_to_pal_error(ERRNO(ret));
            goto out;
        }

#ifdef DEBUG_MUTEX
        if (IS_ERR(ret))
            printf("mutex held by thread %d\n", mut->owner);
#endif

again:
        /* Upon wakeup, we still need to check whether mutex is unlocked or
         * someone else took it.
         * If c==0 upon return from xchg (i.e., the older value of m==0), we
         * will exit the loop. Else, we sleep again (through a futex call).
         */
        c = atomic_dec_and_test(m);
    }

success:
#ifdef DEBUG_MUTEX
    mut->owner = INLINE_SYSCALL(gettid, 0);
#endif
    ret = 0;
out:
    return ret;
}
Esempio n. 3
0
File: chown.c Progetto: chonghw/pemu
int
__real_chown (const char *file, uid_t owner, gid_t group)
{
# if __ASSUME_LCHOWN_SYSCALL == 0
  static int __libc_old_chown;
  int result;

  if (!__libc_old_chown)
    {
      int saved_errno = errno;
#  ifdef __NR_chown32
      if (__libc_missing_32bit_uids <= 0)
	{
	  int result;
	  int saved_errno = errno;

	  result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
	  if (result == 0 || errno != ENOSYS)
	    return result;

	  __set_errno (saved_errno);
	  __libc_missing_32bit_uids = 1;
	}
#  endif /* __NR_chown32 */
      if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
	  || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
	{
	  __set_errno (EINVAL);
	  return -1;
	}

      result = INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);

      if (result >= 0 || errno != ENOSYS)
	return result;

      __set_errno (saved_errno);
      __libc_old_chown = 1;
    }

  return __lchown (file, owner, group);
# elif __ASSUME_32BITUIDS
  /* This implies __ASSUME_LCHOWN_SYSCALL.  */
  return INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
# else
  /* !__ASSUME_32BITUIDS && ASSUME_LCHOWN_SYSCALL  */
#  ifdef __NR_chown32
  if (__libc_missing_32bit_uids <= 0)
    {
      int result;
      int saved_errno = errno;

      result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
      if (result == 0 || errno != ENOSYS)
	return result;

      __set_errno (saved_errno);
      __libc_missing_32bit_uids = 1;
    }
#  endif /* __NR_chown32 */
  if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
      || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
    {
      __set_errno (EINVAL);
      return -1;
    }

  return INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);
# endif
}
Esempio n. 4
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);

  /* 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;

	      /* 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_TKILL)
	    /* The thread is canceled.  */
	    pthread_exit (NULL);
	}
    }
}
Esempio n. 5
0
pid_t __libc_fork (void)
{
    return (pid_t) INLINE_SYSCALL (clone, 2, SIGCHLD, 0);
}
Esempio n. 6
0
/* Change the owner and group of FILE.  */
int
__lchown (const char *file, uid_t owner, gid_t group)
{
  return INLINE_SYSCALL (fchownat, 5, AT_FDCWD, file, owner, group,
                         AT_SYMLINK_NOFOLLOW);
}
Esempio n. 7
0
int _DkVirtualMemoryProtect (void * addr, int size, int prot)
{
    int ret = INLINE_SYSCALL(mprotect, 3, addr, size, HOST_PROT(prot));

    return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : 0;
}
Esempio n. 8
0
int
__new_semctl (int semid, int semnum, int cmd, ...)
{
  union semun arg;
  va_list ap;

  va_start (ap, cmd);

  /* Get the argument.  */
  arg = va_arg (ap, union semun);

  va_end (ap);

#if __ASSUME_32BITUIDS > 0
  return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
			 CHECK_SEMCTL (&arg, semid, cmd | __IPC_64));
#else
  switch (cmd) {
    case SEM_STAT:
    case IPC_STAT:
    case IPC_SET:
      break;
    default:
      return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd,
			     CHECK_SEMCTL (&arg, semid, cmd));
  }

  {
    int result;
    struct __old_semid_ds old;
    struct semid_ds *buf;

#ifdef __NR_getuid32
    if (__libc_missing_32bit_uids <= 0)
      {
	if (__libc_missing_32bit_uids < 0)
	  {
	    int save_errno = errno;

	    /* Test presence of new IPC by testing for getuid32 syscall.  */
	    result = INLINE_SYSCALL (getuid32, 0);
	    if (result == -1 && errno == ENOSYS)
	      __libc_missing_32bit_uids = 1;
	    else
	      __libc_missing_32bit_uids = 0;
	    __set_errno(save_errno);
	  }
	if (__libc_missing_32bit_uids <= 0)
	  {
	    result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64,
				     CHECK_SEMCTL (&arg, semid, cmd | __IPC_64));
	    return result;
	  }
      }
#endif

    buf = arg.buf;
    arg.__old_buf = &old;
    if (cmd == IPC_SET)
      {
	old.sem_perm.uid = buf->sem_perm.uid;
	old.sem_perm.gid = buf->sem_perm.gid;
	old.sem_perm.mode = buf->sem_perm.mode;
	if (old.sem_perm.uid != buf->sem_perm.uid ||
	    old.sem_perm.gid != buf->sem_perm.gid)
	  {
	    __set_errno (EINVAL);
	    return -1;
	  }
      }
    result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd,
			     CHECK_SEMCTL (&arg, semid, cmd));
    if (result != -1 && cmd != IPC_SET)
      {
	memset(buf, 0, sizeof(*buf));
	buf->sem_perm.__key = old.sem_perm.__key;
	buf->sem_perm.uid = old.sem_perm.uid;
	buf->sem_perm.gid = old.sem_perm.gid;
	buf->sem_perm.cuid = old.sem_perm.cuid;
	buf->sem_perm.cgid = old.sem_perm.cgid;
	buf->sem_perm.mode = old.sem_perm.mode;
	buf->sem_perm.__seq = old.sem_perm.__seq;
	buf->sem_otime = old.sem_otime;
	buf->sem_ctime = old.sem_ctime;
	buf->sem_nsems = old.sem_nsems;
      }
    return result;
  }
#endif
}
Esempio n. 9
0
/* Create a one-way communication channel (__pipe).
   If successful, two file descriptors are stored in PIPEDES;
   bytes written on PIPEDES[1] can be read from PIPEDES[0].
   Returns 0 if successful, -1 if not.  */
int
__pipe (int __pipedes[2])
{
  return INLINE_SYSCALL (pipe2, 2, __pipedes, 0);
}
Esempio n. 10
0
int
__shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
  return INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, buf);
}
Esempio n. 11
0
/* Call kernel with additional two arguments the syscall requires.  */
int
reboot (int howto)
{
  return INLINE_SYSCALL (reboot, 3, (int) 0xfee1dead, 672274793, howto);
}
Esempio n. 12
0
/* Create a directory named PATH with protections MODE.  */
int
__mkdir (const char *path, mode_t mode)
{
  return INLINE_SYSCALL (mkdirat, 3, AT_FDCWD, path, mode);
}
Esempio n. 13
0
/* Get information about the file NAME in BUF.  */
int
__xstat (int vers, const char *name, struct stat *buf)
{
  return INLINE_SYSCALL (stat, 2, name, buf);
}
Esempio n. 14
0
int
__real_chown (const char *file, uid_t owner, gid_t group)
{
  return INLINE_SYSCALL (chown32, 3, file, owner, group);
}
Esempio n. 15
0
/* Return information about the filesystem on which FD resides.  */
int
__fstatfs (int fd, struct statfs *buf)
{
  int rc = INLINE_SYSCALL (fstatfs64, 3, fd, sizeof (*buf), buf);
  return rc ?: statfs_overflow (buf);
}
Esempio n. 16
0
int
lockf64 (int fd, int cmd, off64_t len64)
{
#if __ASSUME_FCNTL64 == 0
  struct flock fl;
  off_t len = (off_t) len64;
#endif
#ifdef __NR_fcntl64
  struct flock64 fl64;
  int cmd64;
#endif

#if __ASSUME_FCNTL64 == 0
  memset ((char *) &fl, '\0', sizeof (fl));

  /* lockf is always relative to the current file position.  */
  fl.l_whence = SEEK_CUR;
  fl.l_start = 0;
  fl.l_len = len;
#endif
#ifdef __NR_fcntl64
# if __ASSUME_FCNTL64 == 0
  if (!__have_no_fcntl64)
    {
# endif
      memset ((char *) &fl64, '\0', sizeof (fl64));
      fl64.l_whence = SEEK_CUR;
      fl64.l_start = 0;
      fl64.l_len = len64;
# if __ASSUME_FCNTL64 == 0
    }
# endif
#endif

#if __ASSUME_FCNTL64 == 0 && !defined __NR_fcntl64
  if (len64 != (off64_t) len)
    {
      /* We can't represent the length.  */
      __set_errno (EOVERFLOW);
      return -1;
    }
#endif
  switch (cmd)
    {
    case F_TEST:
      /* Test the lock: return 0 if FD is unlocked or locked by this process;
	 return -1, set errno to EACCES, if another process holds the lock.  */
#if __ASSUME_FCNTL64 > 0
      fl64.l_type = F_RDLCK;
      if (INLINE_SYSCALL (fcntl64, 3, fd, F_GETLK64, &fl64) < 0)
        return -1;
      if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
        return 0;
      __set_errno (EACCES);
      return -1;
#else
# ifdef __NR_fcntl64
      if (!__have_no_fcntl64)
	{
	  int res;

	  fl64.l_type = F_RDLCK;
	  res = INLINE_SYSCALL (fcntl64, 3, fd, F_GETLK64, &fl64);
	  /* If errno == ENOSYS try the 32bit interface if len64 can
             be represented with 32 bits.  */

	  if (res == 0)
	    {
	      if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
		return 0;
	      __set_errno (EACCES);
	      return -1;
	    }
	  else if (errno == ENOSYS)
	    __have_no_fcntl64 = 1;
	  else
	    /* res < 0 && errno != ENOSYS.  */
	    return -1;
	  if (len64 != (off64_t) len)
	    {
	      /* We can't represent the length.  */
	      __set_errno (EOVERFLOW);
	      return -1;
	    }
	}
# endif
      fl.l_type = F_RDLCK;
      if (__fcntl (fd, F_GETLK, &fl) < 0)
	return -1;
      if (fl.l_type == F_UNLCK || fl.l_pid == __getpid ())
	return 0;
      __set_errno (EACCES);
      return -1;
#endif
    case F_ULOCK:
#if __ASSUME_FCNTL64 == 0
      fl.l_type = F_UNLCK;
      cmd = F_SETLK;
#endif
#ifdef __NR_fcntl64
      fl64.l_type = F_UNLCK;
      cmd64 = F_SETLK64;
#endif
      break;
    case F_LOCK:
#if __ASSUME_FCNTL64 == 0
      fl.l_type = F_WRLCK;
      cmd = F_SETLKW;
#endif
#ifdef __NR_fcntl64
      fl64.l_type = F_WRLCK;
      cmd64 = F_SETLKW64;
#endif
      break;
    case F_TLOCK:
#if __ASSUME_FCNTL64 == 0
      fl.l_type = F_WRLCK;
      cmd = F_SETLK;
#endif
#ifdef __NR_fcntl64
      fl64.l_type = F_WRLCK;
      cmd64 = F_SETLK64;
#endif
      break;

    default:
      __set_errno (EINVAL);
      return -1;
    }
#if __ASSUME_FCNTL64 > 0
  return INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);
#else
# ifdef __NR_fcntl64

  if (!__have_no_fcntl64)
    {
      int res = INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);

      /* If errno == ENOSYS try the 32bit interface if len64 can
	 be represented with 32 bits.  */
      if (res == 0 || errno != ENOSYS)
	return res;

      __have_no_fcntl64 = 1;

      if (len64 != (off64_t) len)
	{
	  /* We can't represent the length.  */
	  __set_errno (EOVERFLOW);
	  return -1;
	}
    }
# endif
  return __fcntl (fd, cmd, &fl);
#endif
}
Esempio n. 17
0
/* For Linux we must convert the array of groups from the format that the
   kernel returns.  */
int
__getgroups (int n, gid_t *groups)
{
  return INLINE_SYSCALL (getgroups32, 2, n, CHECK_N (groups, n));
}
Esempio n. 18
0
ssize_t
__libc_recv (int fd, void *buf, size_t n, int flags)
{
  return INLINE_SYSCALL (recvfrom, 6, fd, buf, n, flags, NULL, NULL);
}
Esempio n. 19
0
int _DkVirtualMemoryFree (void * addr, int size)
{
    int ret = INLINE_SYSCALL(munmap, 2, addr, size);

    return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : 0;
}
Esempio n. 20
0
int
__new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
#if __ASSUME_IPC64 > 0
  return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0,
			 CHECK_1 (buf));
#else
  switch (cmd) {
    case SHM_STAT:
    case IPC_STAT:
    case IPC_SET:
#if __WORDSIZE != 32
    case IPC_INFO:
#endif
      break;
    default:
      return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0,
			     CHECK_1 (buf));
  }

  {
    int save_errno = errno, result;
    union
      {
	struct __old_shmid_ds ds;
	struct __old_shminfo info;
      } old;

    /* Unfortunately there is no way how to find out for sure whether
       we should use old or new shmctl.  */
    result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0,
			     CHECK_1 (buf));
    if (result != -1 || errno != EINVAL)
      return result;

    __set_errno(save_errno);
    if (cmd == IPC_SET)
      {
	old.ds.shm_perm.uid = buf->shm_perm.uid;
	old.ds.shm_perm.gid = buf->shm_perm.gid;
	old.ds.shm_perm.mode = buf->shm_perm.mode;
	if (old.ds.shm_perm.uid != buf->shm_perm.uid ||
	    old.ds.shm_perm.gid != buf->shm_perm.gid)
	  {
	    __set_errno (EINVAL);
	    return -1;
	  }
      }
    result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0,
			     __ptrvalue (&old.ds));
    if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT))
      {
	memset(buf, 0, sizeof(*buf));
	buf->shm_perm.__key = old.ds.shm_perm.__key;
	buf->shm_perm.uid = old.ds.shm_perm.uid;
	buf->shm_perm.gid = old.ds.shm_perm.gid;
	buf->shm_perm.cuid = old.ds.shm_perm.cuid;
	buf->shm_perm.cgid = old.ds.shm_perm.cgid;
	buf->shm_perm.mode = old.ds.shm_perm.mode;
	buf->shm_perm.__seq = old.ds.shm_perm.__seq;
	buf->shm_atime = old.ds.shm_atime;
	buf->shm_dtime = old.ds.shm_dtime;
	buf->shm_ctime = old.ds.shm_ctime;
	buf->shm_segsz = old.ds.shm_segsz;
	buf->shm_nattch = old.ds.shm_nattch;
	buf->shm_cpid = old.ds.shm_cpid;
	buf->shm_lpid = old.ds.shm_lpid;
      }
#if __WORDSIZE != 32
    else if (result != -1 && cmd == IPC_INFO)
      {
	struct shminfo *i = (struct shminfo *)buf;

	memset(i, 0, sizeof(*i));
	i->shmmax = old.info.shmmax;
	i->shmmin = old.info.shmmin;
	i->shmmni = old.info.shmmni;
	i->shmseg = old.info.shmseg;
	i->shmall = old.info.shmall;
      }
#endif
    return result;
  }
#endif
}
Esempio n. 21
0
pid_t
__libc_fork (void)
{
  pid_t pid;
  struct used_handler
  {
    struct fork_handler *handler;
    struct used_handler *next;
  } *allp = NULL;

  /* Run all the registered preparation handlers.  In reverse order.
     While doing this we build up a list of all the entries.  */
  struct fork_handler *runp;
  while ((runp = __fork_handlers) != NULL)
    {
      /* Make sure we read from the current RUNP pointer.  */
      atomic_full_barrier ();

      unsigned int oldval = runp->refcntr;

      if (oldval == 0)
	/* This means some other thread removed the list just after
	   the pointer has been loaded.  Try again.  Either the list
	   is empty or we can retry it.  */
	continue;

      /* Bump the reference counter.  */
      if (atomic_compare_and_exchange_bool_acq (&__fork_handlers->refcntr,
						oldval + 1, oldval))
	/* The value changed, try again.  */
	continue;

      /* We bumped the reference counter for the first entry in the
	 list.  That means that none of the following entries will
	 just go away.  The unloading code works in the order of the
	 list.

         While executing the registered handlers we are building a
         list of all the entries so that we can go backward later on.  */
      while (1)
	{
	  /* Execute the handler if there is one.  */
	  if (runp->prepare_handler != NULL)
	    runp->prepare_handler ();

	  /* Create a new element for the list.  */
	  struct used_handler *newp
	    = (struct used_handler *) alloca (sizeof (*newp));
	  newp->handler = runp;
	  newp->next = allp;
	  allp = newp;

	  /* Advance to the next handler.  */
	  runp = runp->next;
	  if (runp == NULL)
	    break;

	  /* Bump the reference counter for the next entry.  */
	  atomic_increment (&runp->refcntr);
	}

      /* We are done.  */
      break;
    }

  __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock);

#ifndef NDEBUG
  pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
#endif

  /* We need to prevent the getpid() code to update the PID field so
     that, if a signal arrives in the child very early and the signal
     handler uses getpid(), the value returned is correct.  */
  pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid);
  THREAD_SETMEM (THREAD_SELF, pid, -parentpid);

#ifdef ARCH_FORK
  pid = ARCH_FORK ();
#else
# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used"
  pid = INLINE_SYSCALL (fork, 0);
#endif


  if (pid == 0)
    {
      struct pthread *self = THREAD_SELF;

      assert (THREAD_GETMEM (self, tid) != ppid);

      if (__fork_generation_pointer != NULL)
	*__fork_generation_pointer += 4;

      /* Adjust the PID field for the new process.  */
      THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid));

#if HP_TIMING_AVAIL
      /* The CPU clock of the thread and process have to be set to zero.  */
      hp_timing_t now;
      HP_TIMING_NOW (now);
      THREAD_SETMEM (self, cpuclock_offset, now);
      GL(dl_cpuclock_offset) = now;
#endif

      /* Reset the file list.  These are recursive mutexes.  */
      fresetlockfiles ();

      /* Reset locks in the I/O code.  */
      STDIO_INIT_MUTEX(_stdio_openlist_add_lock);

      /* XXX reset any locks in dynamic loader */

      /* Run the handlers registered for the child.  */
      while (allp != NULL)
	{
	  if (allp->handler->child_handler != NULL)
	    allp->handler->child_handler ();

	  /* Note that we do not have to wake any possible waiter.
 	     This is the only thread in the new process.  The count
 	     may have been bumped up by other threads doing a fork.
 	     We reset it to 1, to avoid waiting for non-existing
 	     thread(s) to release the count.  */
	  allp->handler->refcntr = 1;

	  /* XXX We could at this point look through the object pool
	     and mark all objects not on the __fork_handlers list as
	     unused.  This is necessary in case the fork() happened
	     while another thread called dlclose() and that call had
	     to create a new list.  */

	  allp = allp->next;
	}

      /* Initialize the fork lock.  */
      __fork_lock = LLL_LOCK_INITIALIZER;
    }
  else
    {
      assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid);

      /* Restore the PID value.  */
      THREAD_SETMEM (THREAD_SELF, pid, parentpid);

      /* We execute this even if the 'fork' call failed.  */
      __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock);

      /* Run the handlers registered for the parent.  */
      while (allp != NULL)
	{
	  if (allp->handler->parent_handler != NULL)
	    allp->handler->parent_handler ();

	  if (atomic_decrement_and_test (&allp->handler->refcntr)
	      && allp->handler->need_signal)
	    lll_futex_wake (allp->handler->refcntr, 1, LLL_PRIVATE);

	  allp = allp->next;
	}
    }

  return pid;
}
Esempio n. 22
0
time_t time(time_t *tp)
{
	return INLINE_SYSCALL(time, 1, tp);
}
Esempio n. 23
0
int sys$testcode(void) {
	  return INLINE_SYSCALL($setprn,0);
}
Esempio n. 24
0
int __libc_statfs(const char *path, struct statfs *buf)
{
	int err = INLINE_SYSCALL(statfs64, 3, path, sizeof(*buf), buf);
	return err;
}
Esempio n. 25
0
int
putmsg (int fildes, const struct strbuf *ctlptr, const struct strbuf *dataptr,
	int flags)
{
  return INLINE_SYSCALL (putpmsg, 5, fildes, ctlptr, dataptr, -1, flags);
}
Esempio n. 26
0
/* Remove the link named NAME.  */
int
__unlink (const char *name)
{
  return INLINE_SYSCALL (unlinkat, 3, AT_FDCWD, name, 0);
}
Esempio n. 27
0
File: chown.c Progetto: chonghw/pemu
/* Compiling under older kernels.  */
int
__chown_is_lchown (const char *file, uid_t owner, gid_t group)
{
  return INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);
}
Esempio n. 28
0
void _DkPrintConsole (const void * buf, int size)
{
    INLINE_SYSCALL(write, 3, 2, buf, size);
}
Esempio n. 29
0
/* Make a link to FROM called TO.  */
int
__link (const char *from, const char *to)
{
    return INLINE_SYSCALL (linkat, 5, AT_FDCWD, from, AT_FDCWD, to, 0);
}
Esempio n. 30
0
/* internally to wait for one object. Also used as a shortcut to wait
   on events and semaphores */
static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout)
{
    /* only for all these handle which has a file descriptor, or
       a eventfd. events and semaphores will skip this part */
    if (handle->__in.flags & HAS_FDS) {
        struct pollfd fds[MAX_FDS];
        int off[MAX_FDS];
        int nfds = 0;
        for (int i = 0 ; i < MAX_FDS ; i++) {
            int events = 0;

            if ((handle->__in.flags & RFD(i)) &&
                !(handle->__in.flags & ERROR(i)))
                events |= POLLIN;

            if ((handle->__in.flags & WFD(i)) &&
                !(handle->__in.flags & WRITEABLE(i)) &&
                !(handle->__in.flags & ERROR(i)))
                events |= POLLOUT;

            if (events) {
                fds[nfds].fd = handle->__in.fds[i];
                fds[nfds].events = events|POLLHUP|POLLERR;
                fds[nfds].revents = 0;
                off[nfds] = i;
                nfds++;
            }
        }

        if (!nfds)
            return -PAL_ERROR_TRYAGAIN;

        int ret = INLINE_SYSCALL(poll, 3, &fds, nfds,
                                 timeout ? timeout : -1);

        if (IS_ERR(ret))
            switch (ERRNO(ret)) {
                case EINTR:
                    return -PAL_ERROR_INTERRUPTED;
                default:
                    return unix_to_pal_error(ERRNO(ret));
            }

        if (!ret)
            return -PAL_ERROR_TRYAGAIN;

        for (int i = 0 ; i < nfds ; i++) {
            if (!fds[i].revents)
                continue;
            if (fds[i].revents & POLLOUT)
                handle->__in.flags |= WRITEABLE(off[i]);
            if (fds[i].revents & (POLLHUP|POLLERR))
                handle->__in.flags |= ERROR(off[i]);
        }

        return 0;
    }

    const struct handle_ops * ops = HANDLE_OPS(handle);

    if (!ops->wait)
        return -PAL_ERROR_NOTSUPPORT;

    return ops->wait(handle, timeout);
}