Back to index

glibc  2.9
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, 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 <pthread.h>
00022 #include <sys/time.h>
00023 #include <time.h>
00024 #include <internals.h>
00025 #include <spinlock.h>
00026 #include <kernel-features.h>
00027 #include <kernel-posix-cpu-timers.h>
00028 
00029 
00030 #if !(__ASSUME_POSIX_CPU_TIMERS > 0)
00031 int __libc_missing_posix_cpu_timers attribute_hidden;
00032 #endif
00033 #if !(__ASSUME_POSIX_TIMERS > 0)
00034 int __libc_missing_posix_timers attribute_hidden;
00035 #endif
00036 
00037 int
00038 pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id)
00039 {
00040 #ifdef __NR_clock_getres
00041   pthread_handle handle = thread_handle(thread_id);
00042   int pid;
00043 
00044   __pthread_lock (&handle->h_lock, NULL);
00045   if (nonexisting_handle (handle, thread_id))
00046     {
00047       __pthread_unlock (&handle->h_lock);
00048       return ESRCH;
00049     }
00050   pid = handle->h_descr->p_pid;
00051   __pthread_unlock (&handle->h_lock);
00052 
00053   /* The clockid_t value is a simple computation from the PID.
00054      But we do a clock_getres call to validate it if we aren't
00055      yet sure we have the kernel support.  */
00056 
00057   const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED);
00058 
00059 # if !(__ASSUME_POSIX_CPU_TIMERS > 0)
00060 #  if !(__ASSUME_POSIX_TIMERS > 0)
00061   if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
00062     __libc_missing_posix_cpu_timers = 1;
00063 #  endif
00064   if (!__libc_missing_posix_cpu_timers)
00065     {
00066       INTERNAL_SYSCALL_DECL (err);
00067       int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL);
00068       if (!INTERNAL_SYSCALL_ERROR_P (r, err))
00069 # endif
00070        {
00071          *clock_id = pidclock;
00072          return 0;
00073        }
00074 
00075 # if !(__ASSUME_POSIX_CPU_TIMERS > 0)
00076 #  if !(__ASSUME_POSIX_TIMERS > 0)
00077       if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
00078        {
00079          /* The kernel doesn't support these calls at all.  */
00080          __libc_missing_posix_timers = 1;
00081          __libc_missing_posix_cpu_timers = 1;
00082        }
00083       else
00084 #  endif
00085        if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
00086          {
00087            /* The kernel doesn't support these clocks at all.  */
00088            __libc_missing_posix_cpu_timers = 1;
00089          }
00090       else
00091        return INTERNAL_SYSCALL_ERRNO (r, err);
00092     }
00093 # endif
00094 #endif
00095 
00096 #ifdef CLOCK_THREAD_CPUTIME_ID
00097   /* We need to store the thread ID in the CLOCKID variable together
00098      with a number identifying the clock.  We reserve the low 3 bits
00099      for the clock ID and the rest for the thread ID.  This is
00100      problematic if the thread ID is too large.  But 29 bits should be
00101      fine.
00102 
00103      If some day more clock IDs are needed the ID part can be
00104      enlarged.  The IDs are entirely internal.  */
00105   if (2 * PTHREAD_THREADS_MAX
00106       >= 1 << (8 * sizeof (*clock_id) - CLOCK_IDFIELD_SIZE))
00107     return ERANGE;
00108 
00109   /* Store the number.  */
00110   *clock_id = CLOCK_THREAD_CPUTIME_ID | (thread_id << CLOCK_IDFIELD_SIZE);
00111 
00112   return 0;
00113 #else
00114   /* We don't have a timer for that.  */
00115   return ENOENT;
00116 #endif
00117 }