コード例 #1
0
ファイル: clock_nanosleep.c プロジェクト: bluecmd/or1k-glibc
/* We can simply use the syscall.  The CPU clocks are not supported
   with this function.  */
int
__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
		   struct timespec *rem)
{
  INTERNAL_SYSCALL_DECL (err);
  int r;

  if (clock_id == CLOCK_THREAD_CPUTIME_ID)
    return EINVAL;
  if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
    clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);

  if (SINGLE_THREAD_P)
    r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem);
  else
    {
      int oldstate = LIBC_CANCEL_ASYNC ();

      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req,
			    rem);

      LIBC_CANCEL_RESET (oldstate);
    }

  return (INTERNAL_SYSCALL_ERROR_P (r, err)
	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
}
コード例 #2
0
static int
maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
{
  int e = EINVAL;

  if (!__libc_missing_posix_cpu_timers)
    {
      INTERNAL_SYSCALL_DECL (err);
      int r = INTERNAL_GETTIME (clock_id, tp);
      if (!INTERNAL_SYSCALL_ERROR_P (r, err))
	return 0;

      e = INTERNAL_SYSCALL_ERRNO (r, err);
# ifndef __ASSUME_POSIX_TIMERS
      if (e == ENOSYS)
	{
	  __libc_missing_posix_timers = 1;
	  __libc_missing_posix_cpu_timers = 1;
	  e = EINVAL;
	}
      else
# endif
	{
	  if (e == EINVAL)
	    {
# ifdef HAVE_CLOCK_GETRES_VSYSCALL
	      /* Check whether the kernel supports CPU clocks at all.
		 If not, record it for the future.  */
	      r = INTERNAL_VSYSCALL (clock_getres, err, 2,
				     MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
				     NULL);
# else
	      /* Check whether the kernel supports CPU clocks at all.
		 If not, record it for the future.  */
	      r = INTERNAL_SYSCALL (clock_getres, err, 2,
				    MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
				    NULL);
# endif
	      if (INTERNAL_SYSCALL_ERROR_P (r, err))
		__libc_missing_posix_cpu_timers = 1;
	    }
	}
    }

  return e;
}
コード例 #3
0
static inline int
maybe_syscall_gettime_cputime (clockid_t clock_id, struct timespec *tp)
{
  return maybe_syscall_gettime_cpu
    (clock_id == CLOCK_THREAD_CPUTIME_ID
     ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
     : MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
     tp);
}
コード例 #4
0
int
__clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
{
  /* The clockid_t value is a simple computation from the PID.
     But we do a clock_getres call to validate it.  */

  const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED);

  INTERNAL_SYSCALL_DECL (err);
  int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL);
  if (!INTERNAL_SYSCALL_ERROR_P (r, err))
    {
      *clock_id = pidclock;
      return 0;
    }

  if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
    {
      /* The clock_getres system call checked the PID for us.  */
      return ESRCH;
    }
  else
    return INTERNAL_SYSCALL_ERRNO (r, err);
}
コード例 #5
0
int
timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
{
#undef timer_create
  {
    clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID
				 ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED)
				 : clock_id == CLOCK_THREAD_CPUTIME_ID
				 ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
				 : clock_id);

    /* If the user wants notification via a thread we need to handle
       this special.  */
    if (evp == NULL
	|| __builtin_expect (evp->sigev_notify != SIGEV_THREAD, 1))
      {
	struct sigevent local_evp;

	/* We avoid allocating too much memory by basically
	   using struct timer as a derived class with the
	   first two elements being in the superclass.  We only
	   need these two elements here.  */
	struct timer *newp = (struct timer *) malloc (offsetof (struct timer,
								thrfunc));
	if (newp == NULL)
	  /* No more memory.  */
	  return -1;

	if (evp == NULL)
	  {
	    /* The kernel has to pass up the timer ID which is a
	       userlevel object.  Therefore we cannot leave it up to
	       the kernel to determine it.  */
	    local_evp.sigev_notify = SIGEV_SIGNAL;
	    local_evp.sigev_signo = SIGALRM;
	    local_evp.sigev_value.sival_ptr = newp;

	    evp = &local_evp;
	  }

	kernel_timer_t ktimerid;
	int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp,
				     &ktimerid);

	if (retval != -1)
	  {
	    newp->sigev_notify = (evp != NULL
				  ? evp->sigev_notify : SIGEV_SIGNAL);
	    newp->ktimerid = ktimerid;

	    *timerid = (timer_t) newp;
	  }
	else
	  {
	    /* Cannot allocate the timer, fail.  */
	    free (newp);
	    retval = -1;
	  }

	return retval;
      }
    else
      {
	/* Create the helper thread.  */
	pthread_once (&__helper_once, __start_helper_thread);
	if (__helper_tid == 0)
	  {
	    /* No resources to start the helper thread.  */
	    __set_errno (EAGAIN);
	    return -1;
	  }

	struct timer *newp;
	newp = (struct timer *) malloc (sizeof (struct timer));
	if (newp == NULL)
	  return -1;

	/* Copy the thread parameters the user provided.  */
	newp->sival = evp->sigev_value;
	newp->thrfunc = evp->sigev_notify_function;
	newp->sigev_notify = SIGEV_THREAD;

	/* We cannot simply copy the thread attributes since the
	   implementation might keep internal information for
	   each instance.  */
	(void) pthread_attr_init (&newp->attr);
	if (evp->sigev_notify_attributes != NULL)
	  {
	    struct pthread_attr *nattr;
	    struct pthread_attr *oattr;

	    nattr = (struct pthread_attr *) &newp->attr;
	    oattr = (struct pthread_attr *) evp->sigev_notify_attributes;

	    nattr->schedparam = oattr->schedparam;
	    nattr->schedpolicy = oattr->schedpolicy;
	    nattr->flags = oattr->flags;
	    nattr->guardsize = oattr->guardsize;
	    nattr->stackaddr = oattr->stackaddr;
	    nattr->stacksize = oattr->stacksize;
	  }

	/* In any case set the detach flag.  */
	(void) pthread_attr_setdetachstate (&newp->attr,
					    PTHREAD_CREATE_DETACHED);

	/* Create the event structure for the kernel timer.  */
	struct sigevent sev =
	  { .sigev_value.sival_ptr = newp,
	    .sigev_signo = SIGTIMER,
	    .sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID,
	    ._sigev_un = { ._pad = { [0] = __helper_tid } } };

	/* Create the timer.  */
	INTERNAL_SYSCALL_DECL (err);
	int res;
	res = INTERNAL_SYSCALL (timer_create, err, 3,
				syscall_clockid, &sev, &newp->ktimerid);
	if (! INTERNAL_SYSCALL_ERROR_P (res, err))
	  {
	    /* Add to the queue of active timers with thread
	       delivery.  */
	    pthread_mutex_lock (&__active_timer_sigev_thread_lock);
	    newp->next = __active_timer_sigev_thread;
	    __active_timer_sigev_thread = newp;
	    pthread_mutex_unlock (&__active_timer_sigev_thread_lock);

	    *timerid = (timer_t) newp;
	    return 0;
	  }

	/* Free the resources.  */
	free (newp);

	__set_errno (INTERNAL_SYSCALL_ERRNO (res, err));

	return -1;
      }
  }
