//------------------------------------------------------------------------------ // Function: ShbIpcEnterAtomicSection // // Description: Enter atomic section for Shared Buffer access // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcEnterAtomicSection (tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; tShbError ShbError; struct timespec curTime, timeout; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst); clock_gettime(CLOCK_REALTIME, &curTime); timeout.tv_sec = 0; timeout.tv_nsec = TIMEOUT_ENTER_ATOMIC * 1000; timespecadd(&timeout, &curTime); if (pthread_mutex_timedlock(&pShbMemHeader->m_mutexBuffAccess, &timeout) == 0) { ShbError = kShbOk; } else { ShbError = kShbBufferInvalid; } return (ShbError); }
static int efirtc_settime(device_t dev, struct timespec *ts) { struct clocktime ct; struct efi_tm tm; /* * We request a timespec with no resolution-adjustment so that we can * apply it ourselves based on whether or not the clock zeroes the * sub-second part of the time when setting the time. */ ts->tv_sec -= utc_offset(); if (!efirtc_zeroes_subseconds) timespecadd(ts, &efirtc_resadj); clock_ts_to_ct(ts, &ct); clock_dbgprint_ct(dev, CLOCK_DBG_WRITE, &ct); bzero(&tm, sizeof(tm)); tm.tm_sec = ct.sec; tm.tm_min = ct.min; tm.tm_hour = ct.hour; tm.tm_mday = ct.day; tm.tm_mon = ct.mon; tm.tm_year = ct.year; tm.tm_nsec = ct.nsec; return (efi_set_time(&tm)); }
/* This function is used by clock_settime and settimeofday */ static int settime1(struct proc *p, const struct timespec *ts, bool check_kauth) { struct timespec delta, now; int s; /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ s = splclock(); nanotime(&now); timespecsub(ts, &now, &delta); if (check_kauth && kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, __UNCONST(ts), &delta, KAUTH_ARG(check_kauth ? false : true)) != 0) { splx(s); return (EPERM); } #ifdef notyet if ((delta.tv_sec < 86400) && securelevel > 0) { /* XXX elad - notyet */ splx(s); return (EPERM); } #endif tc_setclock(ts); timespecadd(&boottime, &delta, &boottime); resettodr(); splx(s); return (0); }
/* * Helper function for semop - copies in the provided timespec and * computes the absolute future time after which we must return. */ static int compute_timeout(timespec_t **tsp, timespec_t *ts, timespec_t *now, timespec_t *timeout) { model_t datamodel = get_udatamodel(); if (datamodel == DATAMODEL_NATIVE) { if (copyin(timeout, ts, sizeof (timespec_t))) return (EFAULT); } else { timespec32_t ts32; if (copyin(timeout, &ts32, sizeof (timespec32_t))) return (EFAULT); TIMESPEC32_TO_TIMESPEC(ts, &ts32) } if (itimerspecfix(ts)) return (EINVAL); /* * Convert the timespec value into absolute time. */ timespecadd(ts, now); *tsp = ts; return (0); }
static int timedwait(semid_t id, u_int msec, u_int *delta, int error) { struct timespec start, end; if (clock_gettime(CLOCK_REALTIME, &start) < 0) { fail_errno("clock_gettime(CLOCK_REALTIME)"); return (-1); } end.tv_sec = msec / 1000; end.tv_nsec = msec % 1000 * 1000000; timespecadd(&end, &start); if (ksem_timedwait(id, &end) < 0) { if (errno != error) { fail_errno("ksem_timedwait"); return (-1); } } else if (error != 0) { fail_err("ksem_timedwait() didn't fail"); return (-1); } if (clock_gettime(CLOCK_REALTIME, &end) < 0) { fail_errno("clock_gettime(CLOCK_REALTIME)"); return (-1); } timespecsub(&end, &start); *delta = end.tv_nsec / 1000000; *delta += end.tv_sec * 1000; return (0); }
void free_rpc_call_ctx(rpc_ctx_t *ctx, uint32_t flags) { struct x_vc_data *xd = (struct x_vc_data *) ctx->ctx_u.clnt.clnt->cl_p1; struct rpc_dplx_rec *rec = xd->rec; struct timespec ts; /* wait for commit of any xfer (ctx specific) */ mutex_lock(&ctx->we.mtx); if (ctx->flags & RPC_CTX_FLAG_WAITSYNC) { /* WAITSYNC is already cleared if the call timed out, but it is * incorrect to wait forever */ (void) clock_gettime(CLOCK_MONOTONIC_FAST, &ts); timespecadd(&ts, &ctx->ctx_u.clnt.timeout); (void) cond_timedwait(&ctx->we.cv, &ctx->we.mtx, &ts); } mutex_lock(&rec->mtx); opr_rbtree_remove(&xd->cx.calls.t, &ctx->node_k); /* interlock */ mutex_unlock(&ctx->we.mtx); mutex_unlock(&rec->mtx); if (ctx->msg) free_rpc_msg(ctx->msg); mem_free(ctx, sizeof(rpc_ctx_t)); }
/* * Copy in the relative timeout provided by the application and convert it * to an absolute timeout. */ static int get_timeout(void *lx_timeout, timestruc_t *timeout) { timestruc_t now; if (get_udatamodel() == DATAMODEL_NATIVE) { if (copyin(lx_timeout, timeout, sizeof (timestruc_t))) return (EFAULT); } #ifdef _SYSCALL32_IMPL else { timestruc32_t timeout32; if (copyin(lx_timeout, &timeout32, sizeof (timestruc32_t))) return (EFAULT); timeout->tv_sec = (time_t)timeout32.tv_sec; timeout->tv_nsec = timeout32.tv_nsec; } #endif gethrestime(&now); if (itimerspecfix(timeout)) return (EINVAL); timespecadd(timeout, &now); return (0); }
/* * Set up the given timer. The value in pt->pt_time.it_value is taken * to be an absolute time for CLOCK_REALTIME/CLOCK_MONOTONIC timers and * a relative time for CLOCK_VIRTUAL/CLOCK_PROF timers. */ void timer_settime(struct ptimer *pt) { struct ptimer *ptn, *pptn; struct ptlist *ptl; KASSERT(mutex_owned(&timer_lock)); if (!CLOCK_VIRTUAL_P(pt->pt_type)) { callout_halt(&pt->pt_ch, &timer_lock); if (timespecisset(&pt->pt_time.it_value)) { /* * Don't need to check tshzto() return value, here. * callout_reset() does it for us. */ callout_reset(&pt->pt_ch, pt->pt_type == CLOCK_MONOTONIC ? tshztoup(&pt->pt_time.it_value) : tshzto(&pt->pt_time.it_value), realtimerexpire, pt); } } else { if (pt->pt_active) { ptn = LIST_NEXT(pt, pt_list); LIST_REMOVE(pt, pt_list); for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list)) timespecadd(&pt->pt_time.it_value, &ptn->pt_time.it_value, &ptn->pt_time.it_value); } if (timespecisset(&pt->pt_time.it_value)) { if (pt->pt_type == CLOCK_VIRTUAL) ptl = &pt->pt_proc->p_timers->pts_virtual; else ptl = &pt->pt_proc->p_timers->pts_prof; for (ptn = LIST_FIRST(ptl), pptn = NULL; ptn && timespeccmp(&pt->pt_time.it_value, &ptn->pt_time.it_value, >); pptn = ptn, ptn = LIST_NEXT(ptn, pt_list)) timespecsub(&pt->pt_time.it_value, &ptn->pt_time.it_value, &pt->pt_time.it_value); if (pptn) LIST_INSERT_AFTER(pptn, pt, pt_list); else LIST_INSERT_HEAD(ptl, pt, pt_list); for ( ; ptn ; ptn = LIST_NEXT(ptn, pt_list)) timespecsub(&ptn->pt_time.it_value, &pt->pt_time.it_value, &ptn->pt_time.it_value); pt->pt_active = 1; } else pt->pt_active = 0; }
int rpc_ctx_wait_reply(rpc_ctx_t *ctx, uint32_t flags) { struct x_vc_data *xd = (struct x_vc_data *) ctx->ctx_u.clnt.clnt->cl_p1; struct rpc_dplx_rec *rec = xd->rec; rpc_dplx_lock_t *lk = &rec->recv.lock; struct timespec ts; int code = 0; /* we hold recv channel lock */ ctx->flags |= RPC_CTX_FLAG_WAITSYNC; while (! (ctx->flags & RPC_CTX_FLAG_SYNCDONE)) { (void) clock_gettime(CLOCK_MONOTONIC_FAST, &ts); timespecadd(&ts, &ctx->ctx_u.clnt.timeout); code = cond_timedwait(&lk->we.cv, &lk->we.mtx, &ts); /* if we timed out, check for xprt destroyed (no more receives) */ if (code == ETIMEDOUT) { SVCXPRT *xprt = rec->hdl.xprt; uint32_t xp_flags; /* dequeue the call */ mutex_lock(&rec->mtx); opr_rbtree_remove(&xd->cx.calls.t, &ctx->node_k); mutex_unlock(&rec->mtx); mutex_lock(&xprt->xp_lock); xp_flags = xprt->xp_flags; mutex_unlock(&xprt->xp_lock); if (xp_flags & SVC_XPRT_FLAG_DESTROYED) { /* XXX should also set error.re_why, but the facility is not * well developed. */ ctx->error.re_status = RPC_TIMEDOUT; } ctx->flags &= ~RPC_CTX_FLAG_WAITSYNC; goto out; } } ctx->flags &= ~RPC_CTX_FLAG_SYNCDONE; /* switch on direction */ switch (ctx->msg->rm_direction) { case REPLY: if (ctx->msg->rm_xid == ctx->xid) return (RPC_SUCCESS); break; case CALL: /* XXX cond transfer control to svc */ /* */ break; default: break; } out: return (code); }
int lwp_timer_copyin(lwp_timer_t *lwptp, timespec_t *tsp) { timespec_t now; int error = 0; if (tsp == NULL) /* not really an error, just need to bzero() */ goto err; lwptp->lwpt_timecheck = timechanged; /* do this before gethrestime() */ gethrestime(&now); /* do this before copyin() */ if (curproc->p_model == DATAMODEL_NATIVE) { if (copyin(tsp, &lwptp->lwpt_rqtime, sizeof (timespec_t))) { error = EFAULT; goto err; } } else { timespec32_t ts32; if (copyin(tsp, &ts32, sizeof (timespec32_t))) { error = EFAULT; goto err; } TIMESPEC32_TO_TIMESPEC(&lwptp->lwpt_rqtime, &ts32); } if (itimerspecfix(&lwptp->lwpt_rqtime)) { error = EINVAL; goto err; } /* * Unless the requested timeout is zero, * get the precise future (absolute) time at * which we are to time out and return ETIME. * We must not return ETIME before that time. */ if (lwptp->lwpt_rqtime.tv_sec == 0 && lwptp->lwpt_rqtime.tv_nsec == 0) { bzero(lwptp, sizeof (lwp_timer_t)); lwptp->lwpt_imm_timeout = 1; } else { lwptp->lwpt_thread = curthread; lwptp->lwpt_tsp = tsp; lwptp->lwpt_time_error = 0; lwptp->lwpt_id = 0; lwptp->lwpt_imm_timeout = 0; timespecadd(&lwptp->lwpt_rqtime, &now); } return (0); err: bzero(lwptp, sizeof (lwp_timer_t)); lwptp->lwpt_time_error = error; return (error); }
//------------------------------------------------------------------------------ // Function: ShbIpcThreadSignalNewData // // Description: Thread for new data signaling // // Parameters: // pvThreadParam_p user parameters for thread // // Return: void * thread exit value (not used) //------------------------------------------------------------------------------ void *ShbIpcThreadSignalNewData (void *pvThreadParam_p) { tShbInstance pShbInstance; tShbMemInst* pShbMemInst; tShbMemHeader* pShbMemHeader; sem_t* pSemNewData; sem_t* pSemStopSignalingNewData; struct timespec curTime, timeout; INT iRetVal; EPL_DBGLVL_SHB_TRACE2("%s(): ThreadId:%ld\n", __func__, syscall(SYS_gettid)); /* thread parameter contains pointer to shared memory */ pShbInstance = (tShbMemInst*)pvThreadParam_p; pShbMemInst = ShbIpcGetShbMemInst (pShbInstance); pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance); /* signal that thread is running */ pShbMemInst->m_fNewDataThreadStarted = TRUE; pSemNewData = &pShbMemHeader->m_semNewData; pSemStopSignalingNewData = &pShbMemHeader->m_semStopSignalingNewData; do { clock_gettime(CLOCK_REALTIME, &curTime); timeout.tv_sec = 0; timeout.tv_nsec = TIMEOUT_CANCEL_THREAD * 1000; timespecadd(&timeout, &curTime); if ((iRetVal = sem_timedwait(pSemNewData, &timeout)) == 0) { //check terminate flag if (!pShbMemInst->m_fThreadTermFlag) { //call Rx Handler //TRACEX("%s() ShbIpcThreadSignalNewData call Rx Handler (%s) sem:%08x instance:%08x\n", __func__, pShbMemInst->m_bufName, (unsigned int)iSemNewDataId, (unsigned int)pShbInstance); pShbMemInst->m_pfnSigHndlrNewData(pShbInstance); } } } while(!pShbMemInst->m_fThreadTermFlag); //set sem thread terminated pShbMemInst->m_fNewDataThreadStarted = FALSE; sem_post(pSemStopSignalingNewData); return NULL; }
//------------------------------------------------------------------------------ // Function: ShbIpcStopSignalingNewData // // Description: Stop signaling of new data (called from reading process) // // Parameters: pShbInstance_p pointer to shared buffer instance // // Return: tShbError = error code //------------------------------------------------------------------------------ tShbError ShbIpcStopSignalingNewData(tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; tShbError ShbError; INT iRetVal = -1; sem_t* pSemStopSignalingNewData; sem_t* pSemNewData; struct timespec curTime, timeout; if (pShbInstance_p == NULL) { return (kShbInvalidArg); } pShbMemHeader = ShbIpcGetShbMemHeader (pShbInstance_p); pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p); pSemNewData = &pShbMemHeader->m_semNewData; pSemStopSignalingNewData = &pShbMemHeader->m_semStopSignalingNewData; ShbError = kShbOk; if (!pShbMemInst->m_fNewDataThreadStarted) { ShbError = kShbBufferAlreadyCompleted; goto Exit; } //set termination flag and signal new data to terminate thread pShbMemInst->m_fThreadTermFlag = TRUE; sem_post(pSemNewData); // waiting for thread to terminate clock_gettime(CLOCK_REALTIME, &curTime); timeout.tv_sec = 1; timeout.tv_nsec = TIMEOUT_WAITING_THREAD * 1000; timespecadd(&timeout, &curTime); iRetVal = sem_timedwait(pSemStopSignalingNewData, &timeout); if (iRetVal != 0) { EPL_DBGLVL_ERROR_TRACE3("%s() Stop Sem TIMEOUT %d (%s)\n", __func__, iRetVal, strerror(errno)); } Exit: return (ShbError); }
/* * Write system time back to RTC */ void resettodr(void) { struct timespec ts; int error; if (disable_rtc_set || clock_dev == NULL) return; getnanotime(&ts); timespecadd(&ts, &clock_adj); ts.tv_sec -= utc_offset(); /* XXX: We should really set all registered RTCs */ if ((error = CLOCK_SETTIME(clock_dev, &ts)) != 0) printf("warning: clock_settime failed (%d), time-of-day clock " "not adjusted to system time\n", error); }
/* * Initialize the time of day register, based on the time base which is, e.g. * from a filesystem. */ void inittodr(time_t base) { struct timespec ts; int error; if (clock_dev == NULL) { printf("warning: no time-of-day clock registered, system time " "will not be set accurately\n"); goto wrong_time; } /* XXX: We should poll all registered RTCs in case of failure */ mtx_lock(&resettodr_lock); error = CLOCK_GETTIME(clock_dev, &ts); mtx_unlock(&resettodr_lock); if (error != 0 && error != EINVAL) { printf("warning: clock_gettime failed (%d), the system time " "will not be set accurately\n", error); goto wrong_time; } if (error == EINVAL || ts.tv_sec < 0) { printf("Invalid time in real time clock.\n" "Check and reset the date immediately!\n"); goto wrong_time; } ts.tv_sec += utc_offset(); timespecadd(&ts, &clock_adj); tc_setclock(&ts); #ifdef FFCLOCK ffclock_reset_clock(&ts); #endif return; wrong_time: if (base > 0) { ts.tv_sec = base; ts.tv_nsec = 0; tc_setclock(&ts); } }
/* Delete a POSIX realtime timer */ int sys_timer_delete(struct lwp *l, const struct sys_timer_delete_args *uap, register_t *retval) { /* { syscallarg(timer_t) timerid; } */ struct proc *p = l->l_proc; timer_t timerid; struct ptimers *pts; struct ptimer *pt, *ptn; timerid = SCARG(uap, timerid); pts = p->p_timers; if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) return (EINVAL); mutex_spin_enter(&timer_lock); if ((pt = pts->pts_timers[timerid]) == NULL) { mutex_spin_exit(&timer_lock); return (EINVAL); } if (CLOCK_VIRTUAL_P(pt->pt_type)) { if (pt->pt_active) { ptn = LIST_NEXT(pt, pt_list); LIST_REMOVE(pt, pt_list); for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list)) timespecadd(&pt->pt_time.it_value, &ptn->pt_time.it_value, &ptn->pt_time.it_value); pt->pt_active = 0; } } itimerfree(pts, timerid); return (0); }
void pps_event(struct pps_state *pps, int event) { struct bintime bt; struct timespec ts, *tsp, *osp; u_int tcount, *pcount; int foff, fhard; pps_seq_t *pseq; KASSERT(pps != NULL, ("NULL pps pointer in pps_event")); /* If the timecounter was wound up underneath us, bail out. */ if (pps->capgen == 0 || pps->capgen != pps->capth->th_generation) return; /* Things would be easier with arrays. */ if (event == PPS_CAPTUREASSERT) { tsp = &pps->ppsinfo.assert_timestamp; osp = &pps->ppsparam.assert_offset; foff = pps->ppsparam.mode & PPS_OFFSETASSERT; fhard = pps->kcmode & PPS_CAPTUREASSERT; pcount = &pps->ppscount[0]; pseq = &pps->ppsinfo.assert_sequence; } else { tsp = &pps->ppsinfo.clear_timestamp; osp = &pps->ppsparam.clear_offset; foff = pps->ppsparam.mode & PPS_OFFSETCLEAR; fhard = pps->kcmode & PPS_CAPTURECLEAR; pcount = &pps->ppscount[1]; pseq = &pps->ppsinfo.clear_sequence; } /* * If the timecounter changed, we cannot compare the count values, so * we have to drop the rest of the PPS-stuff until the next event. */ if (pps->ppstc != pps->capth->th_counter) { pps->ppstc = pps->capth->th_counter; *pcount = pps->capcount; pps->ppscount[2] = pps->capcount; return; } /* Convert the count to a timespec. */ tcount = pps->capcount - pps->capth->th_offset_count; tcount &= pps->capth->th_counter->tc_counter_mask; bt = pps->capth->th_offset; bintime_addx(&bt, pps->capth->th_scale * tcount); bintime_add(&bt, &boottimebin); bintime2timespec(&bt, &ts); /* If the timecounter was wound up underneath us, bail out. */ if (pps->capgen != pps->capth->th_generation) return; *pcount = pps->capcount; (*pseq)++; *tsp = ts; if (foff) { timespecadd(tsp, osp); if (tsp->tv_nsec < 0) { tsp->tv_nsec += 1000000000; tsp->tv_sec -= 1; } } #ifdef PPS_SYNC if (fhard) { uint64_t scale; /* * Feed the NTP PLL/FLL. * The FLL wants to know how many (hardware) nanoseconds * elapsed since the previous event. */ tcount = pps->capcount - pps->ppscount[2]; pps->ppscount[2] = pps->capcount; tcount &= pps->capth->th_counter->tc_counter_mask; scale = (uint64_t)1 << 63; scale /= pps->capth->th_counter->tc_frequency; scale *= 2; bt.sec = 0; bt.frac = 0; bintime_addx(&bt, scale * tcount); bintime2timespec(&bt, &ts); hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); } #endif }
int sscomrxintr(void *arg) { struct sscom_softc *sc = arg; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; u_char *put, *end; u_int cc; if (SSCOM_ISALIVE(sc) == 0) return 0; SSCOM_LOCK(sc); end = sc->sc_ebuf; put = sc->sc_rbput; cc = sc->sc_rbavail; do { u_char msts, delta; u_char uerstat; uint32_t ufstat; ufstat = bus_space_read_4(iot, ioh, SSCOM_UFSTAT); /* XXX: break interrupt with no character? */ if ( (ufstat & (UFSTAT_RXCOUNT|UFSTAT_RXFULL)) && !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { while (cc > 0) { int cn_trapped = 0; /* get status and received character. read status register first */ uerstat = sscom_geterr(iot, ioh); put[0] = sscom_getc(iot, ioh); if (ISSET(uerstat, UERSTAT_BREAK)) { int con_trapped = 0; cn_check_magic(sc->sc_tty->t_dev, CNC_BREAK, sscom_cnm_state); if (con_trapped) continue; #if defined(KGDB) if (ISSET(sc->sc_hwflags, SSCOM_HW_KGDB)) { kgdb_connect(1); continue; } #endif } put[1] = uerstat; cn_check_magic(sc->sc_tty->t_dev, put[0], sscom_cnm_state); if (!cn_trapped) { put += 2; if (put >= end) put = sc->sc_rbuf; cc--; } ufstat = bus_space_read_4(iot, ioh, SSCOM_UFSTAT); if ( (ufstat & (UFSTAT_RXFULL|UFSTAT_RXCOUNT)) == 0 ) break; } /* * Current string of incoming characters ended because * no more data was available or we ran out of space. * Schedule a receive event if any data was received. * If we're out of space, turn off receive interrupts. */ sc->sc_rbput = put; sc->sc_rbavail = cc; if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) sc->sc_rx_ready = 1; /* * See if we are in danger of overflowing a buffer. If * so, use hardware flow control to ease the pressure. */ if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) && cc < sc->sc_r_hiwat) { SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); sscom_hwiflow(sc); } /* * If we're out of space, disable receive interrupts * until the queue has drained a bit. */ if (!cc) { SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); sscom_disable_rxint(sc); sc->sc_ucon &= ~UCON_ERRINT; bus_space_write_4(iot, ioh, SSCOM_UCON, sc->sc_ucon); } } msts = sc->sc_read_modem_status(sc); delta = msts ^ sc->sc_msts; sc->sc_msts = msts; #ifdef notyet /* * Pulse-per-second (PSS) signals on edge of DCD? * Process these even if line discipline is ignoring DCD. */ if (delta & sc->sc_ppsmask) { struct timeval tv; if ((msr & sc->sc_ppsmask) == sc->sc_ppsassert) { /* XXX nanotime() */ microtime(&tv); TIMEVAL_TO_TIMESPEC(&tv, &sc->ppsinfo.assert_timestamp); if (sc->ppsparam.mode & PPS_OFFSETASSERT) { timespecadd(&sc->ppsinfo.assert_timestamp, &sc->ppsparam.assert_offset, &sc->ppsinfo.assert_timestamp); } #ifdef PPS_SYNC if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) hardpps(&tv, tv.tv_usec); #endif sc->ppsinfo.assert_sequence++; sc->ppsinfo.current_mode = sc->ppsparam.mode; } else if ((msr & sc->sc_ppsmask) == sc->sc_ppsclear) { /* XXX nanotime() */ microtime(&tv); TIMEVAL_TO_TIMESPEC(&tv, &sc->ppsinfo.clear_timestamp); if (sc->ppsparam.mode & PPS_OFFSETCLEAR) { timespecadd(&sc->ppsinfo.clear_timestamp, &sc->ppsparam.clear_offset, &sc->ppsinfo.clear_timestamp); } #ifdef PPS_SYNC if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR) hardpps(&tv, tv.tv_usec); #endif sc->ppsinfo.clear_sequence++; sc->ppsinfo.current_mode = sc->ppsparam.mode; } } #endif /* * Process normal status changes */ if (ISSET(delta, sc->sc_msr_mask)) { SET(sc->sc_msr_delta, delta); /* * Stop output immediately if we lose the output * flow control signal or carrier detect. */ if (ISSET(~msts, sc->sc_msr_mask)) { sc->sc_tbc = 0; sc->sc_heldtbc = 0; #ifdef SSCOM_DEBUG if (sscom_debug) sscomstatus(sc, "sscomintr "); #endif } sc->sc_st_check = 1; } /* * Done handling any receive interrupts. */ /* * If we've delayed a parameter change, do it * now, and restart * output. */ if ((ufstat & UFSTAT_TXCOUNT) == 0) { /* XXX: we should check transmitter empty also */ if (sc->sc_heldchange) { sscom_loadchannelregs(sc); sc->sc_heldchange = 0; sc->sc_tbc = sc->sc_heldtbc; sc->sc_heldtbc = 0; } } } while (0); SSCOM_UNLOCK(sc); /* Wake up the poller. */ softint_schedule(sc->sc_si); #ifdef RND_COM rnd_add_uint32(&sc->rnd_source, iir | rsr); #endif return 1; }
/* * Write out process accounting information, on process exit. * Data to be written out is specified in Leffler, et al. * and are enumerated below. (They're also noted in the system * "acct.h" header file.) */ int acct_process(struct proc *p) { struct acct acct; struct process *pr = p->p_p; struct rusage *r; struct timespec ut, st, tmp; int t; struct vnode *vp; int error; /* If accounting isn't enabled, don't bother */ vp = acctp; if (vp == NULL) return (0); /* * Get process accounting information. */ /* (1) The name of the command that ran */ memcpy(acct.ac_comm, p->p_comm, sizeof acct.ac_comm); /* (2) The amount of user and system time that was used */ calctsru(&pr->ps_tu, &ut, &st, NULL); acct.ac_utime = encode_comp_t(ut.tv_sec, ut.tv_nsec); acct.ac_stime = encode_comp_t(st.tv_sec, st.tv_nsec); /* (3) The elapsed time the command ran (and its starting time) */ acct.ac_btime = pr->ps_start.tv_sec; getnanotime(&tmp); timespecsub(&tmp, &pr->ps_start, &tmp); acct.ac_etime = encode_comp_t(tmp.tv_sec, tmp.tv_nsec); /* (4) The average amount of memory used */ r = &p->p_ru; timespecadd(&ut, &st, &tmp); t = tmp.tv_sec * hz + tmp.tv_nsec / (1000 * tick); if (t) acct.ac_mem = (r->ru_ixrss + r->ru_idrss + r->ru_isrss) / t; else acct.ac_mem = 0; /* (5) The number of disk I/O operations done */ acct.ac_io = encode_comp_t(r->ru_inblock + r->ru_oublock, 0); /* (6) The UID and GID of the process */ acct.ac_uid = pr->ps_ucred->cr_ruid; acct.ac_gid = pr->ps_ucred->cr_rgid; /* (7) The terminal from which the process was started */ if ((pr->ps_flags & PS_CONTROLT) && pr->ps_pgrp->pg_session->s_ttyp) acct.ac_tty = pr->ps_pgrp->pg_session->s_ttyp->t_dev; else acct.ac_tty = NODEV; /* (8) The boolean flags that tell how the process terminated, etc. */ acct.ac_flag = pr->ps_acflag; /* * Now, just write the accounting information to the file. */ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&acct, sizeof (acct), (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT|IO_NOLIMIT, p->p_ucred, NULL, p); return error; }
int sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(struct mmsghdr *) mmsg; syscallarg(unsigned int) vlen; syscallarg(unsigned int) flags; syscallarg(struct timespec *) timeout; } */ struct mmsghdr mmsg; struct socket *so; struct msghdr *msg = &mmsg.msg_hdr; int error, s; struct mbuf *from, *control; struct timespec ts, now; unsigned int vlen, flags, dg; if (SCARG(uap, timeout)) { if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0) return error; getnanotime(&now); timespecadd(&now, &ts, &ts); } s = SCARG(uap, s); if ((error = fd_getsock(s, &so)) != 0) return error; vlen = SCARG(uap, vlen); if (vlen > 1024) vlen = 1024; from = NULL; flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; for (dg = 0; dg < vlen;) { error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg)); if (error) break; msg->msg_flags = flags & ~MSG_WAITFORONE; if (from != NULL) { m_free(from); from = NULL; } error = do_sys_recvmsg_so(l, s, so, msg, &from, msg->msg_control != NULL ? &control : NULL, retval); if (error) { if (error == EAGAIN && dg > 0) error = 0; break; } if (msg->msg_control != NULL) error = copyout_msg_control(l, msg, control); if (error) break; error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0, from); if (error) break; ktrkuser("msghdr", msg, sizeof *msg); mmsg.msg_len = *retval; error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg)); if (error) break; dg++; if (msg->msg_flags & MSG_OOB) break; if (SCARG(uap, timeout)) { getnanotime(&now); timespecsub(&now, &ts, &now); if (now.tv_sec > 0) break; } if (flags & MSG_WAITFORONE) flags |= MSG_DONTWAIT; } if (from != NULL) m_free(from); *retval = dg; if (error) so->so_error = error; fd_putfile(s); /* * If we succeeded at least once, return 0, hopefully so->so_error * will catch it next time. */ if (dg) return 0; return error; }