]>
Commit | Line | Data |
---|---|---|
84060bad | 1 | /* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t. Linux version |
93a78ac4 | 2 | Copyright (C) 2000-2012 Free Software Foundation, Inc. |
84060bad RM |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public License as | |
7 | published by the Free Software Foundation; either version 2.1 of the | |
8 | License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
16 | License along with the GNU C Library; see the file COPYING.LIB. If |
17 | not, see <http://www.gnu.org/licenses/>. */ | |
84060bad RM |
18 | |
19 | #include <errno.h> | |
20 | #include <pthreadP.h> | |
21 | #include <sys/time.h> | |
22 | #include <tls.h> | |
45bc95b5 UD |
23 | #include <kernel-features.h> |
24 | #include <kernel-posix-cpu-timers.h> | |
84060bad RM |
25 | |
26 | ||
27 | #if !(__ASSUME_POSIX_CPU_TIMERS > 0) | |
28 | int __libc_missing_posix_cpu_timers attribute_hidden; | |
29 | #endif | |
84060bad RM |
30 | |
31 | int | |
32 | pthread_getcpuclockid (threadid, clockid) | |
33 | pthread_t threadid; | |
34 | clockid_t *clockid; | |
35 | { | |
36 | struct pthread *pd = (struct pthread *) threadid; | |
37 | ||
38 | /* Make sure the descriptor is valid. */ | |
39 | if (INVALID_TD_P (pd)) | |
40 | /* Not a valid thread handle. */ | |
41 | return ESRCH; | |
42 | ||
43 | #ifdef __NR_clock_getres | |
44 | /* The clockid_t value is a simple computation from the TID. | |
45 | But we do a clock_getres call to validate it if we aren't | |
46 | yet sure we have the kernel support. */ | |
47 | ||
48 | const clockid_t tidclock = MAKE_THREAD_CPUCLOCK (pd->tid, CPUCLOCK_SCHED); | |
49 | ||
50 | # if !(__ASSUME_POSIX_CPU_TIMERS > 0) | |
84060bad RM |
51 | if (!__libc_missing_posix_cpu_timers) |
52 | { | |
53 | INTERNAL_SYSCALL_DECL (err); | |
54 | int r = INTERNAL_SYSCALL (clock_getres, err, 2, tidclock, NULL); | |
55 | if (!INTERNAL_SYSCALL_ERROR_P (r, err)) | |
56 | # endif | |
57 | { | |
58 | *clockid = tidclock; | |
59 | return 0; | |
60 | } | |
61 | ||
62 | # if !(__ASSUME_POSIX_CPU_TIMERS > 0) | |
93a78ac4 | 63 | if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL) |
84060bad | 64 | { |
93a78ac4 | 65 | /* The kernel doesn't support these clocks at all. */ |
84060bad RM |
66 | __libc_missing_posix_cpu_timers = 1; |
67 | } | |
68 | else | |
84060bad RM |
69 | return INTERNAL_SYSCALL_ERRNO (r, err); |
70 | } | |
71 | # endif | |
72 | #endif | |
73 | ||
74 | #ifdef CLOCK_THREAD_CPUTIME_ID | |
75 | /* We need to store the thread ID in the CLOCKID variable together | |
76 | with a number identifying the clock. We reserve the low 3 bits | |
77 | for the clock ID and the rest for the thread ID. This is | |
78 | problematic if the thread ID is too large. But 29 bits should be | |
79 | fine. | |
80 | ||
81 | If some day more clock IDs are needed the ID part can be | |
82 | enlarged. The IDs are entirely internal. */ | |
83 | if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE)) | |
84 | return ERANGE; | |
85 | ||
86 | /* Store the number. */ | |
87 | *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE); | |
88 | ||
89 | return 0; | |
90 | #else | |
91 | /* We don't have a timer for that. */ | |
92 | return ENOENT; | |
93 | #endif | |
94 | } |