    /***********************************************************************
                   Copyright (c) 2008 SKY Computers, Inc.
    
     Redistribution and use in source and binary forms are permitted
     provided that this notice is preserved and that due credit is given to
     SKY Computers, Inc. The name of SKY Computers, Inc. may not be used to
     endorse or promote products derived from this software without
     specific prior written permission. This software is provided ``as is''
     without express or implied warranty.
    ************************************************************************/

/*
 *--------------------------------------------------------------------------
 *
 >++
 *
 *   File: lk_sum.c
 *
 *   Function: Provides the sumation logic for the "lock" example.
 *
 *   Calling Sequence: compute_sum (TCB *tcb)
 *
 *   Usage: 
 *       1. See below
 *  
 *   Implementation Details:
 *       1. See below.  
 *
 *   Restrictions:
 *       1. None.  
 *
 >**
 *   Revision Information:
 *    Date       By   Rev    Changes Made....
 *    07/30/08   bwj  ----   New Module.
 *
 >--
 *--------------------------------------------------------------------------
 */

#include "sky_ex_inc.h"
#include "lk_tcb.h"

/*
 *  TimeTrac Externals -- 
 *      Do the following if you want the TimeTrac variables to
 *      disappear when the TimeTrac function calls disappear
 *      (see the Makefile).
 */
#ifdef TIME_TRAC
extern TTHandle Trace_Log[NUM_THREADS];

extern TTEventHandle tt_vsum_bgn, tt_vsum_end;
#endif

/* ---------------------------------------------------------------------- */ 

/*
 >++
 *
 *   int compute_sum (TCB *tcb):
 *       TCB *t: Task block defining this thread.
 *
 *       This is the compute thread entry point for the "sum" child threads.
 *       After startup, it waits for commands from the main thread.
 *   
 *       Returns: Does not.
 >--
 */

int compute_sum (TCB *tcb)
{
  int      i;                         /* misc loop counter */
  int      ret;                       /* value from function call */
  int      pass = -1;
  float   *src[NUM_CO_THREADS];
  float   *dst0;
    
  /* The TimeTrac parameters were set up in th_main(). */
    
  printf ("%2d -- Post Thread starting.\n", tcb->Rank);
  fflush (stdout);
  
  /* Allocate storage for the arrays. */
  for (i = 0; i < NUM_CO_THREADS; i++)
    {
      src[i] = (float *) ex_mem_alloc (tcb->Rank, V_SIZE * sizeof (float), 64, "Array Src");
    }
  dst0 = src[0];
  
  /* We are now running. */
  tcb->Status = STAT_RUN;
  printf ("%2d -- Post Thread running.\n", tcb->Rank);
  fflush (stdout);
      
  /* Process commands from the main thread. */
  while (FOREVER)
    {
      tcb->Pass++;
      tcb->Wdog = WDOG_CLR;
      
      while (FOREVER)
	{
	  /* Wait for the next command to run or exit. */
	  if (tcb->Comm == COMM_EXIT)
	    break;
      
	  /* Wait for the others, sliding this back one. */
	  ret = get_sync (tcb->Rank, tcb->Pass+1);
	  if (ret == LK_TH_GO)
	    break;

	  sched_yield ();
	  usleep (1000);
	}

      tcb->Wdog = WDOG_CLR;


      /* Do the compute function. */
      time_trac_record (Trace_Log[tcb->Rank], tt_vsum_bgn, (float)tcb->Pass);
      for (i = 1; i < NUM_CO_THREADS; i++)
	{
	  vsum (dst0, src[i], dst0, V_SIZE);
	}
      time_trac_record (Trace_Log[tcb->Rank], tt_vsum_end, (float)tcb->Pass);
	
      /* ??????. */
      tcb->Wdog = WDOG_CLR;
      sched_yield ();
    }

  /* Save the events and exit */
  tcb->Status = STAT_EXIT;
    
  /* Thread is done, exit when prent exits. */
  printf ("%2d -- Thread waiting for exit.\n", tcb->Rank);
  while (1)
    sleep (1);
}

/* --------------------------- End of Module ---------------------------- */

