Implement task priorities and message queues

This commit is contained in:
Douglas Clowes
2015-07-29 17:47:46 +10:00
parent 0db57b9bae
commit eff54a5fd9
24 changed files with 1440 additions and 269 deletions
+286 -18
View File
@@ -2,7 +2,7 @@
* This is the SICS interface object to the tasker module
*
* copyright: GPL
*
*
* Mark Koennecke, December 2012
*/
#include <sics.h>
@@ -15,6 +15,37 @@ typedef struct {
char *scriptName;
SConnection *con;
} TclFunc, *pTclFunc;
/*-------------------------------------------------------------------------*/
void TaskObjLogFunc(eTaskLogLevel lvl, const char *buf)
{
OutCode eOut;
switch (lvl) {
case eTaskLogNone:
return;
case eTaskLogInfo:
eOut = eValue;
break;
case eTaskLogDebug:
eOut = eValue;
break;
case eTaskLogWarning:
eOut = eWarning;
break;
case eTaskLogError:
eOut = eError;
break;
case eTaskLogFatal:
eOut = eError;
break;
default:
eOut = eValue;
break;
}
SICSLogWrite(buf, eOut);
return;
}
/*-------------------------------------------------------------------------*/
static int ListCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
@@ -28,8 +59,8 @@ static int ListCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
SCWrite(pCon,"ERROR: out of memory in ListCmd", eError);
return 0;
}
snprintf(buffer,sizeof(buffer),"%20s %20s %12s",
"Task", "Start_Time", "ID");
snprintf(buffer,sizeof(buffer),"%20s %20s %12s",
"Task", "Start_Time", "ID");
DynStringConcat(result,buffer);
DynStringConcatChar(result,'\n');
for(it = TaskIteratorStart(pServ->pTasker); it != NULL; it = TaskIteratorNext(it)){
@@ -39,8 +70,8 @@ static int ListCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pPtr = stptok(pPtr,time,sizeof(time),"|");
pPtr = stptok(pPtr,id,sizeof(id),"|");
pPtr = stptok(pPtr,gid,sizeof(gid),"|");
snprintf(buffer,sizeof(buffer),"%20s %20s %12s %10s",
name,time,id,gid);
snprintf(buffer,sizeof(buffer),"%20s %20s %12s %10s",
name,time,id,gid);
DynStringConcat(result,buffer);
DynStringConcatChar(result,'\n');
free(pDes);
@@ -51,6 +82,103 @@ static int ListCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
return 1;
}
/*-------------------------------------------------------------------------*/
static int PerfCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pDynString result = NULL;
char buffer[256], *pDes, *pPtr, name[80];
char runs[80], waits[80], yields[80], cpu[80], wall[80], yield[80];
pTaskHead it = NULL;
result = CreateDynString(128,128);
if(result == NULL){
SCWrite(pCon,"ERROR: out of memory in PerfCmd", eError);
return 0;
}
snprintf(buffer,sizeof(buffer),"%18s %16s %16s %16s %16s %16s %16s",
"Task", "Runs", "Waits", "Yields", "Processor", "Elapsed", "Yield");
DynStringConcat(result,buffer);
DynStringConcatChar(result,'\n');
for(it = TaskIteratorStart(pServ->pTasker); it != NULL; it = TaskIteratorNext(it)){
pDes = TaskDetail(it);
if(pDes != NULL){
pPtr = stptok(pDes,name,sizeof(name),"|");
pPtr = stptok(pPtr,runs,sizeof(runs),"|");
pPtr = stptok(pPtr,waits,sizeof(waits),"|");
pPtr = stptok(pPtr,yields,sizeof(yields),"|");
pPtr = stptok(pPtr,cpu,sizeof(cpu),"|");
pPtr = stptok(pPtr,wall,sizeof(wall),"|");
pPtr = stptok(pPtr,yield,sizeof(yield),"|");
snprintf(buffer,sizeof(buffer),"%18s %16s %16s %16s %16s %16s %16s",
name,runs,waits,yields,cpu,wall,yield);
DynStringConcat(result,buffer);
DynStringConcatChar(result,'\n');
free(pDes);
}
}
SCWrite(pCon,GetCharArray(result),eValue);
DeleteDynString(result);
return 1;
}
/*----------------------------------------------------------------------*/
static int StackCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pDynString result = NULL;
char buffer[256], *pDes, *pPtr, name[80];
char runs[80], waits[80], yields[80], cpu[80], wall[80], yield[80];
pTaskHead it = NULL;
pTaskHead *stack = NULL;
int i, stackDepth;
result = CreateDynString(128,128);
if(result == NULL){
SCWrite(pCon,"ERROR: out of memory in StackCmd", eError);
return 0;
}
snprintf(buffer,sizeof(buffer),"%18s %16s %16s %16s %16s %16s %16s",
"Task", "Runs", "Waits", "Yields", "Processor", "Elapsed", "Yield");
DynStringConcat(result,buffer);
DynStringConcatChar(result,'\n');
stackDepth = TaskGetStack(pServ->pTasker, NULL);
if (stackDepth <= 0) {
SCWrite(pCon,"No task stack", eValue);
DeleteDynString(result);
return 0;
}
stack = calloc(stackDepth, sizeof(pTaskHead));
if (stack == NULL) {
SCWrite(pCon,"ERROR: out of memory in StackCmd", eError);
DeleteDynString(result);
return 0;
}
stackDepth = TaskGetStack(pServ->pTasker, stack);
for (i = 0; i < stackDepth; ++i) {
it = stack[i];
pDes = TaskDetail(it);
if(pDes != NULL){
pPtr = stptok(pDes,name,sizeof(name),"|");
pPtr = stptok(pPtr,runs,sizeof(runs),"|");
pPtr = stptok(pPtr,waits,sizeof(waits),"|");
pPtr = stptok(pPtr,yields,sizeof(yields),"|");
pPtr = stptok(pPtr,cpu,sizeof(cpu),"|");
pPtr = stptok(pPtr,wall,sizeof(wall),"|");
pPtr = stptok(pPtr,yield,sizeof(yield),"|");
snprintf(buffer,sizeof(buffer),"%18s %16s %16s %16s %16s %16s %16s",
name,runs,waits,yields,cpu,wall,yield);
DynStringConcat(result,buffer);
DynStringConcatChar(result,'\n');
free(pDes);
}
}
SCWrite(pCon,GetCharArray(result),eValue);
DeleteDynString(result);
free(stack);
return 1;
}
/*----------------------------------------------------------------------*/
static int KillCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
@@ -74,6 +202,126 @@ static int KillCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
SCSendOK(pCon);
return 1;
}
/*----------------------------------------------------------------------*/
static int InfoCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
char buffer[256];
char *pArgs = NULL, *pPtr;
char task_task[20], task_name[80], task_info[80];
pTaskHead it = NULL;
if (nPar < 1) {
SCWrite(pCon,"Info.args: NULL", eError);
return 0;
}
if (!SCMatchRights(pCon,usMugger)) {
return 0;
}
pArgs = par[0]->value.v.text;
pPtr = pArgs;
while (pPtr && *pPtr == '/') ++pPtr;
pPtr = stptok(pPtr, task_task, sizeof(task_task), "/");
if (strcasecmp(task_task, "task") != 0) {
SCPrintf(pCon, eError, "ERROR: task info must start with /task/, not %s in %s",
task_task, pArgs);
return 0;
}
while (pPtr && *pPtr == '/') ++pPtr;
pPtr = stptok(pPtr, task_name, sizeof(task_name), "/");
while (pPtr && *pPtr == '/') ++pPtr;
if (strcasecmp(task_name, "count") == 0) {
int count = 0;
for(it = TaskIteratorStart(pServ->pTasker); it != NULL; it = TaskIteratorNext(it)){
++count;
}
SCPrintf(pCon, eValue, "Task.Count = %d", count);
return 1;
} else if (strcasecmp(task_name, "list") == 0) {
int count = 0;
pDynString result = CreateDynString(100, 100);
char txt[80], *pDes;
for(it = TaskIteratorStart(pServ->pTasker); it != NULL; it = TaskIteratorNext(it)) {
pDes = TaskDescription(it);
if (pDes != NULL) {
char buffer[256], *pPtr, name[80], time[80], id[80], gid[80];
pPtr = stptok(pDes,name,sizeof(name),"|");
pPtr = stptok(pPtr,time,sizeof(time),"|");
pPtr = stptok(pPtr,id,sizeof(id),"|");
snprintf(buffer,sizeof(buffer),"%s", id);
if (count++ > 0)
DynStringConcatChar(result,' ');
DynStringConcat(result, buffer);
free(pDes);
}
}
SCWrite(pCon,GetCharArray(result), eValue);
DeleteDynString(result);
return 1;
} else if (strcasecmp(task_name, "current") == 0) {
it = TaskIteratorCurrent(pServ->pTasker);
} else if (strcasecmp(task_name, "by-id") == 0) {
pPtr = stptok(pPtr, task_name, sizeof(task_name), "/");
while (*pPtr == '/') ++pPtr;
it = TaskIteratorByID(pServ->pTasker, atol(task_name));
} else if (strcasecmp(task_name, "by-name") == 0) {
pPtr = stptok(pPtr, task_name, sizeof(task_name), "/");
while (*pPtr == '/') ++pPtr;
it = TaskIteratorByName(pServ->pTasker, task_name);
} else {
SCPrintf(pCon, eError, "ERROR: expected current, by-name or by-id in %s", pArgs);
return 0;
}
if (it == NULL) {
SCPrintf(pCon, eError, "ERROR: task not found in %s", pArgs);
return 0;
}
pPtr = stptok(pPtr, task_info, sizeof(task_info), "/");
if (strcasecmp(task_info, "all") == 0) {
char *pDet, *pDes;
pDes = TaskDescription(it);
pDet = TaskDetail(it);
SCPrintf(pCon, eValue, "%s %s", pDes, pDet);
free(pDes);
free(pDet);
} else {
SCPrintf(pCon, eLog, "Info.args: %s", par[0]->value.v.text);
}
return 1;
}
/*----------------------------------------------------------------------*/
static int LogCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
if (nPar < 1) {
SCWrite(pCon,"ERROR: need log level (none,debug,info,warning,error,fatal)", eError);
return 0;
}
if (!SCMatchRights(pCon,usMugger)) {
return 0;
}
if (strcasecmp("None", par[0]->value.v.text) == 0) {
TaskSetLogLevel(eTaskLogNone);
} else if (strcasecmp("Debug", par[0]->value.v.text) == 0) {
TaskSetLogLevel(eTaskLogDebug);
} else if (strcasecmp("Info", par[0]->value.v.text) == 0) {
TaskSetLogLevel(eTaskLogInfo);
} else if (strcasecmp("Warning", par[0]->value.v.text) == 0) {
TaskSetLogLevel(eTaskLogWarning);
} else if (strcasecmp("Error", par[0]->value.v.text) == 0) {
TaskSetLogLevel(eTaskLogError);
} else if (strcasecmp("Fatal", par[0]->value.v.text) == 0) {
TaskSetLogLevel(eTaskLogFatal);
}
TaskSetLogFunc((TaskLogFunc) TaskObjLogFunc);
SCSendOK(pCon);
return 1;
}
/*--------------------------------------------------------------------*/
static int TclTaskFunction(void *pData)
{
@@ -85,11 +333,11 @@ static int TclTaskFunction(void *pData)
pTcl = InterpGetTcl(pServ->pSics);
assert(pTcl != NULL);
MacroPush(self->con);
status = Tcl_Eval(pTcl, self->scriptName);
MacroPop();
/*
/*
traceSys("task","Executed %s with results %d and %s",self->scriptName, status,
Tcl_GetStringResult(pTcl));
*/
@@ -150,21 +398,21 @@ static int RunCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
data->scriptName = strdup(par[0]->value.v.text);
TaskRegisterN(pServ->pTasker,
data->scriptName,
TclTaskFunction,
TclFuncSignal,
KillTclFunc,
data, 0);
TclTaskFunction,
TclFuncSignal,
KillTclFunc,
data, TASK_PRIO_HIGH);
traceSys("task","Started task %s",data->scriptName);
SCSendOK(pCon);
return 1;
}
/*--------------------------------------------------------------------*/
int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pSICSOBJ pNew = NULL;
pHdb cmd = NULL, node;
pNew = SetupSICSOBJ(pCon,pSics,pData,argc,argv);
if(pNew == NULL){
return 0;
@@ -172,7 +420,9 @@ int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
cmd = AddSICSHdbPar(pNew->objectNode, "ps", usSpy,
MakeSICSFunc(ListCmd));
cmd = AddSICSHdbPar(pNew->objectNode, "perf", usSpy,
MakeSICSFunc(PerfCmd));
cmd = AddSICSHdbPar(pNew->objectNode, "kill", usSpy,
MakeSICSFunc(KillCmd));
SetHdbProperty(cmd,"type","command");
@@ -186,7 +436,7 @@ int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
SetHdbProperty(cmd,"priv","spy");
node = MakeSICSHdbPar("script",usSpy,MakeHdbText("banana"));
AddHipadabaChild(cmd,node,NULL);
return 1;
}
@@ -195,7 +445,7 @@ void InitTaskOBJ()
{
pSICSOBJ pNew = NULL;
pHdb cmd = NULL, node;
pNew = MakeSICSOBJv("task", "TaskOBJ", HIPNONE, usInternal);
if (pNew == NULL) {
@@ -205,7 +455,25 @@ void InitTaskOBJ()
cmd = AddSICSHdbPar(pNew->objectNode, "ps", usSpy,
MakeSICSFunc(ListCmd));
cmd = AddSICSHdbPar(pNew->objectNode, "perf", usSpy,
MakeSICSFunc(PerfCmd));
cmd = AddSICSHdbPar(pNew->objectNode, "stack", usSpy,
MakeSICSFunc(StackCmd));
cmd = AddSICSHdbPar(pNew->objectNode, "info", usSpy,
MakeSICSFunc(InfoCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","spy");
node = MakeSICSHdbPar("args",usSpy,MakeHdbText("banana"));
AddHipadabaChild(cmd,node,NULL);
cmd = AddSICSHdbPar(pNew->objectNode, "log", usSpy,
MakeSICSFunc(LogCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","spy");
node = MakeSICSHdbPar("level",usSpy,MakeHdbText("banana"));
AddHipadabaChild(cmd,node,NULL);
cmd = AddSICSHdbPar(pNew->objectNode, "kill", usSpy,
MakeSICSFunc(KillCmd));
SetHdbProperty(cmd,"type","command");
@@ -222,5 +490,5 @@ void InitTaskOBJ()
AddCommand(pServ->pSics,
"task", InterInvokeSICSOBJ, KillSICSOBJ, pNew);
}