Initial revision
This commit is contained in:
145
src/db/callback.c
Normal file
145
src/db/callback.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/* callback.c */
|
||||
/* share/src/db $Id$ */
|
||||
|
||||
/* general purpose callback tasks */
|
||||
/*
|
||||
* Original Author: Marty Kraimer
|
||||
* Date: 07-18-91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 12-12-91 mrk moved from dbScan.c to callback.c
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <types.h>
|
||||
#include <semLib.h>
|
||||
#include <lstLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <callback.h>
|
||||
#include <taskwd.h>
|
||||
#include <task_params.h>
|
||||
|
||||
static SEM_ID callbackSem[NUM_CALLBACK_PRIORITIES];
|
||||
static int callbackTaskId[NUM_CALLBACK_PRIORITIES];
|
||||
volatile int callbackRestart=FALSE;
|
||||
static volatile CALLBACK *head[NUM_CALLBACK_PRIORITIES];
|
||||
static volatile CALLBACK *tail[NUM_CALLBACK_PRIORITIES];
|
||||
|
||||
/* forward references */
|
||||
void wdCallback(); /*callback from taskwd*/
|
||||
void start(); /*start or restart a callbackTask*/
|
||||
|
||||
/*public routines */
|
||||
long callbackInit()
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
|
||||
start(i);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Routine which places requests into callback queue*/
|
||||
/* This routine can be called from interrupt routine*/
|
||||
long callbackRequest(struct callback *pcallback)
|
||||
{
|
||||
int priority = pcallback->priority;
|
||||
int lockKey;
|
||||
|
||||
if(priority<0 || priority>(NUM_CALLBACK_PRIORITIES)) {
|
||||
logMsg("callbackRequest called with invalid priority");
|
||||
return(-1);
|
||||
}
|
||||
lockKey = intLock();
|
||||
pcallback->next = NULL;
|
||||
tail[priority]->next = pcallback;
|
||||
if(head[priority]==NULL) head[priority] = pcallback;
|
||||
intUnlock(lockKey);
|
||||
if(semGive(callbackSem[priority])!=OK)
|
||||
logMsg("semGive returned error in callbackRequest\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* General purpose callback task */
|
||||
static void callbackTask(int priority)
|
||||
{
|
||||
volatile CALLBACK *pcallback,*next;
|
||||
int lockKey;
|
||||
|
||||
while(TRUE) {
|
||||
/* wait for somebody to wake us up */
|
||||
if(semTake(callbackSem[priority],WAIT_FOREVER)!=OK )
|
||||
logMsg("semTake returned error in callbackRequest\n");
|
||||
|
||||
while(TRUE) {
|
||||
lockKey = intLock();
|
||||
if((pcallback=head[priority])==NULL) break;
|
||||
if((head[priority]=pcallback->next)==NULL) tail[priority]=NULL;
|
||||
intUnlock(lockKey);
|
||||
(*pcallback->callback)(pcallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void start(int ind)
|
||||
{
|
||||
char name[100];
|
||||
int priority;
|
||||
|
||||
head[ind] = tail[ind] = 0;
|
||||
if((callbackSem[ind] = semBCreate(SEM_Q_FIFO,SEM_EMPTY))==NULL)
|
||||
logMsg("semBcreate failed while starting a callback task\n");
|
||||
sprintf(name,"%s%2.2d",CALLBACK_NAME,ind);
|
||||
if(ind==0) priority = CALLBACK_PRI_LOW;
|
||||
else if(ind==1) priority = CALLBACK_PRI_MEDIUM;
|
||||
else if(ind==2) priority = CALLBACK_PRI_HIGH;
|
||||
else {
|
||||
logMsg("semBcreate failed while starting a callback task\n");
|
||||
return;
|
||||
}
|
||||
callbackTaskId[ind] = taskSpawn(name,priority,
|
||||
CALLBACK_OPT,CALLBACK_STACK,
|
||||
(FUNCPTR)callbackTask,ind);
|
||||
if(callbackTaskId[ind]==ERROR) {
|
||||
errMessage(0,"Failed to spawn a callback task");
|
||||
return;
|
||||
}
|
||||
taskwdInsert(callbackTaskId[ind],wdCallback,(void *)(long)ind);
|
||||
}
|
||||
|
||||
|
||||
static void wdCallback(long ind)
|
||||
{
|
||||
taskwdRemove(callbackTaskId[ind]);
|
||||
if(!callbackRestart)return;
|
||||
if(taskDelete(callbackTaskId[ind])!=OK)
|
||||
logMsg("taskDelete failed while restarting a callback task\n");
|
||||
if(semFlush(callbackSem[ind])!=OK)
|
||||
logMsg("semFlush failed while restarting a callback task\n");
|
||||
start(ind);
|
||||
}
|
||||
175
src/db/taskwd.c
Normal file
175
src/db/taskwd.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/* taskwd.c */
|
||||
/* share/src/db $Id$ */
|
||||
|
||||
/* tasks and subroutines for a general purpose task watchdog */
|
||||
/*
|
||||
* Original Author: Marty Kraimer
|
||||
* Date: 07-18-91
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* .01 07-24-91 mrk Replacement for special purpose scan watchdog
|
||||
*/
|
||||
|
||||
|
||||
/* Public routines
|
||||
* taskwdInit() Initialize task watchdor
|
||||
*
|
||||
* taskwdInsert(tid,callback,arg) Insert in lists of tasks to watch
|
||||
* int tid Task Id
|
||||
* VOIDFUNCPTR callback Address of callback routine
|
||||
* void *arg Argument to pass to callback
|
||||
*
|
||||
* taskwdRemove(tid) Remove from list of tasks to watch
|
||||
*
|
||||
* int tid Task Id
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <stdlib.h>
|
||||
#include <types.h>
|
||||
#include <lstLib.h>
|
||||
#include <taskLib.h>
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <taskwd.h>
|
||||
#include <task_params.h>
|
||||
#include <fast_lock.h>
|
||||
|
||||
struct task_list {
|
||||
NODE node;
|
||||
VOIDFUNCPTR callback;
|
||||
void *arg;
|
||||
int tid;
|
||||
int suspended;
|
||||
};
|
||||
|
||||
static LIST list;
|
||||
static FAST_LOCK lock;
|
||||
static int taskwdid=0;
|
||||
volatile int taskwdOn=TRUE;
|
||||
struct freeList{
|
||||
struct freeList *next;
|
||||
};
|
||||
static struct freeList *freeHead=NULL;
|
||||
|
||||
/*forward definitions*/
|
||||
void taskwdTask();
|
||||
struct task_list *allocList();
|
||||
void freeList(struct task_list *);
|
||||
|
||||
void taskwdInit()
|
||||
{
|
||||
FASTLOCKINIT(&lock);
|
||||
lstInit(&list);
|
||||
taskwdid = taskSpawn(TASKWD_NAME,TASKWD_PRI,
|
||||
TASKWD_OPT,TASKWD_STACK,(FUNCPTR )taskwdTask);
|
||||
}
|
||||
|
||||
void taskwdInsert(int tid,VOIDFUNCPTR callback,void *arg)
|
||||
{
|
||||
struct task_list *pt;
|
||||
|
||||
FASTLOCK(&lock);
|
||||
pt = allocList();
|
||||
lstAdd(&list,(void *)pt);
|
||||
pt->suspended = FALSE;
|
||||
pt->tid = tid;
|
||||
pt->callback = callback;
|
||||
pt->arg = arg;
|
||||
FASTUNLOCK(&lock);
|
||||
}
|
||||
|
||||
void taskwdRemove(int tid)
|
||||
{
|
||||
int i;
|
||||
struct task_list *pt;
|
||||
|
||||
FASTLOCK(&lock);
|
||||
(void *)pt = lstFirst(&list);
|
||||
while(pt!=NULL) {
|
||||
if (tid == pt->tid) {
|
||||
lstDelete(&list,(void *)pt);
|
||||
freeList(pt);
|
||||
FASTUNLOCK(&lock);
|
||||
return;
|
||||
}
|
||||
(void *)pt = lstNext((void *)pt);
|
||||
}
|
||||
FASTUNLOCK(&lock);
|
||||
errMessage(-1,"taskwdRemove failed");
|
||||
}
|
||||
|
||||
static void taskwdTask()
|
||||
{
|
||||
struct task_list *pt,*next;
|
||||
|
||||
while(TRUE) {
|
||||
if(taskwdOn) {
|
||||
FASTLOCK(&lock);
|
||||
(void *)pt = lstFirst(&list);
|
||||
while(pt!=NULL) {
|
||||
(void *)next = lstNext((void *)pt);
|
||||
if(taskIsSuspended(pt->tid)) {
|
||||
char *pname;
|
||||
char message[100];
|
||||
|
||||
pname = taskName(pt->tid);
|
||||
if(!pt->suspended) {
|
||||
sprintf(message,"task %d %s suspended",pt->tid,pname);
|
||||
errMessage(-1,message);
|
||||
if(pt->callback) (pt->callback)(pt->arg);
|
||||
}
|
||||
pt->suspended = TRUE;
|
||||
}
|
||||
pt = next;
|
||||
}
|
||||
FASTUNLOCK(&lock);
|
||||
}
|
||||
taskDelay(TASKWD_DELAY*vxTicksPerSecond);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct task_list *allocList()
|
||||
{
|
||||
struct task_list *pt;
|
||||
|
||||
if(freeHead) {
|
||||
(void *)pt = (void *)freeHead;
|
||||
freeHead = freeHead->next;
|
||||
} else pt = calloc(1,sizeof(struct task_list *));
|
||||
if(pt==NULL) {
|
||||
errMessage(0,"taskwd failed on call to calloc\n");
|
||||
exit(1);
|
||||
}
|
||||
return(pt);
|
||||
}
|
||||
|
||||
void freeList(struct task_list *pt)
|
||||
{
|
||||
|
||||
((struct freeList *)pt)->next = freeHead;
|
||||
freeHead = (struct freeList *)pt;
|
||||
}
|
||||
Reference in New Issue
Block a user