xref: /minix3/minix/servers/pm/time.c (revision b80da2a01d0bb632707b7b4e974aa32eaebbcc6f)
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 do_gettime()
22 {
23   clock_t ticks, realtime, clock;
24   time_t boottime;
25   int s;
26 
27   if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
28   	panic("do_time couldn't get uptime: %d", s);
29 
30   switch (m_in.m_lc_pm_time.clk_id) {
31 	case CLOCK_REALTIME:
32 		clock = realtime;
33 		break;
34 	case CLOCK_MONOTONIC:
35 		clock = ticks;
36 		break;
37 	default:
38 		return EINVAL; /* invalid/unsupported clock_id */
39   }
40 
41   mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz);
42   mp->mp_reply.m_pm_lc_time.nsec =
43 	(uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz);
44 
45   return(OK);
46 }
47 
48 /*===========================================================================*
49  *				do_getres				     *
50  *===========================================================================*/
51 int do_getres()
52 {
53   switch (m_in.m_lc_pm_time.clk_id) {
54 	case CLOCK_REALTIME:
55 	case CLOCK_MONOTONIC:
56 		/* tv_sec is always 0 since system_hz is an int */
57 		mp->mp_reply.m_pm_lc_time.sec = 0;
58 		mp->mp_reply.m_pm_lc_time.nsec = 1000000000 / system_hz;
59 		return(OK);
60 	default:
61 		return EINVAL; /* invalid/unsupported clock_id */
62   }
63 }
64 
65 /*===========================================================================*
66  *				do_settime				     *
67  *===========================================================================*/
68 int do_settime()
69 {
70   int s;
71 
72   if (mp->mp_effuid != SUPER_USER) {
73       return(EPERM);
74   }
75 
76   switch (m_in.m_lc_pm_time.clk_id) {
77 	case CLOCK_REALTIME:
78 		s = sys_settime(m_in.m_lc_pm_time.now, m_in.m_lc_pm_time.clk_id,
79 			m_in.m_lc_pm_time.sec, m_in.m_lc_pm_time.nsec);
80 		return(s);
81 	case CLOCK_MONOTONIC: /* monotonic cannot be changed */
82 	default:
83 		return EINVAL; /* invalid/unsupported clock_id */
84   }
85 }
86 
87 /*===========================================================================*
88  *				do_time					     *
89  *===========================================================================*/
90 int do_time()
91 {
92 /* Perform the time(tp) system call. */
93   struct timespec tv;
94 
95   (void)clock_time(&tv);
96 
97   mp->mp_reply.m_pm_lc_time.sec = tv.tv_sec;
98   mp->mp_reply.m_pm_lc_time.nsec = tv.tv_nsec;
99   return(OK);
100 }
101 
102 /*===========================================================================*
103  *				do_stime				     *
104  *===========================================================================*/
105 int do_stime()
106 {
107 /* Perform the stime(tp) system call. Retrieve the system's uptime (ticks
108  * since boot) and pass the new time in seconds at system boot to the kernel.
109  */
110   clock_t uptime, realtime;
111   time_t boottime;
112   int s;
113 
114   if (mp->mp_effuid != SUPER_USER) {
115       return(EPERM);
116   }
117   if ( (s=getuptime(&uptime, &realtime, &boottime)) != OK)
118       panic("do_stime couldn't get uptime: %d", s);
119   boottime = m_in.m_lc_pm_time.sec - (realtime/system_hz);
120 
121   s= sys_stime(boottime);		/* Tell kernel about boottime */
122   if (s != OK)
123 	panic("pm: sys_stime failed: %d", s);
124 
125   return(OK);
126 }
127