コード例 #6
0
int
clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
{
#ifdef __NR_clock_getres
  /* The clockid_t value is a simple computation from the PID.
     But we do a clock_getres call to validate it.  */

  const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED);

# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
  extern int __libc_missing_posix_cpu_timers attribute_hidden;
#  if !(__ASSUME_POSIX_TIMERS > 0)
  extern int __libc_missing_posix_timers attribute_hidden;
  if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
    __libc_missing_posix_cpu_timers = 1;
#  endif
  if (!__libc_missing_posix_cpu_timers)
# endif
    {
      INTERNAL_SYSCALL_DECL (err);
      int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL);
      if (!INTERNAL_SYSCALL_ERROR_P (r, err))
	{
	  *clock_id = pidclock;
	  return 0;
	}

# if !(__ASSUME_POSIX_TIMERS > 0)
      if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
	{
	  /* The kernel doesn't support these calls at all.  */
	  __libc_missing_posix_timers = 1;
	  __libc_missing_posix_cpu_timers = 1;
	}
      else
# endif
	if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
	  {
# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
	    if (pidclock == MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED)
		|| INTERNAL_SYSCALL_ERROR_P (INTERNAL_SYSCALL
					     (clock_getres, err, 2,
					      MAKE_PROCESS_CPUCLOCK
					      (0, CPUCLOCK_SCHED), NULL),
					     err))
	      /* The kernel doesn't support these clocks at all.  */
	      __libc_missing_posix_cpu_timers = 1;
	    else
# endif
	      /* The clock_getres system call checked the PID for us.  */
	      return ESRCH;
	  }
	else
	  return INTERNAL_SYSCALL_ERRNO (r, err);
    }
#endif

  /* We don't allow any process ID but our own.  */
  if (pid != 0 && pid != getpid ())
    return EPERM;

#ifdef CLOCK_PROCESS_CPUTIME_ID
  if (HAS_CPUCLOCK)
    {
      /* Store the number.  */
      *clock_id = CLOCK_PROCESS_CPUTIME_ID;

      return 0;
    }
#endif

  /* We don't have a timer for that.  */
  return ENOENT;
}