
#include "vxWorks.h"
#include "semLib.h"
#include "taskLib.h"
#include "msgQLib.h"
#include "wdLib.h"
#include "logLib.h"
#include "tickLib.h"
#include "sysLib.h"
#include "stdio.h"
#include "sched.h"


/* defines */

#define	HIGH_PRI	10		/* priority of high priority task */
#define	MID_PRI		100		/* priority of high priority task */
#define LOW_PRI		200		/* priority of low priority task */

/* globals */

SEM_ID		semAId;			/* semaphore ID */
SEM_ID		semBId;			/* semaphore ID */
int		highPriId;		/* task ID of high priority task */
int		midPriId;		/* task ID of high priority task */
int		lowPriId;		/* task ID of low priority task */
int		inversionDemoId;		/* task ID of windDemo task */


/* function declarations */

LOCAL void taskHighPri (int iteration);
LOCAL void taskMidPri (int iteration);
LOCAL void taskLowPri (int iteration);

/*******************************************************************************
*
* inversionDemo - parent task to spawn children 
*
*/

void inversionDemo 
(
    int iteration			/* number of iterations of child code */
)
{
    printf ("Entering inversionDemo\n");

    if (iteration == 0)			/* set default to 10,000 */
	iteration = 10000;

    /* create objects used by the child tasks */

    semAId	= semBCreate (SEM_Q_PRIORITY, SEM_FULL);
    semBId	= semBCreate (SEM_Q_PRIORITY, SEM_FULL);

    inversionDemoId = taskIdSelf ();

    /* spawn child tasks to exercise kernel routines */

    lowPriId = taskSpawn ("tLowPri", LOW_PRI, VX_SUPERVISOR_MODE, 4000, 
			   (FUNCPTR) taskLowPri, iteration,0,0,0,0,0,0,0,0,0);

    taskDelay(1);

    highPriId = taskSpawn ("tHighPri", HIGH_PRI, VX_SUPERVISOR_MODE, 4000, 
			   (FUNCPTR) taskHighPri, iteration,0,0,0,0,0,0,0,0,0);

    /* taskDelay(1); */

    midPriId = taskSpawn ("tMidPri", MID_PRI, VX_SUPERVISOR_MODE, 4000, 
			   (FUNCPTR) taskMidPri, iteration,0,0,0,0,0,0,0,0,0);

    printf ("\nParent inversionDemo terminated.\n");

}

/*******************************************************************************
*
* taskHighPri - high priority task
*
* This tasks uses resource B and then A. It will block if the
* resource is not available and relingish the CPU to the next ready task.
*
*/

LOCAL void taskHighPri 
(
    int iteration			/* number of iterations through loop */
)
{
    int    ix, iy;				/* loop counter */

    semTake (semBId, WAIT_FOREVER);
    printf("High priority task is using resource B.\n");

    for (ix = 0; ix < iteration/2; ix++)
    {
       /* printf("High Priority task is doing initial loop:%d\n", ix); */
       for(iy=0; iy<ix; iy++){
           ix = ix + 3000; ix = ix +7000; ix = ix - 10000;
       }
       if (!ix%5)
          taskDelay(NO_WAIT); 
    }

	/* take and give a semaphore - no context switch involved */
    printf("High priority task is taking resource A.\n");

    semTake (semAId, WAIT_FOREVER);		/* semTake with timeout */

    semGive(semBId);
    printf("High priority task has released resource B.\n");
    semGive(semAId);
    printf("High priority task has released resource A.\n");

/*    wdStart (wdId, DELAY, (FUNCPTR) tickGet, 1); 

    wdCancel (wdId); */
}


/*******************************************************************************
*
* taskMidPri - mid priority task
*
* This task runs at a mid priority and is designed to execute a very long
* operation and starve both high and low priority tasks
*
*/

LOCAL void taskMidPri 
(
  int iteration			/* number of times through loop */
)
{
    int    ix, iy;				/* loop counter */

    for (ix = 0; ix < iteration; ix++)
    {
	    /* printf("Mid Priority task is in loop %d\n", ix); */
       for(iy=0; iy<ix; iy++){
           ix = ix + 3000; ix = ix +7000; ix = ix - 10000;
       }
       if (!ix%5)
          taskDelay(NO_WAIT); 
    }
    printf("Mid priority task taking resource B.\n");
    semTake(semBId, WAIT_FOREVER);
    taskDelay(NO_WAIT);
    semGive(semBId);
    printf("Mid priority task received and released resource B.\n");
}

/*******************************************************************************
*
* taskLowPri - low priority task
*
* This task runs at a lower priority and is designed to use resource A
* that high priority task might need.
*
*/

LOCAL void taskLowPri 
(
  int iteration			/* number of times through loop */
)
{
    int    ix, iy;				/* loop counter */

    semTake(semAId, WAIT_FOREVER);
    printf("Low priority task is using resource A.\n");

    for (ix = 0; ix < iteration; ix++)
    {
        /* printf("Low priority task is in loop count:%d\n", ix); */
       for(iy=0; iy<ix; iy++){
           ix = ix + 3000; ix = ix +7000; ix = ix - 10000;
       }
       if (!ix%5)
          taskDelay(NO_WAIT); 
    }

    semGive(semAId);
}

