//------------------------------------------------------------------------------
// 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);
}
Beispiel #2
0
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));
}
Beispiel #3
0
/* 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);
}
Beispiel #4
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);
}
Beispiel #5
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);
}
Beispiel #6
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));
}
Beispiel #7
0
/*
 * 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);
}
Beispiel #8
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;
	}
Beispiel #9
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);
}
Beispiel #10
0
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);
}
Beispiel #11
0
//------------------------------------------------------------------------------
// 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;
}
Beispiel #12
0
//------------------------------------------------------------------------------
// 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);
}
Beispiel #13
0
/*
 * 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);
}
Beispiel #14
0
/*
 * 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);
	}
}
Beispiel #15
0
/* 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);
}
Beispiel #16
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;
}
Beispiel #18
0
/*
 * 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;
}
Beispiel #19
0
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;
}