Void SystemCfg_notifyCB__P(UInt16 procId, UInt16 lineId, UInt32 eventNum,
        UArg arg, UInt32 payload)
{
    Error_Block eb;
    struct SystemCfg *stateObj = (struct SystemCfg *)arg;


    Log_print4(Diags_ENTRY,
        "--> %s: (prodId: %d, eventNum: %d, payload: 0x%x)",
        (IArg)FXNN, (IArg)procId, (IArg)eventNum, (IArg)payload);

    Error_init(&eb);

    switch (Global_EvtMask & payload) {

        case Global_EvtCreateDone:
        case Global_EvtReady:
        case Global_EvtCloseDone:
        case Global_EvtDone:

            SemThread_post(stateObj->semH, &eb);

            if (Error_check(&eb)) {
                /* Log_error() */
                Log_print3(
                    Diags_USER8,
                    "Error: %s, line %d: %s: SemThread_post() returned error",
                    (IArg)__FILE__, (IArg)__LINE__, (IArg)FXNN);
            }
            break;
    }

    Log_print1(Diags_EXIT, "<-- %s:", (IArg)FXNN);
}
/*
 *  ======== Hello_notifyCB ========
 */
static Void Hello_notifyCB(
    UInt16      procId,
    UInt16      lineId,
    UInt32      eventId,
    UArg        arg,
    UInt32      payload)
{
    UInt next;
    Error_Block eb;

    Error_init(&eb);

    /* ignore no-op events */
    if (payload == App_CMD_NOP) {
        return;
    }

    /* compute next slot in queue */
    next = (Module.head + 1) % QUEUESIZE;

    if (next == Module.tail) {
        /* queue is full, drop event and set error flag */
        Module.error = App_E_OVERFLOW;
        return;
    }
    else {
        Module.eventQue[Module.head] = payload;
        Module.head = next;
    }

    /* signal semaphore (counting) that new event is in queue */
    SemThread_post(Module.semH, &eb);
}
/*
 *  ======== doCmd ========
 */
static Int doCmd(Int cmdId, Processor_Handle proc)
{
    Int result;
    IArg key;

    Log_print2(Diags_ENTRY, "[+E] doCmd> Enter (cmdId=%d, proc=0x%x)",
            (IArg)cmdId, (IArg)proc);

    //pthread_mutex_lock(&dcmd.gate);
    key = GateThread_enter(dcmd.gate);

    dcmd.proc = proc;
    dcmd.cmdId = cmdId;
    //pthread_cond_signal(&dcmd.cmdPresent);
    SemThread_post(dcmd.cmdPresent, NULL);

    //while (dcmd.reply == NONE) {
    //    pthread_cond_wait(&dcmd.replyPresent, &dcmd.gate);
    //}
    SemThread_pend(dcmd.replyPresent, SemThread_FOREVER, NULL);

    result = dcmd.reply;
    dcmd.reply = NONE;

    //pthread_mutex_unlock(&dcmd.gate);
    GateThread_leave(dcmd.gate, key);

    Log_print1(Diags_EXIT, "[+X] doCmd> Exit (result=%d)", (IArg)result);

    return (result);
}
Beispiel #4
0
void
dvtb_audPlay(DvevmStThreadInfo *T)
{
	int aud_outBuffer_index = 0;
	int status = DVEVM_ST_SUCCESS;
	int nBytes;

	while (1)
	{
		SemThread_pend(sem_in, SemThread_FOREVER);
		if ((tskPlayState == EXITING) && (0 == availableInBuff))
			break;

		SemThread_pend(sem_block, SemThread_FOREVER);
		availableInBuff -= 1;
		SemThread_post(sem_block);

		if (T->useAlgorithm)
			nBytes = audioDesc[aud_outBuffer_index].aud_bufSize;
		else
			nBytes = AUD_FRAME_BUFF_SIZE;

#ifdef TEST_SEM
		status =  dvtb_fileWrite(T->targetFp, audioDesc[aud_outBuffer_index].aud_outBuffer, nBytes);
#else
//		status = dvtb_audioOut(&T->g.aud, audioDesc[aud_outBuffer_index].aud_outBuffer, nBytes);
#endif

		if (DVEVM_ST_FAIL == status)
		{
			SYS_ERROR("Audio play-back failed\n");
		}

		aud_outBuffer_index++;
		if (AUD_OUTBUF_COUNT <= aud_outBuffer_index)
			aud_outBuffer_index = 0;

		SemThread_post(sem_out);
	}
	tskPlayState = DELETED;
	dvtb_waitThread();
}
/*
 *  ======== putReply ========
 */
