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 22 do_gettime(void) 23 { 24 clock_t ticks, realtime, clock; 25 time_t boottime; 26 int s; 27 28 if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK) 29 panic("do_time couldn't get uptime: %d", s); 30 31 switch (m_in.m_lc_pm_time.clk_id) { 32 case CLOCK_REALTIME: 33 clock = realtime; 34 break; 35 case CLOCK_MONOTONIC: 36 clock = ticks; 37 break; 38 default: 39 return EINVAL; /* invalid/unsupported clock_id */ 40 } 41 42 mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz); 43 mp->mp_reply.m_pm_lc_time.nsec = 44 (uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz); 45 46 return(OK); 47 } 48 49 /*===========================================================================* 50 * do_getres * 51 *===========================================================================*/ 52 int 53 do_getres(void) 54 { 55 switch (m_in.m_lc_pm_time.clk_id) { 56 case CLOCK_REALTIME: 57 case CLOCK_MONOTONIC: 58 /* tv_sec is always 0 since system_hz is an int */ 59 mp->mp_reply.m_pm_lc_time.sec = 0; 60 mp->mp_reply.m_pm_lc_time.nsec = 1000000000 / system_hz; 61 return(OK); 62 default: 63 return EINVAL; /* invalid/unsupported clock_id */ 64 } 65 } 66 67 /*===========================================================================* 68 * do_settime * 69 *===========================================================================*/ 70 int 71 do_settime(void) 72 { 73 int s; 74 75 if (mp->mp_effuid != SUPER_USER) { 76 return(EPERM); 77 } 78 79 switch (m_in.m_lc_pm_time.clk_id) { 80 case CLOCK_REALTIME: 81 s = sys_settime(m_in.m_lc_pm_time.now, m_in.m_lc_pm_time.clk_id, 82 m_in.m_lc_pm_time.sec, m_in.m_lc_pm_time.nsec); 83 return(s); 84 case CLOCK_MONOTONIC: /* monotonic cannot be changed */ 85 default: 86 return EINVAL; /* invalid/unsupported clock_id */ 87 } 88 } 89 90 /*===========================================================================* 91 * do_time * 92 *===========================================================================*/ 93 int 94 do_time(void) 95 { 96 /* Perform the time(tp) system call. */ 97 struct timespec tv; 98 99 (void)clock_time(&tv); 100 101 mp->mp_reply.m_pm_lc_time.sec = tv.tv_sec; 102 mp->mp_reply.m_pm_lc_time.nsec = tv.tv_nsec; 103 return(OK); 104 } 105 106 /*===========================================================================* 107 * do_stime * 108 *===========================================================================*/ 109 int 110 do_stime(void) 111 { 112 /* Perform the stime(tp) system call. Retrieve the system's uptime (ticks 113 * since boot) and pass the new time in seconds at system boot to the kernel. 114 */ 115 clock_t uptime, realtime; 116 time_t boottime; 117 int s; 118 119 if (mp->mp_effuid != SUPER_USER) { 120 return(EPERM); 121 } 122 if ( (s=getuptime(&uptime, &realtime, &boottime)) != OK) 123 panic("do_stime couldn't get uptime: %d", s); 124 boottime = m_in.m_lc_pm_time.sec - (realtime/system_hz); 125 126 s= sys_stime(boottime); /* Tell kernel about boottime */ 127 if (s != OK) 128 panic("pm: sys_stime failed: %d", s); 129 130 return(OK); 131 } 132