DSPRelated.com
Forums

Why can't we use MEM_alloc in SWI?

Started by vuongtuyettien May 25, 2005
Hi all,

I mistakenly used MEM_alloc in a PRD function (which is considered
SWI). What happen was MEM_free later called in another TSK blocked the
caller forever. I used a semaphore to force the sequence alloc/free
and I am sure that MEM_alloc was always called before MEM_free, I also
debuged to see MEM_alloc returned successfuly and MEM_free had right
address pointer passed in. Eventually, I found from DSP/BIOS APIs
documentation that MEM_alloc can't be called from SWI. Then I did
experiment. I replaced the PRD function by a TSK and it ran. So I
suppose the error was MEM_alloc called from SWI.

But it's still confusing me because:
(1) I don't really understand why we can't use MEM_alloc in ISR. I
guess MEM_alloc must be a non-blocking function and it should be
callable from ISR. Could someone give me some insight about the way
MEM_alloc works so that it can't be called from ISR?

(2) If I have 1 PRD function and 1 TSK function do the same thing
describe above then system runs fine (I did a trial). Actually, above
problem I only met when I have 2 PRD functions and 2 TSKs each pair
run like the first case. Why?

I copy my code here:
///////////////part of exercise1.cdb////
object generateEventPrd :: PRD {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
param period :: 6000
param mode :: "continuous"
param function :: @_generateEventPrdFunc
param arg0 :: 0
param arg1 :: 0
param Order :: 1
param iPri :: 0
}

object generateFaultPrd :: PRD {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
param period :: 6000
param mode :: "continuous"
param function :: @_generateFaultPrdFunc
param arg0 :: 0
param arg1 :: 0
param Order :: 2
param iPri :: 0
}

object initTsk :: TSK {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
param iFXN :: @_initTskFunc
param iARG0 :: 0
param iARG1 :: 0
param iARG2 :: 0
param iARG3 :: 0
param iARG4 :: 0
param iARG5 :: 0
param iARG6 :: 0
param iARG7 :: 0
param iAUTOSTK :: 1
param iMANSTK :: @null
param iSTKSZ :: 1024
param iPRI :: 2
param iENV :: 0
param iEXITFLAG :: 1
param iUSETSKNAME :: 0
param Order :: 1
}

object evtGetTsk :: TSK {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
param iFXN :: @_evtGetTskFunc
param iARG0 :: 0
param iARG1 :: 0
param iARG2 :: 0
param iARG3 :: 0
param iARG4 :: 0
param iARG5 :: 0
param iARG6 :: 0
param iARG7 :: 0
param iAUTOSTK :: 1
param iMANSTK :: @null
param iSTKSZ :: 1024
param iPRI :: 1
param iENV :: 0
param iEXITFLAG :: 1
param iUSETSKNAME :: 0
param Order :: 3
}

object fltGetTsk :: TSK {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
param iFXN :: @_fltGetTskFunc
param iARG0 :: 0
param iARG1 :: 0
param iARG2 :: 0
param iARG3 :: 0
param iARG4 :: 0
param iARG5 :: 0
param iARG6 :: 0
param iARG7 :: 0
param iAUTOSTK :: 1
param iMANSTK :: @null
param iSTKSZ :: 1024
param iPRI :: 1
param iENV :: 0
param iEXITFLAG :: 1
param iUSETSKNAME :: 0
param Order :: 4
}

object evtQue :: QUE {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
}

object fltQue :: QUE {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
param iCount :: 0
}

object fltSem :: SEM {
param iComment :: "<add comments here>"
param iIsUsed :: 1
param iId :: 0
param iDelUser :: "USER"
param iDelMsg :: "ok"
param iCount :: 0
}
////////////////main.c//////////////////
#include <std.h>
#include "exercise1cfg.h"
#include <dsk6713.h>

typedef struct MsgObj {
QUE_Elem elem; /* first field for QUE */
Int val; /* message value */
} MsgObj, *MsgObjHandle;

Void main()
{
}

Void initTskFunc(Void)
{
QUE_new(&evtQue);
QUE_new(&fltQue);
}

Void generateEventPrdFunc(Arg arg0, Arg arg1)
{
MsgObjHandle msg;

msg = (MsgObjHandle) MEM_alloc(0, sizeof(MsgObj), 0);
if (msg == MEM_ILLEGAL)
SYS_abort("MEM_alloc failed\n");
msg->val = PRD_getticks();
QUE_put(&evtQue, msg);
SEM_ipost(&evtSem);
}

Void generateFaultPrdFunc(Arg arg0, Arg arg1)
{
MsgObjHandle msg;

msg = (MsgObjHandle) MEM_alloc(0, sizeof(MsgObj), 0);
if (msg == MEM_ILLEGAL)
SYS_abort("MEM_alloc failed\n");
msg->val = PRD_getticks();
QUE_put(&fltQue, msg);
SEM_post(&fltSem);
}

Void evtGetTskFunc(Void)
{
MsgObjHandle dataPtr;
while(1)
{
SEM_pend(&evtSem, SYS_FOREVER);
dataPtr = QUE_get(&evtQue);
if (!MEM_free(0, dataPtr, sizeof(MsgObj)))
SYS_abort("evtGetTsk MEM_free error\n");
LOG_printf(&LOG0,"evtGetTsk ever reachs here\n");
TSK_yield();
}
}

Void fltGetTskFunc(Void)
{
MsgObjHandle dataPtr;
while(1)
{
SEM_pend(&fltSem, SYS_FOREVER);
dataPtr = QUE_get(&fltQue);
if (!MEM_free(0, dataPtr, sizeof(MsgObj)))
SYS_abort("evtGetTsk MEM_free error\n");
LOG_printf(&LOG0,"fltGetTsk ever reachs here\n");
TSK_yield();
}
}
Only "evtGetTsk ever reachs here" printed out. fltGetTskFunc blocked
forever when calling MEM_free.

Thank you for your time