kernel/wait_for_objects: Use BStackOrHeapArray for userland data.
Especially in select(), this cuts overhead significantly, as we now only invoke malloc() once, and for small select()s we never have to.
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
#include <Select.h>
|
#include <Select.h>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
#include <StackOrHeapArray.h>
|
||||||
|
|
||||||
#include <fs/fd.h>
|
#include <fs/fd.h>
|
||||||
#include <port.h>
|
#include <port.h>
|
||||||
@@ -945,9 +946,7 @@ ssize_t
|
|||||||
_user_select(int numFDs, fd_set *userReadSet, fd_set *userWriteSet,
|
_user_select(int numFDs, fd_set *userReadSet, fd_set *userWriteSet,
|
||||||
fd_set *userErrorSet, bigtime_t timeout, const sigset_t *userSigMask)
|
fd_set *userErrorSet, bigtime_t timeout, const sigset_t *userSigMask)
|
||||||
{
|
{
|
||||||
fd_set *readSet = NULL, *writeSet = NULL, *errorSet = NULL;
|
|
||||||
uint32 bytes = _howmany(numFDs, NFDBITS) * sizeof(fd_mask);
|
uint32 bytes = _howmany(numFDs, NFDBITS) * sizeof(fd_mask);
|
||||||
sigset_t sigMask;
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (timeout >= 0) {
|
if (timeout >= 0) {
|
||||||
@@ -968,45 +967,43 @@ _user_select(int numFDs, fd_set *userReadSet, fd_set *userWriteSet,
|
|||||||
|
|
||||||
// copy parameters
|
// copy parameters
|
||||||
|
|
||||||
if (userReadSet != NULL) {
|
BStackOrHeapArray<char, 128> sets(bytes * (
|
||||||
readSet = (fd_set *)malloc(bytes);
|
((userReadSet != NULL) ? 1 : 0) +
|
||||||
if (readSet == NULL)
|
((userWriteSet != NULL) ? 1 : 0) +
|
||||||
return B_NO_MEMORY;
|
((userErrorSet != NULL) ? 1 : 0)));
|
||||||
|
if (!sets.IsValid())
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
if (user_memcpy(readSet, userReadSet, bytes) < B_OK) {
|
char *nextSet = &sets[0];
|
||||||
result = B_BAD_ADDRESS;
|
fd_set *readSet = NULL, *writeSet = NULL, *errorSet = NULL;
|
||||||
goto err;
|
|
||||||
}
|
if (userReadSet != NULL) {
|
||||||
|
readSet = (fd_set *)nextSet;
|
||||||
|
nextSet += bytes;
|
||||||
|
|
||||||
|
if (user_memcpy(readSet, userReadSet, bytes) != B_OK)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userWriteSet != NULL) {
|
if (userWriteSet != NULL) {
|
||||||
writeSet = (fd_set *)malloc(bytes);
|
writeSet = (fd_set *)nextSet;
|
||||||
if (writeSet == NULL) {
|
nextSet += bytes;
|
||||||
result = B_NO_MEMORY;
|
|
||||||
goto err;
|
if (user_memcpy(writeSet, userWriteSet, bytes) != B_OK)
|
||||||
}
|
return B_BAD_ADDRESS;
|
||||||
if (user_memcpy(writeSet, userWriteSet, bytes) < B_OK) {
|
|
||||||
result = B_BAD_ADDRESS;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userErrorSet != NULL) {
|
if (userErrorSet != NULL) {
|
||||||
errorSet = (fd_set *)malloc(bytes);
|
errorSet = (fd_set *)nextSet;
|
||||||
if (errorSet == NULL) {
|
|
||||||
result = B_NO_MEMORY;
|
if (user_memcpy(errorSet, userErrorSet, bytes) != B_OK)
|
||||||
goto err;
|
return B_BAD_ADDRESS;
|
||||||
}
|
|
||||||
if (user_memcpy(errorSet, userErrorSet, bytes) < B_OK) {
|
|
||||||
result = B_BAD_ADDRESS;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigset_t sigMask;
|
||||||
if (userSigMask != NULL
|
if (userSigMask != NULL
|
||||||
&& user_memcpy(&sigMask, userSigMask, sizeof(sigMask)) < B_OK) {
|
&& user_memcpy(&sigMask, userSigMask, sizeof(sigMask)) != B_OK) {
|
||||||
result = B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = common_select(numFDs, readSet, writeSet, errorSet, timeout,
|
result = common_select(numFDs, readSet, writeSet, errorSet, timeout,
|
||||||
@@ -1024,11 +1021,6 @@ _user_select(int numFDs, fd_set *userReadSet, fd_set *userWriteSet,
|
|||||||
result = B_BAD_ADDRESS;
|
result = B_BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
|
||||||
free(readSet);
|
|
||||||
free(writeSet);
|
|
||||||
free(errorSet);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1037,11 +1029,6 @@ ssize_t
|
|||||||
_user_poll(struct pollfd *userfds, int numFDs, bigtime_t timeout,
|
_user_poll(struct pollfd *userfds, int numFDs, bigtime_t timeout,
|
||||||
const sigset_t *userSigMask)
|
const sigset_t *userSigMask)
|
||||||
{
|
{
|
||||||
struct pollfd *fds = NULL;
|
|
||||||
size_t bytes = 0;
|
|
||||||
sigset_t sigMask;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (timeout >= 0) {
|
if (timeout >= 0) {
|
||||||
timeout += system_time();
|
timeout += system_time();
|
||||||
// deal with overflow
|
// deal with overflow
|
||||||
@@ -1049,35 +1036,30 @@ _user_poll(struct pollfd *userfds, int numFDs, bigtime_t timeout,
|
|||||||
timeout = B_INFINITE_TIMEOUT;
|
timeout = B_INFINITE_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numFDs < 0)
|
if (numFDs < 0 || !check_max_fds(numFDs))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
BStackOrHeapArray<struct pollfd, 16> fds(numFDs);
|
||||||
|
if (!fds.IsValid())
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
size_t bytes = 0;
|
||||||
if (numFDs != 0) {
|
if (numFDs != 0) {
|
||||||
|
|
||||||
if (!check_max_fds(numFDs))
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
if (userfds == NULL || !IS_USER_ADDRESS(userfds))
|
if (userfds == NULL || !IS_USER_ADDRESS(userfds))
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
fds = (struct pollfd *)malloc(bytes = numFDs * sizeof(struct pollfd));
|
if (user_memcpy(fds, userfds, bytes) < B_OK)
|
||||||
if (fds == NULL)
|
return B_BAD_ADDRESS;
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
if (user_memcpy(fds, userfds, bytes) < B_OK) {
|
|
||||||
result = B_BAD_ADDRESS;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigset_t sigMask;
|
||||||
if (userSigMask != NULL
|
if (userSigMask != NULL
|
||||||
&& (!IS_USER_ADDRESS(userSigMask)
|
&& (!IS_USER_ADDRESS(userSigMask)
|
||||||
|| user_memcpy(&sigMask, userSigMask, sizeof(sigMask)) < B_OK)) {
|
|| user_memcpy(&sigMask, userSigMask, sizeof(sigMask)) < B_OK)) {
|
||||||
result = B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = common_poll(fds, numFDs, timeout,
|
status_t result = common_poll(fds, numFDs, timeout,
|
||||||
userSigMask != NULL ? &sigMask : NULL, false);
|
userSigMask != NULL ? &sigMask : NULL, false);
|
||||||
|
|
||||||
// copy back results
|
// copy back results
|
||||||
@@ -1085,8 +1067,6 @@ _user_poll(struct pollfd *userfds, int numFDs, bigtime_t timeout,
|
|||||||
if (result >= 0)
|
if (result >= 0)
|
||||||
result = B_BAD_ADDRESS;
|
result = B_BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
err:
|
|
||||||
free(fds);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1114,27 +1094,21 @@ _user_wait_for_objects(object_wait_info* userInfos, int numInfos, uint32 flags,
|
|||||||
if (userInfos == NULL || !IS_USER_ADDRESS(userInfos))
|
if (userInfos == NULL || !IS_USER_ADDRESS(userInfos))
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
int bytes = sizeof(object_wait_info) * numInfos;
|
BStackOrHeapArray<object_wait_info, 16> infos(numInfos);
|
||||||
object_wait_info* infos = (object_wait_info*)malloc(bytes);
|
if (!infos.IsValid())
|
||||||
if (infos == NULL)
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
const int bytes = sizeof(object_wait_info) * numInfos;
|
||||||
|
|
||||||
// copy parameters to kernel space, call the function, and copy the results
|
if (user_memcpy(infos, userInfos, bytes) != B_OK)
|
||||||
// back
|
return B_BAD_ADDRESS;
|
||||||
ssize_t result;
|
|
||||||
if (user_memcpy(infos, userInfos, bytes) == B_OK) {
|
|
||||||
result = common_wait_for_objects(infos, numInfos, flags, timeout,
|
|
||||||
false);
|
|
||||||
|
|
||||||
if (result >= 0 && user_memcpy(userInfos, infos, bytes) != B_OK) {
|
ssize_t result = common_wait_for_objects(infos, numInfos, flags, timeout, false);
|
||||||
result = B_BAD_ADDRESS;
|
|
||||||
} else
|
if (result >= 0 && user_memcpy(userInfos, infos, bytes) != B_OK) {
|
||||||
syscall_restart_handle_timeout_post(result, timeout);
|
|
||||||
} else
|
|
||||||
result = B_BAD_ADDRESS;
|
result = B_BAD_ADDRESS;
|
||||||
|
} else {
|
||||||
free(infos);
|
syscall_restart_handle_timeout_post(result, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user