MIPS: Consolidate NPTL/non versions of vfork
[platform/upstream/glibc.git] / sysdeps / unix / clock_settime.c
1 /* Copyright (C) 1999-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <http://www.gnu.org/licenses/>.  */
17
18 #include <errno.h>
19 #include <time.h>
20 #include <sys/time.h>
21 #include <libc-internal.h>
22 #include <ldsodefs.h>
23
24
25 #if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
26 /* Clock frequency of the processor.  We make it a 64-bit variable
27    because some jokers are already playing with processors with more
28    than 4GHz.  */
29 static hp_timing_t freq;
30
31
32 /* This function is defined in the thread library.  */
33 extern void __pthread_clock_settime (clockid_t clock_id, hp_timing_t offset)
34      __attribute__ ((__weak__));
35
36
37 static int
38 hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
39 {
40   hp_timing_t tsc;
41   hp_timing_t usertime;
42
43   /* First thing is to get the current time.  */
44   HP_TIMING_NOW (tsc);
45
46   if (__glibc_unlikely (freq == 0))
47     {
48       /* This can only happen if we haven't initialized the `freq'
49          variable yet.  Do this now. We don't have to protect this
50          code against multiple execution since all of them should lead
51          to the same result.  */
52       freq = __get_clockfreq ();
53       if (__glibc_unlikely (freq == 0))
54         /* Something went wrong.  */
55         return -1;
56     }
57
58   /* Convert the user-provided time into CPU ticks.  */
59   usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull;
60
61   /* Determine the offset and use it as the new base value.  */
62   if (clock_id == CLOCK_PROCESS_CPUTIME_ID
63       || __pthread_clock_settime == NULL)
64     GL(dl_cpuclock_offset) = tsc - usertime;
65   else
66     __pthread_clock_settime (clock_id, tsc - usertime);
67
68   return 0;
69 }
70 #endif
71
72
73 /* Set CLOCK to value TP.  */
74 int
75 __clock_settime (clockid_t clock_id, const struct timespec *tp)
76 {
77   int retval;
78
79   /* Make sure the time cvalue is OK.  */
80   if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
81     {
82       __set_errno (EINVAL);
83       return -1;
84     }
85
86   switch (clock_id)
87     {
88 #define HANDLE_REALTIME \
89       do {                                                                    \
90         struct timeval tv;                                                    \
91         TIMESPEC_TO_TIMEVAL (&tv, tp);                                        \
92                                                                               \
93         retval = settimeofday (&tv, NULL);                                    \
94       } while (0)
95
96 #ifdef SYSDEP_SETTIME
97       SYSDEP_SETTIME;
98 #endif
99
100 #ifndef HANDLED_REALTIME
101     case CLOCK_REALTIME:
102       HANDLE_REALTIME;
103       break;
104 #endif
105
106     default:
107 #ifdef SYSDEP_SETTIME_CPU
108       SYSDEP_SETTIME_CPU;
109 #endif
110 #ifndef HANDLED_CPUTIME
111 # if HP_TIMING_AVAIL
112       if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
113           || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
114         retval = hp_timing_settime (clock_id, tp);
115       else
116 # endif
117         {
118           __set_errno (EINVAL);
119           retval = -1;
120         }
121 #endif
122       break;
123     }
124
125   return retval;
126 }
127 weak_alias (__clock_settime, clock_settime)