xref: /minix/minix/servers/pm/time.c (revision 045e0ed3)
1 /* This file takes care of those system calls that deal with time.
2  *
3  * The entry points into this file are
4  *   do_getres:		perform the CLOCK_GETRES system call
5  *   do_gettime:	perform the CLOCK_GETTIME system call
6  *   do_settime:	perform the CLOCK_SETTIME system call
7  *   do_time:		perform the GETTIMEOFDAY system call
8  *   do_stime:		perform the STIME system call
9  */
10 
11 #include "pm.h"
12 #include <minix/callnr.h>
13 #include <minix/com.h>
14 #include <signal.h>
15 #include <sys/time.h>
16 #include "mproc.h"
17 
18 /*===========================================================================*
19  *				do_gettime				     *
20  *===========================================================================*/
21 int
22 do_gettime(void)
23 {
24   clock_t ticks, realtime, clock;
25   time_t boottime;
26   int s;
27 
28   if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
29   	panic("do_time couldn't get uptime: %d", s);
30 
31   switch (m_in.m_lc_pm_time.clk_id) {
32 	case CLOCK_REALTIME:
33 		clock = realtime;
34 		break;
35 	case CLOCK_MONOTONIC:
36 		clock = ticks;
37 		break;
38 	default:
39 		return EINVAL; /* invalid/unsupported clock_id */
40   }
41 
42   mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz);
43   mp->mp_reply.m_pm_lc_time.nsec =
44 	(uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz);
45 
46   return(OK);
47 }
48 
49 /*===========================================================================*
50  *				do_getres				     *
51  *===========================================================================*/
52 int
53 do_getres(void)
54 {
55   switch (m_in.m_lc_pm_time.clk_id) {
56 	case CLOCK_REALTIME:
57 	case CLOCK_MONOTONIC:
58 		/* tv_sec is always 0 since system_hz is an int */
59 		mp->mp_reply.m_pm_lc_time.sec = 0;
60 		mp->mp_reply.m_pm_lc_time.nsec = 1000000000 / system_hz;
61 		return(OK);
62 	default:
63 		return EINVAL; /* invalid/unsupported clock_id */
64   }
65 }
66 
67 /*===========================================================================*
68  *				do_settime				     *
69  *===========================================================================*/
70 int
71 do_settime(void)
72 {
73   int s;
74 
75   if (mp->mp_effuid != SUPER_USER) {
76       return(EPERM);
77   }
78 
79   switch (m_in.m_lc_pm_time.clk_id) {
80 	case CLOCK_REALTIME:
81 		s = sys_settime(m_in.m_lc_pm_time.now, m_in.m_lc_pm_time.clk_id,
82 			m_in.m_lc_pm_time.sec, m_in.m_lc_pm_time.nsec);
83 		return(s);
84 	case CLOCK_MONOTONIC: /* monotonic cannot be changed */
85 	default:
86 		return EINVAL; /* invalid/unsupported clock_id */
87   }
88 }
89 
90 /*===========================================================================*
91  *				do_time					     *
92  *===========================================================================*/
93 int
94 do_time(void)
95 {
96 /* Perform the time(tp) system call. */
97   struct timespec tv;
98 
99   (void)clock_time(&tv);
100 
101   mp->mp_reply.m_pm_lc_time.sec = tv.tv_sec;
102   mp->mp_reply.m_pm_lc_time.nsec = tv.tv_nsec;
103   return(OK);
104 }
105 
106 /*===========================================================================*
107  *				do_stime				     *
108  *===========================================================================*/
109 int
110 do_stime(void)
111 {
112 /* Perform the stime(tp) system call. Retrieve the system's uptime (ticks
113  * since boot) and pass the new time in seconds at system boot to the kernel.
114  */
115   clock_t uptime, realtime;
116   time_t boottime;
117   int s;
118 
119   if (mp->mp_effuid != SUPER_USER) {
120       return(EPERM);
121   }
122   if ( (s=getuptime(&uptime, &realtime, &boottime)) != OK)
123       panic("do_stime couldn't get uptime: %d", s);
124   boottime = m_in.m_lc_pm_time.sec - (realtime/system_hz);
125 
126   s= sys_stime(boottime);		/* Tell kernel about boottime */
127   if (s != OK)
128 	panic("pm: sys_stime failed: %d", s);
129 
130   return(OK);
131 }
132