xref: /minix3/minix/kernel/system/do_settime.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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 timediff, timediff_ticks;
23  
24    if (m_ptr->m_lsys_krn_sys_settime.clock_id != CLOCK_REALTIME) /* only realtime can change */
25  	return EINVAL;
26  
27    if (m_ptr->m_lsys_krn_sys_settime.now == 0) { /* user just wants to adjtime() */
28  	/* convert delta value from seconds and nseconds to ticks */
29  	ticks = (m_ptr->m_lsys_krn_sys_settime.sec * system_hz) +
30  			(m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz));
31  	set_adjtime_delta(ticks);
32  	return(OK);
33    } /* else user wants to set the time */
34  
35    timediff = m_ptr->m_lsys_krn_sys_settime.sec - boottime;
36    timediff_ticks = timediff * system_hz;
37  
38    /* prevent a negative value for realtime */
39    if (m_ptr->m_lsys_krn_sys_settime.sec <= boottime ||
40        timediff_ticks < LONG_MIN/2 || timediff_ticks > LONG_MAX/2) {
41    	/* boottime was likely wrong, try to correct it. */
42  	boottime = m_ptr->m_lsys_krn_sys_settime.sec;
43  	set_realtime(1);
44  	return(OK);
45    }
46  
47    /* calculate the new value of realtime in ticks */
48    newclock = timediff_ticks +
49        (m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz));
50  
51    set_realtime(newclock);
52  
53    return(OK);
54  }
55