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

View File

@ -18,6 +18,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
DBENTRY entry; DBENTRY entry;
int ispyrec;
} pyRecord; } pyRecord;
static void pyRecord_dealloc(pyRecord *self) 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); self = (pyRecord*)type->tp_alloc(type, 0);
if(self) { if(self) {
dbInitEntry(pdbbase, &self->entry); dbInitEntry(pdbbase, &self->entry);
self->ispyrec = isPyRecord(self->entry.precnode->precord);
} }
return (PyObject*)self; return (PyObject*)self;
} }
@ -50,6 +52,11 @@ static int pyRecord_Init(pyRecord *self, PyObject *args, PyObject *kws)
return 0; return 0;
} }
static PyObject* pyRecord_ispyrec(pyRecord *self)
{
return PyBool_FromLong(self->ispyrec);
}
static int pyRecord_compare(pyRecord *A, pyRecord *B) static int pyRecord_compare(pyRecord *A, pyRecord *B)
{ {
dbCommon *a=A->entry.precnode->precord, 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; 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 *reason = Py_None;
PyObject *sync = Py_False; 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; return NULL;
if(!PyObject_IsTrue(sync)) { if(!PyObject_IsTrue(sync)) {
@ -136,20 +144,32 @@ static PyObject* pyRecord_scan(pyRecord *self, PyObject *args, PyObject *kws)
Py_RETURN_NONE; Py_RETURN_NONE;
} else { } else {
long ret; long ret=-1;
int ran=1;
setReasonPyRecord(prec, reason); setReasonPyRecord(prec, reason);
Py_BEGIN_ALLOW_THREADS { Py_BEGIN_ALLOW_THREADS {
dbScanLock(prec); 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); dbScanUnlock(prec);
} Py_END_ALLOW_THREADS } Py_END_ALLOW_THREADS
clearReasonPyRecord(prec); 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; return NULL;
} }
Py_INCREF(self); Py_INCREF(self); /* necessary? */
setReasonPyRecord(prec, reason); setReasonPyRecord(prec, reason);
@ -213,6 +233,8 @@ static PyObject *pyRecord_asyncFinish(pyRecord *self, PyObject *args, PyObject *
static PyMethodDef pyRecord_methods[] = { static PyMethodDef pyRecord_methods[] = {
{"name", (PyCFunction)pyRecord_name, METH_NOARGS, {"name", (PyCFunction)pyRecord_name, METH_NOARGS,
"Return record name string"}, "Return record name string"},
{"isPyRecord", (PyCFunction)pyRecord_ispyrec, METH_NOARGS,
"Is this record using Python Device."},
{"info", (PyCFunction)pyRecord_info, METH_VARARGS, {"info", (PyCFunction)pyRecord_info, METH_VARARGS,
"Lookup info name\ninfo(name, def=None)"}, "Lookup info name\ninfo(name, def=None)"},
{"infos", (PyCFunction)pyRecord_infos, METH_NOARGS, {"infos", (PyCFunction)pyRecord_infos, METH_NOARGS,

View File

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