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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Implement fast getrusage call
30 #include <sys/types.h>
31 #include <sys/systm.h>
33 #include <sys/errno.h>
34 #include <sys/resource.h>
35 #include <sys/vm_usage.h>
38 getrusage(void *user_rusage
)
41 kthread_t
*t
= curthread
;
42 proc_t
*p
= ttoproc(t
);
43 hrtime_t snsecs
, unsecs
;
46 bzero(&r
, sizeof (struct rusage
));
48 mutex_enter(&p
->p_lock
);
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
;
63 unsecs
= mstate_aggr_state(p
, LMS_USER
);
64 snsecs
= mstate_aggr_state(p
, LMS_SYSTEM
);
67 if (t
->t_proc_flag
& TP_LWPEXIT
)
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
;
83 } while ((t
= t
->t_forw
) != curthread
);
85 mutex_exit(&p
->p_lock
);
87 hrt2tv(unsecs
, &r
.ru_utime
);
88 hrt2tv(snsecs
, &r
.ru_stime
);
90 #ifdef _SYSCALL32_IMPL
91 if (get_udatamodel() == DATAMODEL_ILP32
) {
94 bzero(&r32
, sizeof (struct rusage32
));
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
;
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
));
114 #endif /* _SYSCALL32_IMPL */
116 if (copyout(&r
, user_rusage
, sizeof (r
)) != 0)
117 return (set_errno(EFAULT
));
123 getrusage_chld(void *user_rusage
)
126 kthread_t
*t
= curthread
;
127 proc_t
*p
= ttoproc(t
);
128 hrtime_t snsecs
, unsecs
;
130 bzero(&r
, sizeof (struct rusage
));
132 mutex_enter(&p
->p_lock
);
134 unsecs
= p
->p_cacct
[LMS_USER
];
135 snsecs
= p
->p_cacct
[LMS_SYSTEM
] + p
->p_cacct
[LMS_TRAP
];
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
;
148 mutex_exit(&p
->p_lock
);
150 hrt2tv(unsecs
, &r
.ru_utime
);
151 hrt2tv(snsecs
, &r
.ru_stime
);
152 #ifdef _SYSCALL32_IMPL
153 if (get_udatamodel() == DATAMODEL_ILP32
) {
156 bzero(&r32
, sizeof (struct rusage32
));
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
;
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
));
176 #endif /* _SYSCALL32_IMPL */
178 if (copyout(&r
, user_rusage
, sizeof (r
)) != 0)
179 return (set_errno(EFAULT
));
185 getrusage_lwp(void *user_rusage
)
188 kthread_t
*t
= curthread
;
190 hrtime_t snsecs
, unsecs
;
193 bzero(&r
, sizeof (struct rusage
));
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
;
212 hrt2tv(unsecs
, &r
.ru_utime
);
213 hrt2tv(snsecs
, &r
.ru_stime
);
214 #ifdef _SYSCALL32_IMPL
215 if (get_udatamodel() == DATAMODEL_ILP32
) {
218 bzero(&r32
, sizeof (struct rusage32
));
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
;
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
));
238 #endif /* _SYSCALL32_IMPL */
240 if (copyout(&r
, user_rusage
, sizeof (r
)) != 0)
241 return (set_errno(EFAULT
));
247 rusagesys(int code
, void *arg1
, void *arg2
, void *arg3
, void *arg4
)
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));
261 return (set_errno(EINVAL
));