enable I/O Intr

This commit is contained in:
Michael Davidsaver
2013-03-30 18:25:35 -04:00
parent 4d0b0b1472
commit 9ba4acb696
3 changed files with 85 additions and 15 deletions

View File

@ -15,6 +15,7 @@
#include <recGbl.h>
#include <alarm.h>
#include <ellLib.h>
#include <dbScan.h>
#include <cantProceed.h>
#include "pydevsup.h"
@ -31,6 +32,9 @@ typedef struct {
PyObject *pyrecord;
PyObject *support;
int allowscan;
IOSCANPVT scan;
PyObject *reason;
} pyDevice;
@ -49,6 +53,7 @@ static long parse_link(dbCommon *prec, const char* src)
return -1;
if(!PyArg_ParseTuple(ret, "OO", &priv->pyrecord, &priv->support)) {
priv->pyrecord = priv->support = NULL; /* paranoia */
Py_DECREF(ret);
return -1;
}
@ -98,6 +103,20 @@ static long process_common(dbCommon *prec)
return 0;
}
static int allow_ioscan(pyDevice *priv)
{
PyObject *ret = PyObject_CallMethod(priv->support, "allowScan", "O", priv->pyrecord);
if(!ret || !PyObject_IsTrue(ret)) {
PyErr_Print();
PyErr_Clear();
Py_XDECREF(ret);
return 0;
} else {
Py_DECREF(ret);
return 1;
}
}
static long init_record(dbCommon *prec)
{
return 0;
@ -146,6 +165,7 @@ static long add_record(dbCommon *prec)
priv = callocMustSucceed(1, sizeof(*priv), "init_record");
priv->precord = prec;
priv->plink = ent.pfield;
scanIoInit(&priv->scan);
if(priv->plink->type != INST_IO) {
fprintf(stderr, "%s: Has invalid link type %d\n", prec->name, priv->plink->type);
@ -194,7 +214,7 @@ static long del_record(dbCommon *prec)
pyDevice *priv=prec->dpvt;
PyGILState_STATE pystate;
if(!priv)
if(!priv || !priv->support)
return 0;
pystate = PyGILState_Ensure();
@ -212,6 +232,22 @@ static long del_record(dbCommon *prec)
return 0;
}
static long get_iointr_info(int dir, dbCommon *prec, IOSCANPVT *scan)
{
pyDevice *priv=prec->dpvt;
if(!priv || !priv->support)
return 0;
if(dir==0) {
if(!allow_ioscan(priv))
return S_db_Blocked;
priv->allowscan = 1;
} else
priv->allowscan = 0;
*scan = priv->scan;
return 0;
}
static long process_record(dbCommon *prec)
{
pyDevice *priv = prec->dpvt;
@ -273,14 +309,28 @@ typedef struct {
DEVSUPFUN proc;
} dset5;
static dset5 pydevsupCom = {{5, NULL, (DEVSUPFUN)&init, (DEVSUPFUN)&init_record, NULL}, (DEVSUPFUN)&process_record};
static dset5 pydevsupCom2 = {{5, NULL, (DEVSUPFUN)&init, (DEVSUPFUN)&init_record2, NULL}, (DEVSUPFUN)&process_record};
static dset5 pydevsupCom = {{5, NULL, (DEVSUPFUN)&init,
(DEVSUPFUN)&init_record,
(DEVSUPFUN)&get_iointr_info},
(DEVSUPFUN)&process_record};
static dset5 pydevsupCom2 = {{5, NULL, (DEVSUPFUN)&init,
(DEVSUPFUN)&init_record2,
(DEVSUPFUN)&get_iointr_info},
(DEVSUPFUN)&process_record};
int isPyRecord(dbCommon *prec)
{
return prec->dset==(dset*)&pydevsupCom || prec->dset==(dset*)&pydevsupCom2;
}
int canIOScanRecord(dbCommon *prec)
{
pyDevice *priv=prec->dpvt;
if(isPyRecord(prec))
return 0;
return priv->allowscan;
}
/* Called with GIL locked */
void pyDBD_cleanup(void)
{
@ -300,12 +350,9 @@ void pyDBD_cleanup(void)
/* cleanup and dealloc */
if(priv->support)
Py_DECREF(priv->support);
if(priv->pyrecord)
Py_DECREF(priv->pyrecord);
if(priv->reason)
Py_DECREF(priv->reason);
Py_XDECREF(priv->support);
Py_XDECREF(priv->pyrecord);
Py_XDECREF(priv->reason);
priv->support = priv->pyrecord = priv->reason = NULL;
free(priv);

View File

@ -18,6 +18,7 @@ typedef struct {
PyObject_HEAD
DBENTRY entry;
int ispyrec;
} pyRecord;
static void pyRecord_dealloc(pyRecord *self)
@ -33,6 +34,7 @@ static PyObject* pyRecord_new(PyTypeObject *type, PyObject *args, PyObject *kws)
self = (pyRecord*)type->tp_alloc(type, 0);
if(self) {
dbInitEntry(pdbbase, &self->entry);
self->ispyrec = isPyRecord(self->entry.precnode->precord);
}
return (PyObject*)self;
}
@ -50,6 +52,11 @@ static int pyRecord_Init(pyRecord *self, PyObject *args, PyObject *kws)
return 0;
}
static PyObject* pyRecord_ispyrec(pyRecord *self)
{
return PyBool_FromLong(self->ispyrec);
}
static int pyRecord_compare(pyRecord *A, pyRecord *B)
{
dbCommon *a=A->entry.precnode->precord,
@ -124,11 +131,12 @@ static PyObject* pyRecord_scan(pyRecord *self, PyObject *args, PyObject *kws)
{
dbCommon *prec = self->entry.precnode->precord;
static char* names[] = {"sync", "reason", NULL};
static char* names[] = {"sync", "reason", "force", NULL};
unsigned int force = 0;
PyObject *reason = Py_None;
PyObject *sync = Py_False;
if(!PyArg_ParseTupleAndKeywords(args, kws, "|OO", names, &sync, &reason))
if(!PyArg_ParseTupleAndKeywords(args, kws, "|OOI", names, &sync, &reason, &force))
return NULL;
if(!PyObject_IsTrue(sync)) {
@ -136,20 +144,32 @@ static PyObject* pyRecord_scan(pyRecord *self, PyObject *args, PyObject *kws)
Py_RETURN_NONE;
} else {
long ret;
long ret=-1;
int ran=1;
setReasonPyRecord(prec, reason);
Py_BEGIN_ALLOW_THREADS {
dbScanLock(prec);
ret = dbProcess(prec);
if(force==1
|| (force==0 && prec->scan==menuScanPassive)
|| (force==2 && prec->scan==menuScanI_O_Intr && canIOScanRecord(prec)))
{
ran = 1;
ret = dbProcess(prec);
}
dbScanUnlock(prec);
} Py_END_ALLOW_THREADS
clearReasonPyRecord(prec);
return PyLong_FromLong(ret);
if(ran)
return PyLong_FromLong(ret);
else {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
}
}
@ -181,7 +201,7 @@ static PyObject *pyRecord_asyncFinish(pyRecord *self, PyObject *args, PyObject *
return NULL;
}
Py_INCREF(self);
Py_INCREF(self); /* necessary? */
setReasonPyRecord(prec, reason);
@ -213,6 +233,8 @@ static PyObject *pyRecord_asyncFinish(pyRecord *self, PyObject *args, PyObject *
static PyMethodDef pyRecord_methods[] = {
{"name", (PyCFunction)pyRecord_name, METH_NOARGS,
"Return record name string"},
{"isPyRecord", (PyCFunction)pyRecord_ispyrec, METH_NOARGS,
"Is this record using Python Device."},
{"info", (PyCFunction)pyRecord_info, METH_VARARGS,
"Lookup info name\ninfo(name, def=None)"},
{"infos", (PyCFunction)pyRecord_infos, METH_NOARGS,

View File

@ -11,6 +11,7 @@ int pyRecord_prepare(void);
void pyRecord_setup(PyObject *module);
int isPyRecord(dbCommon *);
int canIOScanRecord(dbCommon *);
int setReasonPyRecord(dbCommon *, PyObject *);
int clearReasonPyRecord(dbCommon *);