xref: /minix/minix/kernel/system/do_settime.c (revision 9f988b79)
1 /* The kernel call implemented in this file:
2  *   m_type:	SYS_SETTIME
3  *
4  * The parameters for this kernel call are:
5  *   m_lsys_krn_sys_settime.now
6  *   m_lsys_krn_sys_settime.clock_id
7  *   m_lsys_krn_sys_settime.sec
8  *   m_lsys_krn_sys_settime.nsec
9  */
10 
11 #include "kernel/system.h"
12 #include <minix/endpoint.h>
13 #include <time.h>
14 
15 /*===========================================================================*
16  *				do_settime				     *
17  *===========================================================================*/
18 int do_settime(struct proc * caller, message * m_ptr)
19 {
20   clock_t newclock;
21   int32_t ticks;
22   time_t boottime, timediff, timediff_ticks;
23 
24   /* only realtime can change */
25   if (m_ptr->m_lsys_krn_sys_settime.clock_id != CLOCK_REALTIME)
26 	return EINVAL;
27 
28   /* user just wants to adjtime() */
29   if (m_ptr->m_lsys_krn_sys_settime.now == 0) {
30 	/* convert delta value from seconds and nseconds to ticks */
31 	ticks = (m_ptr->m_lsys_krn_sys_settime.sec * system_hz) +
32 		(m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz));
33 	set_adjtime_delta(ticks);
34 	return(OK);
35   } /* else user wants to set the time */
36 
37   boottime = get_boottime();
38 
39   timediff = m_ptr->m_lsys_krn_sys_settime.sec - boottime;
40   timediff_ticks = timediff * system_hz;
41 
42   /* prevent a negative value for realtime */
43   if (m_ptr->m_lsys_krn_sys_settime.sec <= boottime ||
44       timediff_ticks < LONG_MIN/2 || timediff_ticks > LONG_MAX/2) {
45   	/* boottime was likely wrong, try to correct it. */
46 	set_boottime(m_ptr->m_lsys_krn_sys_settime.sec);
47 	set_realtime(1);
48 	return(OK);
49   }
50 
51   /* calculate the new value of realtime in ticks */
52   newclock = timediff_ticks +
53       (m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz));
54 
55   set_realtime(newclock);
56 
57   return(OK);
58 }
59