Пример #1
0
/*
 * Get value from a queued PV.
 */
epicsShareFunc boolean seq_pvGetQ(SS_ID ss, CH_ID chId)
{
	PROG	*sp = ss->prog;
	CHAN	*ch = sp->chan + chId;
	void	*var = valPtr(ch,ss);
	EF_ID	ev_flag = ch->syncedTo;
	PVMETA	*meta = metaPtr(ch,ss);
	boolean	was_empty;
	struct getq_cp_arg arg = {ch, var, meta};

	if (!ch->queue)
	{
		errlogSevPrintf(errlogMajor,
			"pvGetQ(%s): user error (not queued)\n",
			ch->varName
		);
		return FALSE;
	}

	was_empty = seqQueueGetF(ch->queue, getq_cp, &arg);

	if (ev_flag)
	{
		epicsMutexMustLock(sp->lock);
		/* If queue is now empty, clear the event flag */
		if (seqQueueIsEmpty(ch->queue))
		{
			bitClear(sp->evFlags, ev_flag);
		}
		epicsMutexUnlock(sp->lock);
	}

	return (!was_empty);
}
Пример #2
0
/*
 * Return whether the last get completed. In safe mode, as a
 * side effect, copy value from shared buffer to state set local buffer.
 */
epicsShareFunc boolean seq_pvGetComplete(
	SS_ID	ss,
	CH_ID	chId)
{
	PROG	*sp = ss->prog;
	CHAN	*ch = sp->chan + chId;

	if (!ch->dbch)
	{
		/* Anonymous PVs always complete immediately */
		if (!optTest(sp, OPT_SAFE))
			errlogSevPrintf(errlogMajor,
				"pvGetComplete(%s): user error (not assigned to a PV)\n",
				ch->varName);
		return TRUE;
	}
	else if (!ss->getReq[chId])
	{
		pvStat status = check_connected(ch->dbch, metaPtr(ch,ss));
		if (status == pvStatOK && optTest(sp, OPT_SAFE))
		{
			/* In safe mode, copy value and meta data from shared buffer
			   to ss local buffer. */
			/* Copy regardless of whether dirty flag is set or not */
			ss_read_buffer(ss, ch, FALSE);
		}
		return TRUE;
	}
	return FALSE;
}
Пример #3
0
static pvStat seq_pvSingleMonitor(SS_ID ss, CH_ID chId, boolean turn_on, const char *what)
{
	PROG	*sp = ss->prog;
	CHAN	*ch = sp->chan + chId;
	DBCHAN	*dbch = ch->dbch;
	pvStat	status;

	if (!dbch)
	{
		if (optTest(sp, OPT_SAFE))
		{
			ch->monitored = TRUE;
			return pvStatOK;
		}
		else
		{
			errlogSevPrintf(errlogMajor,
				"%s(%s): user error (not assigned to a PV)\n",
				what, ch->varName
			);
			return pvStatERROR;
		}
	}
	ch->monitored = turn_on;
	status = seq_camonitor(ch, turn_on);
	if (status != pvStatOK)
	{
		pv_call_failure(dbch, metaPtr(ch,ss), status);
	}
	return status;
}
Пример #4
0
/*
 * Return whether the last get completed. In safe mode, as a
 * side effect, copy value from shared buffer to state set local buffer.
 */
