[Bug 192842] [patch][linux] linux_ppoll syscall required by linux apps that use pulseaudio (on linux_base-f20)
bugzilla-noreply at freebsd.org
bugzilla-noreply at freebsd.org
Sun Oct 12 13:47:56 UTC 2014
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=192842
Mateusz Guzik <mjg at FreeBSD.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |mjg at FreeBSD.org
--- Comment #6 from Mateusz Guzik <mjg at FreeBSD.org> ---
+linux_ppoll(struct thread *td, struct linux_ppoll_args *pargs)
+{
+ struct l_timespec lts;
+ struct timeval tv, *tvp, tv0, tv1;
+ struct poll_args pa;
+ sigset_t usigmask, *usigmaskp;
+ l_sigset_t lsigmask;
+ int error, retval, mss, msns;
error and retval?
+
+ /* Get the time */
+ if (pargs->timeout_ts != NULL)
+ {
style
+ error = copyin(pargs->timeout_ts, <s, sizeof(lts));
+ if (error != 0)
+ return (error);
+
+ TIMESPEC_TO_TIMEVAL(&tv, <s);
+ if (itimerfix(&tv))
+ return (EINVAL);
+
+ /* Mark the time before the call */
+ microtime(&tv0);
+ tvp = &tv;
+ } else
+ tvp = NULL;
+
+ /* Get the sigmask */
+ if (pargs->sigmask != NULL) {
+ error = copyin(pargs->sigmask, &lsigmask, sizeof(lsigmask));
+ if (error)
+ return (error);
+ linux_to_bsd_sigset(&lsigmask, &usigmask);
+ usigmaskp = &usigmask;
+ } else
+ usigmaskp = NULL;
+
+ /* Set the sigmask */
+ error = kern_sigprocmask (td, SIG_SETMASK, usigmaskp, &td->td_oldsigmask,
0);
+ if (error)
+ return (error);
+
+ pa.fds = pargs->fds;
+ pa.nfds = pargs->nfds;
+
+ /* Linux's ppoll allows NULL timeout which is translated to FreeBSD's
INFTIM (-1) */
+ if (tvp==NULL)
+ pa.timeout = INFTIM;
+ else
+ {
style
+ mss = tvp->tv_sec * 1000;
+ msns = tvp->tv_usec / 1000;
+
+ /*
+ * Handling the multiplication and addition overflow.
+ * If it happens, assing pa.timeout the INT_MAX value
+ */
+ if (mss/1000 == tvp->tv_sec) {
+ pa.timeout = mss + msns;
+ if ( pa.timeout < 0)
+ pa.timeout = INT_MAX;
+ } else
+ pa.timeout = INT_MAX;
+ }
+
+ /*
+ * Ensure that the td_oldsigmask is restored by ast()
+ * when returns to user mode and that the TDP_OLDMASK
+ * is cleared
+ */
+ td->td_pflags |= TDP_OLDMASK;
+ thread_lock(td);
+ td->td_flags |= TDF_ASTPENDING;
+ thread_unlock(td);
Why was not this done immediately after kern_sigprocmask?
Also, this would benefit from kern_ppoll helper.
Given that pselect has similar code, maybe an additional helper should be
introduced.
+
+ /* call sys_poll */
+ retval = sys_poll(td, &pa);
+
+ if (retval == 0 && pargs->timeout_ts) {
+ if (td->td_retval[0]) {
+ /*
+ * Compute how much time was left of the timeout,
+ * by subtracting the current time and the time
+ * before we started the call, and subtracting
+ * that result from the user-supplied value.
+ */
+ microtime(&tv1);
+ timevalsub(&tv1, &tv0);
+ timevalsub(&tv, &tv1);
+ if (tv.tv_sec < 0)
+ timevalclear(&tv);
+ } else
+ timevalclear(&tv);
+
+ TIMEVAL_TO_TIMESPEC(&tv, <s);
+
+ error = copyout(<s, pargs->timeout_ts, sizeof(lts));
+ if (error)
+ return (error);
+ }
+ return retval;
+}
+
+int
--
You are receiving this mail because:
You are the assignee for the bug.
More information about the freebsd-emulation
mailing list