xref: /minix3/minix/servers/pm/time.c (revision ad80a203dbe8dfd72afcba56c4335320c60b2e5a)
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  *===========================================================================*/
21433d6423SLionel Sambuc int do_gettime()
22433d6423SLionel Sambuc {
23433d6423SLionel Sambuc   clock_t ticks, realtime, clock;
24433d6423SLionel Sambuc   time_t boottime;
25433d6423SLionel Sambuc   int s;
26433d6423SLionel Sambuc 
27433d6423SLionel Sambuc   if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
28433d6423SLionel Sambuc   	panic("do_time couldn't get uptime: %d", s);
29433d6423SLionel Sambuc 
30433d6423SLionel Sambuc   switch (m_in.m_lc_pm_time.clk_id) {
31433d6423SLionel Sambuc 	case CLOCK_REALTIME:
32433d6423SLionel Sambuc 		clock = realtime;
33433d6423SLionel Sambuc 		break;
34433d6423SLionel Sambuc 	case CLOCK_MONOTONIC:
35433d6423SLionel Sambuc 		clock = ticks;
36433d6423SLionel Sambuc 		break;
37433d6423SLionel Sambuc 	default:
38433d6423SLionel Sambuc 		return EINVAL; /* invalid/unsupported clock_id */
39433d6423SLionel Sambuc   }
40433d6423SLionel Sambuc 
41433d6423SLionel Sambuc   mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz);
42433d6423SLionel Sambuc   mp->mp_reply.m_pm_lc_time.nsec =
43433d6423SLionel Sambuc 	(uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz);
44433d6423SLionel Sambuc 
45433d6423SLionel Sambuc   return(OK);
46433d6423SLionel Sambuc }
47433d6423SLionel Sambuc 
48433d6423SLionel Sambuc /*===========================================================================*
49433d6423SLionel Sambuc  *				do_getres				     *
50433d6423SLionel Sambuc  *===========================================================================*/
51433d6423SLionel Sambuc int do_getres()
52433d6423SLionel Sambuc {
53433d6423SLionel Sambuc   switch (m_in.m_lc_pm_time.clk_id) {
54433d6423SLionel Sambuc 	case CLOCK_REALTIME:
55433d6423SLionel Sambuc 	case CLOCK_MONOTONIC:
56433d6423SLionel Sambuc 		/* tv_sec is always 0 since system_hz is an int */
57433d6423SLionel Sambuc 		mp->mp_reply.m_pm_lc_time.sec = 0;
58433d6423SLionel Sambuc 		mp->mp_reply.m_pm_lc_time.nsec = 1000000000 / system_hz;
59433d6423SLionel Sambuc 		return(OK);
60433d6423SLionel Sambuc 	default:
61433d6423SLionel Sambuc 		return EINVAL; /* invalid/unsupported clock_id */
62433d6423SLionel Sambuc   }
63433d6423SLionel Sambuc }
64433d6423SLionel Sambuc 
65433d6423SLionel Sambuc /*===========================================================================*
66433d6423SLionel Sambuc  *				do_settime				     *
67433d6423SLionel Sambuc  *===========================================================================*/
68433d6423SLionel Sambuc int do_settime()
69433d6423SLionel Sambuc {
70433d6423SLionel Sambuc   int s;
71433d6423SLionel Sambuc 
72433d6423SLionel Sambuc   if (mp->mp_effuid != SUPER_USER) {
73433d6423SLionel Sambuc       return(EPERM);
74433d6423SLionel Sambuc   }
75433d6423SLionel Sambuc 
76433d6423SLionel Sambuc   switch (m_in.m_lc_pm_time.clk_id) {
77433d6423SLionel Sambuc 	case CLOCK_REALTIME:
78433d6423SLionel Sambuc 		s = sys_settime(m_in.m_lc_pm_time.now, m_in.m_lc_pm_time.clk_id,
79433d6423SLionel Sambuc 			m_in.m_lc_pm_time.sec, m_in.m_lc_pm_time.nsec);
80433d6423SLionel Sambuc 		return(s);
81433d6423SLionel Sambuc 	case CLOCK_MONOTONIC: /* monotonic cannot be changed */
82433d6423SLionel Sambuc 	default:
83433d6423SLionel Sambuc 		return EINVAL; /* invalid/unsupported clock_id */
84433d6423SLionel Sambuc   }
85433d6423SLionel Sambuc }
86433d6423SLionel Sambuc 
87433d6423SLionel Sambuc /*===========================================================================*
88433d6423SLionel Sambuc  *				do_time					     *
89433d6423SLionel Sambuc  *===========================================================================*/
90433d6423SLionel Sambuc int do_time()
91433d6423SLionel Sambuc {
92*ad80a203SDavid van Moolenbroek /* Perform the time(tp) system call. */
93*ad80a203SDavid van Moolenbroek   struct timespec tv;
94433d6423SLionel Sambuc 
95*ad80a203SDavid van Moolenbroek   (void)clock_time(&tv);
96433d6423SLionel Sambuc 
97*ad80a203SDavid van Moolenbroek   mp->mp_reply.m_pm_lc_time.sec = tv.tv_sec;
98*ad80a203SDavid van Moolenbroek   mp->mp_reply.m_pm_lc_time.nsec = tv.tv_nsec;
99433d6423SLionel Sambuc   return(OK);
100433d6423SLionel Sambuc }
101433d6423SLionel Sambuc 
102433d6423SLionel Sambuc /*===========================================================================*
103433d6423SLionel Sambuc  *				do_stime				     *
104433d6423SLionel Sambuc  *===========================================================================*/
105433d6423SLionel Sambuc int do_stime()
106433d6423SLionel Sambuc {
107433d6423SLionel Sambuc /* Perform the stime(tp) system call. Retrieve the system's uptime (ticks
108433d6423SLionel Sambuc  * since boot) and pass the new time in seconds at system boot to the kernel.
109433d6423SLionel Sambuc  */
110433d6423SLionel Sambuc   clock_t uptime, realtime;
111433d6423SLionel Sambuc   time_t boottime;
112433d6423SLionel Sambuc   int s;
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc   if (mp->mp_effuid != SUPER_USER) {
115433d6423SLionel Sambuc       return(EPERM);
116433d6423SLionel Sambuc   }
117433d6423SLionel Sambuc   if ( (s=getuptime(&uptime, &realtime, &boottime)) != OK)
118433d6423SLionel Sambuc       panic("do_stime couldn't get uptime: %d", s);
119433d6423SLionel Sambuc   boottime = m_in.m_lc_pm_time.sec - (realtime/system_hz);
120433d6423SLionel Sambuc 
121433d6423SLionel Sambuc   s= sys_stime(boottime);		/* Tell kernel about boottime */
122433d6423SLionel Sambuc   if (s != OK)
123433d6423SLionel Sambuc 	panic("pm: sys_stime failed: %d", s);
124433d6423SLionel Sambuc 
125433d6423SLionel Sambuc   return(OK);
126433d6423SLionel Sambuc }
127