epicsShareFunc boolean epicsShareAPI seq_pvGetComplete(SS_ID ss, VAR_ID varId)
{
	epicsEventId	getSem = ss->getSemId[varId];
	SPROG		*sp = ss->sprog;
	CHAN		*ch = sp->chan + varId;
	pvStat		status;

	if (!ch->dbch)
	{
		/* Anonymous PVs always complete immediately */
		if (!(sp->options & OPT_SAFE))
			errlogSevPrintf(errlogMajor,
				"pvGetComplete(%s): user error (variable not assigned)\n",
				ch->varName);
		return TRUE;
	}

	if (!ss->getReq[varId])
	{
		errlogSevPrintf(errlogMinor,
			"pvGetComplete(%s): no pending get request for this variable\n",
			ch->varName);
		return TRUE;
	}

	switch (epicsEventTryWait(getSem))
	{
	case epicsEventWaitOK:
		ss->getReq[varId] = NULL;
		epicsEventSignal(getSem);
		status = check_connected(ch->dbch, metaPtr(ch,ss));
		/* TODO: returning either TRUE or FALSE here seems wrong. We return TRUE,
		   so that state sets don't hang. Still means that user code has to check
		   status by calling pvStatus and/or pvMessage. */
		if (status) return TRUE;
		/* In safe mode, copy value and meta data from shared buffer
		   to ss local buffer. */
		if (sp->options & OPT_SAFE)
			/* Copy regardless of whether dirty flag is set or not */
			ss_read_buffer(ss, ch, FALSE);
		return TRUE;
	case epicsEventWaitTimeout:
		return FALSE;
	case epicsEventWaitError:
		ss->getReq[varId] = NULL;
		epicsEventSignal(getSem);
		errlogSevPrintf(errlogFatal, "pvGetComplete: "
		  "epicsEventTryWait(getSemId[%d]) failure\n", varId);
	default: /* pacify gcc which does not understand the we checked all possibilities */
		return FALSE;
	}
}
Пример #5
0
/*
 * Return channel time stamp.
 */
epicsShareFunc epicsTimeStamp seq_pvTimeStamp(SS_ID ss, CH_ID chId)
{
	CHAN	*ch = ss->prog->chan + chId;
	PVMETA	*meta = metaPtr(ch,ss);
	if (ch->dbch)
	{
		return meta->timeStamp;
	}
	else
	{
		epicsTimeStamp ts;
		epicsTimeGetCurrent(&ts);
		return ts;
	}
}
Пример #6
0
/*
 * Return whether the last put completed.
 */
static boolean seq_pvSinglePutComplete(
	SS_ID	ss,
	CH_ID	chId)
{
	PROG	*sp = ss->prog;
	CHAN	*ch = sp->chan + chId;

	if (!ch->dbch)
	{
		/* Anonymous PVs always complete immediately */
		if (!(sp->options & OPT_SAFE))
			errlogSevPrintf(errlogMajor,
				"pvPutComplete(%s): user error (not assigned to a PV)\n",
				ch->varName);
		return TRUE;
	}
	else if (!ss->putReq[chId])
	{
		check_connected(ch->dbch, metaPtr(ch,ss));
		return TRUE;
	}

	return FALSE;
}
Пример #7
0
/*
 * Return channel alarm severity.
 */
epicsShareFunc pvSevr seq_pvSeverity(SS_ID ss, CH_ID chId)
{
	CHAN	*ch = ss->prog->chan + chId;
	PVMETA	*meta = metaPtr(ch,ss);
	return ch->dbch ? meta->severity : pvSevrOK;
}
Пример #8
0
/*
 * Put a variable's value to a PV, with timeout.
 */
