diff options
| -rw-r--r-- | libc/unistd/sysconf.c | 26 | ||||
| -rw-r--r-- | librt/Makefile.in | 31 | ||||
| -rw-r--r-- | librt/clock_getcpuclockid.c | 104 | ||||
| -rw-r--r-- | librt/clock_gettime.c | 301 | ||||
| -rw-r--r-- | librt/clock_nanosleep.c | 96 | ||||
| -rw-r--r-- | librt/kernel-posix-cpu-timers.h | 18 | ||||
| -rw-r--r-- | librt/kernel-posix-timers.h | 14 | ||||
| -rw-r--r-- | librt/mq_receive.c | 41 | ||||
| -rw-r--r-- | librt/mq_send.c | 40 | ||||
| -rw-r--r-- | librt/mq_timedreceive.S | 10 | ||||
| -rw-r--r-- | librt/mq_timedsend.S | 10 | 
11 files changed, 637 insertions, 54 deletions
| diff --git a/libc/unistd/sysconf.c b/libc/unistd/sysconf.c index 87206648e..b3eb12021 100644 --- a/libc/unistd/sysconf.c +++ b/libc/unistd/sysconf.c @@ -33,6 +33,9 @@  #ifdef __UCLIBC_HAS_REGEX__  #include <regex.h>  #endif +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include <sysdep.h> +#endif  #ifdef HAVE_LINUX_CPUMASK_H  # include <linux/cpumask.h> @@ -881,13 +884,32 @@ long int sysconf(int name)  #endif      case _SC_MONOTONIC_CLOCK: -#if defined __UCLIBC_HAS_REALTIME__ && defined __NR_clock_getres -      /* Check using the clock_getres system call.  */ +#ifdef __NR_clock_getres +    /* Check using the clock_getres system call.  */ +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +    { +      struct timespec ts; +      INTERNAL_SYSCALL_DECL (err); +      int r; +      r = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); +      return INTERNAL_SYSCALL_ERROR_P (r, err) ? -1 : _POSIX_VERSION; +    } +# else        if (clock_getres(CLOCK_MONOTONIC, NULL) >= 0)          return _POSIX_VERSION; + +      RETURN_NEG_1; +# endif  #endif +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +    case _SC_THREAD_CPUTIME: +# if _POSIX_THREAD_CPUTIME > 0 +      return _POSIX_THREAD_CPUTIME; +# else        RETURN_NEG_1; +# endif +#endif      }  }  libc_hidden_def(sysconf) diff --git a/librt/Makefile.in b/librt/Makefile.in index aaa19185a..ea1d03eb8 100644 --- a/librt/Makefile.in +++ b/librt/Makefile.in @@ -9,7 +9,12 @@ subdirs += librt  CFLAGS-librt := -DNOT_IN_libc -DIS_IN_librt $(SSP_ALL_CFLAGS) -LDFLAGS-librt.so := $(LDFLAGS) $(call link.asneeded,-lc) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +LDFLAGS-librt.so := $(LDFLAGS) $(top_builddir)lib/libdl.so	\ +		    $(top_builddir)lib/libpthread.so +else +LDFLAGS-librt.so := $(LDFLAGS) +endif  LIBS-librt.so := $(LIBS) @@ -19,22 +24,36 @@ librt_DIR := $(top_srcdir)librt  librt_OUT := $(top_builddir)librt  ifeq ($(UCLIBC_HAS_REALTIME),y) -librt_SRC := $(wildcard $(librt_DIR)/*.c) -librt_OBJ := $(patsubst $(librt_DIR)/%.c,$(librt_OUT)/%.o,$(librt_SRC)) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +librt_CSRC := $(filter-out mq_notify.c timer_create.c timer_delete.c	\ +	      timer_getoverr.c timer_gettime.c timer_settime.c,	\ +	      $(notdir $(wildcard $(librt_DIR)/*.c))) +librt_SSRC := $(wildcard $(librt_DIR)/*.S) +librt_OBJ := $(patsubst %.c,$(librt_OUT)/%.o,$(librt_CSRC)) +librt_OBJ += $(patsubst $(librt_DIR)/%.S,$(librt_OUT)/%.o,$(librt_SSRC)) +else +librt_SRC := $(filter-out clock_nanosleep.c clock_getcpuclockid.c clock_gettime.c,	\ +	     $(notdir $(wildcard $(librt_DIR)/*.c))) +librt_OBJ := $(patsubst %.c,$(librt_OUT)/%.o,$(librt_SRC)) +endif + +ASFLAGS-mq_timedreceive.S = -D_LIBC_REENTRANT +ASFLAGS-mq_timedsend.S = -D_LIBC_REENTRANT  ifeq ($(DOPIC),y)  librt-a-y += $(librt_OBJ:.o=.os)  else  librt-a-y += $(librt_OBJ)  endif -librt-so-y += $(librt_OBJ:.o=.os) +librt-so-y += $(librt_OBJ:.o=.oS)  lib-a-y += $(top_builddir)lib/librt.a  lib-so-y += $(top_builddir)lib/librt.so  endif -ifeq ($(DOPIC),y) -$(top_builddir)lib/librt.so: $(top_builddir)lib/librt.a $(libc.depend) + +ifeq ($(DOPIC)$(UCLIBC_HAS_THREADS_NATIVE),yn) +$(top_builddir)lib/librt.so: $(top_builddir)lib/librt.a $(libc.dpend)  else  $(top_builddir)lib/librt.so: $(librt_OUT)/librt_so.a $(libc.depend)  endif diff --git a/librt/clock_getcpuclockid.c b/librt/clock_getcpuclockid.c new file mode 100644 index 000000000..704c57402 --- /dev/null +++ b/librt/clock_getcpuclockid.c @@ -0,0 +1,104 @@ +/* clock_getcpuclockid -- Get a clockid_t for process CPU time.  Linux version. +   Copyright (C) 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 <errno.h> +#include <time.h> +#include <sysdep.h> +#include <unistd.h> +#include <bits/kernel-features.h> +#include "kernel-posix-cpu-timers.h" + +#ifndef HAS_CPUCLOCK +# define HAS_CPUCLOCK 1 +#endif + +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; +} diff --git a/librt/clock_gettime.c b/librt/clock_gettime.c new file mode 100644 index 000000000..8308329b2 --- /dev/null +++ b/librt/clock_gettime.c @@ -0,0 +1,301 @@ +/* clock_gettime -- Get current time from a POSIX clockid_t.  Linux version. +   Copyright (C) 2003, 2004 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 <sysdep.h> +#include <errno.h> +#include <time.h> +#include "kernel-posix-cpu-timers.h" +#include <bits/kernel-features.h> + + +#define SYSCALL_GETTIME \ +  retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \ +  break + +#ifdef __ASSUME_POSIX_TIMERS + +/* This means the REALTIME and MONOTONIC clock are definitely +   supported in the kernel.  */ +# define SYSDEP_GETTIME							      \ +  SYSDEP_GETTIME_CPUTIME						      \ +  case CLOCK_REALTIME:							      \ +  case CLOCK_MONOTONIC:							      \ +    SYSCALL_GETTIME + +# define __libc_missing_posix_timers 0 +#elif defined __NR_clock_gettime +/* Is the syscall known to exist?  */ +int __libc_missing_posix_timers attribute_hidden; + +static inline int +maybe_syscall_gettime (clockid_t clock_id, struct timespec *tp) +{ +  int e = EINVAL; + +  if (!__libc_missing_posix_timers) +    { +      INTERNAL_SYSCALL_DECL (err); +      int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); +      if (!INTERNAL_SYSCALL_ERROR_P (r, err)) +	return 0; + +      e = INTERNAL_SYSCALL_ERRNO (r, err); +      if (e == ENOSYS) +	{ +	  __libc_missing_posix_timers = 1; +	  e = EINVAL; +	} +    } + +  return e; +} + +/* The REALTIME and MONOTONIC clock might be available.  Try the +   syscall first.  */ +# define SYSDEP_GETTIME							      \ +  SYSDEP_GETTIME_CPUTIME						      \ +  case CLOCK_REALTIME:							      \ +  case CLOCK_MONOTONIC:							      \ +    retval = maybe_syscall_gettime (clock_id, tp);			      \ +    if (retval == 0)							      \ +      break;								      \ +    /* Fallback code.  */						      \ +    if (retval == EINVAL && clock_id == CLOCK_REALTIME)			      \ +      retval = realtime_gettime (tp);					      \ +    else 								      \ +      {									      \ +	__set_errno (retval);						      \ +	retval = -1;							      \ +      }									      \ +    break; +#endif + +#ifdef __NR_clock_gettime +/* We handled the REALTIME clock here.  */ +# define HANDLED_REALTIME	1 +# define HANDLED_CPUTIME	1 + +# if __ASSUME_POSIX_CPU_TIMERS > 0 + +#  define SYSDEP_GETTIME_CPU SYSCALL_GETTIME +#  define SYSDEP_GETTIME_CPUTIME	/* Default catches them too.  */ + +# else + +int __libc_missing_posix_cpu_timers attribute_hidden; + +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_SYSCALL (clock_gettime, err, 2, 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) +	    { +	      /* 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); +	      if (INTERNAL_SYSCALL_ERROR_P (r, err)) +		__libc_missing_posix_cpu_timers = 1; +	    } +	} +    } + +  return e; +} + +#  define SYSDEP_GETTIME_CPU						      \ +  retval = maybe_syscall_gettime_cpu (clock_id, tp);			      \ +  if (retval == 0)							      \ +    break;								      \ +  if (retval != EINVAL || !__libc_missing_posix_cpu_timers)		      \ +    {									      \ +      __set_errno (retval);						      \ +      retval = -1;							      \ +      break;								      \ +    }									      \ +  retval = -1 /* Otherwise continue on to the HP_TIMING version.  */; + +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); +} + +#  define SYSDEP_GETTIME_CPUTIME					      \ +    case CLOCK_PROCESS_CPUTIME_ID:					      \ +    case CLOCK_THREAD_CPUTIME_ID:					      \ +      retval = maybe_syscall_gettime_cputime (clock_id, tp);		      \ +      if (retval == 0)							      \ +	break;								      \ +      if (retval != EINVAL || !__libc_missing_posix_cpu_timers)		      \ +	{								      \ +	  __set_errno (retval);						      \ +	  retval = -1;							      \ +	  break;							      \ +	}								      \ +      retval = hp_timing_gettime (clock_id, tp);			      \ +      break; +#  if !HP_TIMING_AVAIL +#   define hp_timing_gettime(clock_id, tp) (__set_errno (EINVAL), -1) +#  endif + +# endif +#endif + +#include <errno.h> +#include <stdint.h> +#include <time.h> +#include <sys/time.h> +#include <libc-internal.h> +#include <ldsodefs.h> + + +#if HP_TIMING_AVAIL +/* Clock frequency of the processor.  We make it a 64-bit variable +   because some jokers are already playing with processors with more +   than 4GHz.  */ +static hp_timing_t freq; + + +/* This function is defined in the thread library.  */ +extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, +				    struct timespec *tp) +     __attribute__ ((__weak__)); + +static int +hp_timing_gettime (clockid_t clock_id, struct timespec *tp) +{ +  hp_timing_t tsc; + +  if (__builtin_expect (freq == 0, 0)) +    { +      /* This can only happen if we haven't initialized the `freq' +	 variable yet.  Do this now. We don't have to protect this +	 code against multiple execution since all of them should +	 lead to the same result.  */ +      freq = __get_clockfreq (); +      if (__builtin_expect (freq == 0, 0)) +	/* Something went wrong.  */ +	return -1; +    } + +  if (clock_id != CLOCK_PROCESS_CPUTIME_ID +      && __pthread_clock_gettime != NULL) +    return __pthread_clock_gettime (clock_id, freq, tp); + +  /* Get the current counter.  */ +  HP_TIMING_NOW (tsc); + +  /* Compute the offset since the start time of the process.  */ +  tsc -= GL(dl_cpuclock_offset); + +  /* Compute the seconds.  */ +  tp->tv_sec = tsc / freq; + +  /* And the nanoseconds.  This computation should be stable until +     we get machines with about 16GHz frequency.  */ +  tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; + +  return 0; +} +#endif + + +static inline int +realtime_gettime (struct timespec *tp) +{ +  struct timeval tv; +  int retval = gettimeofday (&tv, NULL); +  if (retval == 0) +    /* Convert into `timespec'.  */ +    TIMEVAL_TO_TIMESPEC (&tv, tp); +  return retval; +} + +librt_hidden_proto (clock_gettime) +/* Get current value of CLOCK and store it in TP.  */ +int +clock_gettime (clockid_t clock_id, struct timespec *tp) +{ +  int retval = -1; +#ifndef HANDLED_REALTIME +  struct timeval tv; +#endif + +  switch (clock_id) +    { +#ifdef SYSDEP_GETTIME +      SYSDEP_GETTIME; +#endif + +#ifndef HANDLED_REALTIME +    case CLOCK_REALTIME: +      retval = gettimeofday (&tv, NULL); +      if (retval == 0) +	TIMEVAL_TO_TIMESPEC (&tv, tp); +      break; +#endif + +    default: +#ifdef SYSDEP_GETTIME_CPU +      SYSDEP_GETTIME_CPU; +#endif +#if HP_TIMING_AVAIL +      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) +	  == CLOCK_THREAD_CPUTIME_ID) +	retval = hp_timing_gettime (clock_id, tp); +      else +#endif +	__set_errno (EINVAL); +      break; + +#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME +    case CLOCK_PROCESS_CPUTIME_ID: +      retval = hp_timing_gettime (clock_id, tp); +      break; +#endif +    } + +  return retval; +} +librt_hidden_def (clock_gettime) 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 diff --git a/librt/kernel-posix-cpu-timers.h b/librt/kernel-posix-cpu-timers.h new file mode 100644 index 000000000..164a90dde --- /dev/null +++ b/librt/kernel-posix-cpu-timers.h @@ -0,0 +1,18 @@ +/* Parameters for the Linux kernel ABI for CPU clocks.  */ + +#define CPUCLOCK_PID(clock)		((pid_t) ~((clock) >> 3)) +#define CPUCLOCK_PERTHREAD(clock) \ +	(((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0) +#define CPUCLOCK_PID_MASK	7 +#define CPUCLOCK_PERTHREAD_MASK	4 +#define CPUCLOCK_WHICH(clock)	((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK) +#define CPUCLOCK_CLOCK_MASK	3 +#define CPUCLOCK_PROF		0 +#define CPUCLOCK_VIRT		1 +#define CPUCLOCK_SCHED		2 +#define CPUCLOCK_MAX		3 + +#define MAKE_PROCESS_CPUCLOCK(pid, clock) \ +	((~(clockid_t) (pid) << 3) | (clockid_t) (clock)) +#define MAKE_THREAD_CPUCLOCK(tid, clock) \ +	MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK) diff --git a/librt/kernel-posix-timers.h b/librt/kernel-posix-timers.h index bf246c925..27d3f1fd7 100644 --- a/librt/kernel-posix-timers.h +++ b/librt/kernel-posix-timers.h @@ -10,6 +10,20 @@  #include <pthread.h>  #endif +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +/* Nonzero if the system calls are not available.  */ +extern int __no_posix_timers attribute_hidden; + +/* Callback to start helper thread.  */ +extern void __start_helper_thread (void) attribute_hidden; + +/* Control variable for helper thread creation.  */ +extern pthread_once_t __helper_once attribute_hidden; + +/* TID of the helper thread.  */ +extern pid_t __helper_tid attribute_hidden; +#endif +  /* Type of timers in the kernel */  typedef int kernel_timer_t; diff --git a/librt/mq_receive.c b/librt/mq_receive.c index c0392b0f9..40447dfb9 100644 --- a/librt/mq_receive.c +++ b/librt/mq_receive.c @@ -6,13 +6,18 @@  #include <stddef.h>  #include <sys/syscall.h>  #include <mqueue.h> +#warning FIXME: hard dependency on ADVANCED REALTIME feature +librt_hidden_proto(mq_timedreceive) + +#ifndef __UCLIBC_HAS_THREADS_NATIVE__  #ifdef __NR_mq_timedreceive  #define __NR___syscall_mq_timedreceive __NR_mq_timedreceive -static _syscall5(int, __syscall_mq_timedreceive, int, mqdes, -		 char *, msg_ptr, size_t, msg_len, unsigned int *, -		 msg_prio, const void *, abs_timeout) -# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +static __inline__ _syscall5(int, __syscall_mq_timedreceive, int, mqdes, +			char *, msg_ptr, size_t, msg_len, unsigned int *, +			msg_prio, const void *, abs_timeout); +#endif +  /*   * Receive the oldest from highest priority messages.   * Stop waiting if abs_timeout expires. @@ -21,31 +26,21 @@ ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,  			unsigned int *msg_prio,  			const struct timespec *abs_timeout)  { +#ifdef __NR_mq_timedreceive  	return __syscall_mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio,  					 abs_timeout); +#else +	errno = ENOSYS; +	return -1; +#endif  } -# endif + +librt_hidden_def(mq_timedreceive) +#endif  /* Receive the oldest from highest priority messages */  ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len,  		   unsigned int *msg_prio)  { -	return __syscall_mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, NULL); +	return mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, NULL);  } -#elif defined __UCLIBC_HAS_STUBS__ -# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ -ssize_t mq_timedreceive(mqd_t mqdes attribute_unused, char *msg_ptr attribute_unused, -			size_t msg_len attribute_unused, unsigned int *msg_prio attribute_unused, -			const struct timespec *abs_timeout attribute_unused) -{ -	__set_errno(ENOSYS); -	return -1; -} -# endif -ssize_t mq_receive(mqd_t mqdes attribute_unused, char *msg_ptr attribute_unused, -		   size_t msg_len attribute_unused, unsigned int *msg_prio attribute_unused) -{ -	__set_errno(ENOSYS); -	return -1; -} -#endif diff --git a/librt/mq_send.c b/librt/mq_send.c index 4c1a492b4..f0fcfa35a 100644 --- a/librt/mq_send.c +++ b/librt/mq_send.c @@ -6,14 +6,18 @@  #include <stddef.h>  #include <sys/syscall.h>  #include <mqueue.h> +#warning FIXME: hard dependency on ADVANCED REALTIME feature +librt_hidden_proto(mq_timedsend) + +#ifndef __UCLIBC_HAS_THREADS_NATIVE__  #ifdef __NR_mq_timedsend  #define __NR___syscall_mq_timedsend __NR_mq_timedsend -static _syscall5(int, __syscall_mq_timedsend, int, mqdes, -		 const char *, msg_ptr, size_t, msg_len, unsigned int, -		 msg_prio, const void *, abs_timeout); +static __inline__ _syscall5(int, __syscall_mq_timedsend, int, mqdes, +			const char *, msg_ptr, size_t, msg_len, unsigned int, +			msg_prio, const void *, abs_timeout); +#endif -# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__  /*   * Add a message to queue. If O_NONBLOCK is set and queue is full, wait   * for sufficient room in the queue until abs_timeout expires. @@ -21,31 +25,21 @@ static _syscall5(int, __syscall_mq_timedsend, int, mqdes,  int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len,  		 unsigned int msg_prio, const struct timespec *abs_timeout)  { +#ifdef __NR_mq_timedsend  	return __syscall_mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio,  				      abs_timeout); +#else +	errno = ENOSYS; +	return -1; +#endif  } -# endif + +librt_hidden_def(mq_timedsend) +#endif  /* Add a message to queue */  int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len,  	    unsigned int msg_prio)  { -	return __syscall_mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, NULL); +	return mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, NULL);  } -#elif defined __UCLIBC_HAS_STUBS__ -# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ -int mq_timedsend(mqd_t mqdes attribute_unused, const char *msg_ptr attribute_unused, -		 size_t msg_len attribute_unused, unsigned int msg_prio attribute_unused, -		 const struct timespec *abs_timeout attribute_unused) -{ -	__set_errno(ENOSYS); -	return -1; -} -# endif -int mq_send(mqd_t mqdes attribute_unused, const char *msg_ptr attribute_unused, -	    size_t msg_len attribute_unused, unsigned int msg_prio attribute_unused) -{ -	__set_errno(ENOSYS); -	return -1; -} -#endif diff --git a/librt/mq_timedreceive.S b/librt/mq_timedreceive.S new file mode 100644 index 000000000..015eb8842 --- /dev/null +++ b/librt/mq_timedreceive.S @@ -0,0 +1,10 @@ +#include <sysdep-cancel.h> +#ifndef __NR_mq_timedreceive +#error Missing definition of NR_timedreceive needed for cancellation. +#endif +PSEUDO (__mq_timedreceive, mq_timedreceive, 5) +ret +PSEUDO_END(__mq_timedreceive) +librt_hidden_def (__mq_timedreceive) +weak_alias (__mq_timedreceive, mq_timedreceive) +librt_hidden_weak (mq_timedreceive) diff --git a/librt/mq_timedsend.S b/librt/mq_timedsend.S new file mode 100644 index 000000000..67758a3b9 --- /dev/null +++ b/librt/mq_timedsend.S @@ -0,0 +1,10 @@ +#include <sysdep-cancel.h> +#ifndef __NR_mq_timedsend +#error Missing definition of NR_timedsend needed for cancellation. +#endif +PSEUDO (__mq_timedsend, mq_timedsend, 5) +ret +PSEUDO_END(__mq_timedsend) +librt_hidden_def (__mq_timedsend) +weak_alias (__mq_timedsend, mq_timedsend) +librt_hidden_weak (mq_timedsend) | 
