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