static Void putReply(Int status)
{
    //pthread_mutex_lock(&dcmd.gate);

    dcmd.reply = status;

    //pthread_cond_signal(&dcmd.replyPresent);
    SemThread_post(dcmd.replyPresent, NULL);

    //Log_print2(Diags_USER1, "putReply(0x%x): proc = 0x%lx",
    //        (IArg)status, (IArg)(dcmd.proc));

    //pthread_mutex_unlock(&dcmd.gate);
}
/*
 *  ======== rmanTask ========
 */
Void rmanTask(UArg arg0, UArg arg1)
{
    Int            taskId = (Int)arg0;
    Int            index = (Int)arg1;  /* index into attrsTable */
    IALG_Fxns    * algFxns = (IALG_Fxns *)&DUMALG_TI_IDUMALG;
    IRES_Fxns    * resFxns = &DUMALG_TI_IRES;
    IDUMALG_Handle dumHandle = NULL;
    IDUMALG_Params params;
    Int            scratchId = attrsTable[index].scratchId;
    Int            yieldFlag = attrsTable[index].yieldFlag;
    Int            priority = attrsTable[index].priority;
    Arg            resourceId = (Arg)(&(attrsTable[index].id));
    Int            i;
    IRES_Status    status;

    Log_print0(Diags_ENTRY, "[+E] rmanTask> Enter ");

    params.size = sizeof(IDUMALG_Params);

    Log_print4(Diags_USER4, "[+4] rmanTask> "
            "Task #%d: ScratchId %d, Priority %d Yield %d",
            (IArg)taskId, (IArg)scratchId, (IArg)priority, (IArg)yieldFlag);

    params.yieldFlag  = yieldFlag;
    params.taskId = taskId;

    for (i = 0; i < NUM_RESOURCES; i++) {
        params.hdvicp[i] = *((IRES_HDVICP_RequestType *)resourceId + i);
        Log_print1(Diags_USER4, "[+4] rmanTask> "
                "Requesting resource %d (2 => ANY)",
                (IArg)((Int)params.hdvicp[i]));
    }

    /*
     * Create an instance of the algorithm using "algFxns"
     */
    SemThread_pend(mutex, SemThread_FOREVER, NULL);
    dumHandle = (IDUMALG_Handle)DSKT2_createAlg((Int)scratchId,
            (IALG_Fxns *)algFxns, NULL,(IALG_Params *)&params);

    if (dumHandle == NULL) {
        Log_print0(Diags_USER7, "[+7] rmanTask> Alg creation failed");
        System_abort("DSKT2_createAlg() failed, aborting...\n");
    }

    SemThread_post(mutex, NULL);

    /* Assign resources to the algorithm */
    status = RMAN_assignResources((IALG_Handle)dumHandle, resFxns, scratchId);
    if (status != IRES_OK) {
        Log_print1(Diags_USER7, "[+7] rmanTask> Assign resource failed [%d]",
                (IArg)status);
        System_abort("RMAN_assignResources() failed, aborting...\n");
    }


    /* Activate the Algorithm */
    DSKT2_activateAlg(scratchId, (IALG_Handle)dumHandle);

    /* Activate All Resources */
    RMAN_activateAllResources((IALG_Handle)dumHandle, resFxns, scratchId);

    /* Use IALG interfaces to do something */
    dumHandle->fxns->useHDVICP(dumHandle, taskId);

    /* Deactivate All Resources */
    RMAN_deactivateAllResources((IALG_Handle)dumHandle, resFxns, scratchId);

    /* Deactivate algorithm */
    DSKT2_deactivateAlg(scratchId, (IALG_Handle)dumHandle);

    /* Free resources assigned to this algorihtm */
    status = RMAN_freeResources((IALG_Handle)(dumHandle), resFxns, scratchId);
    if (status != IRES_OK) {
        Log_print1(Diags_USER7, "[+7] rmanTask> Free resource failed [%d]",
                (IArg)status);
        System_abort("RMAN_freeResources() failed, aborting...\n");
    }

    /*
     * Free instance of the algorithm created
     */
    SemThread_pend(mutex, SemThread_FOREVER, NULL);
    DSKT2_freeAlg(scratchId, (IALG_Handle)dumHandle);
    SemThread_post(mutex, NULL);

    SemThread_post(done, NULL);

    Log_print0(Diags_EXIT, "[+X] rmanTask> Exit ");
}
Beispiel #7
0
/*
 *  ======== SyncSemThread_signal ========
 */
