1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Implement fast getrusage call 28 */ 29 30 #include <sys/types.h> 31 #include <sys/systm.h> 32 #include <sys/time.h> 33 #include <sys/errno.h> 34 #include <sys/resource.h> 35 #include <sys/vm_usage.h> 36 37 static int 38 getrusage(void *user_rusage) 39 { 40 struct rusage r; 41 kthread_t *t = curthread; 42 proc_t *p = ttoproc(t); 43 hrtime_t snsecs, unsecs; 44 klwp_t *lwp; 45 46 bzero(&r, sizeof (struct rusage)); 47 48 mutex_enter(&p->p_lock); 49 50 if (p->p_defunct > 0) { 51 r.ru_majflt = p->p_ru.majflt; 52 r.ru_minflt = p->p_ru.minflt; 53 r.ru_nswap = p->p_ru.nswap; 54 r.ru_inblock = p->p_ru.inblock; 55 r.ru_oublock = p->p_ru.oublock; 56 r.ru_msgsnd = p->p_ru.msgsnd; 57 r.ru_msgrcv = p->p_ru.msgrcv; 58 r.ru_nsignals = p->p_ru.nsignals; 59 r.ru_nvcsw = p->p_ru.nvcsw; 60 r.ru_nivcsw = p->p_ru.nivcsw; 61 } 62 63 unsecs = mstate_aggr_state(p, LMS_USER); 64 snsecs = mstate_aggr_state(p, LMS_SYSTEM); 65 66 do { 67 if (t->t_proc_flag & TP_LWPEXIT) 68 continue; 69 70 lwp = ttolwp(t); 71 72 r.ru_majflt += lwp->lwp_ru.majflt; 73 r.ru_minflt += lwp->lwp_ru.minflt; 74 r.ru_nswap += lwp->lwp_ru.nswap; 75 r.ru_inblock += lwp->lwp_ru.inblock; 76 r.ru_oublock += lwp->lwp_ru.oublock; 77 r.ru_msgsnd += lwp->lwp_ru.msgsnd; 78 r.ru_msgrcv += lwp->lwp_ru.msgrcv; 79 r.ru_nsignals += lwp->lwp_ru.nsignals; 80 r.ru_nvcsw += lwp->lwp_ru.nvcsw; 81 r.ru_nivcsw += lwp->lwp_ru.nivcsw; 82 83 } while ((t = t->t_forw) != curthread); 84 85 mutex_exit(&p->p_lock); 86 87 hrt2tv(unsecs, &r.ru_utime); 88 hrt2tv(snsecs, &r.ru_stime); 89 90 #ifdef _SYSCALL32_IMPL 91 if (get_udatamodel() == DATAMODEL_ILP32) { 92 struct rusage32 r32; 93 94 bzero(&r32, sizeof (struct rusage32)); 95 96 r32.ru_utime.tv_sec = r.ru_utime.tv_sec; 97 r32.ru_utime.tv_usec = r.ru_utime.tv_usec; 98 r32.ru_stime.tv_sec = r.ru_stime.tv_sec; 99 r32.ru_stime.tv_usec = r.ru_stime.tv_usec; 100 101 r32.ru_majflt = (int32_t)r.ru_majflt; 102 r32.ru_minflt = (int32_t)r.ru_minflt; 103 r32.ru_nswap = (int32_t)r.ru_nswap; 104 r32.ru_inblock = (int32_t)r.ru_inblock; 105 r32.ru_oublock = (int32_t)r.ru_oublock; 106 r32.ru_msgsnd = (int32_t)r.ru_msgsnd; 107 r32.ru_msgrcv = (int32_t)r.ru_msgrcv; 108 r32.ru_nsignals = (int32_t)r.ru_nsignals; 109 r32.ru_nvcsw = (int32_t)r.ru_nvcsw; 110 r32.ru_nivcsw = (int32_t)r.ru_nivcsw; 111 if (copyout(&r32, user_rusage, sizeof (r32)) != 0) 112 return (set_errno(EFAULT)); 113 } else 114 #endif /* _SYSCALL32_IMPL */ 115 116 if (copyout(&r, user_rusage, sizeof (r)) != 0) 117 return (set_errno(EFAULT)); 118 119 return (0); 120 } 121 122 static int 123 getrusage_chld(void *user_rusage) 124 { 125 struct rusage r; 126 kthread_t *t = curthread; 127 proc_t *p = ttoproc(t); 128 hrtime_t snsecs, unsecs; 129 130 bzero(&r, sizeof (struct rusage)); 131 132 mutex_enter(&p->p_lock); 133 134 unsecs = p->p_cacct[LMS_USER]; 135 snsecs = p->p_cacct[LMS_SYSTEM] + p->p_cacct[LMS_TRAP]; 136 137 r.ru_majflt = p->p_cru.majflt; 138 r.ru_minflt = p->p_cru.minflt; 139 r.ru_nswap = p->p_cru.nswap; 140 r.ru_inblock = p->p_cru.inblock; 141 r.ru_oublock = p->p_cru.oublock; 142 r.ru_msgsnd = p->p_cru.msgsnd; 143 r.ru_msgrcv = p->p_cru.msgrcv; 144 r.ru_nsignals = p->p_cru.nsignals; 145 r.ru_nvcsw = p->p_cru.nvcsw; 146 r.ru_nivcsw = p->p_cru.nivcsw; 147 148 mutex_exit(&p->p_lock); 149 150 hrt2tv(unsecs, &r.ru_utime); 151 hrt2tv(snsecs, &r.ru_stime); 152 #ifdef _SYSCALL32_IMPL 153 if (get_udatamodel() == DATAMODEL_ILP32) { 154 struct rusage32 r32; 155 156 bzero(&r32, sizeof (struct rusage32)); 157 158 r32.ru_utime.tv_sec = r.ru_utime.tv_sec; 159 r32.ru_utime.tv_usec = r.ru_utime.tv_usec; 160 r32.ru_stime.tv_sec = r.ru_stime.tv_sec; 161 r32.ru_stime.tv_usec = r.ru_stime.tv_usec; 162 163 r32.ru_majflt = (int32_t)r.ru_majflt; 164 r32.ru_minflt = (int32_t)r.ru_minflt; 165 r32.ru_nswap = (int32_t)r.ru_nswap; 166 r32.ru_inblock = (int32_t)r.ru_inblock; 167 r32.ru_oublock = (int32_t)r.ru_oublock; 168 r32.ru_msgsnd = (int32_t)r.ru_msgsnd; 169 r32.ru_msgrcv = (int32_t)r.ru_msgrcv; 170 r32.ru_nsignals = (int32_t)r.ru_nsignals; 171 r32.ru_nvcsw = (int32_t)r.ru_nvcsw; 172 r32.ru_nivcsw = (int32_t)r.ru_nivcsw; 173 if (copyout(&r32, user_rusage, sizeof (r32)) != 0) 174 return (set_errno(EFAULT)); 175 } else 176 #endif /* _SYSCALL32_IMPL */ 177 178 if (copyout(&r, user_rusage, sizeof (r)) != 0) 179 return (set_errno(EFAULT)); 180 181 return (0); 182 } 183 184 static int 185 getrusage_lwp(void *user_rusage) 186 { 187 struct rusage r; 188 kthread_t *t = curthread; 189 klwp_t *lwp; 190 hrtime_t snsecs, unsecs; 191 struct mstate *ms; 192 193 bzero(&r, sizeof (struct rusage)); 194 195 lwp = ttolwp(t); 196 ms = &lwp->lwp_mstate; 197 unsecs = ms->ms_acct[LMS_USER]; 198 snsecs = ms->ms_acct[LMS_SYSTEM] + ms->ms_acct[LMS_TRAP]; 199 scalehrtime(&unsecs); 200 scalehrtime(&snsecs); 201 r.ru_majflt = lwp->lwp_ru.majflt; 202 r.ru_minflt = lwp->lwp_ru.minflt; 203 r.ru_nswap = lwp->lwp_ru.nswap; 204 r.ru_inblock = lwp->lwp_ru.inblock; 205 r.ru_oublock = lwp->lwp_ru.oublock; 206 r.ru_msgsnd = lwp->lwp_ru.msgsnd; 207 r.ru_msgrcv = lwp->lwp_ru.msgrcv; 208 r.ru_nsignals = lwp->lwp_ru.nsignals; 209 r.ru_nvcsw = lwp->lwp_ru.nvcsw; 210 r.ru_nivcsw = lwp->lwp_ru.nivcsw; 211 212 hrt2tv(unsecs, &r.ru_utime); 213 hrt2tv(snsecs, &r.ru_stime); 214 #ifdef _SYSCALL32_IMPL 215 if (get_udatamodel() == DATAMODEL_ILP32) { 216 struct rusage32 r32; 217 218 bzero(&r32, sizeof (struct rusage32)); 219 220 r32.ru_utime.tv_sec = r.ru_utime.tv_sec; 221 r32.ru_utime.tv_usec = r.ru_utime.tv_usec; 222 r32.ru_stime.tv_sec = r.ru_stime.tv_sec; 223 r32.ru_stime.tv_usec = r.ru_stime.tv_usec; 224 225 r32.ru_majflt = (int32_t)r.ru_majflt; 226 r32.ru_minflt = (int32_t)r.ru_minflt; 227 r32.ru_nswap = (int32_t)r.ru_nswap; 228 r32.ru_inblock = (int32_t)r.ru_inblock; 229 r32.ru_oublock = (int32_t)r.ru_oublock; 230 r32.ru_msgsnd = (int32_t)r.ru_msgsnd; 231 r32.ru_msgrcv = (int32_t)r.ru_msgrcv; 232 r32.ru_nsignals = (int32_t)r.ru_nsignals; 233 r32.ru_nvcsw = (int32_t)r.ru_nvcsw; 234 r32.ru_nivcsw = (int32_t)r.ru_nivcsw; 235 if (copyout(&r32, user_rusage, sizeof (r32)) != 0) 236 return (set_errno(EFAULT)); 237 } else 238 #endif /* _SYSCALL32_IMPL */ 239 240 if (copyout(&r, user_rusage, sizeof (r)) != 0) 241 return (set_errno(EFAULT)); 242 243 return (0); 244 } 245 246 int 247 rusagesys(int code, void *arg1, void *arg2, void *arg3, void *arg4) 248 { 249 switch (code) { 250 251 case _RUSAGESYS_GETRUSAGE: 252 return (getrusage(arg1)); 253 case _RUSAGESYS_GETRUSAGE_CHLD: 254 return (getrusage_chld(arg1)); 255 case _RUSAGESYS_GETRUSAGE_LWP: 256 return (getrusage_lwp(arg1)); 257 case _RUSAGESYS_GETVMUSAGE: 258 return (vm_getusage((uint_t)(uintptr_t)arg1, (time_t)arg2, 259 (vmusage_t *)arg3, (size_t *)arg4, 0)); 260 default: 261 return (set_errno(EINVAL)); 262 } 263 } 264