diff options
Diffstat (limited to 'librt/clock_nanosleep.c')
| -rw-r--r-- | librt/clock_nanosleep.c | 96 | 
1 files changed, 96 insertions, 0 deletions
| diff --git a/librt/clock_nanosleep.c b/librt/clock_nanosleep.c new file mode 100644 index 000000000..69e60087e --- /dev/null +++ b/librt/clock_nanosleep.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <time.h> +#include <errno.h> + +#include <sysdep-cancel.h> +#include <bits/kernel-features.h> +#include "kernel-posix-cpu-timers.h" + + +#ifdef __ASSUME_POSIX_TIMERS +/* 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); +} + +#else +# ifdef __NR_clock_nanosleep +/* Is the syscall known to exist?  */ +extern int __libc_missing_posix_timers attribute_hidden; + +/* The REALTIME and MONOTONIC clock might be available.  Try the +   syscall first.  */ +#  define SYSDEP_NANOSLEEP \ +  if (!__libc_missing_posix_timers)					      \ +    {									      \ +      clockid_t syscall_clockid;					      \ +      INTERNAL_SYSCALL_DECL (err);					      \ +									      \ +      if (clock_id == CLOCK_THREAD_CPUTIME_ID)				      \ +	return EINVAL;							      \ +      if (clock_id == CLOCK_PROCESS_CPUTIME_ID)				      \ +	syscall_clockid = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);	      \ +      else								      \ +	syscall_clockid = clock_id;					      \ +									      \ +      int oldstate = LIBC_CANCEL_ASYNC ();				      \ +									      \ +      int r = INTERNAL_SYSCALL (clock_nanosleep, err, 4,		      \ +				syscall_clockid, flags, req, rem);	      \ +									      \ +      LIBC_CANCEL_RESET (oldstate);					      \ +									      \ +      if (!INTERNAL_SYSCALL_ERROR_P (r, err))				      \ +	return 0;							      \ +									      \ +      if (INTERNAL_SYSCALL_ERRNO (r, err) != ENOSYS)			      \ +	return INTERNAL_SYSCALL_ERRNO (r, err);				      \ +									      \ +      __libc_missing_posix_timers = 1;					      \ +    } +# endif + +# include <sysdeps/unix/clock_nanosleep.c> +#endif | 
