1433d6423SLionel Sambuc /* The kernel call implemented in this file: 2433d6423SLionel Sambuc * m_type: SYS_SETTIME 3433d6423SLionel Sambuc * 4433d6423SLionel Sambuc * The parameters for this kernel call are: 5433d6423SLionel Sambuc * m_lsys_krn_sys_settime.now 6433d6423SLionel Sambuc * m_lsys_krn_sys_settime.clock_id 7433d6423SLionel Sambuc * m_lsys_krn_sys_settime.sec 8433d6423SLionel Sambuc * m_lsys_krn_sys_settime.nsec 9433d6423SLionel Sambuc */ 10433d6423SLionel Sambuc 11433d6423SLionel Sambuc #include "kernel/system.h" 12433d6423SLionel Sambuc #include <minix/endpoint.h> 13433d6423SLionel Sambuc #include <time.h> 14433d6423SLionel Sambuc 15433d6423SLionel Sambuc /*===========================================================================* 16433d6423SLionel Sambuc * do_settime * 17433d6423SLionel Sambuc *===========================================================================*/ do_settime(struct proc * caller,message * m_ptr)18433d6423SLionel Sambucint do_settime(struct proc * caller, message * m_ptr) 19433d6423SLionel Sambuc { 20433d6423SLionel Sambuc clock_t newclock; 21433d6423SLionel Sambuc int32_t ticks; 22*d91f738bSDavid van Moolenbroek time_t boottime, timediff, timediff_ticks; 23433d6423SLionel Sambuc 24*d91f738bSDavid van Moolenbroek /* only realtime can change */ 25*d91f738bSDavid van Moolenbroek if (m_ptr->m_lsys_krn_sys_settime.clock_id != CLOCK_REALTIME) 26433d6423SLionel Sambuc return EINVAL; 27433d6423SLionel Sambuc 28*d91f738bSDavid van Moolenbroek /* user just wants to adjtime() */ 29*d91f738bSDavid van Moolenbroek if (m_ptr->m_lsys_krn_sys_settime.now == 0) { 30433d6423SLionel Sambuc /* convert delta value from seconds and nseconds to ticks */ 31433d6423SLionel Sambuc ticks = (m_ptr->m_lsys_krn_sys_settime.sec * system_hz) + 32433d6423SLionel Sambuc (m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz)); 33433d6423SLionel Sambuc set_adjtime_delta(ticks); 34433d6423SLionel Sambuc return(OK); 35433d6423SLionel Sambuc } /* else user wants to set the time */ 36433d6423SLionel Sambuc 37*d91f738bSDavid van Moolenbroek boottime = get_boottime(); 38*d91f738bSDavid van Moolenbroek 39433d6423SLionel Sambuc timediff = m_ptr->m_lsys_krn_sys_settime.sec - boottime; 40433d6423SLionel Sambuc timediff_ticks = timediff * system_hz; 41433d6423SLionel Sambuc 42433d6423SLionel Sambuc /* prevent a negative value for realtime */ 43433d6423SLionel Sambuc if (m_ptr->m_lsys_krn_sys_settime.sec <= boottime || 44433d6423SLionel Sambuc timediff_ticks < LONG_MIN/2 || timediff_ticks > LONG_MAX/2) { 45433d6423SLionel Sambuc /* boottime was likely wrong, try to correct it. */ 46*d91f738bSDavid van Moolenbroek set_boottime(m_ptr->m_lsys_krn_sys_settime.sec); 47433d6423SLionel Sambuc set_realtime(1); 48433d6423SLionel Sambuc return(OK); 49433d6423SLionel Sambuc } 50433d6423SLionel Sambuc 51433d6423SLionel Sambuc /* calculate the new value of realtime in ticks */ 52433d6423SLionel Sambuc newclock = timediff_ticks + 53433d6423SLionel Sambuc (m_ptr->m_lsys_krn_sys_settime.nsec/(1000000000/system_hz)); 54433d6423SLionel Sambuc 55433d6423SLionel Sambuc set_realtime(newclock); 56433d6423SLionel Sambuc 57433d6423SLionel Sambuc return(OK); 58433d6423SLionel Sambuc } 59