Void SyncSemThread_signal(SyncSemThread_Object *obj)
{
    SemThread_post(obj->semThread, NULL);
}
Beispiel #8
0
void
dvtb_AudDec1Play(DvevmStThreadInfo *T)
{
	int nBytes = DVEVM_ST_FAIL, nFrames = 0, frameSize = 0, totalBytesConsumed = 0, bytesRemaining = 0,
		buffsize = 1000000, thresh_hold = 900000, hugeChunk = 0, decDuration = 0, aud_outBuffer_index = 0,
		noOfOutChannels = 0, inFrameSize =0;
	char *buff = NULL, *inBuffer = NULL;
	unsigned int inputFileSize = 0;

	Thread_Handle thrHandle = NULL;
	Thread_Params thrParams;

	DvevmStRetCode status = DVEVM_ST_FAIL;
	DvevmStBool usecaseFailed = DVEVM_ST_FALSE, audioDeviceOpened =	DVEVM_ST_FALSE, fileBased = DVEVM_ST_TRUE;


	if (!T->sourceFp)
	{
		SYS_ERROR("Source file cannot be opened. It is a mandatory parameter\n");
		dvtb_fileClose(&T->sourceFp, &T->targetFp);
		dvtb_freeThread(T);
		dvtb_waitThread();
	}

	if (!T->targetFp)
	{
		SYS_ERROR("Target file cannot be opened. It is a mandatory parameter\n");
		dvtb_fileClose(&T->sourceFp, &T->targetFp);
		dvtb_freeThread(T);
		dvtb_waitThread();
	}

	if (DVEVM_ST_FAIL == dvtb_audDec1SemOpen(&sem_in, 0, &sem_out, AUD_OUTBUF_COUNT-2, &sem_block, 1))
	{
		SYS_ERROR("sem_open() FAILED\n");
		dvtb_fileClose(&T->sourceFp, &T->targetFp);
		dvtb_freeThread(T);
		dvtb_waitThread();

	}

//	dvtb_audDec1SemInit(sem_in, 0, sem_out, AUD_OUTBUF_COUNT-2, sem_block, 1);

	if (!T->targetFp)
		fileBased = DVEVM_ST_FALSE;

	dvtb_startMessage(DVEVM_ST_DECODE, "Audio", T->useAlgorithm, fileBased);
	dvtb_audDec1InitPtrs(&T->g.adec1);
	dvtb_audDec1InitPlayThreadBuffs(audioDesc, AUD_OUTBUF_COUNT);


	// [Decode][Play] scenario
	do
	{
		T->g.adec1.hTime = dvtb_timeCreate();
		if(NULL == T->g.adec1.hTime)
		{
			SYS_ERROR("Unable to Create Time handle. \n");
			usecaseFailed = DVEVM_ST_TRUE;
			break;
		}

		if (T->useAlgorithm)
		{
			if (DVEVM_ST_FAIL == dvtb_audDec1HanInit(&T->g.adec1, T->g.eng.name))
			{
				SYS_ERROR("Unable to initialize Audio decode handle \n");
				usecaseFailed = DVEVM_ST_TRUE;
				break;
			}
			SYS_OUT("Audio Decoder <%s> initialized\n", T->g.adec1.adecName);
		}

		if (DVEVM_ST_FALSE == fileBased)
		{
			if (!T->useAlgorithm)
			{
#if 0
				T->g.aud.mode = SND_PCM_STREAM_PLAYBACK;
				status = dvtb_audioSetup(&T->g.aud);
				if (DVEVM_ST_FAIL == status)
				{
					SYS_ERROR("Unable to setup Audio device <%s> for playback\n", T->g.aud.device);
					usecaseFailed = DVEVM_ST_TRUE;
					break;
				}

				audioDeviceOpened = DVEVM_ST_TRUE;
				SYS_OUT("Audio device <%s> initialized for playback\n", T->g.aud.device);
#endif
			}

			dvtb_audDec1InitThread(&thrParams);
		}

		hugeChunk = buffsize;
		//Get file Size
		if (DVEVM_ST_FAIL == dvtb_getFileSize(T->sourceFp, &inputFileSize))
		{
			SYS_ERROR("Unable to Get file size\n");
			usecaseFailed = DVEVM_ST_TRUE;
			break;
		}

		//If input file size is less than huge chunk than set hugeChunk to input file Size
		if ((int)inputFileSize < hugeChunk)
			hugeChunk = inputFileSize;

		if (DVEVM_ST_FAIL == dvtb_allocSingleBufCmem(&inBuffer, buffsize))
		{
			SYS_ERROR("Unable to allocate memory for In Buffer\n");
			usecaseFailed = DVEVM_ST_TRUE;
			break;
		}

		bytesRemaining = 0;
		if (DVEVM_ST_FAIL == dvtb_audDec1ReadInput(inBuffer, &totalBytesConsumed, &bytesRemaining, buffsize, T->sourceFp, &nBytes))
		{
			SYS_ERROR("Error in Read Input\n");
			usecaseFailed = DVEVM_ST_TRUE;
			break;
		}

		if (DVEVM_ST_FAIL == dvtb_audDec1AllocPlayThreadBuffs(audioDesc, T->g.adec1.outBuf.bufSizes[0], AUD_OUTBUF_COUNT))
		{
			SYS_ERROR("Unable to allocate Buffers for play thread \n");
			usecaseFailed = DVEVM_ST_TRUE;
			break;
		}

		aud_outBuffer_index = 0;
		T->g.adec1.outBuf.bufs[0] = audioDesc[aud_outBuffer_index].aud_outBuffer;
		if (T->useAlgorithm)
		{
			inFrameSize = T->g.adec1.inBuf.bufSizes[0];
		}
		else
			inFrameSize = AUD_FRAME_BUFF_SIZE;

		while (!feof(T->sourceFp) || bytesRemaining)
		{
			if (totalBytesConsumed > thresh_hold)
			{
				if (DVEVM_ST_FAIL == dvtb_audDec1ReadInput(inBuffer, &totalBytesConsumed, &bytesRemaining, buffsize, T->sourceFp, &nBytes))
				{
					SYS_ERROR("Error in Read Input\n");
					usecaseFailed = DVEVM_ST_TRUE;
					break;
				}

				hugeChunk = nBytes;
				if (nBytes == 0)
				{
					SYS_OUT("End of file reached. Exiting...\n");
					break;
				}
			}
			nFrames++;

			if (bytesRemaining < inFrameSize)
				nBytes = bytesRemaining;
			else
				nBytes = inFrameSize;

			buff = &inBuffer[totalBytesConsumed];
			T->g.adec1.inBuf.bufs[0] = buff;

			if (T->useAlgorithm)
			{
				T->g.adec1.inFrameSize = nBytes;
				if(DVEVM_ST_FAIL == dvtb_audDec1DecProcess(&T->g.adec1, &decDuration))
				{
					SYS_ERROR("Unable to decode frame # %d\n",	nFrames);
					if (DVEVM_ST_FALSE == fileBased)
					{
						tskPlayState = EXITING;
						SemThread_post(sem_in);
					}
					usecaseFailed = DVEVM_ST_TRUE;
					break;
				}

				frameSize = T->g.adec1.decFrameSize;
				totalBytesConsumed += frameSize;
				bytesRemaining = hugeChunk - totalBytesConsumed;

				buff = T->g.adec1.outBuf.bufs[0];

				nBytes = dvtb_audDec1getOutPutBytes(&T->g.adec1.adecStatus);
				audioDesc[aud_outBuffer_index].aud_bufSize = nBytes;

#if 0
				if (T->g.aud.sampleRate != T->g.adec1.adecStatus.sampleRate)
					T->g.aud.sampleRate = T->g.adec1.adecStatus.sampleRate;
#endif

				noOfOutChannels = (T->g.adec1.adecStatus.channelMode == 0) ? 1 : 2;


#ifdef PERF
				if(!T->g.adec1.pEnable)
				{
					SYS_PERF("Thread, %x, Frame#, %d, Decoded Frame Size(bytes), %d, DecTime(us), %d\n", (unsigned int) T, nFrames, nBytes, decDuration);
					SYS_DEBUG("Frame#, %d, Frame Size(bytes), %d, DecTime(us), %d\n", nFrames, frameSize, decDuration);
				}
#endif
			}
			else
			{
				memcpy(audioDesc[aud_outBuffer_index].aud_outBuffer, buff, nBytes);
				totalBytesConsumed += nBytes;
				bytesRemaining = hugeChunk - totalBytesConsumed;
			}
#ifndef TEST_SEM
			if (DVEVM_ST_TRUE == fileBased)
			{
				if(DVEVM_ST_FAIL ==  dvtb_fileWrite(T->targetFp, buff, nBytes))
				{
					SYS_ERROR("Error in writing to file.\n");
					usecaseFailed = DVEVM_ST_TRUE;
					break;
				}
			}
			else
#endif
			{
#if 0
				if (T->useAlgorithm && (noOfOutChannels != T->g.aud.numChannels))
				{
					SYS_ERROR("No of channels of audio driver is not set correctly \n");
					SYS_ERROR("Decoder: number of channels %d \n", noOfOutChannels);
					SYS_ERROR("Driver: number of channels %d \n", T->g.aud.numChannels);
					usecaseFailed = DVEVM_ST_TRUE;
					tskPlayState = EXITING;
					SemThread_post(sem_in);
					break;
				}
#endif
				SemThread_post(sem_in);

				SemThread_pend(sem_block, SemThread_FOREVER);
				availableInBuff += 1;
				SemThread_post(sem_block);

				status = DVEVM_ST_SUCCESS;
				//status = dvtb_audioOut(&T->g.aud, buff, nBytes);
				SemThread_pend(sem_out, SemThread_FOREVER);
			}

			aud_outBuffer_index++;

			if (AUD_OUTBUF_COUNT == aud_outBuffer_index)
				aud_outBuffer_index = 0;

			T->g.adec1.outBuf.bufs[0] = audioDesc[aud_outBuffer_index].aud_outBuffer;
			if (nFrames == (AUD_OUTBUF_COUNT-2))
			{
#ifndef TEST_SEM
				if ((DVEVM_ST_FALSE == fileBased))
#endif
				{
					if(T->useAlgorithm)
					{
#if 0
						T->g.aud.mode = SND_PCM_STREAM_PLAYBACK;
						T->g.aud.framesize = T->g.adec1.outBuf.bufSizes[0];
						status = dvtb_audioSetup(&T->g.aud);
						if (DVEVM_ST_FAIL == status)
						{
							SYS_ERROR("Unable to setup Audio device <%s> for playback\n", T->g.aud.device);
							usecaseFailed = DVEVM_ST_TRUE;
							break;
						}
						audioDeviceOpened = DVEVM_ST_TRUE;
						SYS_OUT("Audio device <%s> initialized for playback\n", T->g.aud.device);
#endif
					}

						tskPlayState = RUNNING;
		        		thrParams.arg = (IArg)T;
				        thrParams.name = "dvtb_audPlay";
				        thrParams.priority = Thread_Priority_HIGHEST;

				        if (DVEVM_ST_FAIL == dvtb_createThread((Thread_RunFxn) dvtb_audPlay, &thrParams, &thrHandle))
				        {
						SYS_ERROR("Unable to create a thread\n");
						usecaseFailed = DVEVM_ST_TRUE;
						break;
		        		}
				}
			}

		}

#ifdef TEST_SEM
		if (DVEVM_ST_FALSE == fileBased)
#endif
		{
			if (EXITING > tskPlayState)
			{
				tskPlayState = EXITING;
				SemThread_post(sem_in);
			}
			if(NULL != thrHandle)
			{
				while (DELETED != tskPlayState)
				{
					dvtb_sleepThread(1);
				}
				dvtb_deleteThread(&thrHandle);
			}

		}
	} while (DVEVM_ST_FALSE); // Dummy loop

	dvtb_audDec1ProcessEndMessage(T->useAlgorithm, fileBased, nFrames);

#if 0
	if (DVEVM_ST_TRUE == audioDeviceOpened)
	{
		dvtb_audioClose(&T->g.aud);
		SYS_OUT("Audio Device <%s> closed\n", T->g.aud.device);
	}
#endif

	if (NULL != inBuffer)
	{
		dvtb_freeSingleBufCmem(inBuffer, buffsize);
		inBuffer = NULL;
	}

	if (T->useAlgorithm)
		dvtb_audDec1HanClose(&T->g.adec1, T->g.eng.name);

	dvtb_audDec1FreePlayThreadBuffs(audioDesc, T->g.adec1.inBuf.bufSizes[0], AUD_OUTBUF_COUNT);

	dvtb_fileClose(&T->sourceFp, &T->targetFp);

	dvtb_audDec1SemClose(&sem_in, &sem_out, &sem_block);
	dvtb_timeDelete(T->g.adec1.hTime);
	dvtb_exitMessage(DVEVM_ST_DECODE, "Audio", T->useAlgorithm, fileBased, usecaseFailed);

	dvtb_freeThread(T);
	dvtb_waitThread();
}
Beispiel #9
0
Int RcmClient_getReturnMsg_P(RcmClient_Object *obj, const UInt16 msgId,
    RcmClient_Message **returnMsg)
{
    List_Elem *elem;
    Recipient *recipient;
    RcmClient_Packet *packet;
    Bool messageDelivered;
    MessageQ_Msg msgqMsg = NULL;
    Bool messageFound = FALSE;
    Int queueLockAcquired = 0;
    Error_Block eb;
    Int rval;
    Int status = RcmClient_S_SUCCESS;


    Log_print3(Diags_ENTRY,
        "--> "FXNN": (obj=0x%x, msgId=%d, returnMsgPtr=0x%x",
        (IArg)obj, (IArg)msgId, (IArg)returnMsg);

    Error_init(&eb);
    *returnMsg = NULL;

    /* keep trying until message found */
    while (!messageFound) {

        /* acquire the mailbox lock */
        Semaphore_pend(obj->mbxLock, Semaphore_FOREVER, &eb);
        if (Error_check(&eb)) {
            /* TODO */
            goto leave;
        }

        /* search new mail list for message */
        elem = NULL;
        while ((elem = List_next(obj->newMail, elem)) != NULL) {
            packet = getPacketAddrElem(elem);
            if (msgId == packet->msgId) {
                List_remove(obj->newMail, elem);
                *returnMsg = &packet->message;
                messageFound = TRUE;
                break;
            }
        }

        if (messageFound) {
            /* release the mailbox lock */
            Semaphore_post(obj->mbxLock, &eb);
            if (Error_check(&eb)) {
                /* TODO */
            }
        }
        else {
            /* attempt the message queue lock */
            queueLockAcquired = Semaphore_pend(obj->queueLock, 0, &eb);
            if (Error_check(&eb)) {
                /* TODO */
                goto leave;
            }

            if (1 == queueLockAcquired) {
                /*
                 * mailman role
                 */

                /* deliver new mail until message found */
                while (!messageFound) {

                    /* get message from queue if available (non-blocking) */
                    if (NULL == msgqMsg) {
                        rval = MessageQ_get(obj->msgQue, &msgqMsg, 0);

                        if ((MessageQ_E_TIMEOUT != rval) && (rval < 0)) {
                            Log_error0(FXNN": lost return message");
                            status = RcmClient_E_LOSTMSG;
                            goto leave;
                        }
                        Log_print0(Diags_INFO, FXNN": return message received");
                    }

                    while (NULL != msgqMsg) {

                        /* check if message found */
                        packet = getPacketAddrMsgqMsg(msgqMsg);
                        messageFound = (msgId == packet->msgId);

                        if (messageFound) {
                            *returnMsg = &packet->message;

                            /* search wait list for new mailman */
                            elem = NULL;
                            while ((elem =
                                List_next(obj->recipients, elem)) != NULL) {
                                recipient = (Recipient *)elem;
                                if (NULL == recipient->msg) {
                                    /* signal recipient's event */
                                    SemThread_post(SemThread_handle(
                                        &recipient->event), &eb);
                                    break;
                                }
                            }

                            /* release the message queue lock */
                            Semaphore_post(obj->queueLock, &eb);
                            if (Error_check(&eb)) {
                                /* TODO */
                            }

                            /* release the mailbox lock */
                            Semaphore_post(obj->mbxLock, &eb);
                            if (Error_check(&eb)) {
                                /* TODO */
                            }

                            break;
                        }
                        else {
                            /*
                             * deliver message to mailbox
                             */

                            /* search recipient list for message owner */
                            elem = NULL;
                            messageDelivered = FALSE;
                            while ((elem =
                                List_next(obj->recipients, elem)) != NULL) {
                                recipient = (Recipient *)elem;
                                if (recipient->msgId == packet->msgId) {
                                    recipient->msg = &packet->message;
                                    /* signal the recipient's event */
                                    SemThread_post(SemThread_handle(
                                        &recipient->event), &eb);
                                    messageDelivered = TRUE;
                                    break;
                                }
                            }

                            /* add undelivered message to new mail list */
                            if (!messageDelivered) {
                                /* use the elem in the MessageQ header */
                                elem = (List_Elem *)&packet->msgqHeader;
                                List_put(obj->newMail, elem);
                            }
                        }

                        /* get next message from queue if available */
                        rval = MessageQ_get(obj->msgQue, &msgqMsg, 0);

                        if ((MessageQ_E_TIMEOUT != rval) && (rval < 0)) {
                            Log_error0(FXNN": lost return message");
                            status = RcmClient_E_LOSTMSG;
                            goto leave;
                        }
                        Log_print0(Diags_INFO, FXNN": return message received");
                    }

                    if (!messageFound) {
                        /*
                         * message queue empty
                         */

                        /* release the mailbox lock */
                        Semaphore_post(obj->mbxLock, &eb);
                        if (Error_check(&eb)) {
                            /* TODO */
                        }

                        /* get next message, this blocks the thread */
                        rval = MessageQ_get(obj->msgQue, &msgqMsg,
                            MessageQ_FOREVER);

                        if (rval < 0) {
                            Log_error0(FXNN": lost return message");
                            status = RcmClient_E_LOSTMSG;
                            goto leave;
                        }
                        Log_print0(Diags_INFO, FXNN": return message received");

                        if (msgqMsg == NULL) {
                            Log_error0(FXNN": reply message has been lost");
                            status = RcmClient_E_LOSTMSG;
                            goto leave;
                        }

                        /* acquire the mailbox lock */
                        Semaphore_pend(obj->mbxLock, Semaphore_FOREVER, &eb);
                        if (Error_check(&eb)) {
                            goto leave;  /* TODO */
                        }
                    }
                }
            }
            else {
                /* construct recipient on local stack */
                Recipient self;
                self.msgId = msgId;
                self.msg = NULL;
                SemThread_construct(&self.event, 0, NULL, &eb);
                if (Error_check(&eb)) {
                    /* TODO */
                }

                /* add recipient to wait list */
                elem = &self.elem;
                List_put(obj->recipients, elem);

                /* release the mailbox lock */
                Semaphore_post(obj->mbxLock, &eb);
                if (Error_check(&eb)) {
                    /* TODO */
                }

                /* wait on event */
                SemThread_pend(SemThread_handle(&self.event),
                    Semaphore_FOREVER, &eb);
                if (Error_check(&eb)) {
                    /* TODO */
                }

                /* acquire the mailbox lock */
                Semaphore_pend(obj->mbxLock, Semaphore_FOREVER, &eb);
                if (Error_check(&eb)) {
                    goto leave;  /* TODO */
                }

                if (NULL != self.msg) {
                    /* pickup message */
                    *returnMsg = self.msg;
                    messageFound = TRUE;
                }

                /* remove recipient from wait list */
                List_remove(obj->recipients, elem);
                SemThread_destruct(&self.event);

                /* release the mailbox lock */
                Semaphore_post(obj->mbxLock, &eb);
                if (Error_check(&eb)) {
                    /* TODO */
                }
            }
        }
    } /* while (!messageFound) */

leave:
    Log_print2(Diags_EXIT, "<-- %s: %d", (IArg)FXNN, (IArg)status);
    return(status);
}