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