diff --git a/headers/private/kernel/team.h b/headers/private/kernel/team.h
index 2fb555e..e376409 100644
a
|
b
|
thread_id _user_load_image(const char* const* flatArgs, size_t flatArgsSize,
|
69 | 69 | status_t _user_wait_for_team(team_id id, status_t *_returnCode); |
70 | 70 | void _user_exit_team(status_t returnValue); |
71 | 71 | status_t _user_kill_team(thread_id thread); |
72 | | pid_t _user_wait_for_child(thread_id child, uint32 flags, siginfo_t* info); |
| 72 | pid_t _user_wait_for_child(thread_id child, uint32 flags, siginfo_t* info, |
| 73 | team_usage_info* usageInfo); |
73 | 74 | status_t _user_exec(const char *path, const char* const* flatArgs, |
74 | 75 | size_t flatArgsSize, int32 argCount, int32 envCount, mode_t umask); |
75 | 76 | thread_id _user_fork(void); |
diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h
index e90e258..720a221 100644
a
|
b
|
struct job_control_entry : DoublyLinkedListLinkImpl<job_control_entry> {
|
116 | 116 | status_t status; |
117 | 117 | uint16 reason; // reason for the team's demise, one of the |
118 | 118 | // CLD_* values defined in <signal.h> |
| 119 | bigtime_t user_time; |
| 120 | bigtime_t kernel_time; |
119 | 121 | |
120 | 122 | job_control_entry(); |
121 | 123 | ~job_control_entry(); |
diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h
index 35fe2a1..9d5e8f2 100644
a
|
b
|
extern status_t _kern_kill_team(team_id team);
|
141 | 141 | extern team_id _kern_get_current_team(); |
142 | 142 | extern status_t _kern_wait_for_team(team_id team, status_t *_returnCode); |
143 | 143 | extern pid_t _kern_wait_for_child(thread_id child, uint32 flags, |
144 | | siginfo_t* info); |
| 144 | siginfo_t* info, team_usage_info* usageInfo); |
145 | 145 | extern status_t _kern_exec(const char *path, const char* const* flatArgs, |
146 | 146 | size_t flatArgsSize, int32 argCount, int32 envCount, |
147 | 147 | mode_t umask); |
diff --git a/src/libs/bsd/wait.c b/src/libs/bsd/wait.c
index 368d8dd..57fc328 100644
a
|
b
|
|
12 | 12 | #include <sys/wait.h> |
13 | 13 | |
14 | 14 | |
| 15 | extern pid_t _waitpid(pid_t pid, int* _status, int options, |
| 16 | team_usage_info *usage_info); |
| 17 | |
| 18 | |
15 | 19 | pid_t |
16 | 20 | wait3(int *status, int options, struct rusage *rusage) |
17 | 21 | { |
… |
… |
wait3(int *status, int options, struct rusage *rusage)
|
22 | 26 | pid_t |
23 | 27 | wait4(pid_t pid, int *status, int options, struct rusage *rusage) |
24 | 28 | { |
25 | | pid_t waitPid = waitpid(pid, status, options); |
26 | | if (waitPid != -1) { |
27 | | team_usage_info info; |
28 | | |
29 | | // Obtain info for the process that changed state. |
30 | | if (get_team_usage_info(waitPid, RUSAGE_SELF, &info) != B_OK) |
31 | | return -1; |
32 | | |
| 29 | team_usage_info info; |
| 30 | pid_t waitPid = _waitpid(pid, status, options, |
| 31 | rusage != NULL ? &info : NULL); |
| 32 | if (waitPid != -1 && rusage != NULL) { |
33 | 33 | rusage->ru_utime.tv_sec = info.user_time / 1000000; |
34 | 34 | rusage->ru_utime.tv_usec = info.user_time % 1000000; |
35 | 35 | |
diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp
index 1b364fe..5a78c08 100644
a
|
b
|
job_control_entry::InitDeadState()
|
2369 | 2369 | reason = team->exit.reason; |
2370 | 2370 | signal = team->exit.signal; |
2371 | 2371 | signaling_user = team->exit.signaling_user; |
| 2372 | user_time = team->dead_threads_user_time |
| 2373 | + team->dead_children.user_time; |
| 2374 | kernel_time = team->dead_threads_kernel_time |
| 2375 | + team->dead_children.kernel_time; |
2372 | 2376 | |
2373 | 2377 | team = NULL; |
2374 | 2378 | } |
… |
… |
job_control_entry::operator=(const job_control_entry& other)
|
2387 | 2391 | group_id = other.group_id; |
2388 | 2392 | status = other.status; |
2389 | 2393 | reason = other.reason; |
| 2394 | user_time = other.user_time; |
| 2395 | kernel_time = other.kernel_time; |
2390 | 2396 | |
2391 | 2397 | return *this; |
2392 | 2398 | } |
… |
… |
job_control_entry::operator=(const job_control_entry& other)
|
2395 | 2401 | /*! This is the kernel backend for waitid(). |
2396 | 2402 | */ |
2397 | 2403 | static thread_id |
2398 | | wait_for_child(pid_t child, uint32 flags, siginfo_t& _info) |
| 2404 | wait_for_child(pid_t child, uint32 flags, siginfo_t& _info, |
| 2405 | team_usage_info& _usage_info) |
2399 | 2406 | { |
2400 | 2407 | Thread* thread = thread_get_current_thread(); |
2401 | 2408 | Team* team = thread->team; |
… |
… |
wait_for_child(pid_t child, uint32 flags, siginfo_t& _info)
|
2533 | 2540 | _info.si_code = foundEntry.reason; |
2534 | 2541 | _info.si_status = foundEntry.reason == CLD_EXITED |
2535 | 2542 | ? foundEntry.status : foundEntry.signal; |
| 2543 | _usage_info.user_time = foundEntry.user_time; |
| 2544 | _usage_info.kernel_time = foundEntry.kernel_time; |
2536 | 2545 | break; |
2537 | 2546 | case JOB_CONTROL_STATE_STOPPED: |
2538 | 2547 | _info.si_code = CLD_STOPPED; |
… |
… |
_user_fork(void)
|
3915 | 3924 | |
3916 | 3925 | |
3917 | 3926 | pid_t |
3918 | | _user_wait_for_child(thread_id child, uint32 flags, siginfo_t* userInfo) |
| 3927 | _user_wait_for_child(thread_id child, uint32 flags, siginfo_t* userInfo, |
| 3928 | team_usage_info* usageInfo) |
3919 | 3929 | { |
3920 | 3930 | if (userInfo != NULL && !IS_USER_ADDRESS(userInfo)) |
3921 | 3931 | return B_BAD_ADDRESS; |
| 3932 | if (usageInfo != NULL && !IS_USER_ADDRESS(usageInfo)) |
| 3933 | return B_BAD_ADDRESS; |
3922 | 3934 | |
3923 | 3935 | siginfo_t info; |
3924 | | pid_t foundChild = wait_for_child(child, flags, info); |
| 3936 | team_usage_info usage_info; |
| 3937 | pid_t foundChild = wait_for_child(child, flags, info, usage_info); |
3925 | 3938 | if (foundChild < 0) |
3926 | 3939 | return syscall_restart_handle_post(foundChild); |
3927 | 3940 | |
3928 | 3941 | // copy info back to userland |
3929 | 3942 | if (userInfo != NULL && user_memcpy(userInfo, &info, sizeof(info)) != B_OK) |
3930 | 3943 | return B_BAD_ADDRESS; |
| 3944 | // copy usage_info back to userland |
| 3945 | if (usageInfo != NULL && user_memcpy(usageInfo, &usage_info, |
| 3946 | sizeof(usage_info)) != B_OK) { |
| 3947 | return B_BAD_ADDRESS; |
| 3948 | } |
3931 | 3949 | |
3932 | 3950 | return foundChild; |
3933 | 3951 | } |
diff --git a/src/system/libroot/posix/sys/wait.cpp b/src/system/libroot/posix/sys/wait.cpp
index 1c785c9..d410a48 100644
a
|
b
|
wait(int* _status)
|
23 | 23 | return waitpid(-1, _status, 0); |
24 | 24 | } |
25 | 25 | |
26 | | |
27 | | pid_t |
28 | | waitpid(pid_t pid, int* _status, int options) |
| 26 | extern "C" pid_t |
| 27 | _waitpid(pid_t pid, int* _status, int options, team_usage_info *usage_info) |
29 | 28 | { |
30 | 29 | // wait |
31 | 30 | siginfo_t info; |
32 | | pid_t child = _kern_wait_for_child(pid, options, &info); |
| 31 | pid_t child = _kern_wait_for_child(pid, options, &info, usage_info); |
33 | 32 | |
34 | 33 | pthread_testcancel(); |
35 | 34 | |
… |
… |
waitpid(pid_t pid, int* _status, int options)
|
84 | 83 | } |
85 | 84 | |
86 | 85 | |
| 86 | pid_t |
| 87 | waitpid(pid_t pid, int* _status, int options) |
| 88 | { |
| 89 | return _waitpid(pid, _status, options, NULL); |
| 90 | } |
| 91 | |
| 92 | |
87 | 93 | int |
88 | 94 | waitid(idtype_t idType, id_t id, siginfo_t* info, int options) |
89 | 95 | { |
… |
… |
waitid(idtype_t idType, id_t id, siginfo_t* info, int options)
|
111 | 117 | RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); |
112 | 118 | } |
113 | 119 | |
114 | | pid_t child = _kern_wait_for_child(id, options, info); |
| 120 | pid_t child = _kern_wait_for_child(id, options, info, NULL); |
115 | 121 | if (child >= 0 || child == B_WOULD_BLOCK) |
116 | 122 | return 0; |
117 | 123 | |
diff --git a/src/tests/libs/bsd/wait4_test.cpp b/src/tests/libs/bsd/wait4_test.cpp
index e5d761d..46f2615 100644
a
|
b
|
|
5 | 5 | |
6 | 6 | |
7 | 7 | #include <errno.h> |
| 8 | #include <inttypes.h> |
8 | 9 | #include <stdio.h> |
9 | 10 | #include <string.h> |
10 | 11 | #include <sys/resource.h> |
… |
… |
main(int argc, char** argv)
|
55 | 56 | struct rusage usage; |
56 | 57 | pid_t pid; |
57 | 58 | do { |
| 59 | memset(&usage, 0, sizeof(usage)); |
58 | 60 | int childStatus = -1; |
59 | 61 | pid = wait4(-1, &childStatus, 0, &usage); |
60 | | printf("wait4() returned %ld (%s), child status %d\n", |
61 | | pid, strerror(errno), childStatus); |
| 62 | printf("wait4() returned %" PRId32 " (%s), child status %" PRId32 |
| 63 | ", kernel: %ld.%06" PRId32 " user: %ld.%06" PRId32 "\n", |
| 64 | pid, strerror(errno), childStatus, usage.ru_stime.tv_sec, |
| 65 | usage.ru_stime.tv_usec, usage.ru_utime.tv_sec, |
| 66 | usage.ru_utime.tv_usec); |
62 | 67 | } while (pid >= 0); |
63 | 68 | |
64 | 69 | return 0; |