1*433d6423SLionel Sambuc /* This file takes care of those system calls that deal with time. 2*433d6423SLionel Sambuc * 3*433d6423SLionel Sambuc * The entry points into this file are 4*433d6423SLionel Sambuc * do_getres: perform the CLOCK_GETRES system call 5*433d6423SLionel Sambuc * do_gettime: perform the CLOCK_GETTIME system call 6*433d6423SLionel Sambuc * do_settime: perform the CLOCK_SETTIME system call 7*433d6423SLionel Sambuc * do_time: perform the GETTIMEOFDAY system call 8*433d6423SLionel Sambuc * do_stime: perform the STIME system call 9*433d6423SLionel Sambuc */ 10*433d6423SLionel Sambuc 11*433d6423SLionel Sambuc #include "pm.h" 12*433d6423SLionel Sambuc #include <minix/callnr.h> 13*433d6423SLionel Sambuc #include <minix/com.h> 14*433d6423SLionel Sambuc #include <signal.h> 15*433d6423SLionel Sambuc #include <sys/time.h> 16*433d6423SLionel Sambuc #include "mproc.h" 17*433d6423SLionel Sambuc 18*433d6423SLionel Sambuc /*===========================================================================* 19*433d6423SLionel Sambuc * do_gettime * 20*433d6423SLionel Sambuc *===========================================================================*/ 21*433d6423SLionel Sambuc int do_gettime() 22*433d6423SLionel Sambuc { 23*433d6423SLionel Sambuc clock_t ticks, realtime, clock; 24*433d6423SLionel Sambuc time_t boottime; 25*433d6423SLionel Sambuc int s; 26*433d6423SLionel Sambuc 27*433d6423SLionel Sambuc if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK) 28*433d6423SLionel Sambuc panic("do_time couldn't get uptime: %d", s); 29*433d6423SLionel Sambuc 30*433d6423SLionel Sambuc switch (m_in.m_lc_pm_time.clk_id) { 31*433d6423SLionel Sambuc case CLOCK_REALTIME: 32*433d6423SLionel Sambuc clock = realtime; 33*433d6423SLionel Sambuc break; 34*433d6423SLionel Sambuc case CLOCK_MONOTONIC: 35*433d6423SLionel Sambuc clock = ticks; 36*433d6423SLionel Sambuc break; 37*433d6423SLionel Sambuc default: 38*433d6423SLionel Sambuc return EINVAL; /* invalid/unsupported clock_id */ 39*433d6423SLionel Sambuc } 40*433d6423SLionel Sambuc 41*433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz); 42*433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.nsec = 43*433d6423SLionel Sambuc (uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz); 44*433d6423SLionel Sambuc 45*433d6423SLionel Sambuc return(OK); 46*433d6423SLionel Sambuc } 47*433d6423SLionel Sambuc 48*433d6423SLionel Sambuc /*===========================================================================* 49*433d6423SLionel Sambuc * do_getres * 50*433d6423SLionel Sambuc *===========================================================================*/ 51*433d6423SLionel Sambuc int do_getres() 52*433d6423SLionel Sambuc { 53*433d6423SLionel Sambuc switch (m_in.m_lc_pm_time.clk_id) { 54*433d6423SLionel Sambuc case CLOCK_REALTIME: 55*433d6423SLionel Sambuc case CLOCK_MONOTONIC: 56*433d6423SLionel Sambuc /* tv_sec is always 0 since system_hz is an int */ 57*433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.sec = 0; 58*433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.nsec = 1000000000 / system_hz; 59*433d6423SLionel Sambuc return(OK); 60*433d6423SLionel Sambuc default: 61*433d6423SLionel Sambuc return EINVAL; /* invalid/unsupported clock_id */ 62*433d6423SLionel Sambuc } 63*433d6423SLionel Sambuc } 64*433d6423SLionel Sambuc 65*433d6423SLionel Sambuc /*===========================================================================* 66*433d6423SLionel Sambuc * do_settime * 67*433d6423SLionel Sambuc *===========================================================================*/ 68*433d6423SLionel Sambuc int do_settime() 69*433d6423SLionel Sambuc { 70*433d6423SLionel Sambuc int s; 71*433d6423SLionel Sambuc 72*433d6423SLionel Sambuc if (mp->mp_effuid != SUPER_USER) { 73*433d6423SLionel Sambuc return(EPERM); 74*433d6423SLionel Sambuc } 75*433d6423SLionel Sambuc 76*433d6423SLionel Sambuc switch (m_in.m_lc_pm_time.clk_id) { 77*433d6423SLionel Sambuc case CLOCK_REALTIME: 78*433d6423SLionel Sambuc s = sys_settime(m_in.m_lc_pm_time.now, m_in.m_lc_pm_time.clk_id, 79*433d6423SLionel Sambuc m_in.m_lc_pm_time.sec, m_in.m_lc_pm_time.nsec); 80*433d6423SLionel Sambuc return(s); 81*433d6423SLionel Sambuc case CLOCK_MONOTONIC: /* monotonic cannot be changed */ 82*433d6423SLionel Sambuc default: 83*433d6423SLionel Sambuc return EINVAL; /* invalid/unsupported clock_id */ 84*433d6423SLionel Sambuc } 85*433d6423SLionel Sambuc } 86*433d6423SLionel Sambuc 87*433d6423SLionel Sambuc /*===========================================================================* 88*433d6423SLionel Sambuc * do_time * 89*433d6423SLionel Sambuc *===========================================================================*/ 90*433d6423SLionel Sambuc int do_time() 91*433d6423SLionel Sambuc { 92*433d6423SLionel Sambuc /* Perform the time(tp) system call. This returns the time in seconds since 93*433d6423SLionel Sambuc * 1.1.1970. MINIX is an astrophysically naive system that assumes the earth 94*433d6423SLionel Sambuc * rotates at a constant rate and that such things as leap seconds do not 95*433d6423SLionel Sambuc * exist. 96*433d6423SLionel Sambuc */ 97*433d6423SLionel Sambuc clock_t ticks, realtime; 98*433d6423SLionel Sambuc time_t boottime; 99*433d6423SLionel Sambuc int s; 100*433d6423SLionel Sambuc 101*433d6423SLionel Sambuc if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK) 102*433d6423SLionel Sambuc panic("do_time couldn't get uptime: %d", s); 103*433d6423SLionel Sambuc 104*433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.sec = boottime + (realtime / system_hz); 105*433d6423SLionel Sambuc mp->mp_reply.m_pm_lc_time.nsec = 106*433d6423SLionel Sambuc (uint32_t) ((realtime % system_hz) * 1000000000ULL / system_hz); 107*433d6423SLionel Sambuc return(OK); 108*433d6423SLionel Sambuc } 109*433d6423SLionel Sambuc 110*433d6423SLionel Sambuc /*===========================================================================* 111*433d6423SLionel Sambuc * do_stime * 112*433d6423SLionel Sambuc *===========================================================================*/ 113*433d6423SLionel Sambuc int do_stime() 114*433d6423SLionel Sambuc { 115*433d6423SLionel Sambuc /* Perform the stime(tp) system call. Retrieve the system's uptime (ticks 116*433d6423SLionel Sambuc * since boot) and pass the new time in seconds at system boot to the kernel. 117*433d6423SLionel Sambuc */ 118*433d6423SLionel Sambuc clock_t uptime, realtime; 119*433d6423SLionel Sambuc time_t boottime; 120*433d6423SLionel Sambuc int s; 121*433d6423SLionel Sambuc 122*433d6423SLionel Sambuc if (mp->mp_effuid != SUPER_USER) { 123*433d6423SLionel Sambuc return(EPERM); 124*433d6423SLionel Sambuc } 125*433d6423SLionel Sambuc if ( (s=getuptime(&uptime, &realtime, &boottime)) != OK) 126*433d6423SLionel Sambuc panic("do_stime couldn't get uptime: %d", s); 127*433d6423SLionel Sambuc boottime = m_in.m_lc_pm_time.sec - (realtime/system_hz); 128*433d6423SLionel Sambuc 129*433d6423SLionel Sambuc s= sys_stime(boottime); /* Tell kernel about boottime */ 130*433d6423SLionel Sambuc if (s != OK) 131*433d6423SLionel Sambuc panic("pm: sys_stime failed: %d", s); 132*433d6423SLionel Sambuc 133*433d6423SLionel Sambuc return(OK); 134*433d6423SLionel Sambuc } 135