epicsShareFunc pvStat seq_pvPutTmo(SS_ID ss, CH_ID chId, enum compType compType, double tmo)
{
	PROG	*sp = ss->prog;
	CHAN	*ch = sp->chan + chId;
	pvStat	status;
	unsigned count;
	char	*var = valPtr(ch,ss);	/* ptr to value */
	PVREQ	*req;
	DBCHAN	*dbch = ch->dbch;
	PVMETA	*meta = metaPtr(ch,ss);

	DEBUG("pvPut: pv name=%s, var=%p\n", dbch ? dbch->dbName : "<anonymous>", var);

	/* First handle anonymous PV (safe mode only) */
	if (optTest(sp, OPT_SAFE) && !dbch)
	{
		anonymous_put(ss, ch);
		return pvStatOK;
	}
	if (!dbch)
	{
		errlogSevPrintf(errlogMajor,
			"pvPut(%s): user error (not assigned to a PV)\n",
			ch->varName
		);
		return pvStatERROR;
	}

	/* Check for channel connected */
	status = check_connected(dbch, meta);
	if (status != pvStatOK) return status;

	/* Determine whether to perform synchronous, asynchronous, or
	   plain put ((+a) option was never honored for put, so DEFAULT
	   means fire-and-forget) */
	status = check_pending(pvEventPut, ss, ss->putReq + chId, ch->varName,
		dbch, meta, compType, tmo);
	if (status != pvStatOK)
		return status;

	/* Determine number of elements to put (don't try to put more
	   than db count) */
	count = dbch->dbCount;

	/* Perform the PV put operation (either non-blocking or with a
	   callback routine specified) */
	if (compType == DEFAULT)
	{
		status = pvVarPutNoBlock(
				&dbch->pvid,		/* PV id */
				ch->type->putType,	/* data type */
				count,			/* element count */
				(pvValue *)var);	/* data value */
		if (status != pvStatOK)
		{
			pv_call_failure(dbch, meta, status);
			errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutNoBlock() failure: %s\n",
				ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid));
			return status;
		}
	}
	else
	{
		/* Allocate and initialize a pv request */
		req = (PVREQ *)freeListMalloc(sp->pvReqPool);
		req->ss = ss;
		req->ch = ch;

		assert(ss->putReq[chId] == NULL);
		ss->putReq[chId] = req;

		status = pvVarPutCallback(
				&dbch->pvid,		/* PV id */
				ch->type->putType,	/* data type */
				count,			/* element count */
				(pvValue *)var,		/* data value */
				req);			/* user arg */
		if (status != pvStatOK)
		{
			pv_call_failure(dbch, meta, status);
			errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutCallback() failure: %s\n",
				ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid));
			ss->putReq[chId] = NULL;	/* cancel the request */
			freeListFree(sp->pvReqPool, req);
			check_connected(dbch, meta);
			return status;
		}

		if (compType == SYNC)			/* wait for completion */
		{
			pvSysFlush(sp->pvSys);
			status = wait_complete(pvEventPut, ss, ss->putReq + chId, dbch, meta, tmo);
			if (status != pvStatOK)
				return status;
		}
	}
	return pvStatOK;
}
Пример #9
0
/*
 * Return whether the last put completed.
 */
epicsShareFunc boolean epicsShareAPI seq_pvPutComplete(
	SS_ID		ss,
	VAR_ID		varId,
	unsigned	length,
	boolean		any,
	boolean		*complete)
{
	SPROG		*sp = ss->sprog;
	boolean		anyDone = FALSE, allDone = TRUE;
	unsigned	n;

	for (n = 0; n < length; n++)
	{
		epicsEventId	putSem = ss->putSemId[varId+n];
		boolean		done = FALSE;
		CHAN		*ch = sp->chan + varId + n;

		if (!ch->dbch)
		{
		        /* Anonymous PVs always complete immediately */
			if (!(sp->options & OPT_SAFE))
			        errlogSevPrintf(errlogMajor,
				        "pvPutComplete(%s): user error (variable not assigned)\n",
				        ch->varName);
			done = TRUE;
		}
		else if (!ss->putReq[varId])
		{
		        errlogSevPrintf(errlogMinor,
			        "pvPutComplete(%s): no pending put request for this variable\n",
			        ch->varName);
			done = TRUE;
		}
		else
		{
			switch (epicsEventTryWait(putSem))
			{
			case epicsEventWaitOK:
				ss->putReq[varId] = NULL;
				epicsEventSignal(putSem);
				check_connected(ch->dbch, metaPtr(ch,ss));
				/* TODO: returning either TRUE or FALSE here seems wrong. We return TRUE,
				   so that state sets don't hang. Still means that user code has to check
				   status by calling pvStatus and/or pvMessage. */
				done = TRUE;
				break;
			case epicsEventWaitTimeout:
				break;
			case epicsEventWaitError:
				ss->putReq[varId] = NULL;
				epicsEventSignal(putSem);
				errlogSevPrintf(errlogFatal, "pvPutComplete(%s): "
				  "epicsEventTryWait(putSem[%d]) failure\n", ch->varName, varId);
				break;
			}
		}

		anyDone = anyDone || done;
		allDone = allDone && done;

		if (complete)
		{
			complete[n] = done;
		}
		else if (any && done)
		{
			break;
		}
	}

	DEBUG("pvPutComplete: varId=%u, length=%u, anyDone=%u, allDone=%u\n",
		varId, length, anyDone, allDone);

	return any?anyDone:allDone;
}
Пример #10
0
/*
 * Get value from a channel, with timeout.
 */
