Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/sys_generic.c
Show First 20 Lines • Show All 1,408 Lines • ▼ Show 20 Lines | if (uap->timeout != INFTIM) { | ||||
if (uap->timeout < 0) | if (uap->timeout < 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
ts.tv_sec = uap->timeout / 1000; | ts.tv_sec = uap->timeout / 1000; | ||||
ts.tv_nsec = (uap->timeout % 1000) * 1000000; | ts.tv_nsec = (uap->timeout % 1000) * 1000000; | ||||
tsp = &ts; | tsp = &ts; | ||||
} else | } else | ||||
tsp = NULL; | tsp = NULL; | ||||
return (kern_poll(td, uap->fds, uap->nfds, tsp, NULL)); | return (kern_poll_ufds(td, uap->fds, uap->nfds, tsp, NULL)); | ||||
} | } | ||||
int | int | ||||
kern_poll(struct thread *td, struct pollfd *ufds, u_int nfds, | kern_poll_kfds(struct thread *td, struct pollfd *kfds, u_int nfds, | ||||
struct timespec *tsp, sigset_t *uset) | struct timespec *tsp, sigset_t *uset) | ||||
kib: I do not see much sense in the second sentence. | |||||
{ | { | ||||
struct pollfd *kfds; | |||||
struct pollfd stackfds[32]; | |||||
sbintime_t sbt, precision, tmp; | sbintime_t sbt, precision, tmp; | ||||
time_t over; | time_t over; | ||||
struct timespec ts; | struct timespec ts; | ||||
int error; | int error; | ||||
precision = 0; | precision = 0; | ||||
if (tsp != NULL) { | if (tsp != NULL) { | ||||
if (tsp->tv_sec < 0) | if (tsp->tv_sec < 0) | ||||
Show All 14 Lines | else { | ||||
precision >>= tc_precexp; | precision >>= tc_precexp; | ||||
if (TIMESEL(&sbt, tmp)) | if (TIMESEL(&sbt, tmp)) | ||||
sbt += tc_tick_sbt; | sbt += tc_tick_sbt; | ||||
sbt += tmp; | sbt += tmp; | ||||
} | } | ||||
} else | } else | ||||
sbt = -1; | sbt = -1; | ||||
/* | |||||
* This is kinda bogus. We have fd limits, but that is not | |||||
* really related to the size of the pollfd array. Make sure | |||||
* we let the process use at least FD_SETSIZE entries and at | |||||
* least enough for the system-wide limits. We want to be reasonably | |||||
* safe, but not overly restrictive. | |||||
*/ | |||||
if (nfds > maxfilesperproc && nfds > FD_SETSIZE) | |||||
return (EINVAL); | |||||
if (nfds > nitems(stackfds)) | |||||
kfds = mallocarray(nfds, sizeof(*kfds), M_TEMP, M_WAITOK); | |||||
else | |||||
kfds = stackfds; | |||||
error = copyin(ufds, kfds, nfds * sizeof(*kfds)); | |||||
if (error) | |||||
goto done; | |||||
if (uset != NULL) { | if (uset != NULL) { | ||||
error = kern_sigprocmask(td, SIG_SETMASK, uset, | error = kern_sigprocmask(td, SIG_SETMASK, uset, | ||||
&td->td_oldsigmask, 0); | &td->td_oldsigmask, 0); | ||||
if (error) | if (error) | ||||
goto done; | return (error); | ||||
td->td_pflags |= TDP_OLDMASK; | td->td_pflags |= TDP_OLDMASK; | ||||
/* | /* | ||||
* Make sure that ast() is called on return to | * Make sure that ast() is called on return to | ||||
* usermode and TDP_OLDMASK is cleared, restoring old | * usermode and TDP_OLDMASK is cleared, restoring old | ||||
* sigmask. | * sigmask. | ||||
*/ | */ | ||||
thread_lock(td); | thread_lock(td); | ||||
td->td_flags |= TDF_ASTPENDING; | td->td_flags |= TDF_ASTPENDING; | ||||
Show All 10 Lines | for (;;) { | ||||
if (error) | if (error) | ||||
break; | break; | ||||
error = pollrescan(td); | error = pollrescan(td); | ||||
if (error || td->td_retval[0] != 0) | if (error || td->td_retval[0] != 0) | ||||
break; | break; | ||||
} | } | ||||
seltdclear(td); | seltdclear(td); | ||||
done: | |||||
/* poll is not restarted after signals... */ | /* poll is not restarted after signals... */ | ||||
if (error == ERESTART) | if (error == ERESTART) | ||||
error = EINTR; | error = EINTR; | ||||
if (error == EWOULDBLOCK) | if (error == EWOULDBLOCK) | ||||
error = 0; | error = 0; | ||||
if (error == 0) { | |||||
error = pollout(td, kfds, ufds, nfds); | |||||
if (error) | |||||
goto out; | |||||
} | |||||
out: | |||||
if (nfds > nitems(stackfds)) | |||||
free(kfds, M_TEMP); | |||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
sys_ppoll(struct thread *td, struct ppoll_args *uap) | sys_ppoll(struct thread *td, struct ppoll_args *uap) | ||||
{ | { | ||||
struct timespec ts, *tsp; | struct timespec ts, *tsp; | ||||
sigset_t set, *ssp; | sigset_t set, *ssp; | ||||
Show All 9 Lines | sys_ppoll(struct thread *td, struct ppoll_args *uap) | ||||
if (uap->set != NULL) { | if (uap->set != NULL) { | ||||
error = copyin(uap->set, &set, sizeof(set)); | error = copyin(uap->set, &set, sizeof(set)); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
ssp = &set; | ssp = &set; | ||||
} else | } else | ||||
ssp = NULL; | ssp = NULL; | ||||
/* | /* | ||||
* fds is still a pointer to user space. kern_poll() will | * fds is still a pointer to user space. kern_poll_ufds() will | ||||
* take care of copyin that array to the kernel space. | * take care of copyin that array to the kernel space. | ||||
*/ | */ | ||||
return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp)); | return (kern_poll_ufds(td, uap->fds, uap->nfds, tsp, ssp)); | ||||
} | |||||
int | |||||
kern_poll_ufds(struct thread *td, struct pollfd *ufds, u_int nfds, | |||||
struct timespec *tsp, sigset_t *set) | |||||
{ | |||||
struct pollfd *kfds; | |||||
struct pollfd stackfds[32]; | |||||
int error; | |||||
error = kern_poll_maxfds(nfds); | |||||
kibUnsubmitted Done Inline ActionsI would make kern_poll_maxfds() returning bool, and then just write if (!kern_poll_maxfds(nfds)) return (EINVAL); kib: I would make kern_poll_maxfds() returning bool, and then just write
```
if (! | |||||
if (error != 0) | |||||
return (error); | |||||
if (nfds > nitems(stackfds)) | |||||
kfds = mallocarray(nfds, sizeof(*kfds), M_TEMP, M_WAITOK); | |||||
else | |||||
kfds = stackfds; | |||||
error = copyin(ufds, kfds, nfds * sizeof(*kfds)); | |||||
if (error != 0) | |||||
goto out; | |||||
error = kern_poll_kfds(td, kfds, nfds, tsp, set); | |||||
if (error == 0) | |||||
error = pollout(td, kfds, ufds, nfds); | |||||
out: | |||||
if (nfds > nitems(stackfds)) | |||||
free(kfds, M_TEMP); | |||||
return (error); | |||||
} | |||||
int | |||||
kern_poll_maxfds(u_int nfds) | |||||
{ | |||||
/* | |||||
* This is kinda bogus. We have fd limits, but that is not | |||||
* really related to the size of the pollfd array. Make sure | |||||
* we let the process use at least FD_SETSIZE entries and at | |||||
* least enough for the system-wide limits. We want to be reasonably | |||||
* safe, but not overly restrictive. | |||||
*/ | |||||
if (nfds > maxfilesperproc && nfds > FD_SETSIZE) | |||||
return (EINVAL); | |||||
else | |||||
return (0); | |||||
} | } | ||||
static int | static int | ||||
pollrescan(struct thread *td) | pollrescan(struct thread *td) | ||||
{ | { | ||||
struct seltd *stp; | struct seltd *stp; | ||||
struct selfd *sfp; | struct selfd *sfp; | ||||
struct selfd *sfn; | struct selfd *sfn; | ||||
▲ Show 20 Lines • Show All 439 Lines • Show Last 20 Lines |
I do not see much sense in the second sentence.