Date: Tue, 05 Feb 2013 21:41:38 -0700 From: Ian Lepore <ian@FreeBSD.org> To: "freebsd-hackers@freebsd.org" <freebsd-hackers@FreeBSD.org> Subject: Request for review, time_pps_fetch() enhancement Message-ID: <1360125698.93359.566.camel@revolution.hippie.lan>
next in thread | raw e-mail | index | archive | help
--=-6J1XeQ0MmbsUd9NHPIee Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit I'd like feedback on the attached patch, which adds support to our time_pps_fetch() implementation for the blocking behaviors described in section 3.4.3 of RFC 2783. The existing implementation can only return the most recently captured data without blocking. These changes add the ability to block (forever or with timeout) until a new event occurs. -- Ian --=-6J1XeQ0MmbsUd9NHPIee Content-Disposition: inline; filename="pps_fetchwait.diff" Content-Type: text/x-patch; name="pps_fetchwait.diff"; charset="us-ascii" Content-Transfer-Encoding: 7bit Index: sys/kern/kern_tc.c =================================================================== --- sys/kern/kern_tc.c (revision 246337) +++ sys/kern/kern_tc.c (working copy) @@ -1446,6 +1446,50 @@ * RFC 2783 PPS-API implementation. */ +static int +pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps) +{ + int err, timo; + pps_seq_t aseq, cseq; + struct timeval tv; + + if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) + return (EINVAL); + + /* + * If no timeout is requested, immediately return whatever values were + * most recently captured. If timeout seconds is -1, that's a request + * to block without a timeout. WITNESS won't let us sleep forever + * without a lock (we really don't need a lock), so just repeatedly + * sleep a long time. + */ + if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) { + if (fapi->timeout.tv_sec == -1) + timo = 0x7fffffff; + else { + tv.tv_sec = fapi->timeout.tv_sec; + tv.tv_usec = fapi->timeout.tv_nsec / 1000; + timo = tvtohz(&tv); + } + aseq = pps->ppsinfo.assert_sequence; + cseq = pps->ppsinfo.clear_sequence; + while (aseq == pps->ppsinfo.assert_sequence && + cseq == pps->ppsinfo.clear_sequence) { + err = tsleep(pps, PCATCH, "ppsfch", timo); + if (err == EWOULDBLOCK && fapi->timeout.tv_sec == -1) { + continue; + } else if (err != 0) { + return (err); + } + } + } + + pps->ppsinfo.current_mode = pps->ppsparam.mode; + fapi->pps_info_buf = pps->ppsinfo; + + return (0); +} + int pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) { @@ -1485,13 +1529,7 @@ return (0); case PPS_IOC_FETCH: fapi = (struct pps_fetch_args *)data; - if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) - return (EINVAL); - if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) - return (EOPNOTSUPP); - pps->ppsinfo.current_mode = pps->ppsparam.mode; - fapi->pps_info_buf = pps->ppsinfo; - return (0); + return (pps_fetch(fapi, pps)); #ifdef FFCLOCK case PPS_IOC_FETCH_FFCOUNTER: fapi_ffc = (struct pps_fetch_ffc_args *)data; @@ -1540,7 +1578,7 @@ void pps_init(struct pps_state *pps) { - pps->ppscap |= PPS_TSFMT_TSPEC; + pps->ppscap |= PPS_TSFMT_TSPEC | PPS_CANWAIT; if (pps->ppscap & PPS_CAPTUREASSERT) pps->ppscap |= PPS_OFFSETASSERT; if (pps->ppscap & PPS_CAPTURECLEAR) @@ -1680,6 +1718,9 @@ hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); } #endif + + /* Wakeup anyone sleeping in pps_fetch(). */ + wakeup(pps); } /* --=-6J1XeQ0MmbsUd9NHPIee--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1360125698.93359.566.camel>