xref: /minix3/minix/servers/pm/time.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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. This returns the time in seconds since
93  * 1.1.1970.  MINIX is an astrophysically naive system that assumes the earth
94  * rotates at a constant rate and that such things as leap seconds do not
95  * exist.
96  */
97   clock_t ticks, realtime;
98   time_t boottime;
99   int s;
100 
101   if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
102   	panic("do_time couldn't get uptime: %d", s);
103 
104   mp->mp_reply.m_pm_lc_time.sec = boottime + (realtime / system_hz);
105   mp->mp_reply.m_pm_lc_time.nsec =
106 	(uint32_t) ((realtime % system_hz) * 1000000000ULL / system_hz);
107   return(OK);
108 }
109 
110 /*===========================================================================*
111  *				do_stime				     *
112  *===========================================================================*/
113 int do_stime()
114 {
115 /* Perform the stime(tp) system call. Retrieve the system's uptime (ticks
116  * since boot) and pass the new time in seconds at system boot to the kernel.
117  */
118   clock_t uptime, realtime;
119   time_t boottime;
120   int s;
121 
122   if (mp->mp_effuid != SUPER_USER) {
123       return(EPERM);
124   }
125   if ( (s=getuptime(&uptime, &realtime, &boottime)) != OK)
126       panic("do_stime couldn't get uptime: %d", s);
127   boottime = m_in.m_lc_pm_time.sec - (realtime/system_hz);
128 
129   s= sys_stime(boottime);		/* Tell kernel about boottime */
130   if (s != OK)
131 	panic("pm: sys_stime failed: %d", s);
132 
133   return(OK);
134 }
135