epicsShareFunc pvStat seq_pvGetTmo(SS_ID ss, CH_ID chId, enum compType compType, double tmo)
{
	PROG		*sp = ss->prog;
	CHAN		*ch = sp->chan + chId;
	pvStat		status;
	PVREQ		*req;
	DBCHAN		*dbch = ch->dbch;
	PVMETA		*meta = metaPtr(ch,ss);

	/* Anonymous PV and safe mode, just copy from shared buffer.
	   Note that completion is always immediate, so no distinction
	   between SYNC and ASYNC needed. See also pvGetComplete. */
	if (optTest(sp, OPT_SAFE) && !dbch)
	{
		/* Copy regardless of whether dirty flag is set or not */
		ss_read_buffer(ss, ch, FALSE);
		return pvStatOK;
	}
	/* No named PV and traditional mode => user error */
	if (!dbch)
	{
		errlogSevPrintf(errlogMajor,
			"pvGet(%s): user error (not assigned to a PV)\n",
			ch->varName
		);
		return pvStatERROR;
	}

	if (compType == DEFAULT)
	{
		compType = optTest(sp, OPT_ASYNC) ? ASYNC : SYNC;
	}

	status = check_pending(pvEventGet, ss, ss->getReq + chId, ch->varName,
		dbch, meta, compType, tmo);
	if (status != pvStatOK)
		return status;

	/* Allocate and initialize a pv request */
	req = (PVREQ *)freeListMalloc(sp->pvReqPool);
	req->ss = ss;
	req->ch = ch;

	assert(ss->getReq[chId] == NULL);
	ss->getReq[chId] = req;

	/* Perform the PV get operation with a callback routine specified.
	   Requesting more than db channel has available is ok. */
	status = pvVarGetCallback(
			&dbch->pvid,		/* PV id */
			ch->type->getType,	/* request type */
			ch->count,		/* element count */
			req);			/* user arg */
	if (status != pvStatOK)
	{
		pv_call_failure(dbch, meta, status);
		errlogSevPrintf(errlogFatal,
			"pvGet(var %s, pv %s): pvVarGetCallback() failure: %s\n",
			ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid));
		ss->getReq[chId] = NULL;	/* cancel the request */
		freeListFree(sp->pvReqPool, req);
		check_connected(dbch, meta);
		return status;
	}

	/* Synchronous: wait for completion */
	if (compType == SYNC)
	{
		pvSysFlush(sp->pvSys);
		status = wait_complete(pvEventGet, ss, ss->getReq + chId, dbch, meta, tmo);
		if (status != pvStatOK)
			return status;
		if (optTest(sp, OPT_SAFE))
			/* Copy regardless of whether dirty flag is set or not */
			ss_read_buffer(ss, ch, FALSE);
	}

	return pvStatOK;
}
Пример #11
0
/*
 * Get value from a channel.
 * TODO: add optional timeout argument.
 */
