1433d6423SLionel Sambuc /* This file takes care of those system calls that deal with time.
2433d6423SLionel Sambuc *
3433d6423SLionel Sambuc * The entry points into this file are
4433d6423SLionel Sambuc * do_getres: perform the CLOCK_GETRES system call
5433d6423SLionel Sambuc * do_gettime: perform the CLOCK_GETTIME system call
6433d6423SLionel Sambuc * do_settime: perform the CLOCK_SETTIME system call
7433d6423SLionel Sambuc * do_time: perform the GETTIMEOFDAY system call
8433d6423SLionel Sambuc * do_stime: perform the STIME system call
9433d6423SLionel Sambuc */
10433d6423SLionel Sambuc
11433d6423SLionel Sambuc #include "pm.h"
12433d6423SLionel Sambuc #include <minix/callnr.h>
13433d6423SLionel Sambuc #include <minix/com.h>
14433d6423SLionel Sambuc #include <signal.h>
15433d6423SLionel Sambuc #include <sys/time.h>
16433d6423SLionel Sambuc #include "mproc.h"
17433d6423SLionel Sambuc
18433d6423SLionel Sambuc /*===========================================================================*
19433d6423SLionel Sambuc * do_gettime *
20433d6423SLionel Sambuc *===========================================================================*/
21*637f688fSRichard Sailer int
do_gettime(void)22*637f688fSRichard Sailer do_gettime(void)
23433d6423SLionel Sambuc {
24433d6423SLionel Sambuc clock_t ticks, realtime, clock;
25433d6423SLionel Sambuc time_t boottime;
26433d6423SLionel Sambuc int s;
27433d6423SLionel Sambuc
28433d6423SLionel Sambuc if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
29433d6423SLionel Sambuc panic("do_time couldn't get uptime: %d", s);
30433d6423SLionel Sambuc
31433d6423SLionel Sambuc switch (m_in.m_lc_pm_time.clk_id) {
32433d6423SLionel Sambuc case CLOCK_REALTIME:
33433d6423SLionel Sambuc clock = realtime;
34433d6423SLionel Sambuc break;
35433d6423SLionel Sambuc case CLOCK_MONOTONIC:
36433d6423SLionel Sambuc clock = ticks;
37433d6423SLionel Sambuc break;
38433d6423SLionel Sambuc default:
39433d6423SLionel Sambuc return EINVAL; /* invalid/unsupported clock_id */
40433d6423SLionel Sambuc }
41433d6423SLionel Sambuc
42433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz);
43433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.nsec =
44433d6423SLionel Sambuc (uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz);
45433d6423SLionel Sambuc
46433d6423SLionel Sambuc return(OK);
47433d6423SLionel Sambuc }
48433d6423SLionel Sambuc
49433d6423SLionel Sambuc /*===========================================================================*
50433d6423SLionel Sambuc * do_getres *
51433d6423SLionel Sambuc *===========================================================================*/
52*637f688fSRichard Sailer int
do_getres(void)53*637f688fSRichard Sailer do_getres(void)
54433d6423SLionel Sambuc {
55433d6423SLionel Sambuc switch (m_in.m_lc_pm_time.clk_id) {
56433d6423SLionel Sambuc case CLOCK_REALTIME:
57433d6423SLionel Sambuc case CLOCK_MONOTONIC:
58433d6423SLionel Sambuc /* tv_sec is always 0 since system_hz is an int */
59433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.sec = 0;
60433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.nsec = 1000000000 / system_hz;
61433d6423SLionel Sambuc return(OK);
62433d6423SLionel Sambuc default:
63433d6423SLionel Sambuc return EINVAL; /* invalid/unsupported clock_id */
64433d6423SLionel Sambuc }
65433d6423SLionel Sambuc }
66433d6423SLionel Sambuc
67433d6423SLionel Sambuc /*===========================================================================*
68433d6423SLionel Sambuc * do_settime *
69433d6423SLionel Sambuc *===========================================================================*/
70*637f688fSRichard Sailer int
do_settime(void)71*637f688fSRichard Sailer do_settime(void)
72433d6423SLionel Sambuc {
73433d6423SLionel Sambuc int s;
74433d6423SLionel Sambuc
75433d6423SLionel Sambuc if (mp->mp_effuid != SUPER_USER) {
76433d6423SLionel Sambuc return(EPERM);
77433d6423SLionel Sambuc }
78433d6423SLionel Sambuc
79433d6423SLionel Sambuc switch (m_in.m_lc_pm_time.clk_id) {
80433d6423SLionel Sambuc case CLOCK_REALTIME:
81433d6423SLionel Sambuc s = sys_settime(m_in.m_lc_pm_time.now, m_in.m_lc_pm_time.clk_id,
82433d6423SLionel Sambuc m_in.m_lc_pm_time.sec, m_in.m_lc_pm_time.nsec);
83433d6423SLionel Sambuc return(s);
84433d6423SLionel Sambuc case CLOCK_MONOTONIC: /* monotonic cannot be changed */
85433d6423SLionel Sambuc default:
86433d6423SLionel Sambuc return EINVAL; /* invalid/unsupported clock_id */
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc }
89433d6423SLionel Sambuc
90433d6423SLionel Sambuc /*===========================================================================*
91433d6423SLionel Sambuc * do_time *
92433d6423SLionel Sambuc *===========================================================================*/
93*637f688fSRichard Sailer int
do_time(void)94*637f688fSRichard Sailer do_time(void)
95433d6423SLionel Sambuc {
96ad80a203SDavid van Moolenbroek /* Perform the time(tp) system call. */
97ad80a203SDavid van Moolenbroek struct timespec tv;
98433d6423SLionel Sambuc
99ad80a203SDavid van Moolenbroek (void)clock_time(&tv);
100433d6423SLionel Sambuc
101ad80a203SDavid van Moolenbroek mp->mp_reply.m_pm_lc_time.sec = tv.tv_sec;
102ad80a203SDavid van Moolenbroek mp->mp_reply.m_pm_lc_time.nsec = tv.tv_nsec;
103433d6423SLionel Sambuc return(OK);
104433d6423SLionel Sambuc }
105433d6423SLionel Sambuc
106433d6423SLionel Sambuc /*===========================================================================*
107433d6423SLionel Sambuc * do_stime *
108433d6423SLionel Sambuc *===========================================================================*/
109*637f688fSRichard Sailer int
do_stime(void)110*637f688fSRichard Sailer do_stime(void)
111433d6423SLionel Sambuc {
112433d6423SLionel Sambuc /* Perform the stime(tp) system call. Retrieve the system's uptime (ticks
113433d6423SLionel Sambuc * since boot) and pass the new time in seconds at system boot to the kernel.
114433d6423SLionel Sambuc */
115433d6423SLionel Sambuc clock_t uptime, realtime;
116433d6423SLionel Sambuc time_t boottime;
117433d6423SLionel Sambuc int s;
118433d6423SLionel Sambuc
119433d6423SLionel Sambuc if (mp->mp_effuid != SUPER_USER) {
120433d6423SLionel Sambuc return(EPERM);
121433d6423SLionel Sambuc }
122433d6423SLionel Sambuc if ( (s=getuptime(&uptime, &realtime, &boottime)) != OK)
123433d6423SLionel Sambuc panic("do_stime couldn't get uptime: %d", s);
124433d6423SLionel Sambuc boottime = m_in.m_lc_pm_time.sec - (realtime/system_hz);
125433d6423SLionel Sambuc
126433d6423SLionel Sambuc s= sys_stime(boottime); /* Tell kernel about boottime */
127433d6423SLionel Sambuc if (s != OK)
128433d6423SLionel Sambuc panic("pm: sys_stime failed: %d", s);
129433d6423SLionel Sambuc
130433d6423SLionel Sambuc return(OK);
131433d6423SLionel Sambuc }
132