Back to index

glibc  2.9
pthread_getcpuclockid.c
Go to the documentation of this file.
00001 /* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t.  Linux version
00002    Copyright (C) 2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public License as
00007    published by the Free Software Foundation; either version 2.1 of the
00008    License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00017    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.  */
00019 
00020 #include <errno.h>
00021 #include <pthreadP.h>
00022 #include <sys/time.h>
00023 #include <tls.h>
00024 #include <kernel-features.h>
00025 #include <kernel-posix-cpu-timers.h>
00026 
00027 
00028 #if !(__ASSUME_POSIX_CPU_TIMERS > 0)
00029 int __libc_missing_posix_cpu_timers attribute_hidden;
00030 #endif
00031 #if !(__ASSUME_POSIX_TIMERS > 0)
00032 int __libc_missing_posix_timers attribute_hidden;
00033 #endif
00034 
00035 int
00036 pthread_getcpuclockid (threadid, clockid)
00037      pthread_t threadid;
00038      clockid_t *clockid;
00039 {
00040   struct pthread *pd = (struct pthread *) threadid;
00041 
00042   /* Make sure the descriptor is valid.  */
00043   if (INVALID_TD_P (pd))
00044     /* Not a valid thread handle.  */
00045     return ESRCH;
00046 
00047 #ifdef __NR_clock_getres
00048   /* The clockid_t value is a simple computation from the TID.
00049      But we do a clock_getres call to validate it if we aren't
00050      yet sure we have the kernel support.  */
00051 
00052   const clockid_t tidclock = MAKE_THREAD_CPUCLOCK (pd->tid, CPUCLOCK_SCHED);
00053 
00054 # if !(__ASSUME_POSIX_CPU_TIMERS > 0)
00055 #  if !(__ASSUME_POSIX_TIMERS > 0)
00056   if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
00057     __libc_missing_posix_cpu_timers = 1;
00058 #  endif
00059   if (!__libc_missing_posix_cpu_timers)
00060     {
00061       INTERNAL_SYSCALL_DECL (err);
00062       int r = INTERNAL_SYSCALL (clock_getres, err, 2, tidclock, NULL);
00063       if (!INTERNAL_SYSCALL_ERROR_P (r, err))
00064 # endif
00065        {
00066          *clockid = tidclock;
00067          return 0;
00068        }
00069 
00070 # if !(__ASSUME_POSIX_CPU_TIMERS > 0)
00071 #  if !(__ASSUME_POSIX_TIMERS > 0)
00072       if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
00073        {
00074          /* The kernel doesn't support these calls at all.  */
00075          __libc_missing_posix_timers = 1;
00076          __libc_missing_posix_cpu_timers = 1;
00077        }
00078       else
00079 #  endif
00080        if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
00081          {
00082            /* The kernel doesn't support these clocks at all.  */
00083            __libc_missing_posix_cpu_timers = 1;
00084          }
00085       else
00086        return INTERNAL_SYSCALL_ERRNO (r, err);
00087     }
00088 # endif
00089 #endif
00090 
00091 #ifdef CLOCK_THREAD_CPUTIME_ID
00092   /* We need to store the thread ID in the CLOCKID variable together
00093      with a number identifying the clock.  We reserve the low 3 bits
00094      for the clock ID and the rest for the thread ID.  This is
00095      problematic if the thread ID is too large.  But 29 bits should be
00096      fine.
00097 
00098      If some day more clock IDs are needed the ID part can be
00099      enlarged.  The IDs are entirely internal.  */
00100   if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE))
00101     return ERANGE;
00102 
00103   /* Store the number.  */
00104   *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE);
00105 
00106   return 0;
00107 #else
00108   /* We don't have a timer for that.  */
00109   return ENOENT;
00110 #endif
00111 }