+
+int
+proc_get_rusage(proc_t p, int flavor, user_addr_t buffer, __unused int is_zombie)
+{
+ struct rusage_info_v0 ri_v0;
+ struct rusage_info_v1 ri_v1;
+ struct rusage_info_v2 ri_v2;
+ struct rusage_info_v3 ri_v3;
+
+ rusage_info_current ri_current;
+
+ int error = 0;
+
+ switch (flavor) {
+ case RUSAGE_INFO_V0:
+ /*
+ * If task is still alive, collect info from the live task itself.
+ * Otherwise, look to the cached info in the zombie proc.
+ */
+ if (p->p_ru == NULL) {
+ gather_rusage_info(p, &ri_current, flavor);
+ ri_current.ri_proc_exit_abstime = 0;
+ rusage_info_conversion(&ri_v0, &ri_current, flavor);
+ } else {
+ rusage_info_conversion(&ri_v0, &p->p_ru->ri, flavor);
+ }
+ error = copyout(&ri_v0, buffer, sizeof (ri_v0));
+ break;
+
+ case RUSAGE_INFO_V1:
+ /*
+ * If task is still alive, collect info from the live task itself.
+ * Otherwise, look to the cached info in the zombie proc.
+ */
+ if (p->p_ru == NULL) {
+ gather_rusage_info(p, &ri_current, flavor);
+ ri_current.ri_proc_exit_abstime = 0;
+ rusage_info_conversion(&ri_v1, &ri_current, flavor);
+ } else {
+ rusage_info_conversion(&ri_v1, &p->p_ru->ri, flavor);
+ }
+ error = copyout(&ri_v1, buffer, sizeof (ri_v1));
+ break;
+
+ case RUSAGE_INFO_V2:
+ /*
+ * If task is still alive, collect info from the live task itself.
+ * Otherwise, look to the cached info in the zombie proc.
+ */
+ if (p->p_ru == NULL) {
+ gather_rusage_info(p, &ri_current, flavor);
+ ri_current.ri_proc_exit_abstime = 0;
+ rusage_info_conversion(&ri_v2, &ri_current, flavor);
+ } else {
+ rusage_info_conversion(&ri_v2, &p->p_ru->ri, flavor);
+ }
+ error = copyout(&ri_v2, buffer, sizeof (ri_v2));
+ break;
+
+ case RUSAGE_INFO_V3:
+ /*
+ * If task is still alive, collect info from the live task itself.
+ * Otherwise, look to the cached info in the zombie proc.
+ */
+ if (p->p_ru == NULL) {
+ gather_rusage_info(p, &ri_v3, flavor);
+ ri_v3.ri_proc_exit_abstime = 0;
+ } else {
+ ri_v3 = p->p_ru->ri;
+ }
+ error = copyout(&ri_v3, buffer, sizeof (ri_v3));
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);