epicsShareFunc pvStat epicsShareAPI seq_pvGet(SS_ID ss, VAR_ID varId, enum compType compType)
{
	SPROG		*sp = ss->sprog;
	CHAN		*ch = sp->chan + varId;
	pvStat		status;
	PVREQ		*req;
	epicsEventId	getSem = ss->getSemId[varId];
	DBCHAN		*dbch = ch->dbch;
	PVMETA		*meta = metaPtr(ch,ss);
	double		tmo = seq_sync_timeout;

	/* Anonymous PV and safe mode, just copy from shared buffer.
	   Note that completion is always immediate, so no distinction
	   between SYNC and ASYNC needed. See also pvGetComplete. */
	if ((sp->options & OPT_SAFE) && !dbch)
	{
		/* Copy regardless of whether dirty flag is set or not */
		ss_read_buffer(ss, ch, FALSE);
		return pvStatOK;
	}
	/* No named PV and traditional mode => user error */
	if (!dbch)
	{
		errlogSevPrintf(errlogMajor,
			"pvGet(%s): user error (variable not assigned)\n",
			ch->varName
		);
		return pvStatERROR;
	}

	if (compType == DEFAULT)
	{
		compType = (sp->options & OPT_ASYNC) ? ASYNC : SYNC;
	}

	if (compType == SYNC)
	{
		double before, after;
		pvTimeGetCurrentDouble(&before);
		switch (epicsEventWaitWithTimeout(getSem, tmo))
		{
		case epicsEventWaitOK:
			status = check_connected(dbch, meta);
			if (status) return epicsEventSignal(getSem), status;
			pvTimeGetCurrentDouble(&after);
			tmo -= (after - before);
			break;
		case epicsEventWaitTimeout:
			errlogSevPrintf(errlogMajor,
				"pvGet(ss %s, var %s, pv %s): failed (timeout "
				"waiting for other get requests to finish)\n",
				ss->ssName, ch->varName, dbch->dbName
			);
			return pvStatERROR;
		case epicsEventWaitError:
			/* try to recover */
			ss->getReq[varId] = NULL;
			epicsEventSignal(getSem);
			errlogSevPrintf(errlogFatal,
				"pvGet: epicsEventWaitWithTimeout() failure\n");
			return pvStatERROR;
		}
	}
	else if (compType == ASYNC)
	{
		switch (epicsEventTryWait(getSem))
		{
		case epicsEventWaitOK:
			if (ss->getReq[varId] != NULL)
			{
				/* previous request timed out but user
				   did not call pvGetComplete */
				ss->getReq[varId] = NULL;
			}
			status = check_connected(dbch, meta);
			if (status) return epicsEventSignal(getSem), status;
			break;
		case epicsEventWaitTimeout:
			errlogSevPrintf(errlogMajor,
				"pvGet(ss %s, var %s, pv %s): user error "
				"(there is already a get pending for this variable/"
				"state set combination)\n",
				ss->ssName, ch->varName, dbch->dbName
			);
			return pvStatERROR;
		case epicsEventWaitError:
			/* try to recover */
			ss->getReq[varId] = NULL;
			epicsEventSignal(getSem);
			errlogSevPrintf(errlogFatal,
				"pvGet: epicsEventTryWait() failure\n");
			return pvStatERROR;
		}
	}

	/* Allocate and initialize a pv request */
	req = (PVREQ *)freeListMalloc(sp->pvReqPool);
	req->ss = ss;
	req->ch = ch;

	assert(ss->getReq[varId] == NULL);
	ss->getReq[varId] = req;

	/* Perform the PV get operation with a callback routine specified.
	   Requesting more than db channel has available is ok. */
	status = pvVarGetCallback(
			dbch->pvid,		/* PV id */
			ch->type->getType,	/* request type */
			ch->count,		/* element count */
			seq_get_handler,	/* callback handler */
			req);			/* user arg */
	if (status != pvStatOK)
	{
		meta->status = pvStatERROR;
		meta->severity = pvSevrMAJOR;
		meta->message = "get failure";
		errlogSevPrintf(errlogFatal, "pvGet(var %s, pv %s): pvVarGetCallback() failure: %s\n",
			ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid));
		ss->getReq[varId] = NULL;
		freeListFree(sp->pvReqPool, req);
		epicsEventSignal(getSem);
		check_connected(dbch, meta);
		return status;
	}

	/* Synchronous: wait for completion */
	if (compType == SYNC)
	{
		epicsEventWaitStatus event_status;

		pvSysFlush(sp->pvSys);
		event_status = epicsEventWaitWithTimeout(getSem, tmo);
		ss->getReq[varId] = NULL;
		epicsEventSignal(getSem);
		switch (event_status)
		{
		case epicsEventWaitOK:
			status = check_connected(dbch, meta);
			if (status) return status;
			if (sp->options & OPT_SAFE)
				/* Copy regardless of whether dirty flag is set or not */
				ss_read_buffer(ss, ch, FALSE);
			break;
		case epicsEventWaitTimeout:
			meta->status = pvStatTIMEOUT;
			meta->severity = pvSevrMAJOR;
			meta->message = "get completion timeout";
			return meta->status;
		case epicsEventWaitError:
			meta->status = pvStatERROR;
			meta->severity = pvSevrMAJOR;
			meta->message = "get completion failure";
			return meta->status;
		}
	}

	return pvStatOK;
}
Пример #12
0
/*
 * Return channel error message.
 */
