Cleaned up ANSTO code to merge with sinqdev.sics
This is our new RELEASE-4_0 branch which was taken from ansto/93d9a7c Conflicts: .gitignore SICSmain.c asynnet.c confvirtualmot.c counter.c devexec.c drive.c event.h exebuf.c exeman.c histmem.c interface.h motor.c motorlist.c motorsec.c multicounter.c napi.c napi.h napi4.c network.c nwatch.c nxscript.c nxxml.c nxxml.h ofac.c reflist.c scan.c sicshipadaba.c sicsobj.c site_ansto/docs/Copyright.txt site_ansto/instrument/lyrebird/config/tasmad/sicscommon/nxsupport.tcl site_ansto/instrument/lyrebird/config/tasmad/taspub_sics/tasscript.tcl statusfile.c tasdrive.c tasub.c tasub.h tasublib.c tasublib.h
This commit is contained in:
279
task.c
279
task.c
@ -10,19 +10,32 @@
|
||||
|
||||
NO WARRANTIES OF ANY KIND WHATSOEVER TAKEN BY ME OR MY EMPLOYER.
|
||||
YOU ARE AT YOUR OWN!
|
||||
|
||||
Reworked to have a task name, stop by task name and better listing.
|
||||
|
||||
Mark Koennecke, December 2012
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include "fortify.h"
|
||||
#include "task.h"
|
||||
#define READY 1
|
||||
#define WAITING 2
|
||||
#define YIELDING 3
|
||||
|
||||
#define IDUNDEFINED 0L
|
||||
#define TASKMAGIC 777111999
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef struct __TaskHead {
|
||||
long magic;
|
||||
long lID;
|
||||
long groupID;
|
||||
int iStatus;
|
||||
long lWait;
|
||||
char *name;
|
||||
time_t start_time;
|
||||
TaskFunc pRun;
|
||||
SignalFunc pSignal;
|
||||
void *pData;
|
||||
@ -34,15 +47,19 @@ typedef struct __TaskHead {
|
||||
typedef struct __TaskMan {
|
||||
int iID;
|
||||
int iStop;
|
||||
pTaskHead pCurrent;
|
||||
pTaskHead pCurrent; /* Think trice before you interfere with this! */
|
||||
pTaskHead pHead;
|
||||
} TaskMan;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static long lIDMama = 0L;
|
||||
/*---------------------------------------------------------------------------
|
||||
The 7 below solves a subtle bug which occurs when a groupID in user code
|
||||
has been initialized to 0 and starting fails. Then it seems as if this
|
||||
group keeps running. As there will always be some task running at 0.
|
||||
----------------------------------------------------------------------------*/
|
||||
static long lIDMama = 7L;
|
||||
#define TASKERID 123399
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static pTaskHead MakeTaskHead(TaskFunc pTask, SignalFunc pSignal,
|
||||
static pTaskHead MakeTaskHead(char *name, TaskFunc pTask, SignalFunc pSignal,
|
||||
void *pData, TaskKillFunc pKill)
|
||||
{
|
||||
pTaskHead pNew = NULL;
|
||||
@ -53,12 +70,21 @@ static pTaskHead MakeTaskHead(TaskFunc pTask, SignalFunc pSignal,
|
||||
}
|
||||
memset(pNew, 0, sizeof(TaskHead));
|
||||
|
||||
pNew->magic = TASKMAGIC;
|
||||
pNew->name = strdup(name);
|
||||
pNew->start_time = time(NULL);
|
||||
pNew->pRun = pTask;
|
||||
pNew->pSignal = pSignal;
|
||||
pNew->pData = pData;
|
||||
pNew->pKill = pKill;
|
||||
pNew->lID = lIDMama++;
|
||||
lIDMama++;
|
||||
pNew->lID = lIDMama;
|
||||
pNew->iStatus = READY;
|
||||
pNew->groupID = IDUNDEFINED;
|
||||
|
||||
if(lIDMama < 0){
|
||||
lIDMama = 7;
|
||||
}
|
||||
|
||||
return pNew;
|
||||
}
|
||||
@ -73,6 +99,9 @@ static void DeleteTaskHead(pTaskHead self)
|
||||
self->pKill(self->pData);
|
||||
}
|
||||
}
|
||||
if(self->name != NULL){
|
||||
free(self->name);
|
||||
}
|
||||
/* unlink */
|
||||
if (self->pPrevious != NULL) {
|
||||
self->pPrevious->pNext = self->pNext;
|
||||
@ -80,6 +109,7 @@ static void DeleteTaskHead(pTaskHead self)
|
||||
if (self->pNext != NULL) {
|
||||
self->pNext->pPrevious = self->pPrevious;
|
||||
}
|
||||
memset(self,0,sizeof(TaskHead));
|
||||
free(self);
|
||||
}
|
||||
|
||||
@ -105,7 +135,7 @@ int TaskerInit(pTaskMan * self)
|
||||
pNew->iID = TASKERID;
|
||||
|
||||
/* create a dummy task as start point */
|
||||
pDummyTask = MakeTaskHead(DummyTask, NULL, NULL, NULL);
|
||||
pDummyTask = MakeTaskHead("init",DummyTask, NULL, NULL, NULL);
|
||||
if (!pDummyTask) {
|
||||
free(pNew);
|
||||
return 0;
|
||||
@ -140,9 +170,14 @@ int TaskerDelete(pTaskMan * pData)
|
||||
*pData = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------- temporary for backwards compatability -------------*/
|
||||
long TaskRegister(pTaskMan self,TaskFunc pTask, SignalFunc pSignal,
|
||||
TaskKillFunc pKill, void *pData, int iPriority)
|
||||
{
|
||||
return TaskRegisterN(self,"Unknown", pTask, pSignal, pKill, pData, iPriority);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
long TaskRegister(pTaskMan self, TaskFunc pTask, SignalFunc pSignal,
|
||||
long TaskRegisterN(pTaskMan self, char *name, TaskFunc pTask, SignalFunc pSignal,
|
||||
TaskKillFunc pKill, void *pData, int iPriority)
|
||||
{
|
||||
pTaskHead pNew = NULL;
|
||||
@ -151,7 +186,7 @@ long TaskRegister(pTaskMan self, TaskFunc pTask, SignalFunc pSignal,
|
||||
assert(self->iID == TASKERID);
|
||||
assert(pTask);
|
||||
|
||||
pNew = MakeTaskHead(pTask, pSignal, pData, pKill);
|
||||
pNew = MakeTaskHead(name, pTask, pSignal, pData, pKill);
|
||||
if (!pNew) {
|
||||
return -1;
|
||||
}
|
||||
@ -166,7 +201,6 @@ long TaskRegister(pTaskMan self, TaskFunc pTask, SignalFunc pSignal,
|
||||
|
||||
return pNew->lID;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void IncrTaskPointer(pTaskMan self)
|
||||
{
|
||||
@ -362,6 +396,10 @@ void TaskRemove(pTaskMan self, TaskFunc pTaskRun, void *pData)
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (pCurrent->pRun == pTaskRun && pCurrent->pData == pData) {
|
||||
if(pCurrent == self->pCurrent){
|
||||
/* cannot kill myself */
|
||||
return;
|
||||
}
|
||||
/* unlink */
|
||||
if (pCurrent->pPrevious != NULL) {
|
||||
pCurrent->pPrevious->pNext = pCurrent->pNext;
|
||||
@ -369,8 +407,229 @@ void TaskRemove(pTaskMan self, TaskFunc pTaskRun, void *pData)
|
||||
if (pCurrent->pNext != NULL) {
|
||||
pCurrent->pNext->pPrevious = pCurrent->pPrevious;
|
||||
}
|
||||
if(pCurrent->name != NULL){
|
||||
free(pCurrent->name);
|
||||
}
|
||||
free(pCurrent);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int StopTask(pTaskMan self, char *name)
|
||||
{
|
||||
int iRet;
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return 0;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (strcmp(pCurrent->name,name) == 0) {
|
||||
if(self->pCurrent == pCurrent){
|
||||
/**
|
||||
* cannot kill myself
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
/* unlink */
|
||||
if (pCurrent->pPrevious != NULL) {
|
||||
pCurrent->pPrevious->pNext = pCurrent->pNext;
|
||||
}
|
||||
if (pCurrent->pNext != NULL) {
|
||||
pCurrent->pNext->pPrevious = pCurrent->pPrevious;
|
||||
}
|
||||
if(pCurrent->name != NULL){
|
||||
free(pCurrent->name);
|
||||
}
|
||||
free(pCurrent);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int isTaskRunning(pTaskMan self, char *name)
|
||||
{
|
||||
int iRet;
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return 0;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (strcmp(pCurrent->name,name) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int isTaskIDRunning(pTaskMan self, long lID)
|
||||
{
|
||||
int iRet;
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return 0;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (pCurrent->lID == lID) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
pTaskHead TaskIteratorStart(pTaskMan self)
|
||||
{
|
||||
if (self == NULL) return NULL;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
return self->pHead->pNext; /* skip dummy task */
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
pTaskHead TaskIteratorNext(pTaskHead it)
|
||||
{
|
||||
if(it != NULL && it->magic == TASKMAGIC){
|
||||
return it->pNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
char *TaskDescription(pTaskHead it)
|
||||
{
|
||||
char *result;
|
||||
int length;
|
||||
const struct tm *tm;
|
||||
|
||||
if(it == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = strlen(it->name) + 120;
|
||||
result = malloc(length*sizeof(char));
|
||||
if(result == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(result,0,length*sizeof(char));
|
||||
strcpy(result,it->name);
|
||||
strcat(result,"|");
|
||||
|
||||
length = strlen(result);
|
||||
tm = localtime((const time_t *)&it->start_time);
|
||||
strftime(result+length,100,"%F-%k-%m-%S",tm);
|
||||
length = strlen(result);
|
||||
snprintf(result+length,120-20,"|%ld", it->lID);
|
||||
length = strlen(result);
|
||||
snprintf(result+length,120-40,"|%.0ld ", it->groupID);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
long GetTaskID(pTaskHead it)
|
||||
{
|
||||
return it->lID;
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
long GetGroupID(pTaskHead it)
|
||||
{
|
||||
return it->groupID;
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
const char * GetTaskName(pTaskHead it)
|
||||
{
|
||||
return (const char*)it->name;
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
const void *GetTaskData(pTaskHead it)
|
||||
{
|
||||
if(it->magic == TASKMAGIC){
|
||||
return (const void*)it->pData;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
long GetTaskGroupID(pTaskMan self)
|
||||
{
|
||||
lIDMama++;
|
||||
return lIDMama;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
void AddTaskToGroup(pTaskMan self, long taskID, long groupID)
|
||||
{
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (pCurrent->lID == taskID) {
|
||||
pCurrent->groupID = groupID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------------
|
||||
This simply checks if there are any more tasks with the desired groupID in the
|
||||
list. If none, then all sub tasks have finished.
|
||||
-----------------------------------------------------------------------------------*/
|
||||
int isTaskGroupRunning(pTaskMan self, long groupID)
|
||||
{
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return 0;
|
||||
if (groupID == IDUNDEFINED) return 0;
|
||||
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (pCurrent->groupID != IDUNDEFINED && pCurrent->groupID == groupID) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
int TaskGroupTask(void *data)
|
||||
{
|
||||
pTaskGroupData self = (pTaskGroupData)data;
|
||||
|
||||
return isTaskGroupRunning(self->tasker,self->groupID);
|
||||
}
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
int TaskSignalGroup(pTaskMan self, int iSignal, void *pSigData, long groupID)
|
||||
{
|
||||
pTaskHead pTemp, pEnd;
|
||||
|
||||
assert(self);
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
/* Do one cycle until we are at the caller, then return to him */
|
||||
pEnd = self->pCurrent;
|
||||
IncrTaskPointer(self);
|
||||
while (self->pCurrent != pEnd) {
|
||||
if (self->pCurrent->pSignal && self->pCurrent->groupID == groupID) {
|
||||
self->pCurrent->pSignal(self->pCurrent->pData, iSignal, pSigData);
|
||||
}
|
||||
IncrTaskPointer(self);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user