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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Implement fast getrusage call 30 */ 31 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/time.h> 35 #include <sys/errno.h> 36 #include <sys/resource.h> 37 #include <sys/vm_usage.h> 38 39 static int 40 getrusage(void *user_rusage) 41 { 42 struct rusage r; 43 kthread_t *t = curthread; 44 proc_t *p = ttoproc(t); 45 hrtime_t snsecs, unsecs; 46 klwp_t *lwp; 47 48 bzero(&r, sizeof (struct rusage)); 49 50 mutex_enter(&p->p_lock); 51 52 if (p->p_defunct > 0) { 53 r.ru_majflt = p->p_ru.majflt; 54 r.ru_minflt = p->p_ru.minflt; 55 r.ru_nswap = p->p_ru.nswap; 56 r.ru_inblock = p->p_ru.inblock; 57 r.ru_oublock = p->p_ru.oublock; 58 r.ru_msgsnd = p->p_ru.msgsnd; 59 r.ru_msgrcv = p->p_ru.msgrcv; 60 r.ru_nsignals = p->p_ru.nsignals; 61 r.ru_nvcsw = p->p_ru.nvcsw; 62 r.ru_nivcsw = p->p_ru.nivcsw; 63 } 64 65 unsecs = mstate_aggr_state(p, LMS_USER); 66 snsecs = mstate_aggr_state(p, LMS_SYSTEM); 67 68 do { 69 if (t->t_proc_flag & TP_LWPEXIT) 70 continue; 71 72 lwp = ttolwp(t); 73 74 r.ru_majflt += lwp->lwp_ru.majflt; 75 r.ru_minflt += lwp->lwp_ru.minflt; 76 r.ru_nswap += lwp->lwp_ru.nswap; 77 r.ru_inblock += lwp->lwp_ru.inblock; 78 r.ru_oublock += lwp->lwp_ru.oublock; 79 r.ru_msgsnd += lwp->lwp_ru.msgsnd; 80 r.ru_msgrcv += lwp->lwp_ru.msgrcv; 81 r.ru_nsignals += lwp->lwp_ru.nsignals; 82 r.ru_nvcsw += lwp->lwp_ru.nvcsw; 83 r.ru_nivcsw += lwp->lwp_ru.nivcsw; 84 85 } while ((t = t->t_forw) != curthread); 86 87 mutex_exit(&p->p_lock); 88 89 hrt2tv(unsecs, &r.ru_utime); 90 hrt2tv(snsecs, &r.ru_stime); 91 92 #ifdef _SYSCALL32_IMPL 93 if (get_udatamodel() == DATAMODEL_ILP32) { 94 struct rusage32 r32; 95 96 bzero(&r32, sizeof (struct rusage32)); 97 98 r32.ru_utime.tv_sec = r.ru_utime.tv_sec; 99 r32.ru_utime.tv_usec = r.ru_utime.tv_usec; 100 r32.ru_stime.tv_sec = r.ru_stime.tv_sec; 101 r32.ru_stime.tv_usec = r.ru_stime.tv_usec; 102 103 r32.ru_majflt = (int32_t)r.ru_majflt; 104 r32.ru_minflt = (int32_t)r.ru_minflt; 105 r32.ru_nswap = (int32_t)r.ru_nswap; 106 r32.ru_inblock = (int32_t)r.ru_inblock; 107 r32.ru_oublock = (int32_t)r.ru_oublock; 108 r32.ru_msgsnd = (int32_t)r.ru_msgsnd; 109 r32.ru_msgrcv = (int32_t)r.ru_msgrcv; 110 r32.ru_nsignals = (int32_t)r.ru_nsignals; 111 r32.ru_nvcsw = (int32_t)r.ru_nvcsw; 112 r32.ru_nivcsw = (int32_t)r.ru_nivcsw; 113 if (copyout(&r32, user_rusage, sizeof (r32)) != 0) 114 return (set_errno(EFAULT)); 115 } else 116 #endif /* _SYSCALL32_IMPL */ 117 118 if (copyout(&r, user_rusage, sizeof (r)) != 0) 119 return (set_errno(EFAULT)); 120 121 return (0); 122 } 123 124 static int 125 getrusage_chld(void *user_rusage) 126 { 127 struct rusage r; 128 kthread_t *t = curthread; 129 proc_t *p = ttoproc(t); 130 hrtime_t snsecs, unsecs; 131 132 bzero(&r, sizeof (struct rusage)); 133 134 mutex_enter(&p->p_lock); 135 136 unsecs = p->p_cacct[LMS_USER]; 137 snsecs = p->p_cacct[LMS_SYSTEM] + p->p_cacct[LMS_TRAP]; 138 139 r.ru_majflt = p->p_cru.majflt; 140 r.ru_minflt = p->p_cru.minflt; 141 r.ru_nswap = p->p_cru.nswap; 142 r.ru_inblock = p->p_cru.inblock; 143 r.ru_oublock = p->p_cru.oublock; 144 r.ru_msgsnd = p->p_cru.msgsnd; 145 r.ru_msgrcv = p->p_cru.msgrcv; 146 r.ru_nsignals = p->p_cru.nsignals; 147 r.ru_nvcsw = p->p_cru.nvcsw; 148 r.ru_nivcsw = p->p_cru.nivcsw; 149 150 mutex_exit(&p->p_lock); 151 152 hrt2tv(unsecs, &r.ru_utime); 153 hrt2tv(snsecs, &r.ru_stime); 154 #ifdef _SYSCALL32_IMPL 155 if (get_udatamodel() == DATAMODEL_ILP32) { 156 struct rusage32 r32; 157 158 bzero(&r32, sizeof (struct rusage32)); 159 160 r32.ru_utime.tv_sec = r.ru_utime.tv_sec; 161 r32.ru_utime.tv_usec = r.ru_utime.tv_usec; 162 r32.ru_stime.tv_sec = r.ru_stime.tv_sec; 163 r32.ru_stime.tv_usec = r.ru_stime.tv_usec; 164 165 r32.ru_majflt = (int32_t)r.ru_majflt; 166 r32.ru_minflt = (int32_t)r.ru_minflt; 167 r32.ru_nswap = (int32_t)r.ru_nswap; 168 r32.ru_inblock = (int32_t)r.ru_inblock; 169 r32.ru_oublock = (int32_t)r.ru_oublock; 170 r32.ru_msgsnd = (int32_t)r.ru_msgsnd; 171 r32.ru_msgrcv = (int32_t)r.ru_msgrcv; 172 r32.ru_nsignals = (int32_t)r.ru_nsignals; 173 r32.ru_nvcsw = (int32_t)r.ru_nvcsw; 174 r32.ru_nivcsw = (int32_t)r.ru_nivcsw; 175 if (copyout(&r32, user_rusage, sizeof (r32)) != 0) 176 return (set_errno(EFAULT)); 177 } else 178 #endif /* _SYSCALL32_IMPL */ 179 180 if (copyout(&r, user_rusage, sizeof (r)) != 0) 181 return (set_errno(EFAULT)); 182 183 return (0); 184 } 185 186 static int 187 getrusage_lwp(void *user_rusage) 188 { 189 struct rusage r; 190 kthread_t *t = curthread; 191 klwp_t *lwp; 192 hrtime_t snsecs, unsecs; 193 struct mstate *ms; 194 195 bzero(&r, sizeof (struct rusage)); 196 197 lwp = ttolwp(t); 198 ms = &lwp->lwp_mstate; 199 unsecs = ms->ms_acct[LMS_USER]; 200 snsecs = ms->ms_acct[LMS_SYSTEM] + ms->ms_acct[LMS_TRAP]; 201 scalehrtime(&unsecs); 202 scalehrtime(&snsecs); 203 r.ru_majflt = lwp->lwp_ru.majflt; 204 r.ru_minflt = lwp->lwp_ru.minflt; 205 r.ru_nswap = lwp->lwp_ru.nswap; 206 r.ru_inblock = lwp->lwp_ru.inblock; 207 r.ru_oublock = lwp->lwp_ru.oublock; 208 r.ru_msgsnd = lwp->lwp_ru.msgsnd; 209 r.ru_msgrcv = lwp->lwp_ru.msgrcv; 210 r.ru_nsignals = lwp->lwp_ru.nsignals; 211 r.ru_nvcsw = lwp->lwp_ru.nvcsw; 212 r.ru_nivcsw = lwp->lwp_ru.nivcsw; 213 214 hrt2tv(unsecs, &r.ru_utime); 215 hrt2tv(snsecs, &r.ru_stime); 216 #ifdef _SYSCALL32_IMPL 217 if (get_udatamodel() == DATAMODEL_ILP32) { 218 struct rusage32 r32; 219 220 bzero(&r32, sizeof (struct rusage32)); 221 222 r32.ru_utime.tv_sec = r.ru_utime.tv_sec; 223 r32.ru_utime.tv_usec = r.ru_utime.tv_usec; 224 r32.ru_stime.tv_sec = r.ru_stime.tv_sec; 225 r32.ru_stime.tv_usec = r.ru_stime.tv_usec; 226 227 r32.ru_majflt = (int32_t)r.ru_majflt; 228 r32.ru_minflt = (int32_t)r.ru_minflt; 229 r32.ru_nswap = (int32_t)r.ru_nswap; 230 r32.ru_inblock = (int32_t)r.ru_inblock; 231 r32.ru_oublock = (int32_t)r.ru_oublock; 232 r32.ru_msgsnd = (int32_t)r.ru_msgsnd; 233 r32.ru_msgrcv = (int32_t)r.ru_msgrcv; 234 r32.ru_nsignals = (int32_t)r.ru_nsignals; 235 r32.ru_nvcsw = (int32_t)r.ru_nvcsw; 236 r32.ru_nivcsw = (int32_t)r.ru_nivcsw; 237 if (copyout(&r32, user_rusage, sizeof (r32)) != 0) 238 return (set_errno(EFAULT)); 239 } else 240 #endif /* _SYSCALL32_IMPL */ 241 242 if (copyout(&r, user_rusage, sizeof (r)) != 0) 243 return (set_errno(EFAULT)); 244 245 return (0); 246 } 247 248 int 249 rusagesys(int code, void *arg1, void *arg2, void *arg3, void *arg4) 250 { 251 switch (code) { 252 253 case _RUSAGESYS_GETRUSAGE: 254 return (getrusage(arg1)); 255 case _RUSAGESYS_GETRUSAGE_CHLD: 256 return (getrusage_chld(arg1)); 257 case _RUSAGESYS_GETRUSAGE_LWP: 258 return (getrusage_lwp(arg1)); 259 case _RUSAGESYS_GETVMUSAGE: 260 return (vm_getusage((uint_t)(uintptr_t)arg1, (time_t)arg2, 261 (vmusage_t *)arg3, (size_t *)arg4)); 262 default: 263 return (set_errno(EINVAL)); 264 } 265 } 266