epicsShareFunc const char *seq_pvMessage(SS_ID ss, CH_ID chId)
{
	CHAN	*ch = ss->prog->chan + chId;
	PVMETA	*meta = metaPtr(ch,ss);
	return ch->dbch ? meta->message : "";
}
Пример #13
0
/*
 * Put a variable's value to a PV.
 */
epicsShareFunc pvStat epicsShareAPI seq_pvPut(SS_ID ss, VAR_ID varId, enum compType compType)
{
	SPROG	*sp = ss->sprog;
	CHAN	*ch = sp->chan + varId;
	pvStat	status;
	unsigned count;
	char	*var = valPtr(ch,ss);	/* ptr to value */
	PVREQ	*req;
	DBCHAN	*dbch = ch->dbch;
	PVMETA	*meta = metaPtr(ch,ss);
	epicsEventId	putSem = ss->putSemId[varId];
	double	tmo = seq_sync_timeout;

	DEBUG("pvPut: pv name=%s, var=%p\n", dbch ? dbch->dbName : "<anonymous>", var);

	/* First handle anonymous PV (safe mode only) */
	if ((sp->options & OPT_SAFE) && !dbch)
	{
		anonymous_put(ss, ch);
		return pvStatOK;
	}
	if (!dbch)
	{
		errlogSevPrintf(errlogMajor,
			"pvPut(%s): user error (variable not assigned)\n",
			ch->varName
		);
		return pvStatERROR;
	}

	/* Check for channel connected */
	status = check_connected(dbch, meta);
	if (status) return status;

	/* Determine whether to perform synchronous, asynchronous, or
	   plain put ((+a) option was never honored for put, so DEFAULT
	   means non-blocking and therefore implicitly asynchronous) */
	if (compType == SYNC)
	{
		double before, after;
		pvTimeGetCurrentDouble(&before);
		switch (epicsEventWaitWithTimeout(putSem, tmo))
		{
		case epicsEventWaitOK:
			pvTimeGetCurrentDouble(&after);
			tmo -= (after - before);
			break;
		case epicsEventWaitTimeout:
			errlogSevPrintf(errlogMajor,
				"pvPut(ss %s, var %s, pv %s): failed (timeout "
				"waiting for other put requests to finish)\n",
				ss->ssName, ch->varName, dbch->dbName
			);
			return pvStatERROR;
		case epicsEventWaitError:
			/* try to recover */
			ss->putReq[varId] = NULL;
			epicsEventSignal(putSem);
			errlogSevPrintf(errlogFatal,
				"pvPut: epicsEventWaitWithTimeout() failure\n");
			return pvStatERROR;
		}
	}
	else if (compType == ASYNC)
	{
		switch (epicsEventTryWait(putSem))
		{
		case epicsEventWaitOK:
			if (ss->putReq[varId] != NULL)
			{
				/* previous request timed out but user
				   did not call pvPutComplete */
				ss->putReq[varId] = NULL;
			}
			break;
		case epicsEventWaitTimeout:
			meta->status = pvStatERROR;
			meta->severity = pvSevrMAJOR;
			meta->message = "already one put pending";
			status = meta->status;
			errlogSevPrintf(errlogMajor,
				"pvPut(ss %s, var %s, pv %s): user error "
				"(there is already a put pending for this variable/"
				"state set combination)\n",
				ss->ssName, ch->varName, dbch->dbName
			);
			return pvStatERROR;
		case epicsEventWaitError:
			/* try to recover */
			ss->putReq[varId] = NULL;
			epicsEventSignal(putSem);
			errlogSevPrintf(errlogFatal,
				"pvPut: epicsEventTryWait() failure\n");
			return pvStatERROR;
		}
	}

	/* Determine number of elements to put (don't try to put more
	   than db count) */
	count = dbch->dbCount;

	/* Perform the PV put operation (either non-blocking or with a
	   callback routine specified) */
	if (compType == DEFAULT)
	{
		status = pvVarPutNoBlock(
				dbch->pvid,		/* PV id */
				ch->type->putType,	/* data type */
				count,			/* element count */
				(pvValue *)var);	/* data value */
		if (status != pvStatOK)
		{
			errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutNoBlock() failure: %s\n",
				ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid));
			return status;
		}
	}
	else
	{
		/* Allocate and initialize a pv request */
		req = (PVREQ *)freeListMalloc(sp->pvReqPool);
		req->ss = ss;
		req->ch = ch;

		assert(ss->putReq[varId] == NULL);
		ss->putReq[varId] = req;

		status = pvVarPutCallback(
				dbch->pvid,		/* PV id */
				ch->type->putType,	/* data type */
				count,			/* element count */
				(pvValue *)var,		/* data value */
				seq_put_handler,	/* callback handler */
				req);			/* user arg */
		if (status != pvStatOK)
		{
			ss->putReq[varId] = NULL;
			errlogSevPrintf(errlogFatal, "pvPut(var %s, pv %s): pvVarPutCallback() failure: %s\n",
				ch->varName, dbch->dbName, pvVarGetMess(dbch->pvid));
			freeListFree(sp->pvReqPool, req);
			epicsEventSignal(putSem);
			check_connected(dbch, meta);
			return status;
		}
	}

	/* Synchronous: wait for completion (10s timeout) */
	if (compType == SYNC)
	{
		epicsEventWaitStatus event_status;

		pvSysFlush(sp->pvSys);
		event_status = epicsEventWaitWithTimeout(putSem, tmo);
		ss->putReq[varId] = NULL;
		epicsEventSignal(putSem);
		switch (event_status)
		{
		case epicsEventWaitOK:
			status = check_connected(dbch, meta);
			if (status) return status;
			break;
		case epicsEventWaitTimeout:
			meta->status = pvStatTIMEOUT;
			meta->severity = pvSevrMAJOR;
			meta->message = "put completion timeout";
			return meta->status;
			break;
		case epicsEventWaitError:
			meta->status = pvStatERROR;
			meta->severity = pvSevrMAJOR;
			meta->message = "put completion failure";
			return meta->status;
			break;
		}
	}

	return pvStatOK;
}
Пример #14
0
/*
 * Return channel alarm status.
 */
