1*dea9f5e6SRobert Mustacchi /*
2*dea9f5e6SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*dea9f5e6SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*dea9f5e6SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*dea9f5e6SRobert Mustacchi * 1.0 of the CDDL.
6*dea9f5e6SRobert Mustacchi *
7*dea9f5e6SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*dea9f5e6SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*dea9f5e6SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*dea9f5e6SRobert Mustacchi */
11*dea9f5e6SRobert Mustacchi
12*dea9f5e6SRobert Mustacchi /*
13*dea9f5e6SRobert Mustacchi * Copyright 2021 Oxide Computer Company
14*dea9f5e6SRobert Mustacchi */
15*dea9f5e6SRobert Mustacchi
16*dea9f5e6SRobert Mustacchi /*
17*dea9f5e6SRobert Mustacchi * This clock backend implements basic support for the following two clocks:
18*dea9f5e6SRobert Mustacchi *
19*dea9f5e6SRobert Mustacchi * o CLOCK_VIRTUAL This provides the ability to read the amount of
20*dea9f5e6SRobert Mustacchi * user CPU time that the calling thread has spent
21*dea9f5e6SRobert Mustacchi * on CPU. This is the LMS_USER cpu microstate.
22*dea9f5e6SRobert Mustacchi *
23*dea9f5e6SRobert Mustacchi * o CLOCK_THREAD_CPUTIME_ID This clock is similar to the above; however, it
24*dea9f5e6SRobert Mustacchi * also includes system time. This is the LMS_USER,
25*dea9f5e6SRobert Mustacchi * LMS_SYSTEM, and LMS_TRAP microstates combined
26*dea9f5e6SRobert Mustacchi * together. We include LMS_TRAP here because that
27*dea9f5e6SRobert Mustacchi * is what you see in a thread's lwpstatus file.
28*dea9f5e6SRobert Mustacchi *
29*dea9f5e6SRobert Mustacchi * At this time, we only provide the ability to read the current time (e.g.
30*dea9f5e6SRobert Mustacchi * through a call to clock_gettime(3C)). There is never a case where being able
31*dea9f5e6SRobert Mustacchi * to set the time makes sense today and truthfully, lying about a process's
32*dea9f5e6SRobert Mustacchi * runtime should be left to mdb -kw. Today, we do not support the ability to
33*dea9f5e6SRobert Mustacchi * create interval timers based on this backend (e.g. timer_create(3C) and
34*dea9f5e6SRobert Mustacchi * timer_settime(3C)). However, there is no reason that couldn't be added.
35*dea9f5e6SRobert Mustacchi *
36*dea9f5e6SRobert Mustacchi * A nice simplification here is that this clock is always about reading from
37*dea9f5e6SRobert Mustacchi * the current thread. This means that one can always access it. Because the
38*dea9f5e6SRobert Mustacchi * calling thread exists and is in this code, it means that we know it is here.
39*dea9f5e6SRobert Mustacchi * Any other privilege information is left to the broader kernel.
40*dea9f5e6SRobert Mustacchi *
41*dea9f5e6SRobert Mustacchi * Because the only difference between these is the question of whether or not
42*dea9f5e6SRobert Mustacchi * we include LMS_SYSTEM time in the value, we generally use the same actual
43*dea9f5e6SRobert Mustacchi * clock backend functions except for the one that implements
44*dea9f5e6SRobert Mustacchi * clk_clock_gettime().
45*dea9f5e6SRobert Mustacchi */
46*dea9f5e6SRobert Mustacchi
47*dea9f5e6SRobert Mustacchi #include <sys/timer.h>
48*dea9f5e6SRobert Mustacchi #include <sys/cyclic.h>
49*dea9f5e6SRobert Mustacchi #include <sys/msacct.h>
50*dea9f5e6SRobert Mustacchi
51*dea9f5e6SRobert Mustacchi static clock_backend_t clock_thread_usr;
52*dea9f5e6SRobert Mustacchi static clock_backend_t clock_thread_usrsys;
53*dea9f5e6SRobert Mustacchi
54*dea9f5e6SRobert Mustacchi static int
clock_thread_settime(timespec_t * ts)55*dea9f5e6SRobert Mustacchi clock_thread_settime(timespec_t *ts)
56*dea9f5e6SRobert Mustacchi {
57*dea9f5e6SRobert Mustacchi return (EINVAL);
58*dea9f5e6SRobert Mustacchi }
59*dea9f5e6SRobert Mustacchi
60*dea9f5e6SRobert Mustacchi static int
clock_thread_usr_gettime(timespec_t * ts)61*dea9f5e6SRobert Mustacchi clock_thread_usr_gettime(timespec_t *ts)
62*dea9f5e6SRobert Mustacchi {
63*dea9f5e6SRobert Mustacchi hrtime_t hrt;
64*dea9f5e6SRobert Mustacchi kthread_t *t = curthread;
65*dea9f5e6SRobert Mustacchi klwp_t *lwp = ttolwp(t);
66*dea9f5e6SRobert Mustacchi
67*dea9f5e6SRobert Mustacchi hrt = lwp->lwp_mstate.ms_acct[LMS_USER];
68*dea9f5e6SRobert Mustacchi scalehrtime(&hrt);
69*dea9f5e6SRobert Mustacchi hrt2ts(hrt, ts);
70*dea9f5e6SRobert Mustacchi
71*dea9f5e6SRobert Mustacchi return (0);
72*dea9f5e6SRobert Mustacchi }
73*dea9f5e6SRobert Mustacchi
74*dea9f5e6SRobert Mustacchi static int
clock_thread_usrsys_gettime(timespec_t * ts)75*dea9f5e6SRobert Mustacchi clock_thread_usrsys_gettime(timespec_t *ts)
76*dea9f5e6SRobert Mustacchi {
77*dea9f5e6SRobert Mustacchi hrtime_t hrt;
78*dea9f5e6SRobert Mustacchi kthread_t *t = curthread;
79*dea9f5e6SRobert Mustacchi
80*dea9f5e6SRobert Mustacchi /*
81*dea9f5e6SRobert Mustacchi * mstate_thread_onproc_time() takes care of doing the following:
82*dea9f5e6SRobert Mustacchi *
83*dea9f5e6SRobert Mustacchi * o Combining LMS_USER, LMS_SYSTEM, and LMS_TRAP.
84*dea9f5e6SRobert Mustacchi * o Ensuring that the result is scaled
85*dea9f5e6SRobert Mustacchi * o Ensuring that the time that's elapsed to the point of our asking
86*dea9f5e6SRobert Mustacchi * is included. By definition the kernel is executing in LMS_SYSTEM
87*dea9f5e6SRobert Mustacchi * so this ensures that we add that time which isn't currently in the
88*dea9f5e6SRobert Mustacchi * microstate to this.
89*dea9f5e6SRobert Mustacchi */
90*dea9f5e6SRobert Mustacchi thread_lock(t);
91*dea9f5e6SRobert Mustacchi hrt = mstate_thread_onproc_time(t);
92*dea9f5e6SRobert Mustacchi thread_unlock(t);
93*dea9f5e6SRobert Mustacchi
94*dea9f5e6SRobert Mustacchi hrt2ts(hrt, ts);
95*dea9f5e6SRobert Mustacchi return (0);
96*dea9f5e6SRobert Mustacchi }
97*dea9f5e6SRobert Mustacchi
98*dea9f5e6SRobert Mustacchi /*
99*dea9f5e6SRobert Mustacchi * The question of the resolution here is a thorny one. Technically this would
100*dea9f5e6SRobert Mustacchi * really be based upon the resolution of gethrtime_unscaled(), as we can
101*dea9f5e6SRobert Mustacchi * actually tell that much due to our use of CPU microstate accounting. However,
102*dea9f5e6SRobert Mustacchi * from a timer resolution perspective it's actually quite different and would
103*dea9f5e6SRobert Mustacchi * in theory be based on the system tick rate.
104*dea9f5e6SRobert Mustacchi *
105*dea9f5e6SRobert Mustacchi * This basically leaves us with two options:
106*dea9f5e6SRobert Mustacchi *
107*dea9f5e6SRobert Mustacchi * 1) Use 'nsec_per_tick' to go down the Hz path.
108*dea9f5e6SRobert Mustacchi * 2) Use the cyclic resolution, which basically is kind of the resolution of
109*dea9f5e6SRobert Mustacchi * that timer.
110*dea9f5e6SRobert Mustacchi *
111*dea9f5e6SRobert Mustacchi * POSIX is unclear as to the effect of the resolution in the case of timer_*()
112*dea9f5e6SRobert Mustacchi * functions and only really says it is used to impact the implementation of
113*dea9f5e6SRobert Mustacchi * clock_settime() which of course isn't actually supported here. As a result,
114*dea9f5e6SRobert Mustacchi * we opt to prefer the cyclic resolution, which is closer to the actual
115*dea9f5e6SRobert Mustacchi * resolution of this subsystem. Strictly speaking, this might not be completely
116*dea9f5e6SRobert Mustacchi * accurate, but should be on current platforms.
117*dea9f5e6SRobert Mustacchi */
118*dea9f5e6SRobert Mustacchi static int
clock_thread_getres(timespec_t * ts)119*dea9f5e6SRobert Mustacchi clock_thread_getres(timespec_t *ts)
120*dea9f5e6SRobert Mustacchi {
121*dea9f5e6SRobert Mustacchi hrt2ts(cyclic_getres(), (timestruc_t *)ts);
122*dea9f5e6SRobert Mustacchi
123*dea9f5e6SRobert Mustacchi return (0);
124*dea9f5e6SRobert Mustacchi }
125*dea9f5e6SRobert Mustacchi
126*dea9f5e6SRobert Mustacchi static int
clock_thread_timer_create(itimer_t * it,void (* fire)(itimer_t *))127*dea9f5e6SRobert Mustacchi clock_thread_timer_create(itimer_t *it, void (*fire)(itimer_t *))
128*dea9f5e6SRobert Mustacchi {
129*dea9f5e6SRobert Mustacchi return (EINVAL);
130*dea9f5e6SRobert Mustacchi }
131*dea9f5e6SRobert Mustacchi
132*dea9f5e6SRobert Mustacchi static int
clock_thread_timer_settime(itimer_t * it,int flags,const struct itimerspec * when)133*dea9f5e6SRobert Mustacchi clock_thread_timer_settime(itimer_t *it, int flags,
134*dea9f5e6SRobert Mustacchi const struct itimerspec *when)
135*dea9f5e6SRobert Mustacchi {
136*dea9f5e6SRobert Mustacchi return (EINVAL);
137*dea9f5e6SRobert Mustacchi }
138*dea9f5e6SRobert Mustacchi
139*dea9f5e6SRobert Mustacchi static int
clock_thread_timer_gettime(itimer_t * it,struct itimerspec * when)140*dea9f5e6SRobert Mustacchi clock_thread_timer_gettime(itimer_t *it, struct itimerspec *when)
141*dea9f5e6SRobert Mustacchi {
142*dea9f5e6SRobert Mustacchi return (EINVAL);
143*dea9f5e6SRobert Mustacchi }
144*dea9f5e6SRobert Mustacchi
145*dea9f5e6SRobert Mustacchi static int
clock_thread_timer_delete(itimer_t * it)146*dea9f5e6SRobert Mustacchi clock_thread_timer_delete(itimer_t *it)
147*dea9f5e6SRobert Mustacchi {
148*dea9f5e6SRobert Mustacchi return (EINVAL);
149*dea9f5e6SRobert Mustacchi }
150*dea9f5e6SRobert Mustacchi
151*dea9f5e6SRobert Mustacchi static void
clock_thread_timer_lwpbind(itimer_t * it)152*dea9f5e6SRobert Mustacchi clock_thread_timer_lwpbind(itimer_t *it)
153*dea9f5e6SRobert Mustacchi {
154*dea9f5e6SRobert Mustacchi }
155*dea9f5e6SRobert Mustacchi
156*dea9f5e6SRobert Mustacchi void
clock_thread_init(void)157*dea9f5e6SRobert Mustacchi clock_thread_init(void)
158*dea9f5e6SRobert Mustacchi {
159*dea9f5e6SRobert Mustacchi /*
160*dea9f5e6SRobert Mustacchi * While this clock backends don't support notifications right now, we
161*dea9f5e6SRobert Mustacchi * still fill out the default for what it would be.
162*dea9f5e6SRobert Mustacchi */
163*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_default.sigev_signo = SIGALRM;
164*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_default.sigev_notify = SIGEV_SIGNAL;
165*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_default.sigev_value.sival_ptr = NULL;
166*dea9f5e6SRobert Mustacchi
167*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_clock_settime = clock_thread_settime;
168*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_clock_gettime = clock_thread_usr_gettime;
169*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_clock_getres = clock_thread_getres;
170*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_timer_create = clock_thread_timer_create;
171*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_timer_settime = clock_thread_timer_settime;
172*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_timer_gettime = clock_thread_timer_gettime;
173*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_timer_delete = clock_thread_timer_delete;
174*dea9f5e6SRobert Mustacchi clock_thread_usr.clk_timer_lwpbind = clock_thread_timer_lwpbind;
175*dea9f5e6SRobert Mustacchi
176*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_default.sigev_signo = SIGALRM;
177*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_default.sigev_notify = SIGEV_SIGNAL;
178*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_default.sigev_value.sival_ptr = NULL;
179*dea9f5e6SRobert Mustacchi
180*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_clock_settime = clock_thread_settime;
181*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_clock_gettime = clock_thread_usrsys_gettime;
182*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_clock_getres = clock_thread_getres;
183*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_timer_create = clock_thread_timer_create;
184*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_timer_settime = clock_thread_timer_settime;
185*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_timer_gettime = clock_thread_timer_gettime;
186*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_timer_delete = clock_thread_timer_delete;
187*dea9f5e6SRobert Mustacchi clock_thread_usrsys.clk_timer_lwpbind = clock_thread_timer_lwpbind;
188*dea9f5e6SRobert Mustacchi
189*dea9f5e6SRobert Mustacchi clock_add_backend(CLOCK_VIRTUAL, &clock_thread_usr);
190*dea9f5e6SRobert Mustacchi clock_add_backend(CLOCK_THREAD_CPUTIME_ID, &clock_thread_usrsys);
191*dea9f5e6SRobert Mustacchi }
192