use threadOnce; add lazy init

This commit is contained in:
Marty Kraimer
2000-03-07 14:51:05 +00:00
parent 4ed3956c92
commit 635df95acb
2 changed files with 107 additions and 128 deletions

View File

@@ -4,38 +4,24 @@
/*
* 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
* .02 05-04-94 mrk Allow user callback to call taskwdRemove
*/
*/
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1991 Regents of the University of California,
and the University of Chicago Board of Governors.
This software was developed under a United States Government license
described on the COPYRIGHT_Combined file included as part
of this distribution.
**********************************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#define epicsExportSharedSymbols
#include "dbDefs.h"
#include "osiThread.h"
@@ -48,14 +34,14 @@
typedef void (*MYFUNCPTR)();
struct task_list {
ELLNODE node;
MYFUNCPTR callback;
void *arg;
union {
threadId tid;
void *userpvt;
} id;
int suspended;
ELLNODE node;
MYFUNCPTR callback;
void *arg;
union {
threadId tid;
void *userpvt;
} id;
int suspended;
};
static ELLLIST list;
@@ -72,13 +58,13 @@ static struct freeList *freeHead=NULL;
/* Task delay times (seconds) */
#define TASKWD_DELAY 6.0
/*forward definitions*/
static void taskwdTask(void);
static struct task_list *allocList(void);
static void freeList(struct task_list *pt);
static void taskwdInitPvt(void *);
void taskwdInit()
static void taskwdInitPvt(void *arg)
{
lock = semMutexMustCreate();
anylock = semMutexMustCreate();
@@ -89,11 +75,18 @@ void taskwdInit()
"taskwd",threadPriorityLow,threadGetStackSize(threadStackSmall),
(THREADFUNC)taskwdTask,0);
}
void taskwdInit()
{
static threadOnceId taskwdOnceFlag = OSITHREAD_ONCE_INIT;
void *arg = 0;
threadOnce(&taskwdOnceFlag,taskwdInitPvt,arg);
}
void taskwdInsert(threadId tid,TASKWDFUNCPRR callback,void *arg)
{
struct task_list *pt;
taskwdInit();
semMutexMustTake(lock);
pt = allocList();
ellAdd(&list,(void *)pt);
@@ -103,11 +96,12 @@ void taskwdInsert(threadId tid,TASKWDFUNCPRR callback,void *arg)
pt->arg = arg;
semMutexGive(lock);
}
void taskwdAnyInsert(void *userpvt,TASKWDANYFUNCPRR callback,void *arg)
{
struct task_list *pt;
taskwdInit();
semMutexMustTake(anylock);
pt = allocList();
ellAdd(&anylist,(void *)pt);
@@ -121,16 +115,17 @@ void taskwdRemove(threadId tid)
{
struct task_list *pt;
taskwdInit();
semMutexMustTake(lock);
pt = (struct task_list *)ellFirst(&list);
while(pt!=NULL) {
if (tid == pt->id.tid) {
ellDelete(&list,(void *)pt);
freeList(pt);
semMutexGive(lock);
return;
}
pt = (struct task_list *)ellNext((ELLNODE *)pt);
if (tid == pt->id.tid) {
ellDelete(&list,(void *)pt);
freeList(pt);
semMutexGive(lock);
return;
}
pt = (struct task_list *)ellNext((ELLNODE *)pt);
}
semMutexGive(lock);
errMessage(-1,"taskwdRemove failed");
@@ -140,16 +135,17 @@ void taskwdAnyRemove(void *userpvt)
{
struct task_list *pt;
taskwdInit();
semMutexMustTake(anylock);
pt = (struct task_list *)ellFirst(&anylist);
while(pt!=NULL) {
if (userpvt == pt->id.userpvt) {
ellDelete(&anylist,(void *)pt);
freeList(pt);
semMutexGive(anylock);
return;
}
pt = (struct task_list *)ellNext((void *)pt);
if (userpvt == pt->id.userpvt) {
ellDelete(&anylist,(void *)pt);
freeList(pt);
semMutexGive(anylock);
return;
}
pt = (struct task_list *)ellNext((void *)pt);
}
semMutexGive(anylock);
errMessage(-1,"taskwdanyRemove failed");
@@ -160,46 +156,46 @@ static void taskwdTask(void)
struct task_list *pt,*next;
while(TRUE) {
if(taskwdOn) {
semMutexMustTake(lock);
pt = (struct task_list *)ellFirst(&list);
while(pt) {
next = (struct task_list *)ellNext((void *)pt);
if(threadIsSuspended(pt->id.tid)) {
char message[100];
if(taskwdOn) {
semMutexMustTake(lock);
pt = (struct task_list *)ellFirst(&list);
while(pt) {
next = (struct task_list *)ellNext((void *)pt);
if(threadIsSuspended(pt->id.tid)) {
char message[100];
if(!pt->suspended) {
struct task_list *ptany;
if(!pt->suspended) {
struct task_list *ptany;
pt->suspended = TRUE;
sprintf(message,"task %p suspended",pt->id.tid);
errMessage(-1,message);
ptany = (struct task_list *)ellFirst(&anylist);
while(ptany) {
if(ptany->callback) {
TASKWDANYFUNCPRR pcallback = pt->callback;
(pcallback)(ptany->arg,pt->id.tid);
}
ptany = (struct task_list *)ellNext((ELLNODE *)ptany);
}
if(pt->callback) {
TASKWDFUNCPRR pcallback = pt->callback;
void *arg = pt->arg;
pt->suspended = TRUE;
sprintf(message,"task %p suspended",pt->id.tid);
errMessage(-1,message);
ptany = (struct task_list *)ellFirst(&anylist);
while(ptany) {
if(ptany->callback) {
TASKWDANYFUNCPRR pcallback = pt->callback;
(pcallback)(ptany->arg,pt->id.tid);
}
ptany = (struct task_list *)ellNext((ELLNODE *)ptany);
}
if(pt->callback) {
TASKWDFUNCPRR pcallback = pt->callback;
void *arg = pt->arg;
/*Must allow callback to call taskwdRemove*/
semMutexGive(lock);
(pcallback)(arg);
/*skip rest because we have unlocked*/
break;
}
}
} else {
pt->suspended = FALSE;
}
pt = next;
}
semMutexGive(lock);
}
/*Must allow callback to call taskwdRemove*/
semMutexGive(lock);
(pcallback)(arg);
/*skip rest because we have unlocked*/
break;
}
}
} else {
pt->suspended = FALSE;
}
pt = next;
}
semMutexGive(lock);
}
threadSleep(TASKWD_DELAY);
}
}
@@ -210,12 +206,12 @@ static struct task_list *allocList(void)
semMutexMustTake(alloclock);
if(freeHead) {
pt = (struct task_list *)freeHead;
freeHead = freeHead->next;
pt = (struct task_list *)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);
errMessage(0,"taskwd failed on call to calloc\n");
exit(1);
}
semMutexGive(alloclock);
return(pt);

View File

@@ -5,32 +5,19 @@
/*
* 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 Initial version
*/
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1991 Regents of the University of California,
and the University of Chicago Board of Governors.
This software was developed under a United States Government license
described on the COPYRIGHT_Combined file included as part
of this distribution.
**********************************************************************/
#ifndef INCtaskwdh
#define INCtaskwdh 1
@@ -40,23 +27,19 @@
typedef void (*TASKWDFUNCPRR)(void *parm);
typedef void (*TASKWDANYFUNCPRR)(void *parm,threadId tid);
#if defined(__STDC__) || defined(__cplusplus)
#ifdef __cplusplus
extern "C" {
#endif
epicsShareFunc void taskwdInit(void);
epicsShareFunc void taskwdInsert(threadId tid, TASKWDFUNCPRR callback,void *arg);
epicsShareFunc void taskwdAnyInsert(void *userpvt, TASKWDANYFUNCPRR callback,void *arg);
epicsShareFunc void taskwdRemove(threadId tid);
epicsShareFunc void taskwdAnyRemove(void *userpvt);
#ifdef __cplusplus
}
#endif
#else
epicsShareFunc void taskwdInit();
epicsShareFunc void taskwdInsert();
epicsShareFunc void taskwdAnyInsert();
epicsShareFunc void taskwdRemove();
epicsShareFunc void taskwdAnyRemove();
#endif /*__STDC__*/
#endif /*INCtaskwdh*/