epicsShareFunc pvStat seq_pvStatus(SS_ID ss, CH_ID chId)
{
	CHAN	*ch = ss->prog->chan + chId;
	PVMETA	*meta = metaPtr(ch,ss);
	return ch->dbch ? meta->status : pvStatOK;
}
Пример #15
0
/*
 * Return channel error message.
 */
epicsShareFunc const char *epicsShareAPI seq_pvMessage(SS_ID ss, VAR_ID varId)
{
	CHAN	*ch = ss->sprog->chan + varId;
	PVMETA	*meta = metaPtr(ch,ss);
	return ch->dbch ? meta->message : "";
}
Пример #16
0
/*
 * Return channel alarm severity.
 */
epicsShareFunc pvSevr epicsShareAPI seq_pvSeverity(SS_ID ss, VAR_ID varId)
{
	CHAN	*ch = ss->sprog->chan + varId;
	PVMETA	*meta = metaPtr(ch,ss);
	return ch->dbch ? meta->severity : pvSevrOK;
}
Пример #17
0
/*
 * Return channel alarm status.
 */
epicsShareFunc pvStat epicsShareAPI seq_pvStatus(SS_ID ss, VAR_ID varId)
{
	CHAN	*ch = ss->sprog->chan + varId;
	PVMETA	*meta = metaPtr(ch,ss);
	return ch->dbch ? meta->status : pvStatOK;
}